Skip to content

differential: compare initials() on roles-identical names (#484); fix the facade's dropped E/Y initial (#462) - #494

Merged
derek73 merged 6 commits into
masterfrom
claude/v2-3-prioritization-ca7dea
Sep 2, 2026
Merged

differential: compare initials() on roles-identical names (#484); fix the facade's dropped E/Y initial (#462)#494
derek73 merged 6 commits into
masterfrom
claude/v2-3-prioritization-ca7dea

Conversation

@derek73

@derek73 derek73 commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes #484. Closes #462.

What

  • tools/differential/compare.py gains an _initials pseudo-field on both surfaces (the facade's at every baseline, the core's from 2.0 on). It enters a name's diff only when the seven roles and _ambiguities agree: a role move drags its initials with it, so that movement is the role diff's consequence, not render drift. Strict subset semantics were measured and rejected (53 / 43 / 36 existing rules at 1.4.0 / 2.0.0 / 2.1.0 would have needed _initials for no added discrimination). A rule listing _initials lists nothing else; the validator refuses the mix. The report prints _initials only under main()'s own verdict, so an UNEXPLAINED block always pastes into a rule the validator accepts.
  • What it surfaced, classified with fields = ["_initials"] rules: the R2 all-particle readmission (27 names, three ledgers -- shipped in 2.2.0 with a release note but no rule the gate could hold), Mc Donald and Ste Marie read the particle as the given name #360's los (1), and the facade initialing each WORD of a joined run since 2.0.0 where 1.4.0 grouped the run (98 names at 1.4.0, never recorded -- classified late, with a 2.3.0 release bullet saying so; four rules because the Latin-alternation guard admits one copied vocabulary per rule).
  • HumanName('Scott E. Werner').initials() drops the middle initial — the facade reads E as the conjunction #462: HumanName.initials() dropped a dotted or bare-capital E/Y middle initial since 2.0.0 (Scott E. Werner -> S. W.); v1's conjunction test excluded initial-shaped words and the facade's did not. Restored with _render._INITIAL, scoped to _process_initial. 14 corpus names come into 1.4.0 agreement; parse().initials() was already right.
  • AGENTS.md's release-note doctrine now says initials() is visible to the gate as a floor, not a population (measured 83 / 28 / 55 at 2.1.0); R2, R3 and R4 gain dated amendments retiring the gate-cannot-see-initials limit; a new decisions entry, differential-ledger, the initials view, carries the semantics, the three clusters, and the recompute recipe.

Measured

Gate exit 0 at 1.4.0 / 2.0.0 / 2.1.0 / 2.2.0, unexplained 0, radar unclassified 0; intentional totals 226 / 205 / 113 / 0 -> 352 / 247 / 155 / 14, exactly the new rules' explained counts (27+1+66+19+11+2; 27+1+14; 27+1+14; 14). Mutation run: with the roles-identical guard removed, 117 role-moving names lose their rule on the shipped tree (143 before the _initials rules existed), so the guard is live. Suite: 6429 passed.

Commits (each green on its own)

  1. fix(facade): HumanName('Scott E. Werner').initials() drops the middle initial — the facade reads E as the conjunction #462, its v1-bank tests, the release bullet. The gate cannot see initials yet, so it is unchanged here.
  2. tooling(differential): the pseudo-field, its tests, README, AGENTS.md, all seven rules with their guard rosters, the per-word release bullet. Green at all four baselines.
  3. docs(design): the decisions entry, the R3 bullet, two pointer comments.
  4. review round: four reviewers' findings -- the entry's own numbers re-derived on the shipped tree, the R2/R3/R4 amendments, a printer change showing the core's initials movement when it differs from the facade's, with its tests.

Spec: docs/superpowers/specs/2026-09-01-initials-pseudo-field-design.md (gitignored, main checkout).

Follow-up worth its own issue (not filed): _CORPUS_CLAIMS records a rule's regex REACH, not its explained count, so a rule that goes from explaining 14 names to 2 stays green until it explains zero; a dated explained-count dimension on _Claim would pin it.

🤖 Generated with Claude Code

derek73 and others added 4 commits September 2, 2026 00:21
…462)

HumanName.initials() dropped a dotted or bare-capital E/Y in the middle
or family group: 'Scott E. Werner' gave 'S. W.' since 2.0.0 where 1.4.0
gave 'S. E. W.'. v1's is_conjunction was 'in the set AND NOT
is_an_initial'; the 2.0 facade kept the first half only. Restored with
_render._INITIAL, v1's own initial shape, scoped to _process_initial.
parse().initials() never had the bug. 14 corpus names come into 1.4.0
agreement; the differential cannot see it until the next commit gives
it an initials column, where they carry a fix(#462) rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
)

The gate compared the seven roles plus _ambiguities, so a render-layer
change with every role identical was invisible to it by construction.
Both surfaces now carry an _initials pseudo-field -- the facade's at
every baseline, the core's from 2.0 on -- and it enters a name's diff
only when the roles and ambiguity kinds agree: a role move drags its
initials with it, so that movement is the role diff's consequence, not
drift. Strict subset semantics were measured and rejected: they would
have put _initials onto a long tail of existing rules for no added
discrimination (the counts are in the decisions entry that lands with
this PR). The report prints _initials only under main()'s own verdict,
so an UNEXPLAINED block always pastes into a rule the validator accepts.

What it surfaced, now classified with fields = ["_initials"] rules:
the R2 all-particle readmission (27 names, three ledgers, shipped in
2.2.0 with a release note but no rule the gate could hold), #360's
'los' (1 name), and HumanName.initials() initialing each WORD of a
joined run where 1.4.0 initialed the run as one group -- 98 names at
1.4.0, changed in 2.0.0 and recorded nowhere until now. AGENTS.md's
release-note doctrine now says initials() is visible to the gate as a
floor, not a population.

The 14 names the facade's dropped E/Y initial moved (#462, fixed in
the previous commit) now move against the three 2.x baselines instead
and carry a fix(#462) rule in each, so the gate is green at all four
baselines at this commit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… R3 twin

The decisions entry for #484: why _initials enters a diff only when
the roles agree (strict semantics measured at 43 / 43 / 36 rules of
churn for no discrimination), the three clusters it surfaced with
their counts and tiers, why the per-word grouping is classified three
minors late, and the recompute recipe with its mutation check. R3
gains the #462 bullet. Two pointer comments so the next reader of the
case table's 'no initials column' note and the facade's 'not pinned'
comment knows the differential now looks, and one ledger header clause
reworded so #462 does not read as 2.2.0-era.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ires

Four reviewers over the three commits. Documentation truth: the #462
names agree with 1.4.0 again since the fix, so two comments that said
they diff there now say what the connective rule's two exclusions
actually buy -- any future facade initials change on those shapes
surfaces UNEXPLAINED at 1.4.0 rather than being absorbed as per-word
grouping; R2, R3 and R4 carried the gate-cannot-see-initials limit in
the present tense and gain dated amendments; the README's standing
rule count is gone; _facade.py's "v1 parser.py:427 verbatim" says
"after ..., not verbatim", the loop no longer being a textual copy;
and the release bullet's John E Smith is a bare ASCII capital, since
_render._INITIAL is ^(\w\.|[A-Z])$ and an undotted Cyrillic capital is
not initial-shaped.

The initials-view entry's own measured claims re-derived on the
shipped tree: the 1.4.0 churn numerator (53 of 72, not 43), the
140 / 28 cluster totals dated to the pre-fix tree with the shipped
tree's 126 / 42 / 42 / 14 beside them, two illustrations replaced by
inputs that reproduce, the 14 given the population the bug could reach
(14 of 14, the rule's regex reaching four more in leading position).
The RECOMPUTE bullet splits into two recipes, because only one of them
runs off the gate: the classified totals are the sum of the
fields = ["_initials"] rules' heading counts, while the per-name split
and the pre-fix figures need the in-memory run.

One printer change, in both the UNEXPLAINED and the UNCLASSIFIED
(radar) block, which share _print_field_diffs: it shows the core's
initials movement when that differs from the facade's, the two being
independent implementations -- with a test for the differing pair and
one for the identical pair the print-once convention still covers.

The bound-given rule's ordering rationale is measured rather than
asserted: TWO corpus names carry both a bound word and a particle
chain, not three, and neither has an `_initials` diff -- the third
name the note counted shares with the Ph. D. rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@derek73 derek73 self-assigned this Sep 2, 2026
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

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

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #494   +/-   ##
=======================================
  Coverage   98.66%   98.66%           
=======================================
  Files          45       45           
  Lines        3218     3219    +1     
=======================================
+ Hits         3175     3176    +1     
  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 and others added 2 commits September 2, 2026 03:00
…gers

Four review agents over PR #494. Ledger comments: a precedent that
cited a rule the 1.4.0 ledger does not have (fix(#445) is the name-list
precedent there), planning labels and a false narrow-first claim in the
_initials block header, 'Ph. D., Jr.' diffs on roles not nothing, the
particle-chain gloss named a middle that is a family, and the 14 dated
with the invariant behind the other four. All THIRTEEN _initials rules
gain orders = ["DEFAULT"] -- six at 1.4.0, three each at 2.0.0 and
2.1.0, one at 2.2.0: each describes a default-order render, and an
order-bearing entry never consults the facade, so a core-side
family-first regression must not be absorbed under a rule whose prose
says facade. compare.py: a docstring clause named the wrong branch; the
validator's mixed-fields message printed an empty list on a duplicated
_initials; the _RULE_FIELDS comment gains the ambiguity kinds. Tests:
the fixture refuses unknown row keys (a misspelled _initials would
otherwise default to the tree's value and silently agree); five gap
tests -- the radar block, the order-bearing path, the guard's v2 half,
facade-moved-core-agreed, and a surface-distinguishing name for the
exec'd worker test; the facade fix pinned on a group that used to
vanish and on the bare-Cyrillic boundary. Docs: the release headline
says middle- or family-group; R4's 140 split into 126 + 14; the given
group, not leading position, is the discriminator; AGENTS.md counts
entries, not names.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review round 2 conditioned the mixed-_initials check on the OTHER
names in `fields`, which made `["_initials", "_initials"]` pass where
it had been refused with an empty-list message. classify() reads
`fields` as a set, so a repeat matches nothing more; it is a
copy-paste slip that every check below would otherwise swallow, and
the `_initials` check in particular would read the pair as `_initials`
alone. Both validators now refuse it, with a row in each rejection
table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@derek73
derek73 merged commit c1a98a9 into master Sep 2, 2026
11 checks passed
@derek73
derek73 deleted the claude/v2-3-prioritization-ca7dea branch September 2, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

1 participant