Skip to content

Differential harness: CJK corpus generated from the case table - #304

Merged
derek73 merged 2 commits into
masterfrom
v2.1/cjk-corpus
Jul 30, 2026
Merged

Differential harness: CJK corpus generated from the case table#304
derek73 merged 2 commits into
masterfrom
v2.1/cjk-corpus

Conversation

@derek73

@derek73 derek73 commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #295. The fix(#271/#272) rule in expected_changes.toml had never classified a name in a real run — both existing corpora are structurally blind to unspaced CJK (v1's banks never tested it; build_issues_corpus.py requires an internal space). This adds the third corpus with a third provenance: corpus_cjk.jsonl, generated by build_cjk_corpus.py from every case-table text bearing a codepoint the script table classifies, selected through the same _script_matcher the parser uses. A no-network pin in test_regex_sync.py asserts the checked-in file equals the generator's selection, so a CJK case row added without regenerating fails the suite — and #298's future rows enter the corpus automatically.

First real run: 685 names, 44 intentional diffs, 0 unexplained, the CJK rule claiming 23 names — and the corpus immediately earned its place by surfacing a shape no rule covered: names where delimiter recognition (corner brackets / the nakaguro nickname join) and the CJK family-first flip land in the same diff. Neither single-change rule may claim that union (each excludes the other's fields on purpose, so lone regressions stay loud); the new narrow fix(cjk-delimited-nickname) rule takes exactly it, scoped to CJK-typographic delimiters, with an issue slug that deliberately avoids the #271/#272 substrings the sync test keys on.

Test plan

  • compare.py: exit 0, 685/44/0, CJK rule fires (23), compound rule fires (3)
  • Full suite 2673 passed / 13 skipped / 11 xfailed (incl. the new freshness pin); mypy, ruff clean

🤖 Generated with Claude Code

The fix(#271/#272) rule in expected_changes.toml had never classified
a name in a real run: corpus.jsonl regenerates from v1's test banks
(no reason to test CJK) and build_issues_corpus.py requires an
internal space, which unspaced names -- the exact shape the rule
explains -- never have. The rule was verified once against a
throwaway synthetic corpus during #294 and was otherwise dead weight
the harness could not distinguish from coverage.

corpus_cjk.jsonl is the third corpus with the third provenance:
generated by build_cjk_corpus.py from every distinct case-table text
bearing a codepoint the script table classifies, through the same
_script_matcher the parser uses. Row context is deliberately ignored
-- the corpus carries name STRINGS and the harness parses them with
the default facade, so a zh-scoped row's text is simply one more CJK
name to diff. The selection self-extends: a case row added for future
CJK work enters the corpus at the next regeneration, and
test_regex_sync.py pins the checked-in file against the generator's
selection so a stale corpus fails the suite.

First real run: 685 names, 44 intentional diffs, 0 unexplained, with
the CJK rule claiming 23 names. It also immediately surfaced a shape
no rule covered -- a name where delimiter recognition (corner
brackets, the nakaguro nickname join) and the CJK family-first flip
change fields in the SAME diff, which neither single-change rule may
claim because each excludes the other's fields on purpose. The new
fix(cjk-delimited-nickname) rule takes exactly that union, scoped to
the CJK-typographic delimiters so it cannot absorb a Latin delimiter
diff; its issue slug avoids the literal #271/#272 substrings the
sync test uses to select the one canonical CJK rule.

Closes #295

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.43%. Comparing base (58e93d7) to head (4eff183).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #304   +/-   ##
=======================================
  Coverage   98.43%   98.43%           
=======================================
  Files          41       41           
  Lines        2750     2750           
=======================================
  Hits         2707     2707           
  Misses         43       43           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@derek73 derek73 self-assigned this Jul 30, 2026
Review found the delimiter-only regex claiming more than its comment
said: 「」『』 sit in CJK Symbols and Punctuation, OUTSIDE every
classified span, so 'John 「Jack」 Kennedy' matched and a bare
first/last regression on a Latin name classified as intended. The
rule now requires a classified codepoint alongside the delimiter
(both lookaheads), drops the unearned middle field (all three claimed
diffs touch exactly first/last/nickname), and its comment owns the
one absorption subset-matching cannot avoid -- a nickname-only diff
on a nakaguro name -- instead of claiming 'cannot absorb'.

The second lookahead is the toml's second hand copy of the script
spans, so it gets the same sync pin as the first, which also pins the
delimiter set and records the #271/#272-substring taboo where a rule
author will look. Plus the smaller review items: the provenance
comment now credits the parity rows (the corpus members that pin
NON-diffs), the positional note within the name_regex tier is stated,
test_regex_sync's module docstring counts its outside-the-package
tests correctly, and the README comma splice is mended.

Noted, not changed: the Latin probes the review used do not fall to
UNEXPLAINED without the compound rule -- the fields-only
fix(suffix-routing) rule absorbs any bare first/last diff on any
name, and always has. Pre-existing fields-tier looseness, outside
this change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@derek73
derek73 merged commit 0e49f61 into master Jul 30, 2026
9 checks passed
@derek73
derek73 deleted the v2.1/cjk-corpus branch July 31, 2026 01:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Differential harness: no corpus contains a CJK name, so the fix(#271) rule never fires in a real run

1 participant