Repository navigation
Description
Two rules grew this week by a clause that reads a signal the rule did not read before. docs/design/AGENTS.md's review axis 12 names that as the finding that asks for a split ("A signal the rule did not already read is a new rule wanting its own ID"), and the reviews of both PRs recommended it. No behavior changes; this is a move of rule text, examples and citations.
Measured on master 670b349, 2026-11-12, with the size report's own measure (tests/v2/rules_size.py, measure(); the "before" columns are the same measure at the parent of each PR's merge commit, read with rules_text_at):
| rule | PR | whole rule, words | Then, words | Except | Precedence | Accepted |
|---|---|---|---|---|---|---|
| C5 (paired initials after the comma) | #1338 | 378 → 594 | 94 → 302 | 2 → 2 | 2 → 2 | 1 → 2 |
| O4 (positional assignment and declared order) | #1348 | 102 → 443 | 68 → 203 | 0 → 4 | 0 → 1 | 0 → 2 |
For scale: the 97 rules hold 41,428 words; C5 is the 25th longest and O4 the 41st. Length is not the test (decisions/rules-size-record: "Length is still not the signal; count the signals"). The signals are:
- C5's
Signal:line now joins two:shape: paired initials after the comma, dotted or as two undotted capitals + neighbor: credentials behind the undotted pair. A line naming two signals with+is a split candidate by docs/design/rules/README.md; 14 rules carry one today (grep -lE '^\*\*Signal:\*\*.* \+ ' docs/design/rules/*.md). - O4's
Signal:line also joins two:position + shape: … and, for the order report, the count of name words and the initials' written shape (T5). O4 is the default every other rule carves exceptions from (no-boundary:); the report is a separate decision with its own Except bullets, Precedence and Accepted clause, and all four of O4's Except bullets belong to the report, none to positional assignment.
The precedent for O4 is rules/O5 (the lone name word's convention, and reporting it): a report with a rule of its own, beside the rule whose reading it reports on. The precedents for the mechanics are S2's split by #682 (S2 into S2 and S4–S9), C1's by #728 and the 2026-10-19 splits #755/#756, each driven by a rule's signals and each retargeting citations by hand.
Proposed split:
-
C17 — two capitals before credentials after the comma (C section; C16 is the last ID in use).
- Moves from C5: the Then bullet "Undotted, where the name carries the case contrast C6 asks for …" with its thirteen example lines; the Accepted bullet "Undotted initials of a given name behind a surname of two words, written with credentials behind them …" (
García Márquez, MJ PhD); the words "save the undotted pair's company of credentials above" in C5's first Except bullet become a pointer to C17; the second half of C5's Precedence bullet on a generation before the comma (the undotted pair, C12) goes with it. - Stays in C5: the dotted pair, the Because, both Except bullets (the second,
García Márquez, MJ JK, is about a second shape word and stays), the H10 Precedence bullet, the three-initials Accepted bullet. Signal:lines: C5shape: paired initials after the comma, dotted or as two undotted capitals; C17neighbor: credentials behind an undotted pair of capitals after the comma.- C1 is the hub of the comma decision (
hub of C3, C4, C5, C6, C7, C8, C9, C10, C11, C12, C13, C16), so C17 joins itsSignal:line and a bullet of its map; the doc tests hold the two to each other, both ways. - A new
decisions/C17-…mdopening with## Standingand## Log, taking the ShouldJane Doe, BM PhDreadBMas a credential, not the given name? #1323/Read two capitals before credentials after a comma as a credential (#1323) #1338 entries from decisions/C5 (or pointing at them), plus index lines in both READMEs.
- Moves from C5: the Then bullet "Undotted, where the name carries the case contrast C6 asks for …" with its thirteen example lines; the Accepted bullet "Undotted initials of a given name behind a surname of two words, written with credentials behind them …" (
-
O9 — a name word followed by nothing but initials reports the order (O section; O8 is the last ID in use).
- Moves from O4: the Then bullet "A name word followed by nothing but initials reports the order …" with its five example lines; all four Except bullets; the Precedence bullet (a particle in front); both Accepted bullets.
- Stays in O4: When, the first three Then bullets, Because and its three examples,
no-boundary:. O4 returns to 102 words andSignal: position. - O9's
Signal:line:count + shape: one name word, then the initials' written shape (T5), ending the name words. That is still two tags, as O5's neighbours carry; whether it wantscountalone is a question for the split. - decisions/O4's After a name with no comma, are initials the family name or the given name's initials? (
Armitage JOvsLakshmi R S) #1254/Report the order on a name of one word followed by initials (#1254) #1348 entries move to a newdecisions/O9-…md, or stay with a pointer. - rules/A1 says the order report names no alternative; it and the rules that name O4 (A1, O5, P1, P4, P8, P10, S10 and the O section's Background) need each mention read by hand: is it the positional default or the report?
Citations that must move with the text (grep -rn "rules/C5\|rules/O4" nameparser tests, 2026-11-12):
- To C17 (they quote or name the undotted clause):
nameparser/_pipeline/_comma.py:789, the quoted excerpt "undotted, two capitals followed by credentials and standing beside nothing else are the credential run" (the excerpt must exist verbatim in C17).nameparser/_pipeline/_comma.py:427, a docstring naming the rule for the same test.tests/v2/cases.py: therules/C5 (#1323)notes at lines 6245, 6252, 6282, 6313, 6324, 6395, 6414, 6422, 6429, 6436, 6445, 6453, and line 1341's note on ShouldB.Pharm,C.PsychandM.Kesbe listed credentials, now thatAhmed Ali M.Hassanloses its surname to the same guess? #998 if it is the undotted pair's.
- Staying on C5:
_comma.py:756(the dotted pair's quote),_vocab.py:1193,tests/v2/test_parser.py:2256,tests/v2/test_locales.py:2525,tests/v2/pipeline/test_comma.py:121,cases.py5679, 5725, 5747, 5785. - To O9 (the report):
nameparser/_pipeline/_assign.py:580, the quoted excerpt "a name word followed by nothing but initials reports the order".nameparser/_pipeline/_assign.py:16(the module docstring's "rules/O4's order report stands down under it").nameparser/_types.py:608(rules/O4, rules/O8on theorderkind).tests/v2/test_parser.py:510,3678,3718;tests/v2/test_benchmark.py:739;tests/v2/test_cases.py:577;tests/v2/cases.py:11977,11986.
- Staying on O4:
_assign.py:365(the positional quote). - Outside the citation check's reach, by hand: decisions files that name
rules/C5(C1, C3, C5, C16, H5, H10, S9, vocabulary-model) andrules/O4;nameparser/_pipeline/AGENTS.md("save the order report (rules/A1 …)"); docs/suggest.rst and docs/*.rst if they name either.
Tests that enforce the result:
tests/v2/test_doc_citations.py: every quoted excerpt verbatim in the rule it names, every ID a real rule; a quote left onrules/C5orrules/O4after its text moved fails here.tests/v2/test_rules_doc.py: every example line runs, each rule carries a boundary example orno-boundary:, andimplemented:matches the modules that cite the rule (so_comma.pymust cite C17 and_assign.pyO9).tests/v2/test_design_docs.py: each new rule and decisions file indexed once under a title matching its heading and file name; the hub'sSignal:line against its map (C1 and C17).tests/v2/test_snapshot.py:tools/differential/corpus_rules.jsonlis rebuilt from the rules' examples (build_rules_corpus.py); a move with no example added or dropped leavessnapshot.jsonlbyte-identical, which is the check that nothing but text moved.uv run python -m tests.v2.rules_size --since origin/masterprints the four rules' sizes for the PR body.- Not enforced: positional references in the moved text ("above", "the Except below"). docs/design/AGENTS.md asks for a grep of the moved text and the folder for
above,below,this ruleafter any move; C5's "save the undotted pair's company of credentials above" and "only as the Except below has it" are two.
Open:
- Both splits, one, or neither? C5's is the clearer by the
Signal:test; O4's has the closer precedent (O5). - One PR or two? They are file-disjoint.
- Do the decisions entries move to the new keys, or stay under C5 and O4 with pointers? The earlier splits moved them.
- O9's
Signal:line: one tag or two? - Twelve other rules carry a two-signal line. Is a sweep of those wanted, or only splits that a review asks for?
🤖 Generated with Claude Code
Activity