You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
docs/adr: three open PRs collide on ADR numbers and all merge clean — ADR-027 twice, ADR-025 against main, and ADR-018 already duplicated for 22 days #1402
Three open PRs are about to add ADR files whose numbers already belong to something else. All of them merge clean, so nothing will go red and nothing will tell a reviewer.
Measured, not argued
main (cf10ee6ec) already carries one duplicate, which is the precedent:
Collision 2 — #1295 vs a file already merged.ADR-025-connector-substrate.md has been on main since before #1295 was opened; #1295 adds ADR-025-user-scoped-connectors-and-channel-routing.md:
(#1256 and #1083 also touch docs/adr/, but they edit existing filenames — those conflict normally and are fine. The defect is specific to adding a new file under a taken number.)
Why it's invisible
Disjoint filenames share no text, so git has nothing to conflict on. docs/adr/ has no index and no numbering check in CI. Highest number on main is ADR-026; every author independently and correctly reasoned "next is 027". Nothing they could have run would have shown them the other PR.
This is not carelessness by any of the three authors. It is a missing guard, and it has already fired once (ADR-018, undetected for 22 days).
Decision needed
Who keeps ADR-027. #1399 has seniority by 3 minutes; renumbering the other to ADR-028 is a filename change plus its internal self-references. Same call for #1295 — either renumber to the next free number, or, if it's genuinely an amendment to the connector substrate, fold it into the existing ADR-025-connector-substrate.md so it conflicts honestly.
Suggested guard
A CI check that fails when two files in docs/adr/ share an ADR-NNN prefix. It is a one-line uniq -d — the same command run above — and it would have caught all three instances, including the one that has been on main for 22 days.
Worth noting for whoever picks this up: #1401 is itself the ADR that documents the ADR-018 duplicate as evidence for a decision ledger. It is about to reproduce its own finding, which is the most concrete argument for the guard that I can offer.
ADR-018 on main — still unguarded, still the precedent.
The guard proposal is unaffected, and the correction actually strengthens it. That same comment identifies the identical defect one level down: once #1295 folds, the merged file carries two independent D1…D7 sequences, so "ADR-025 D3" resolves to two different decisions and nothing goes red. A uniq -d on filename prefixes would not catch that — so if anyone builds the guard, the shape worth reaching for is ambiguous decision identifiers, of which duplicate ADR numbers are the coarsest case.
On how I got it wrong, since it is the same failure this repo keeps paying for: I measured three merge-trees and filed, without reading the PR's existing comments. The record was on the object I was filing against, it was a day old, and it named me in its second sentence. A measurement is not a substitute for reading what is already on the thing you are measuring — and being rigorous about the mechanical part is exactly what made the reading step feel already done.
The two get cross-linked — the ledger is what the projection projects, siblings in the way 025/027 are.
That closes the last open decision in this issue. Recording the reasoning behind the cross-link because it is the part a renumber alone would lose: these two ADRs are not merely adjacent, they are coupled, and the coupling is exactly what the numbering accident obscured. Per the repo's own ADR-status discipline, when two ADRs sit adjacent on a subject the one a reader reaches first must carry a scope-boundary note naming the other.
Ruled earlier (fold into one ADR-025); I withdrew my duplicate finding
ADR-018 (two files on main)
Still unguarded, 22 days
What this issue is now for: the guard, and only the guard. All three collisions were caught by a human reading titles, twice after the fact. Nothing in CI can see any of them, because disjoint filenames have nothing to conflict on.
Restating the target shape from the earlier correction, since it survives the rulings: the check worth building is ambiguous decision identifiers, of which duplicate ADR-NNN filename prefixes are the coarsest case. A uniq -d on prefixes catches ADR-018 and would have caught both of tonight's — but it will not catch the finer case @pod-architect identified on #1295, where one reconciled file carries two independent D1…D7 sequences and a citation to "ADR-025 D3" resolves to two different decisions.
I will re-stamp #1401 once the renumber lands; my gate is pinned to a6225e2e and a rename moves the tree.
(Edited to repair two code spans — ADR-NNN and uniq -d — that my shell ate as backtick command substitution when I posted this inline instead of from a file. They vanished silently rather than erroring, leaving "duplicate filename prefixes". Flagging rather than quietly fixing, since a swallowed span in a spec sentence is the same failure class this issue is about.)
Update: collision 2 has stopped being hypothetical. This issue argued the ADR-025 duplicate would misresolve citations. It now does, in a PR under review.
#1399's ADR-027 carries three ADR-025 D* citations. Resolved against both files:
D2 — "Transport is kernel; judgment is agent (inherits ADR-025 D2)"
"Transport is kernel; curation is agent" — match
"Add a conversational outbound verb to the provider contract"
D3 — "The mapping table IS the router"
"Outbound messages carry their pod"
"A provider declares its directions"
The D2 match is verbatim, so the intent is unambiguous: #1399 is written against #1295's numbering, which is not on main. A reader who follows that citation against the merged tree today lands on a different decision. I have corrected my own review on #1399, which had filed this as a future ratification risk rather than a present error.
So the cost of this issue is no longer "a reviewer might get confused later" — it is one ADR already citing the wrong document, found by @pod-architect and confirmed here against both files.
One correction to the guard I proposed
The check in the opening comment is uniq -d over main's docs/adr/. That check cannot see collision 2. Run today it returns ADR-018 only:
main holds exactly one ADR-025; the duplicate only exists in the merge result with #1295. A guard that runs against the base branch is structurally blind to the case where a PR adds the colliding file — which is every case that matters, because that is the only moment the collision is still cheap to fix. The guard has to run on the PR's merge result (or equivalently, diff the PR's added ADR filenames against the base's number set). Same class of error as validating a review's sha against the value it was copied from: the two sides agree by construction, so their agreement carries no information.
Why ADR-018 has survived 22 days
Worth recording, because it explains the absence of symptoms and it does not generalise:
$ git show origin/main:docs/adr/ADR-018-agent-identity.md | head -3
# ADR-018 — Agent identity
**Status:** Proposed (stub — decision not yet made)
That file has zero D-headings. So all 20+ ADR-018 Dk citations in the codebase resolve unambiguously to ADR-018-agent-attention-claims.md — not because the number is unique, but because only one of the two claimants has any decisions to cite. The moment anyone writes a D1 into the identity stub, every one of those citations becomes ambiguous at once, including CLAUDE.md's own ADR-status-discipline section, which cites ADR-018 D8 while arguing about ADR-018 vs ADR-020.
That is not a stable state to leave a repo in, and it is not visible to anyone who is not looking for it — the citations keep working right up until they silently don't.
Re-measured against origin/main at cf10ee6e and all 100 open PRs. One of the three collisions in the title has resolved; two are live. Updating so this issue stops carrying a stale claim.
Every open PR that adds a new ADR file (swept all open PRs, not a sample):
ADR numbers on main: 021 022 023 024 025 026. Next free is ADR-029.
RESOLVED — "ADR-027 twice."#1401 was renumbered to ADR-028 and I re-stamped it at 770fb1fa. 027 is now claimed once, by #1399.
LIVE — ADR-025 against main.#1295 still adds a second ADR-025-* beside ADR-025-connector-substrate.md. I have now filed a BLOCK on that PR with the renumber-to-029 remedy. Worth recording that this one is a reviewer failure and not only a tooling gap: the substrate ADR landed on main 2026-08-29 18:02 and I passed #1295 fourteen hours later, at 08-30 08:18, without checking its number against the tree. A guard would have caught what I did not.
LIVE — ADR-018 duplicated on main. Confirmed present today:
This one matters for guard design, and it is the counterexample to my own earlier correction on this issue. I noted before that a uniq -d over main could not detect the #1295 collision because that duplicate exists only in the merge result. Both halves are true and they imply the guard needs both checks, not one:
a main-state check (uniq -d over the tree) — catches ADR-018, which no PR-scoped check will ever see because no open PR touches it.
A guard with only the first never notices the duplicate that has been sitting on main for weeks; a guard with only the second passes #1295 cleanly. That asymmetry is the actual design requirement here.
Activity
lilyshen0722 commentedon Aug 31, 2026
Correction to the issue body: #1295 is not an open decision. It was already ruled, a day before I filed this.
I listed three collisions needing a decision. Only one of them does.
The guard proposal is unaffected, and the correction actually strengthens it. That same comment identifies the identical defect one level down: once #1295 folds, the merged file carries two independent
D1…D7sequences, so "ADR-025 D3" resolves to two different decisions and nothing goes red. Auniq -don filename prefixes would not catch that — so if anyone builds the guard, the shape worth reaching for is ambiguous decision identifiers, of which duplicate ADR numbers are the coarsest case.On how I got it wrong, since it is the same failure this repo keeps paying for: I measured three merge-trees and filed, without reading the PR's existing comments. The record was on the object I was filing against, it was a day old, and it named me in its second sentence. A measurement is not a substitute for reading what is already on the thing you are measuring — and being rigorous about the mechanical part is exactly what made the reading step feel already done.
lilyshen0722 commentedon Aug 31, 2026
Ruled. Sam settled the ADR-027 collision (2026-08-31 03:44Z):
That closes the last open decision in this issue. Recording the reasoning behind the cross-link because it is the part a renumber alone would lose: these two ADRs are not merely adjacent, they are coupled, and the coupling is exactly what the numbering accident obscured. Per the repo's own ADR-status discipline, when two ADRs sit adjacent on a subject the one a reader reaches first must carry a scope-boundary note naming the other.
Status of all three collisions:
What this issue is now for: the guard, and only the guard. All three collisions were caught by a human reading titles, twice after the fact. Nothing in CI can see any of them, because disjoint filenames have nothing to conflict on.
Restating the target shape from the earlier correction, since it survives the rulings: the check worth building is ambiguous decision identifiers, of which duplicate
ADR-NNNfilename prefixes are the coarsest case. Auniq -don prefixes catches ADR-018 and would have caught both of tonight's — but it will not catch the finer case @pod-architect identified on #1295, where one reconciled file carries two independentD1…D7sequences and a citation to "ADR-025 D3" resolves to two different decisions.I will re-stamp #1401 once the renumber lands; my gate is pinned to
a6225e2eand a rename moves the tree.(Edited to repair two code spans —
ADR-NNNanduniq -d— that my shell ate as backtick command substitution when I posted this inline instead of from a file. They vanished silently rather than erroring, leaving "duplicate filename prefixes". Flagging rather than quietly fixing, since a swallowed span in a spec sentence is the same failure class this issue is about.)lilyshen0722 commentedon Aug 31, 2026
Update: collision 2 has stopped being hypothetical. This issue argued the ADR-025 duplicate would misresolve citations. It now does, in a PR under review.
#1399's ADR-027 carries three
ADR-025 D*citations. Resolved against both files:The D2 match is verbatim, so the intent is unambiguous: #1399 is written against #1295's numbering, which is not on
main. A reader who follows that citation against the merged tree today lands on a different decision. I have corrected my own review on #1399, which had filed this as a future ratification risk rather than a present error.So the cost of this issue is no longer "a reviewer might get confused later" — it is one ADR already citing the wrong document, found by @pod-architect and confirmed here against both files.
One correction to the guard I proposed
The check in the opening comment is
uniq -dovermain'sdocs/adr/. That check cannot see collision 2. Run today it returnsADR-018only:mainholds exactly one ADR-025; the duplicate only exists in the merge result with #1295. A guard that runs against the base branch is structurally blind to the case where a PR adds the colliding file — which is every case that matters, because that is the only moment the collision is still cheap to fix. The guard has to run on the PR's merge result (or equivalently, diff the PR's added ADR filenames against the base's number set). Same class of error as validating a review's sha against the value it was copied from: the two sides agree by construction, so their agreement carries no information.Why ADR-018 has survived 22 days
Worth recording, because it explains the absence of symptoms and it does not generalise:
That file has zero D-headings. So all 20+
ADR-018 Dkcitations in the codebase resolve unambiguously toADR-018-agent-attention-claims.md— not because the number is unique, but because only one of the two claimants has any decisions to cite. The moment anyone writes aD1into the identity stub, every one of those citations becomes ambiguous at once, includingCLAUDE.md's own ADR-status-discipline section, which citesADR-018 D8while arguing about ADR-018 vs ADR-020.That is not a stable state to leave a repo in, and it is not visible to anyone who is not looking for it — the citations keep working right up until they silently don't.
lilyshen0722 commentedon Aug 31, 2026
Re-measured against
origin/mainatcf10ee6eand all 100 open PRs. One of the three collisions in the title has resolved; two are live. Updating so this issue stops carrying a stale claim.Every open PR that adds a new ADR file (swept all open PRs, not a sample):
ADR numbers on
main:021 022 023 024 025 026. Next free is ADR-029.RESOLVED — "ADR-027 twice." #1401 was renumbered to ADR-028 and I re-stamped it at
770fb1fa. 027 is now claimed once, by #1399.LIVE — ADR-025 against main. #1295 still adds a second
ADR-025-*besideADR-025-connector-substrate.md. I have now filed a BLOCK on that PR with the renumber-to-029 remedy. Worth recording that this one is a reviewer failure and not only a tooling gap: the substrate ADR landed on main 2026-08-29 18:02 and I passed #1295 fourteen hours later, at 08-30 08:18, without checking its number against the tree. A guard would have caught what I did not.LIVE — ADR-018 duplicated on main. Confirmed present today:
This one matters for guard design, and it is the counterexample to my own earlier correction on this issue. I noted before that a
uniq -dovermaincould not detect the #1295 collision because that duplicate exists only in the merge result. Both halves are true and they imply the guard needs both checks, not one:main-only scan is blind to;uniq -dover the tree) — catches ADR-018, which no PR-scoped check will ever see because no open PR touches it.A guard with only the first never notices the duplicate that has been sitting on main for weeks; a guard with only the second passes #1295 cleanly. That asymmetry is the actual design requirement here.