docs(design): name the pattern five PRs rediscovered (#438) - #440
Merged
Conversation
mechanisms.md had no entry for "two stages need the same answer about the same input", though the codebase has executed it five times and decisions.md states the principle twice inside dated entries about specific fixes, where nobody looks it up. ONE-PREDICATE-PER-QUESTION: the site that does not own the decision calls the deciding stage's own predicate, never a condition written to match it. A hand-written mirror agrees with its original until one of them moves, and the drift is invisible in both directions -- each site keeps passing its own tests while disagreeing about an input neither covers. The Known-limit clause is the half worth writing down. The share is only available in the IMPORT direction: assign imports group, so a piece-level predicate both stages ask must live in group. Where the reader comes after the decider, the alternative is to record the answer on the state (ParseState.order is that shape) -- unavailable whenever the earlier stage is the one asking. That asymmetry is what made #429's design a discovery rather than a lookup. _group.py's module docstring restated the import-direction claim in free prose, which the mechanisms preamble names as the failure mode ("Free- prose restatements of mechanism claims are how one wrong sentence has shipped six times"). It cites the slug now. Two claims corrected against the record while writing it, both of which I had carried from session notes rather than the docs: - #401/#421's `reads_as_suffix` no longer exists -- #425 superseded it with the shared peel -- so that pair's lasting artifact is `is_trailing_numeral_suffix`, and the entry names that instead. - "four inexact-mirror drafts" and "twice the right answer" are counts no committed document supports. The record carries the lesson (mirror assign's WALK, not its condition) but not the tally, so the entry states the lesson without the number. Closes #438 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #440 +/- ##
=======================================
Coverage 98.59% 98.59%
=======================================
Files 44 44
Lines 3064 3064
=======================================
Hits 3021 3021
Misses 43 43 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #438.
mechanisms.mdhad no entry for "two stages need the same answer about the same input", though the codebase has executed the pattern five times anddecisions.mdstates the principle twice — each time inside a dated entry about a specific fix, where nobody looks it up.The entry
ONE-PREDICATE-PER-QUESTION— the stage that does not decide calls the one that does.The site that does not own the decision calls the deciding stage's own predicate, never a condition written to match it. A hand-written mirror agrees with its original until one of them moves, and the drift is invisible in both directions: each site keeps passing its own tests while they disagree about an input neither covers.
The five instances, each found as a defect before it was found as a pattern:
is_wholly_suffix→_vocabis_trailing_numeral_suffix→_vocab_peel_walk/_peel_trailing_is_leading_title/_leading_titles→_grouptitle()missed H2's unlisted abbreviations_segment_holds_no_name→_groupThe Known-limit clause is the half worth writing down
The share is only available in the import direction.
_assignimports_group, so a piece-level predicate both stages ask has to live in_group— not because grouping owns it. A text-level one goes to_vocabinstead: the destination follows the layer, not the topic.Where the reader comes after the decider, the alternative is to record the answer on the state —
ParseState.orderis exactly that shape, and says so in its own docstring. That option is unavailable whenever the earlier stage is the one asking, which is what made #429's design a discovery rather than a lookup.One citation added
_group.py's module docstring restated the import-direction claim in free prose — which the mechanisms preamble names as the failure mode: "Free-prose restatements of mechanism claims are how one wrong sentence has shipped six times." It cites the slug now.Two claims corrected while writing it
Both were carried from session notes rather than the committed record, and both were caught by running axis 1 (recompute every number) and axis 4 (claims about a document vs what it says) on my own draft:
reads_as_suffixno longer exists. It was real in fix(group): the bound-given reserve and join ask what assign reads (#401, #421) #423, butabdul Smith Jr Maloses the family name — P5's reserve does not mirror S2's bare-acronym fork #425 superseded it with the shared peel. That pair's lasting artifact isis_trailing_numeral_suffix, which is what the entry names. (The originating issue body has the stale name.)Verification
Docs-and-one-comment only. Suite 5668 passed, mypy and ruff clean, differential 0 unexplained at the default baseline (unchanged, as expected for a change that alters no parse).
Axes run: 1 (recompute — found both corrections above), 2 (no detector used), 4 (every quoted excerpt checked verbatim against its source — #319's decisions line,
ParseState.order's docstring, the mechanisms preamble), 7 (the "Reach for it when" clause is advisory and sweeps in nothing), 9 (the new anchor resolves; the citation test passes). Axes 3, 5, 6 are rules.md-specific and inapplicable — no rule statement, example orinteracts:line changed. Axis 8 inapplicable: no guard added. Axis 10: the entry's only capability claim is that_assignimports_groupand cannot be imported back, verified.🤖 Generated with Claude Code