Commit Graph

5 Commits

Author SHA1 Message Date
Clayton Kim 7da5764aa0 Transform UNSLOP around the core rewrite contract 2026-08-05 13:37:43 -07:00
Clayton Kim 749754d776 Teach title claim-function rules (#3)
* Teach title claim-function rules

* Fix contributor template on Python 3.11

---------

Co-authored-by: Clayton Kim <claytonkim@users.noreply.github.com>
2026-07-24 09:53:56 -07:00
Clayton Kim 460339eb14 Validate contribute's pattern-name slug and fix the exclamation ReDoS
contribute.py joined --pattern-name into a filesystem path before any
validation, so a value like ../evil escaped .unslop/contrib/ and wrote
four bundle files there before the only containment check (a
relative_to call in the success print) ever ran. Reject non-slug names
up front with the file's existing error-JSON convention, exit 2, no
write.

The exclamation_overuse structural pattern had two adjacent unbounded
quantifiers over overlapping character classes (\s is a subset of
[^.]), causing quadratic backtracking on a long unclosed exclamation
run (5.7s at 32k chars, in-process callers like harvest and refine run
it with no timeout). Excluding ! from the interior class removes the
overlap and keeps identical match spans on FP-37 and REC-17.

New rows SLUG-01 and REGX-01 pin both fixes; REGX-01 times the live
STRUCTURAL_PATTERNS entry directly so it tracks the production regex.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CYksdLbXbTAxcAQjvHz5
2026-07-07 06:17:44 -07:00
Clayton Kim d6f632117f Consolidate eval/scanner internals: shared modules, in-process calls, faster gates
Applies a reviewed cleanup list without changing any script's CLI flags, JSON
keys, exit codes, or stderr messages (all pinned by eval rows).

Shared modules (dedup):
- scripts/_lang.py: ENGLISH_FUNCTION_WORDS/english_function_share/is_probably_english,
  previously byte-identical copies in banned_phrase_scan.py and structure_scan.py.
- structure_scan.py now imports split_sentences from readability_metrics instead
  of keeping its own copy.
- silhouette_scan.py's stopword set is a verified pure superset of
  structure_scan's; SILHOUETTE_STOPWORDS = structure's set | the extras.
- harvest_classify.py imports recency_value/DATE_FLOOR from harvest_samples.
- evals/_check_support.py: ROOT, run(cmd, timeout=60), load_evals() -- the
  timeout=60 safety net that only check_contrib.py had now covers check_pairs,
  check_seeded_docs, check_mimic, check_contrib, check_voice, and
  check_pattern_coverage too.

Small cleanups: contribute.py's row_fn drops its unused category param;
run_model_parity.py's resolve_models param renamed responses->payload;
harvest_classify.py's heuristic() attaches suspect_ai/dictated so
rank_enriched needs no reconstruction; check_pattern_coverage.py's paired flag
formulas become a plain "if neither: both = True"; check_contrib.py drops the
__import__("scripts.contribute", ...) spelling for a normal import;
run_mimic_refine.py computes docs_a/matrix_a once and passes it to both
make_live_source and write_outputs; calibrate_pairs.py factors its four
near-identical contraction-replacement closures into one _contraction_repl
helper used by both directions.

Altitude items: GENRE_SUPPRESSIONS lookup tables replace the inline
`genre != "..."` conditionals in structure_scan.py and silhouette_scan.py;
check_gates_doc.py additively verifies every *.py token in a gate command
exists under ROOT (behavioral-tune and rubric-judge are exempt -- neither
command has a .py token).

Efficiency (Phase 2), each verified against the same eval rows / diffed
outputs before landing:
- run_model_parity.py replaces its subprocess-per-scanner-call helpers with
  in-process imports of banned_phrase_scan/structure_scan/validate_preservation
  (mirrors run_mimic_refine's import pattern). PARITY slice: 14.2s -> 0.33s.
- voice_score.py's lcs_len (O(n*m) DP) is replaced by
  has_common_substring_over(), an O(n+m) rolling-hash check for "any shared
  substring longer than the 120-char threshold" (hash matches are verified
  against the source text, so no false positives). Nothing pins the exact
  longest_common_substring value (checked); it now reports the matched
  threshold window length on a hit, 0 otherwise -- documented in the
  docstring. The violation boolean is unchanged.
- gi_score() precomputes per-key distances once per candidate/impostor
  instead of recomputing distances() from scratch every trial; trials do a
  subset-weighted sum over the precomputed values. Arithmetically exact
  (same RNG draw order, same float sums) -- verified the VOICE-08
  determinism value and the full check_voice --separation/--gi/--gaming
  output are byte-identical before/after.
- check_voice.py and check_pairs.py convert their subprocess-per-cell/row
  scanner calls to in-process imports (voice_score/voice_profile,
  banned_phrase_scan/structure_scan), mirroring the CLI's own decline/exit
  logic so output stays byte-compatible.

Deferred (out of scope for a contract-safe pass): a protects-grain redesign,
giving silhouette_scan.py its own English-decline gate, and decomposing
run_mimic_refine.py's build_report().

python3 evals/run_adversarial.py: 434 PASS / 1 XFAIL / 0 FAIL, unchanged
throughout; wall time 54.8s -> 25.3s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CYksdLbXbTAxcAQjvHz5
2026-07-06 16:34:29 -07:00
Clayton Kim 04de83e99e Add contribute pipeline: wild-caught snippets become eval rows and structured PRs
scripts/contribute.py (precheck/scaffold/verify/report, fully offline):
specimen fidelity byte-for-byte, redaction safety (tell-overlap exit 4),
red-first verification with TODO-refusal, golden-tested PR body template.
references/contribute.md: agent procedure with two user-confirmation gates
(redaction, publication), explicit bundle-to-suite bridge, fork path.
CONTRIB-01..10 rows + contribute gate.

Review fixes: frozen --date injection (fixtures no longer date-fragile),
casefolded phrase assertions (capitalized tells mergeable), structure_scan
flags honored in precheck (both-scanners contract), conditional REC row in
the template.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:14:04 -07:00