Skip to content

tooling(differential): the six 2.x contests get their winners, and a regex accident is narrowed away - #506

Merged
derek73 merged 5 commits into
masterfrom
claude/501-contest-pins
Sep 5, 2026
Merged

tooling(differential): the six 2.x contests get their winners, and a regex accident is narrowed away#506
derek73 merged 5 commits into
masterfrom
claude/501-contest-pins

Conversation

@derek73

@derek73 derek73 commented Sep 5, 2026

Copy link
Copy Markdown
Owner

The six contested diffs in the 2.x ledgers get pinned winners, each with its argument, and the regex accident that put a false label on a contract-tier name is narrowed away in both ledgers that shipped it. Closes #501.

The adjudication

#501 asked whether contests that are measured but unargued should be pinned. They were argued — per name, against each admitting rule's prose and the measured old/new field values at the pinned wheel (the #372 test: does the winning rule DESCRIBE the change?) — and three of the six turned out to be argued already, in expected_since_2.0.0.toml's own comment naming the names. One of those three arguments was wrong.

name ledger winner why
田中さん 様., 田中さん, 様. 2.0.0 glued-peel fix(#308/#312/#319/#320) both mechanisms fire and each rule describes one half; nested narrow-first; the glued rule's #312/#319/#320 clauses name these strings and only it describes 田中さん shrinking to 田中
김민준 박사님 2.0.0 spaced fix(#307/#308/#320)after narrowing the glued rule won by reaching inside 박사님; measured, nothing is peeled (rules.md#W2's second sentence, its witness); its own comment conceded the accident
선생님 2.0.0 order rule fix(#271/#272/#298) the whole diff described; the glued rule's admission was the same interior- accident with suffix moving nowhere; fields intersect without nesting (#498's class)
MD, PHD 2.0.0, 2.1.0 fix(#296) a credential-only comma string… the same pair and winner as its 1.4.0 row; equal fields; "the string is nothing but credentials" is a property of the string, not the shape

The narrowing

(?<!박사)(?<!선생)(?<!교수) on the glued-peel rule's name_regex in both the 2.0.0 and 1.4.0 ledgers (byte-identical patterns; the three are the only listed honorifics containing another). Measured: exactly one name changes hands per ledger (김민준 박사님), summary lines byte-identical to master, no 1.4.0 pin moves, order_contests unchanged, two _CORPUS_CLAIMS reaches 37 → 35 losing exactly 김민준 박사님 and 선생님. Its sharpest consequence: two of the six contests dissolved김민준 박사님 and 선생님 are now one-runner rows, pinned the way 13 of the 1.4.0 rows are — so the plan's swap control for 선생님 was inert as written; the honest control (wide regex restored and the swap) fails on both names.

What the records now say

_CROSS_RULE_WINNERS's 2.x sections stop being "a stated position": the criterion is argued anywhere, not argued in the guard module — a ledger comment's argument is exactly what no guard can see, and the roster is the only thing that can check it (mechanisms.md#CROSS-RULE-OUTCOME-PINS). _WATCHED_DIFFS drops to 41 / 31 / 30 / 5 = 107 rows over 50 names, now exactly the sole-watched population (MD, PHD at 2.0.0 was a watched row too, so five moved). A dated decisions.md entry carries the six verdicts, the narrowing's measurements, the three controls, and three doctrine gaps the adjudication exposed: a two-mechanism compound with one rule per half has no "which half is the change" test; a regex accident in a narrow-first or non-nested pair has no declaration site (precedes_narrower is wide-first-only — the shape that put a false label on a contract name and stayed green; closed here by narrowing the accident away); and "argued in this file" was the wrong locus.

Verification

Intentional counts 352 / 247 / 155 / 14 byte-identical at every commit, 0 unexplained, 0 radar-unclassified, no MOVED SHAPE / NOT CHECKED. Three in-memory controls, each failing the winner guard on exactly the expected names. Every figure re-derived by an independent reviewer (regex completeness, per-ledger classification diff against master's exported ledgers, regenerated claim digests, all ledger-comment counts). Full suite green; ruff and mypy clean.

🤖 Generated with Claude Code

derek73 and others added 5 commits September 5, 2026 14:33
…nger honorific

Both ledgers ship the same glued-peel `name_regex`, and both matched a
listed honorific sitting INSIDE a longer listed one. 박사님, 선생님 and
교수님 are the only entries of that alternation containing another
entry of it, so the interior 님 was the one way a SPACED honorific
could reach a rule whose title says a glued one was peeled off the
name. It reached two corpus names, and on one of them the label was
simply false: '김민준 박사님' has nothing peeled off it at all --
rules.md#W2's second sentence says a part that is not name text is
never the name's end, and its witness line for this very string is
suffix="박사님", the honorific whole and standing as its own word. That
is a FALSE label on a contract-tier name, held green by every guard in
the suite. The other, '선생님', moves no `suffix` whatsoever: its diff
is the order flip's {given, family} and the CJK order rule claims it
either way.

`(?<!박사)(?<!선생)(?<!교수)` goes in immediately after the existing
`(?<=[^\s,])` in both ledgers. It refuses the interior position only:
a glued '김민준박사님' still matches on 박사님 itself.

MEASURED CONSEQUENCE, 2026-09-05. Exactly ONE name changes hands per
ledger and it is '김민준 박사님' -- to the spaced rule
fix(#307/#308/#320) at 2.0.0, whose title is what happens to it, and to
fix(cjk-honorific-suffix) at 1.4.0. Diffed as (name, order, rule)
triples by wrapping classify() and driving main() at all four
baselines, before and after: 1 change at 1.4.0, 1 at 2.0.0, 0 at 2.1.0,
0 at 2.2.0, and no name entered or left the compared population.
Summary lines byte-identical at every baseline -- 352 / 247 / 155 / 14
intentional, 0 unexplained, 0 radar unclassified, exit 0 -- with no
MOVED SHAPE and no finding block. order_contests is unchanged: 11
wide-first nested contests at 1.4.0 over the same names, the
compound/peel row still 17, and 0 at each 2.x ledger. No 1.4.0 pin
moves. _HONORIFIC_SOURCES is untouched, the alternation body being
untouched, and its guard passes.

RE-RECORDED, the roster's own way (_claim over the shipped rule, never
a hand-edited digest): both _CORPUS_CLAIMS rows go
_Claim(37, ('family', 'given', 'suffix'), "719c31233502", None) ->
_Claim(35, ('family', 'given', 'suffix'), "9a1b4c202a65", None), the
two names lost from reach being the two above.

Ledger prose that the change made stale, re-measured rather than
adjusted: the 1.4 peel rule explains 16 corpus names, not 17; twelve of
those are contract tier, where three `precedes_narrower` blocks said
fourteen -- one of which the period-class demotion had already taken
and one the narrowing takes. The claim that deleting the rule leaves
TWELVE contract names unexplained still holds, before and after, and
says so now.

A hermetic test pins the property rather than the pattern: over both
ledgers read off disk, `_entry_matches` is False for '김민준 박사님' and
'선생님' and True for the glued '김민준씨', so a narrowing that
overshoots fails as loudly as the accident did not.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The two 2.x sections of _CROSS_RULE_WINNERS and of _RECORDED_DIFFS
stood empty on a position: contests were MEASURED there -- 5 of the 247
diffs at 2.0.0 and 1 of the 155 at 2.1.0 move a shape two or more rules
admit -- and the rule was that a row is owed when somebody ARGUES a
boundary, not when one is merely measured. #501 argued all six
(2026-09-05). The five rows at 2.0.0 and the one at 2.1.0 move from
compare._WATCHED_DIFFS to _RECORDED_DIFFS with their shapes unchanged,
which is what that dict's NO WINNER clause says happens the day a
winner is argued, and the six winners go in beside them.

WHAT THE POSITION GOT WRONG was WHERE an argument counts. Three of the
six boundaries were already argued -- in the 2.0.0 ledger's own comment
on fix(#308/#312/#319/#320), which named '田中さん 様.', '田中さん, 様.'
and '김민준 박사님' one by one and said for each why the glued rule
should win. One of those three arguments was FALSE, and it stood for a
month with every guard green because no row here made classify() answer
for it. That is the case for the criterion being ARGUED SOMEWHERE
rather than argued in this file: a ledger comment's claim about which
rule wins a name is checked by nothing, and this roster is the only
thing in the tree that can check it.

THE SIX, with the argument each rests on:
  '田中さん 様.' and '田中さん, 様.' -> fix(#308/#312/#319/#320). The
  only live two-runner contest of the six. A compound of two mechanisms
  with one rule per half and fields that do not nest, so no
  precedes_narrower block can name the pair and file order is the whole
  decision. #312/#319/#320 are the glued rule's clauses and they name
  both strings; no clause of the spaced rule mentions either.
  '김민준 박사님' -> fix(#307/#308/#320), the SPACED rule, which only
  wins after the narrowing in the commit before this one.
  '선생님' -> fix(#271/#272/#298). The whole diff is the order flip's
  {given, family}; the glued rule's claim declared a `suffix` that
  moves nowhere. The pair is the #498 class -- intersecting `fields`,
  neither nested -- so undeclared_contests looks past it.
  'MD, PHD' at 2.0.0 and at 2.1.0 -> fix(#296) a credential-only comma
  string reads a name and its postnominal. Both #296 rules declare
  EQUAL `fields` here, so only file order decides; the distinguishing
  clause is a property of the STRING, which holds no name.

MUTATION CONTROLS, in memory around the guard, per row so that a
failure on one cannot mask the rest:
  (i) glued <-> spaced at 2.0.0 -- fails on both '様.' names:
  "expected_since_2.0.0.toml: '田中さん 様.' diffing ['family',
  'given', 'suffix'] is now explained by 'fix(#307/#308/#320) spaced
  CJK postnominal honorific routed to suffix', not
  'fix(#308/#312/#319/#320) glued CJK honorific peeled off the name
  into suffix'."
  (ii) the two fix(#296) credential rules swapped -- fails at BOTH
  baselines: "expected_since_2.0.0.toml: 'MD, PHD' diffing ['suffix',
  'title'] is now explained by 'fix(#296) a lone post-comma credential
  is a suffix', not 'fix(#296) a credential-only comma string reads a
  name and its postnominal'." and the same sentence under
  expected_since_2.1.0.toml.
  (iii) the pre-narrowing glued regex restored AND the CJK order rule
  swapped with it -- fails on both remaining rows:
  "expected_since_2.0.0.toml: '김민준 박사님' ... is now explained by
  'fix(#308/#312/#319/#320) ...', not 'fix(#307/#308/#320) ...'." and
  "expected_since_2.0.0.toml: '선생님' diffing ['family', 'given'] is
  now explained by 'fix(#308/#312/#319/#320) glued CJK honorific peeled
  off the name into suffix', not 'fix(#271/#272/#298) native-script
  CJK: ...'."
  Every one of the six rows is moved by some control; no pin is inert.
  The regex restore is part of (iii) because the reorder ALONE is now
  inert -- 0 of the 247 classifications move -- which the narrowing did
  and which the '선생님' row's comment records: after it, that row's
  work is against a re-widening rather than against a reorder. The
  widening alone suffices for '김민준 박사님', the glued rule already
  sitting ahead of the spaced one.
  Each control leaves `unexplained` at 0, so the gate's summary line
  reports none of them.

COUNTS, recomputed with the script in the dict's own header rather than
adjusted: _WATCHED_DIFFS goes 41 / 32 + 4 / 31 / 5 = 113 rows to
41 / 31 / 30 / 5 = 107, over 50 names where it was 51 plus the four
contests -- and the roster is now exactly the sole-watched population
the sweep draws, the rows beyond it having left. 48 of the 50 sit in
corpus_issues.jsonl and 3 in corpus.jsonl, overlapping on 'dr Vincent
van Gogh dr'. The tests/-only scan still says 52 names; the two it
counts that this dict does not are 'Carod i' and, since this commit,
'MD, PHD', both carrying a contest row at every baseline they diff at.

THREE of the six pinned names are RADAR tier ('田中さん 様.',
'田中さん, 様.', 'MD, PHD'), so a moved shape on them is now fatal
where a watched row would have printed. Accepted as the SEVERITY rule
written: a contest row is fatal on either tier because it carries an
argument. 22 of the 31 rows at 1.4.0 are radar names on those same
terms.

Gate x4 byte-identical to the previous commit's, line for line, apart
from the baseline worker's temp path: 352 / 247 / 155 / 14 intentional,
0 unexplained, 0 radar unclassified, exit 0, no MOVED SHAPE and no
NOT CHECKED.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A dated entry in decisions.md for the ninth ledger arc, the amendments
the two commits before it made owed to the arc above, and one sentence
each in the two mechanisms entries the arc moves.

THE ENTRY records the six verdicts one at a time -- the admitting
rules with their file positions, `fields` and pair class, the measured
old -> new field values at the pinned wheel, the ledger or rules.md
sentence each verdict rests on quoted, and the in-memory swap the pin
now catches -- then the narrowing and its per-ledger consequence, four
findings, three declines and the recompute for all of it.

MEASURED THIS SESSION at ddd8b2b, from one instrumented run of main()
at all four baselines with classify() and _run_worker spied. 352 / 247
/ 155 / 14 intentional, 0 unexplained, 0 radar unclassified, exit 0,
no MOVED SHAPE and no NOT CHECKED. The controls reproduce ddd8b2b's
captures byte for byte.

THE SHARPEST FINDING is that the narrowing dissolved two of the six
contests. At 2.0.0 only three of the 247 classifications now have more
than one admitting rule; '김민준 박사님' and '선생님' are one-runner rows, of
the kind 13 of the 31 at 1.4.0 are, and they stay because the test is
mechanisms.md#RECORDED-ROSTERS' -- would the consumer answer
differently if the row were wrong. Measured: '김민준 박사님' routes to
fix(#271/#272/#298) under other shapes as 11 of those 13 do, and
'선생님' routes nowhere else, its whole work being against a re-widening.
The plan's control (iii) as written was therefore INERT -- the reorder
alone moves 0 of the 247 -- and the honest control restores the wide
regex AND swaps.

TWO CORRECTIONS to figures this branch made stale, both as dated
clauses rather than rewrites: 'MD, PHD' at 2.0.0 was itself a
_WATCHED_DIFFS row, so FIVE rows left that section and not four and
six in all; and the pair class of the '様.' contest is strictly NESTED
and narrow-first ({family, given, suffix} inside {family, given,
middle, suffix}), not non-nesting -- what survives is the conclusion,
that no precedes_narrower block is owed, and order_contests reports
the pair only in the arrangement nobody ships (measured both ways).

THE WATCHED-SHAPES ARC gets seven dated amendments, in the form line
811 already uses: 41 / 36 / 31 / 5 = 113 over 51 names became 41 / 31
/ 30 / 5 = 107 over 50, the roster now being exactly the sole-watched
population; the exposure bullet's figures re-derived over the 107 as
363 / 66 gross, 310 / 58 net, 35 other-rule, with both of the figures
its argument rests on reproducing unchanged; the per-file split 48 + 3
over 50; and its `Declined:` bullet on pinning the six marked REVERSED
the same day, its text untouched.

ONE FIGURE IS LEFT UNRECONCILED and says so: 22 of the 31 rows at
1.4.0 sit on radar names today against the 21 measured 2026-09-03. No
corpus file and no _CORPUS_TIERS value differs between the two trees
and the section held the same 31 rows on both days, so it is a recipe
difference; the entry gives the recompute and enumerates the nine
contract rows so the next reader can settle it by hand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Prose only; no rule, roster row, regex or assertion moves, and every
figure below was measured on this tree this session.

FIVE CLAIMS. (1) _sorted_rules' docstring said three names match both
honorific rules; two do since the narrowing (measured over the
corpus*.jsonl union: '田中さん 様.' and '田中さん, 様.'; three at master,
e004ccf, where '김민준 박사님' was the third). It is the twin of the
ledger sentence a6a82d6 already fixed. (2) The '様.' row's comment
called the pair one whose fields do not nest. They nest strictly --
the glued rule's {given, family, suffix} inside the spaced rule's
{given, middle, family, suffix} -- and the glued rule is written
FIRST, so the pair is nested NARROW-FIRST and no `precedes_narrower`
is owed because the narrower rule already wins. Measured over the
corpus union, order_contests reports nothing for this ledger as it
stands and reports this pair, both names, only with the two rules
swapped; undeclared_contests likewise. What is unusual about the pair
survives the correction and is now stated as itself: narrow-first's
JUSTIFICATION does not apply, both mechanisms firing at once with each
rule describing one half, so the row pins a default that is correct
without being justified. (3) '5 of the 247 at 2.0.0 and 1 of the 155
at 2.1.0' is the pre-narrowing figure and now says so; the same recipe
here gives 3 and 1, the narrowing having dissolved two of the six
contests, which the paragraph below it already said. (4) 'THREE of the
six are RADAR-tier names' counted names and said rows: four of the six
ROWS are radar, three distinct NAMES, 'MD, PHD' carrying a row at each
2.x baseline. (5) 'the commit before this one' is now the 2026-09-05
narrowing of the glued-peel `name_regex` named outright.

THE 21/22 COUNT is a tier move, not a recipe difference, and the row
is '김민준 씨.': eb2d0d2, the period-class demotion of PR #505, moved it
from corpus_cjk.jsonl (contract) to corpus_cjk_tolerated.jsonl
(radar), so it counted contract on 2026-09-03 and counts radar now.
The 31 rows are byte-identical between the two trees. The #501 entry's
"no corpus file changed" check ran `git show` at `88b025b^` = d0faed4,
three commits AFTER the move -- the one thing the window could not
see. Both candidate recipes were run on both trees and at baselines
1.4.0 and 2.0.0: first-corpus-file-with-contract-first, and main()'s
own tier_of, give 21/10 at 17a9e66 and 22/9 here, name for name. They
can differ in principle -- a string in files of both tiers whose
contract copy is order-bearing loses that copy to the baseline-minimum
skip -- and no row of this section is in that position today. The
"NOT reconciled" sentence goes; README.md's tier paragraph, which
carries the live recompute, says what the 21 became and why.

VERIFIED: pytest tests/v2/ -k "doc or rules or decisions or mechanisms
or guard or citation" 704 passed 1 skipped; test_ledger_guards.py +
test_differential.py 298 passed; ruff clean; mypy clean over 111
files; gate exit 0 at 2.0.0 (247 intentional, 0 unexplained, 0 radar
unclassified) and at 1.4.0 (352, 0, 0), no MOVED SHAPE, no NOT
CHECKED.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
All five sit in docs/design/decisions.md and were made false, or written
wrong, by this branch's own commits. Every figure below measured
2026-09-05 on this tree.

(1) The #501 entry's lead counted NAMES where the roster counts ROWS.
_RECORDED_DIFFS' 2.x sections hold SIX rows over FIVE distinct names:
radar is 4 rows / 3 names ('田中さん 様.' and '田中さん, 様.' in
corpus_cjk_tolerated.jsonl, 'MD, PHD' in corpus_issues.jsonl with a row
at each 2.x baseline), contract 2 rows / 2 names ('김민준 박사님',
'선생님', corpus_cjk.jsonl). "THREE of the six pinned names are radar
tier" was neither reading. Now says both, as compare.py's own 2.x
comment does.

(2) The recorded-shapes arc (2026-09-03, #497) still described the two
2.x sections as empty and #501 as open. _CROSS_RULE_WINNERS reads
31 / 5 / 1 / 0 on this tree and #501 closes with this PR. A dated
superseding parenthetical goes in beside the original sentences, in the
style that arc already uses one bullet earlier, and the header's pointer
loses "empty". The criterion those sentences state is what FILLED the
sections and is not superseded: a row is owed when someone argues a
boundary, and three of the six were found already argued, in the 2.0.0
ledger's own comment.

(3) The watched-shapes arc said three of the four #501 rows sit in
contract corpora. TWO do: '김민준 박사님' and '선생님' are in
corpus_cjk.jsonl and corpus_rules.jsonl, the two '様.' strings in
corpus_cjk_tolerated.jsonl only -- the same four files at HEAD and at
master (e004ccf), so this is not a move the branch made. The same
sentence pointed at a line in _WATCHED_DIFFS' header ("a row consults
the case row before this roster") that this branch DELETED, e004ccf's
compare.py:1805 having no counterpart here; past-tensed, with why the
header no longer needs it.

(4) Two relative pointers replaced by what they point at: "the
narrowing in the commit before it" -> the 2026-09-05 narrowing of the
glued-peel name_regex in both ledgers (a6a82d6); "each of the branch's
two commits" -> every commit of the branch, the branch having four,
with the review round's own two-baseline record named rather than
implied.

(5) The declined fatal-on-radar bullet's 51 now carries its tree, as
its siblings in the same arc already do: the 51 as measured before the
#501 adjudication, 50 after. The arc's three counts (50 / 51 / 52) each
say which tree they are on.

MEASURED with the scratch scripts, against compare.py and
test_ledger_guards.py loaded from this worktree: row and name counts
per ledger section, the tier of each pinned name by the first corpus
file holding it with contract files sorted first, and the corpus
membership of the four #501 names on both trees by git show.

VERIFIED: pytest tests/v2/ -k "doc or rules or decisions or mechanisms
or guard or citation" 704 passed 1 skipped; ruff clean.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@derek73 derek73 added docs Documentation fixes and updates tooling tests labels Sep 5, 2026
@derek73 derek73 self-assigned this Sep 5, 2026
@codecov

codecov Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.66%. Comparing base (e004ccf) to head (f776a48).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #506   +/-   ##
=======================================
  Coverage   98.66%   98.66%           
=======================================
  Files          45       45           
  Lines        3219     3219           
=======================================
  Hits         3176     3176           
  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 merged commit fca8bf4 into master Sep 5, 2026
11 checks passed
@derek73
derek73 deleted the claude/501-contest-pins branch September 5, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation fixes and updates tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Six contested diffs in the 2.x ledgers have no pin, and the empty rosters read as if none existed (MD, PHD goes to whichever rule comes first)

1 participant