Skip to content

Replace the differential ledgers with a committed snapshot (#664) - #666

Merged
derek73 merged 10 commits into
masterfrom
claude/differential-harness-review-138733
Oct 13, 2026
Merged

derek73 merged 10 commits into
masterfrom
claude/differential-harness-review-138733

Conversation

@derek73

@derek73 derek73 commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Closes #664.

The differential ledgers were built to show that 2.0 changed nothing against 1.4 except listed fixes. They did that job. As a standing check, every parser change had to be classified once per ledger, and the guards policing the ledgers grew longer than the ledgers. This PR replaces them with a committed snapshot of how the tree reads every corpus name.

What changes

The snapshot. tools/differential/snapshot.py writes snapshot.jsonl: one line per (name, order) across every corpus*.jsonl. Each line holds the seven role fields, ambiguity kinds and initials(), plus the facade's reading where it differs (3 names today). tests/v2/test_snapshot.py fails on drift and prints the moved names grouped by changed field. A change that moves readings re-records the file, and its diff in the PR is the list of names it moved.

  • --since <ref> compares against the snapshot at a tag, for release notes.
  • --tree PATH reads with another checkout.

compare.py stays, unclassified. It is down from 3,732 lines to about 400.

  • Kept: the PyPI-wheel runner and its checks against comparing the tree with itself (version tell, source-package check, stripped PYTHONPATH).
  • Changed: it prints the same grouped report as the snapshot, plus the population: entries compared, order-bearing entries skipped below 2.0.0, how many moved names are Latin-only, and how many only corpus_cldr.jsonl holds. It always exits 0, and --corpus PATH still compares a file of your own names.

Deleted:

  • the six expected_since_*.toml ledgers
  • tests/v2/test_ledger_guards.py
  • the contract/radar tiers and the roster tables

With the tiers gone, two simplifications followed. Neither changes the snapshot:

  • corpus_cjk_tolerated.jsonl folds back into corpus_cjk.jsonl (same 153 names).
  • build_rules_corpus.py stops skipping tolerated rules' examples (8 W3 texts, which the CJK corpus already held).

Kept, unchanged: the CLDR agreement ratchet.

Tests that guarded surviving code moved:

  • The corpus-generation pins and the four issue-harvester tests are now in tests/v2/test_corpora.py.
  • The phrase-entry storage test is now in test_lexicon.py.

Docs:

  • tools/differential/README.md drops from 995 lines to about 400.
  • AGENTS.md: the Release-log claims paragraph and release checklist steps 1 and 8 now use snapshot.py --since (or compare.py for a tag older than the snapshot).
  • decisions.md: a new dated entry records the retirement, the measurements, the accepted costs and what was declined.
  • mechanisms.md: three ledger-only entries are marked retired. Their headings stay because decisions.md cites them.
  • rules.md: the tolerated-marker paragraph and the S2, S3, C1, C2 and W3 passages no longer argue from an enforced corpus.

Measurements

These replace the figures in the issue description, which were partly wrong; the correction is posted on #664.

Accepted costs

  • No forced explanation per moved name. A large snapshot diff can be approved unread; the grouping by changed field is the mitigation.
  • The 1.4 compatibility promise becomes a question you ask when needed (compare.py --baseline 1.4.0, 808 of 2,635 compared entries move today), not a gate at every release.

Review

  • Code review (first round): found that snapshot.py didn't check which nameparser it imported, that --tree used a weak path check, that compare.py skipped entries without saying how many, and that four harvester tests had been deleted. All fixed.
  • Docs/design review: found wrong figures, a deleted exemplar still cited, and stale tier arguments in rules.md. All fixed.
  • Second-round review of the fix commits: found two counts that no test asserted and a misleading error message. All fixed.
  • Mutation checks: each new guard was mutated out and fails its test.

Test plan

Follow-up: cut 2.4.1 after this merges, so a release tag carries the first snapshot.

🤖 Generated with Claude Code

derek73 and others added 10 commits October 12, 2026 23:37
tools/differential/snapshot.py records one line per (name, order)
across every corpus*.jsonl: the seven role fields, ambiguity kinds and
initials() on the 2.0 surface, plus the facade's fields where they
differ. tests/v2/test_snapshot.py fails on drift and prints the moves
grouped by which fields changed; --since REF compares against the
snapshot at a git ref, --tree PATH reads with another checkout.

Measured 2026-10-12: 3,422 readings, 495 KB, ~1.1s test. Run before
and after #655, it reports five moved names where that PR spent 241
lines on ledger and guard edits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deletes the six expected_since_*.toml ledgers and
tests/v2/test_ledger_guards.py. The snapshot (tools/differential/
snapshot.py and tests/v2/test_snapshot.py) is now how a change shows
which corpus names it moved: the PR diff of snapshot.jsonl.

compare.py keeps the released-wheel runner and its checks against a
comparison of one tree with itself (version tell, path checks,
stripped PYTHONPATH), and prints the moves grouped by changed fields
through snapshot.py's row format and grouping. It classifies nothing
and exits 0. Corpus-line validation moved into snapshot.py, so both
tools read the corpora through one loader.

With the contract/radar tiers gone, the CJK corpus is one file again
(corpus_cjk_tolerated.jsonl folded into corpus_cjk.jsonl, same 153
names) and build_rules_corpus.py stops skipping tolerated rules'
examples (8 W3 texts the CJK corpus already held); the snapshot is
unchanged by both.

The corpus-generation pins move to tests/v2/test_corpora.py, the
phrase-entry storage test to test_lexicon.py; test_doc_citations.py
stops sweeping ledger comments and tests the lead forms only the
ledgers exemplified directly against the grammar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/differential/README.md keeps the invocation traps and corpus
provenance and drops the ledger, tier and roster sections (995 -> ~400
lines). AGENTS.md's Release-log claims paragraph now draws claims from
`snapshot.py --since <tag>` (or compare.py for a tag older than the
snapshot), and release checklist steps 1 and 8 shrink to reading that
report and moving DEFAULT_BASELINE.

docs/design: a decisions.md entry records the retirement with its
measurements and accepted costs; mechanisms.md keeps the headings
decisions.md cites but marks LEDGER-RULE-SEPARATION,
CROSS-RULE-OUTCOME-PINS and SENTINEL-SET-OVER-MATCH-CHECK retired,
moves RECORDED-ROSTERS' exemplar to the snapshot, and drops the
ledger-only field note; rules.md's tolerated-marker paragraph and two
W3/S3 passages stop describing a radar tier.

compare.py regains --corpus (now a path list through snapshot.py's
loader), which docs/migrate.rst offers users for their own names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on (#664)

- snapshot.py checks that the tree side is a source package
  (check_source, shared with compare.py's _check_tree); --tree used the
  weaker under-the-root test, which an ancestor of the checkout passed
  while the import fell through to the checkout itself.
- compare.py reports how many entries it compared and how many
  order-bearing ones it skipped below 2.0.0 (788 at 1.4.0).
- The four build_issues_corpus.py harvester tests, deleted with the old
  test_differential.py, return in test_corpora.py.
- --since on a ref with no snapshot says so instead of a traceback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iers (#664)

- decisions.md: the share recipe names its head (04cc081) and its
  exact exclusions; 21% not 20%; #655's ledger and guard edits were 236
  lines, not 241 (the other 5 were corpus data); the per-PR spread is
  stated as measured (0-82%, median 11%, above 30% on 11 of the 29
  commits touching nameparser/) instead of "30-60%".
- AGENTS.md and mechanisms.md named _EXCLUSION_EFFECT, deleted with the
  guards, as the recorded-negative-control exemplar; it is
  _UNGUARDED_EFFECT now.
- rules.md S2, C1 and C2 argued against example lines from the cost of
  entering the enforced corpus; the reason now given is the promise an
  example would make.
- Both tools print how many moved names only corpus_cldr.jsonl holds,
  which a release figure counts out.
- Stale tier/roster mentions in _script_segment.py and cases.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…664)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- only_in's test now holds a name CLDR shares with another corpus
  (マイケル), so the subtraction is exercised; without it, dropping
  '- others' passed every test.
- compare.py's CLDR-only count is asserted, at 0 and at 1.
- --since names both causes of a missing snapshot (unknown ref, or one
  from before the snapshot).
- A stale 'the gate witnesses it' comment in test_group.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@derek73 derek73 added this to the 2.5 milestone Oct 13, 2026
@derek73 derek73 self-assigned this Oct 13, 2026
@derek73 derek73 modified the milestones: 2.5, 2.4.1 Oct 13, 2026
@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.02%. Comparing base (1f0b374) to head (767b49a).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #666   +/-   ##
=======================================
  Coverage   99.02%   99.02%           
=======================================
  Files          46       46           
  Lines        4534     4534           
=======================================
  Hits         4490     4490           
  Misses         44       44           

☔ 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 merged commit 2c2e58b into master Oct 13, 2026
12 checks passed
@derek73
derek73 deleted the claude/differential-harness-review-138733 branch October 13, 2026 07:43
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.

Replace the differential ledgers with a committed snapshot of corpus readings

1 participant