Skip to content

Order CONTRIBUTING's source-conflict steps the way the guard enforces them - #10588

Merged
MaxGhenis merged 5 commits into
mainfrom
contributing-source-conflict-order
Nov 2, 2026
Merged

MaxGhenis merged 5 commits into
mainfrom
contributing-source-conflict-order

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

What changes

The "Source conflicts" section of CONTRIBUTING.md said one PR "does three things": add the rulespec-us entry, mark the deciding line, and refresh the pinned copy "once the entry is on rulespec-us main". One PR can't do all three:

  • policyengine_us/tests/code_health/test_source_conflicts.py fails a marker whose entry isn't in the pinned copy, or whose entry doesn't list the marker's file under implementations (test_every_marker_names_a_registered_entry_that_lists_its_file).
  • The register pins only commits reachable from main, and no commit of an open PR is reachable from main until it merges. A squash merge never makes the PR's own commits reachable.

The paragraph and list now give the four steps in order:

  1. The ruling PR records a candidate in candidates.yaml, adds what step 2 pins (YAML test cases and any source capture) and adds no marker. The rulespec-us entry may list the open PR under proposed.
  2. After the merge, the rulespec-us entry gets the implementation with cites_entry: false, its pin to the commit on main that merged the ruling PR, and its YAML pins. A proposed row moves to implementations.
  3. A follow-up PR marks the deciding line, refreshes the pin, deletes the candidate and deletes the file's KNOWN_UNMARKED line.
  4. After the follow-up merges, the rulespec-us entry re-pins each implementation to the follow-up's commit with cites_entry: true, and a later PR here refreshes the pin again, so test_registered_implementations_carry_their_marker guards the marker.

The list keeps every bullet's content: sources and kinds, alternatives with ids, years, the implementation fields, YAML pins by commit, path and case name, unpublished_sources, and the marker format with its example.

Other changes:

The principles and the rest of the guard description are unchanged.

Before

Every such conflict is recorded in the register that PolicyEngine shares with Axiom: known-source-conflicts.yaml in rulespec-us. Its fields are defined in that repository's tools/README.md, under "Source-conflict register". A PR that takes such a reading, or finds one already in the code, does three things:

  1. Add or update the entry in rulespec-us.
    • Give each source's text and its kind (statute, regulation, form, instructions, manual, guidance, agency practice, ...).
    • Give the alternatives, each with an id, and the years.
    • Add an implementation for each file here: repo: PolicyEngine/policyengine-us, a commit, the path, follows (what the code does), and adopts with a basis (the reading it intends, and why).
    • Add the YAML test cases that pin each reading, by commit, path and case name. Pin only commits on main: the register records shipped code. An open PR goes under proposed until it merges.
    • Describe correspondence with an agency in unpublished_sources. Never quote it or name the person.
  2. Mark the deciding line in the variable or parameter file: # Source conflict <jurisdiction>:<id>, for example # Source conflict us-hi:claim-of-right-deduction-floor.
  3. Refresh the pinned copy once the entry is on rulespec-us main: python scripts/update_source_conflicts.py --commit <rulespec-us commit>. Delete the item from source_conflicts/candidates.yaml if it was there.

After

Every such conflict belongs in the register that PolicyEngine shares with Axiom: known-source-conflicts.yaml in rulespec-us. That repository's tools/README.md defines its fields, under "Source-conflict register". When a PR takes such a reading, or finds one already in the code, the conflict goes into the register in four steps, in this order. One PR can't do them all: the guard below rejects a marker unless the pinned copy of the register lists the marker's file under its entry's implementations, and the register pins an implementation only to a commit reachable from main, which a ruling PR's commits aren't until it merges (and a squash merge never makes the PR's own commits reachable).

  1. The ruling PR records the conflict in source_conflicts/candidates.yaml: its id, program, question, years, at least two sources, readings, pe_us (follows, code, prs) and state. If the backlog already lists the conflict, it updates that item instead. If the pinned copy already holds the conflict, it adds no item, because the guard fails a registered id. It adds no marker. It also adds what step 2 pins to a commit on main: the YAML test cases for its reading and, if the Axiom corpus lacks a source's text, a capture under source_conflicts/sources/. You can also add the entry to rulespec-us now, listing the open PR under proposed, if every text it cites is in the corpus or captured on main already.
  2. After the ruling PR merges, add or complete the entry in rulespec-us.
    • Give each source's text and its kind (statute, regulation, form, instructions, manual, guidance, agency practice, ...). Cite a text the corpus lacks under pending_texts, pinned to its capture's commit on main.
    • Give the alternatives, each with an id, and the years.
    • Add an implementation for each file here that holds a deciding line (the candidate's pe_us.code can list more): repo: PolicyEngine/policyengine-us, the commit on main that merged the ruling PR (its squash commit, for a squash merge), the path, cites_entry: false (the file doesn't name the global id yet; verify reads the file's text, so a # Candidate: <jurisdiction>:<id> comment counts), follows (what the code does), and adopts with a basis (the reading it intends, and why). If step 1 listed the PR under proposed, move that row to implementations.
    • Add the YAML test cases that pin each reading, by commit, path and case name. Pin only commits on main: the register records shipped code.
    • Describe correspondence with an agency in unpublished_sources. Never quote it or name the person.
  3. Once that entry is on rulespec-us main, a follow-up PR here marks the deciding line and refreshes the pin.
    • Mark the deciding line in each variable or parameter file the entry lists under implementations: # Source conflict <jurisdiction>:<id>, for example # Source conflict us-hi:claim-of-right-deduction-floor.
    • Refresh the pinned copy: python scripts/update_source_conflicts.py --commit <rulespec-us commit>.
    • Delete the item from source_conflicts/candidates.yaml if it was there. The guard fails a candidate whose id is already in the pinned copy, so the deletion goes in the same PR as the refresh.
    • Delete the file's line from KNOWN_UNMARKED in policyengine_us/tests/code_health/test_source_conflicts.py if it has one. A valid marker exempts the file from the ratchet, so the guard fails a leftover line.
  4. After the follow-up merges, finish the entry in rulespec-us: re-pin each implementation to the follow-up's commit on main and set cites_entry: true. Then refresh the pin here again, so the guard checks that the marker stays.

For code already on main that the PR doesn't change, you can skip step 1: pin the implementation to a current main commit. The follow-up PR is then the first PolicyEngine US PR, unless step 2 needs a YAML test case or a source capture that isn't on main yet. A PR here adds those first.

The marker comes only in the follow-up PR, because the guard rejects a marker whose entry isn't in the pinned copy, or whose entry doesn't list the marker's file under implementations. A proposed row doesn't count.

Ratchet bullet, before:

A new file or a higher count means register and mark the conflict, or reword the comment; a lower count means lower KNOWN_UNMARKED.

After:

A new file or a higher count means reword a comment that describes no conflict. If it describes a real conflict, keep it, record the conflict as a candidate (step 1) and add or raise the file's KNOWN_UNMARKED line in the same PR; the marker in step 3 then exempts the file, and its line comes out. A lower count means lower KNOWN_UNMARKED.

Checks

  • test_source_conflicts.py run on its own at an earlier head of this PR: 103 passed. The test doesn't read CONTRIBUTING.md, and CI runs it again at the final head.
  • scripts/update_source_conflicts.py only vendors the register at a given commit and writes pin.yaml. It doesn't touch candidates.yaml, so the text says to delete the candidate by hand.
  • rulespec-us tools/README.md at fe62a527af: the implementations row defines cites_entry, "which says whether the file contains the global id"; verify checks that "each cites_entry claim matches its file"; the proposed row says to "move one to implementations once it merges, pinned to the commit on the default branch"; and pins must be "reachable from their repository's default branch (a squash-merged pull request's own commits are not)".
  • PolicyEngine US allows squash, merge-commit and rebase merges (repository settings), so the text covers a squash merge without assuming one.

impact: none (docs only)

axiom: n/a

🤖 Generated with Claude Code

… them

The section told one PR to add the register entry, mark the deciding line
and refresh the pin. One PR can't: test_source_conflicts.py rejects a
marker whose entry isn't in the pinned copy, the register pins only
commits on main, and squash-merging means a ruling PR's own commits never
reach main. Describe the three steps in order: a candidate in the ruling
PR, the register entry pinned to the squash commit after it merges, then
the marker, pin refresh and candidate deletion in a follow-up PR. The
ratchet bullet now points to the same steps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review

Head: 3fdc4973c2bec50ab2c82d0129d87a87a202cc62 (draft)

What the item asked, and how I resolved it

  • Rewrote the paragraph and list in CONTRIBUTING.md "Source conflicts" (CONTRIBUTING.md:106-120) as three ordered steps: candidate in the ruling PR, then the rulespec-us entry with the implementation pinned to the squash commit, then a follow-up PR with the marker, the pin refresh and the candidate deletion. It says plainly that the marker comes only in the follow-up, and why.
  • Kept every bullet's content: sources and kinds, alternatives with ids, years, implementation fields, YAML pins by commit, path and case name, unpublished_sources, and the marker format and example. proposed moved from the YAML-pins bullet to step 1.
  • Guard description: only the ratchet bullet (CONTRIBUTING.md:128) repeated the old order ("register and mark the conflict"). It now points to steps 1 and 3. The principles are unchanged.
  • Changelog: changelog.d/contributing-source-conflict-order.changed.md. pr.yaml requires a fragment on every PR.

Claims checked against code

  • Marker without a pinned entry, or with an entry that doesn't list the file, fails: test_every_marker_names_a_registered_entry_that_lists_its_file.
  • A candidate already in the pinned register fails: test_candidates_are_not_yet_registered. That is why step 3 deletes the candidate in the same PR as the refresh.
  • The ratchet fails new unmarked conflict-sounding comments: test_conflict_sounding_comments_do_not_grow. So a ruling PR has to word its comments around it.
  • scripts/update_source_conflicts.py vendors the file and writes pin.yaml only; it doesn't edit candidates.yaml.
  • Not checked: TheAxiomFoundation/rulespec-us tools/README.md (implementations and proposed rows). That repository is outside this session's GitHub scope. The "pin only commits on main" and proposed statements are carried over from the existing text.

Tests: test_source_conflicts.py alone: 103 passed.

CI: not run, because the PR is a draft.

Judgment calls

  • The ratchet bullet edit goes beyond the paragraph, but it repeated the old one-PR order, which the brief allows changing.
  • The API rewrote the body's closing line into the standard "Generated by Claude Code" footer.

Generated by Claude Code

@MaxGhenis
MaxGhenis marked this pull request as ready for review November 2, 2026 08:11
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Ready for hub review
VERDICT: REQUEST_CHANGES
3fdc497
METHODOLOGY_CHOICE: no

The PR head is still 3fdc4973c2. Main has moved past the PR's base (97b6d513), but no later commit touches CONTRIBUTING.md, test_source_conflicts.py, scripts/update_source_conflicts.py or source_conflicts/. No earlier "Hub review in progress" comment exists, so this review starts from the beginning.

The reordering is right, and every bullet from the old list survives. Two statements are wrong or incomplete, though, and a reader would act on both. I read rulespec-us tools/README.md and the history of the register's own entries, and they show that the process has a fourth step, which the PR leaves out. The PR also gives a false reason for why one PR can't do all three steps.

Findings

P2. The process leaves out cites_entry and the step that sets it, so following the text leaves every implementation reading "does not cite its entry"

CONTRIBUTING.md:112 (step 2 implementation fields) and CONTRIBUTING.md:115-118 (step 3).

rulespec-us tools/README.md (at fe62a527af23) defines implementations as "repo, commit, path, follows (what the code does today) and cites_entry, which says whether the file contains the global id". Its verify checks that "each cites_entry claim matches its file", at the pinned commit. The verify report also lists "implementations that do not cite their entry yet".

In the PR's order, step 2 pins the implementation to the ruling PR's merge commit. That file has no marker, so cites_entry has to be false there. Step 3 then adds the marker in PolicyEngine US, but nothing tells anyone to re-pin the implementation to the follow-up's commit and set cites_entry: true. If nobody does, test_registered_implementations_carry_their_marker (test_source_conflicts.py:392) skips the entry for good ("not merged here yet, or not marked yet"), and later deleting the marker fails nothing. The CONTRIBUTING bullet at line 127 describes that guard, but the steps never produce the cites_entry: true it depends on.

The register's own history shows the fourth step happening:

$ git log --format='%h %ad %s' --date=short -- source_conflicts/pin.yaml
1961791ace 2026-10-25 Vendor the source-conflict register at rulespec-us ad03b325 (#10445)
eeaf8096e0 2026-10-24 Mark nine source conflicts now in the shared register (#10441)
ce9377ee80 2026-10-20 Tie source-conflict markers to the register shared with Axiom (#10287)

# cites_entry: true count in the vendored register at each commit
1961791ace: 12   eeaf8096e0: 0   ce9377ee80: 0

At eeaf8096e0 (the marking PR, step 3), the Colorado entry's implementation is commit: 7bb70aab…, cites_entry: False. In the current vendored copy, all nine PolicyEngine US implementations are pinned to eeaf8096e0, the marking PR's own squash commit, with cites_entry: True. #10445 then refreshed the pin a second time.

Replacement. In step 2's implementation bullet, after the path, add:

cites_entry: false (the file has no marker yet),

Then add a step 4 after step 3:

  1. After the follow-up merges, finish the entry in rulespec-us: re-pin each implementation to the follow-up's commit on main and set cites_entry: true. Then refresh the pin here again, so the guard checks that the marker stays.

Also change "in three steps" on line 106 to "in four steps".

P2. "PolicyEngine US squash-merges, so a ruling PR's own commits never reach main" is false, and the true reason doesn't depend on it

CONTRIBUTING.md:106, and "the squash commit on main" at CONTRIBUTING.md:112.

The repository allows merge commits and rebase merges as well as squash merges, and main has merge commits:

$ gh api repos/PolicyEngine/policyengine-us --jq '[.allow_squash_merge,.allow_merge_commit,.allow_rebase_merge]|@tsv'
true	true	true
$ git log --first-parent origin/main -300 --format='%p' | awk '{print NF}' | sort | uniq -c
    284 1
     16 2
$ git show -s --format='%H %P %s' 33eb9d21c9
33eb9d21c9… 926ed24e… 30b0a6a7… Merge pull request #10519 from PolicyEngine/fix-10296-ca-ssp-meal-allowance-default
$ git merge-base --is-ancestor 30b0a6a7… origin/main && echo reachable
reachable

So a merge-committed PR's own commits do reach main, and such a PR has no "squash commit". The README's rule is "pinned to commits reachable from their repository's default branch (a squash-merged pull request's own commits are not)". What blocks a single PR is timing, not the merge method: no commit of an open PR is reachable from main until it merges. That is true for every merge method.

Replacement for the last sentence of line 106:

One PR can't do all three: the guard below rejects a marker whose entry isn't in the pinned copy of the register, and the register pins only commits reachable from main, which a ruling PR's commits aren't until it merges (and a squash merge never makes its own commits reachable).

Line 112: replace "the squash commit on main" with "the commit on main that merged the ruling PR (its squash commit, when squash-merged)".

P3. Step 1 names fewer candidate fields than the guard requires

CONTRIBUTING.md:108. test_candidate_fields (test_source_conflicts.py:833-838) requires id, program, question, sources, pe_us and state, needs at least two sources, and checks years when it's present. Step 1 lists "its sources, readings, pe_us.follows, code, prs and state". That leaves out the required id, program and question, and it lists readings, which the guard doesn't check. Replacement:

its id, program, question, years, at least two sources, readings, pe_us (follows, code, prs) and state.

P3. Step 2 no longer says to move the proposed row once the PR merges

CONTRIBUTING.md:108-113. The README's proposed row says to "move one to implementations once it merges, pinned to the commit on the default branch". The old text said "An open PR goes under proposed until it merges". The new text keeps only the first half, in step 1, and step 2 never says to remove the proposed row. The register has three proposed rows today (PRs #10200, #10195 and #10203). Add this to step 2's implementation bullet:

If step 1 listed the PR under proposed, move that row to implementations.

P3. The order is too strict for a conflict found in code that's already on main

CONTRIBUTING.md:106-108. The paragraph covers a PR that "finds one already in the code", but it routes that PR through a candidate and a merge as well. When the deciding file is already on main and the PR doesn't change it, the implementation can be pinned to any main commit holding the file, and one PolicyEngine US PR can add the marker and refresh the pin once the entry is on rulespec-us main. #10441 did that for nine conflicts. The old step 3 handled this case with "Delete the item … if it was there", and the new step 3 makes the deletion unconditional. Suggested addition after step 3:

For code already on main that the PR doesn't change, step 1 is optional: pin the implementation to a current main commit, and the follow-up PR is the first PolicyEngine US PR.

In step 3, restore "if it was there" after "Delete the item from source_conflicts/candidates.yaml".

Checked and sound

  • Diff scope. The PR changes only CONTRIBUTING.md (lines 106-120 and 128) and changelog.d/contributing-source-conflict-order.changed.md. Nothing is under .github/ or policyengine_us/tests/policy/baseline/partners/. The fragment path matches pr.yaml's regex ^changelog\.d/[^/]+\.(breaking|added|changed|fixed|removed)\.md$.
  • Nothing lost (old against new). Every old bullet is still there: source text and kinds, alternatives with ids, years, repo/commit/path/follows/adopts+basis, YAML pins by commit, path and case name, "Pin only commits on main", unpublished_sources with "never quote it or name the person", the marker format and its example, and the update_source_conflicts.py --commit command. The only weakening is the proposed hand-off (P3 above). The principles above the list and the other guard bullets are unchanged.
  • Marker claim (lines 106 and 120). test_every_marker_names_a_registered_entry_that_lists_its_file (test_source_conflicts.py:374-389) fails a marker whose id isn't in the vendored register, or whose entry has no PolicyEngine/policyengine-us implementation with that path. This matches the text.
  • Candidate deletion (line 118). test_candidates_are_not_yet_registered (:825-830) fails any candidate id that's in the vendored register, so the deletion has to go in the same PR as the pin refresh. This is correct.
  • Script (line 117). scripts/update_source_conflicts.py only fetches known-source-conflicts.yaml at the given commit, writes it to source_conflicts/ and writes pin.yaml. It never touches candidates.yaml, so deleting the candidate by hand is the right instruction. Its docstring ("normally a merge commit on main") agrees.
  • Ratchet bullet (line 128). test_conflict_sounding_comments_do_not_grow (:431-452) fails a new file or a higher count in a file with no valid marker, and a file with any valid marker is exempt. A candidate exempts nothing, so "reword the comment … the marker follows in step 3" is accurate. The test's failure message still says "register it … and mark the deciding line", which is the old one-PR order. That's a follow-up for the test, not for this PR.
  • rulespec-us statements. "Pin only commits on main" matches the README's verify rule (default branch, which is main here). The proposed fields (repo, pr, path, follows) match step 1's "listing the open PR under proposed". The PR body says these statements weren't checked against the README. I checked them, and they hold, apart from the cites_entry gap (P2).
  • Hand-off claims. "103 passed": I reran uv run pytest -q -p no:cacheprovider policyengine_us/tests/code_health/test_source_conflicts.py at the head and got 103 passed, 1 warning in 25.13s. CI at the head: the "Pull request" run succeeded, and every job in it succeeded (PR validation, Quick Feedback, Package and compatibility, Household API Partners, all Baseline, Contrib and Python shards, and Microsimulation). One other run at this SHA was skipped, and I don't count it.
  • Body lines. impact: none (docs only) and axiom: n/a are both present. The diff changes no code or parameter, so it can't move any output at baseline, and no population check is needed.
  • Overlap. No open PR edits CONTRIBUTING.md. Compare federal school meal income limits at USDA's whole-dollar thresholds #10384 and Follow the statute where IRS forms differ: refundable CTC housing deduction, joint filing test, EITC trust royalties, former 32(c)(1)(F) #10297 add candidates, and Follow the statute where IRS forms differ: refundable CTC housing deduction, joint filing test, EITC trust royalties, former 32(c)(1)(F) #10297 also edits test_source_conflicts.py. Follow the statute where IRS forms differ: refundable CTC housing deduction, joint filing test, EITC trust royalties, former 32(c)(1)(F) #10297 raises KNOWN_UNMARKED for four new files, while the new ratchet text says to reword the comments in that case. Neither PR conflicts textually with this one, but the hub may want the two to agree.
  • Sections the brief skipped. It skipped the defect reproduction, mutants and readers because the PR changes only docs. No statute or regulation is in play, so I fetched no law sources.

What I couldn't check

  • gh api repos/TheAxiomFoundation/rulespec-us/contents/tools/README.md returned no content in this session, because that repository is outside its GitHub scope. I read the same file from raw.githubusercontent.com at rulespec-us main = fe62a527af2315170d653c413345e27834a5d221, and its sha256 matched across two fetches.
  • I didn't read rulespec-us's verify code itself, only the README's description of it. So the claim that verify fails a cites_entry: true whose pinned file lacks the id rests on that description and on the register's history shown above.

Generated by Claude Code

MaxGhenis and others added 4 commits November 2, 2026 16:33
… reason

Step 2 pins the merging commit with cites_entry false and moves a proposed
row; a new step 4 re-pins to the follow-up with cites_entry true. Step 1
names the fields the guard requires, and code already on main can skip it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Say what the ruling PR adds for step 2 to pin. Add the KNOWN_UNMARKED
deletion the guard forces in step 3. Name the path merged PRs use when
a conflict-sounding comment describes a real conflict: keep it, record a
candidate and add the allowance. Tie the reason to `implementations`,
since a `proposed` row doesn't satisfy the guard. Extend the changelog
to the fourth step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Step 2 asks for an implementation only where a file holds a deciding
line, and step 3 marks each file the entry lists: a second file with no
marker fails the guard at step 4. Say that verify reads the file's text
for cites_entry. Step 1 now covers a conflict the backlog or the pinned
copy already lists, and an early entry cites only texts already on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`verify` matches only the global id, so the comment needs the jurisdiction as well as the local id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit e6338c3 into main Nov 2, 2026
34 checks passed
@MaxGhenis
MaxGhenis deleted the contributing-source-conflict-order branch November 2, 2026 23:58
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10588 at 68f7bfb843779a0f35ee676087b6e62fcb8dbf57 (squash): Order CONTRIBUTING's source-conflict steps the way the guard enforces them.

  • Review: r1 REQUEST_CHANGES at 3fdc497; delta REQUEST_CHANGES at 468b203, applied as 0efd234; second delta REQUEST_CHANGES at 0efd234, applied as 83f368c; confirm APPROVE at 83f368c (Opus 5.5, independent), whose one wording note this head applies as 68f7bfb.
  • Gates checked live at merge:
    • gh pr checks exits 0;
    • the latest Pull request run at the head concluded success;
    • MERGEABLE;
    • not a draft;
    • no reviewer's latest review requests changes;
    • the semantic-overlap guard;
    • head pinned.
  • Impact: None (docs only)
  • Axiom: n/a

MaxGhenis added a commit that referenced this pull request Nov 2, 2026
#10588 made the ruling PR record a candidate, with the register entry and the marker after it merges. The failure message and the KNOWN_UNMARKED comment still said to register and mark in one PR, and the docstring said verify checks that cites_entry is true, where it checks that the claim matches the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Nov 3, 2026
* Fix docs helper import and tighten docs and test hygiene

The documentation helper imported colours Core never exported, so the CTC,
ACP and Lifeline notebooks failed on import. The PIA-ratio guide was linked
from the calculator page but missing from the table of contents. Comments in
the pinned-system test described interpolation metadata Core no longer
writes. The calculator reference test checked only direct children, so a
calculator-only leaf under a kept node passed, and a stale
NEW_PARAMETER_NODES path went unnoticed because apply skips it silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6H3e3QDf7E1R8JgS82

* Give the source-conflict guard's texts CONTRIBUTING's order

#10588 made the ruling PR record a candidate, with the register entry and the marker after it merges. The failure message and the KNOWN_UNMARKED comment still said to register and mark in one PR, and the docstring said verify checks that cites_entry is true, where it checks that the claim matches the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* List the Social Security lever pages in the table of contents

The calculator page links them, and nothing in the navigation led to them. The review built this table of contents with CI's toolchain, and it exits 0. Also let the source-conflict guard's message cover a conflict the pinned register already lists, since test_candidates_are_not_yet_registered fails a second candidate for one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants