Skip to content

Should rules/C5's "two capitals before credentials" clause and rules/O4's order report each be a rule of their own? (Jane Doe, BM PhD; Armitage J. O. reports order) #1358

Open

Description

@derek73

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:

  1. 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: C5 shape: paired initials after the comma, dotted or as two undotted capitals; C17 neighbor: 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 its Signal: line and a bullet of its map; the doc tests hold the two to each other, both ways.
    • A new decisions/C17-…md opening with ## Standing and ## Log, taking the Should Jane Doe, BM PhD read BM as 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.
  2. 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 and Signal: 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 wants count alone 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 JO vs Lakshmi R S) #1254/Report the order on a name of one word followed by initials (#1254) #1348 entries move to a new decisions/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):
  • 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.py 5679, 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/O8 on the order kind).
    • 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) and rules/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 on rules/C5 or rules/O4 after its text moved fails here.
  • tests/v2/test_rules_doc.py: every example line runs, each rule carries a boundary example or no-boundary:, and implemented: matches the modules that cite the rule (so _comma.py must cite C17 and _assign.py O9).
  • 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's Signal: line against its map (C1 and C17).
  • tests/v2/test_snapshot.py: tools/differential/corpus_rules.jsonl is rebuilt from the rules' examples (build_rules_corpus.py); a move with no example added or dropped leaves snapshot.jsonl byte-identical, which is the check that nothing but text moved.
  • uv run python -m tests.v2.rules_size --since origin/master prints 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 rule after any move; C5's "save the undotted pair's company of credentials above" and "only as the Except below has it" are two.

Open:

  1. Both splits, one, or neither? C5's is the clearer by the Signal: test; O4's has the closer precedent (O5).
  2. One PR or two? They are file-disjoint.
  3. Do the decisions entries move to the new keys, or stay under C5 and O4 with pointers? The earlier splits moved them.
  4. O9's Signal: line: one tag or two?
  5. 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

  1. self-assigned this
    on Nov 12, 2026
  2. added
    docsDocumentation fixes and updates
    on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

docsDocumentation fixes and updates

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions