Context
Four independent instances this week of the same unwritten decision: when a constant or a small decision cannot be imported across a boundary, duplicate it — and pin the copies with a test rather than a comment. Nobody has written that down, so each author re-derives it, and each defends it in prose that decays.
The instances, all arrived at separately:
- PR #17348 —
@neo-fable-clio duplicates a three-line conflation check across the app→Brain boundary rather than importing, JSDoc-named "parity-twin" on both sides.
- PR #17348 review — I filed a
[KB_GAP] saying the convention is unwritten, then found the twins were not pinned: two specs importing one twin each, at different assertion depths, so one side's canonicalization could be deleted with its spec still green.
- PR #17325 —
@neo-opus-grace's satisfiesRequiredModelIdOnOpenAiCompatibleLane delegates instead of duplicating, because there the import was structurally possible.
- A fourth instance in a private repository, where the rule is both implemented and articulated in a docblock. Not cited here for the usual reason; the three above are sufficient and public.
Instance 3 is the one that makes this filable rather than a style note. It is the inverse case, and it supplies the discriminator the other three only imply.
The Problem
A convention assembled from two sightings is a proposal. Assembled from four across two repositories, with a worked example in each direction, it is a description of what the team already does — which needs adopting, not inventing.
The gap has a specific decay mode, and it is not hypothetical. In #17348 the duplication was defended by a comment on both sides and pinned by nothing. A comment explaining a duplication expires the moment someone edits the other side; a test does not. The reviewer (me) had to discover that by comparing two spec files by hand, which is exactly the labour a written rule removes.
The trap of writing only half of it. A convention that says "here is how to pin duplication" reads as licence to duplicate, and the next reader takes the easy half. The rule needs both clauses or it makes things worse:
Duplicate only when importing is structurally impossible. When you do, pin the copies by test, never by comment.
Instance 3 is the proof the first clause is load-bearing: there the import was possible, so delegation was correct and duplication would have been the error. Instance 1's _users-style case is the proof it is sometimes genuinely impossible — the would-be importer is itself imported by the target module, so reaching back closes a cycle.
The Architectural Reality
- App→Brain boundary (#17239) — the boundary that makes some imports architecturally forbidden even where they are technically possible.
- Cycle-forced duplication — a module that is imported by the module holding the constant cannot import back; this is structural, not stylistic, and it is the clearest qualifying case.
- Test-as-pin — the enforcement primitive already used in practice: a spec that drives both sides from one fixture, so divergence fails rather than surviving. Distinct from a spec-per-side, which is what #17348 shipped and what does not pin anything.
- A test importing across a boundary is not a runtime coupling. That distinction is what makes the pin available at all, and it is currently left implicit.
The Fix
Corrected after filing — @tobiu caught that the original prescription had no reader. It said "write a process note under learn/agentos/process/" and left the routing optional ("existing review guidance can link"). Measured: every file currently in that directory is routed to by at least one skill via a <!-- trigger: … -> read … --> comment, and there are zero orphans. The directory works because every resident has a router. An unrouted note would have been its first, and it would have been a convention about enforcement that was itself unenforced.
So the routing trigger is the deliverable, not a follow-up.
- Payload: a short audit under
.agents/skills/pr-review/audits/, beside core-idiom-audit.md and identity-claim-audit.md — the established home for "when X appears in a diff, check Y".
- Router (the actual deliverable): a trigger line in
pr-review-guide.md, in the same form the guide already uses:
<!-- trigger: diff introduces a deliberate duplication -> read ../audits/… -->
Without this line the payload does not exist for any practical purpose.
- Author side: the same rule needs a reader at authoring time, not only at review. One line in the
pull-request or ticket-create guidance, or an explicit decision that review-time is the only enforcement point — recorded either way rather than left silent.
- Content order: the restraining clause leads. Name the discriminator (duplicate only when importing is structurally impossible) before the technique (pin by test), so the clause that limits duplication cannot be skimmed past.
- Cite existing articulation rather than inventing prose. The rule has already been stated well in a real docblock; quote a live instance so the convention reads as description rather than decree.
Acceptance criteria
Out of Scope
- Retrofitting existing duplications. #17348 fixed its own under review; others should surface through the reviewer trigger, not a sweep.
- Any general policy on code duplication. This is narrowly about duplication forced by a boundary or a cycle — the only case where the trade-off is not simply "don't".
- The app→Brain boundary rules themselves (#17239). This documents how to survive one consequence of that boundary, not where the boundary sits.
Avoided Traps
- Writing the pinning half alone. Reads as licence to duplicate; the next reader takes the easy half. This is why the discriminator leads.
- Filing an unrouted note. The original version of this ticket did exactly that, and it is the sharper trap: a convention about enforcement, shipped without enforcement. Every payload in the target directory has a router; the routing line is what makes the difference between substrate and a diary entry.
- Filing it as a skill. Substrate bloat with its own retirement condition, for a two-sentence rule.
- Inventing fresh prose when the rule already exists in a docblock. A convention quoting real practice is much harder to argue with than one asserting a preference.
Decision Record impact
none — this documents an existing practice; it neither amends nor challenges an accepted ADR.
Related
- #17348 — the duplication and the unpinned twins that surfaced the gap.
- #17325 — the inverse instance; delegation where the import was possible.
- #17239 — the app→Brain boundary that forces the qualifying cases.
Assembled by @neo-opus-grace, who supplied the inverse instance and the count, and who declined to file it herself. Live latest-open sweep: latest 20 open issues read created-descending at 2026-08-18T12:26Z, nearest neighbours #17344 and #17339, no equivalent found. A2A in-flight claim sweep: latest 30 messages, all read-states; no competing claim.
Origin Session ID: 1baae1f2-97e4-418c-9119-c3112763f552
Retrieval Hint: query_raw_memories("parity twin duplication pinned by test not comment cross-boundary import")
Context
Four independent instances this week of the same unwritten decision: when a constant or a small decision cannot be imported across a boundary, duplicate it — and pin the copies with a test rather than a comment. Nobody has written that down, so each author re-derives it, and each defends it in prose that decays.
The instances, all arrived at separately:
@neo-fable-clioduplicates a three-line conflation check across the app→Brain boundary rather than importing, JSDoc-named "parity-twin" on both sides.[KB_GAP]saying the convention is unwritten, then found the twins were not pinned: two specs importing one twin each, at different assertion depths, so one side's canonicalization could be deleted with its spec still green.@neo-opus-grace'ssatisfiesRequiredModelIdOnOpenAiCompatibleLanedelegates instead of duplicating, because there the import was structurally possible.Instance 3 is the one that makes this filable rather than a style note. It is the inverse case, and it supplies the discriminator the other three only imply.
The Problem
A convention assembled from two sightings is a proposal. Assembled from four across two repositories, with a worked example in each direction, it is a description of what the team already does — which needs adopting, not inventing.
The gap has a specific decay mode, and it is not hypothetical. In #17348 the duplication was defended by a comment on both sides and pinned by nothing. A comment explaining a duplication expires the moment someone edits the other side; a test does not. The reviewer (me) had to discover that by comparing two spec files by hand, which is exactly the labour a written rule removes.
The trap of writing only half of it. A convention that says "here is how to pin duplication" reads as licence to duplicate, and the next reader takes the easy half. The rule needs both clauses or it makes things worse:
Instance 3 is the proof the first clause is load-bearing: there the import was possible, so delegation was correct and duplication would have been the error. Instance 1's
_users-style case is the proof it is sometimes genuinely impossible — the would-be importer is itself imported by the target module, so reaching back closes a cycle.The Architectural Reality
The Fix
Corrected after filing — @tobiu caught that the original prescription had no reader. It said "write a process note under
learn/agentos/process/" and left the routing optional ("existing review guidance can link"). Measured: every file currently in that directory is routed to by at least one skill via a<!-- trigger: … -> read … -->comment, and there are zero orphans. The directory works because every resident has a router. An unrouted note would have been its first, and it would have been a convention about enforcement that was itself unenforced.So the routing trigger is the deliverable, not a follow-up.
.agents/skills/pr-review/audits/, besidecore-idiom-audit.mdandidentity-claim-audit.md— the established home for "when X appears in a diff, check Y".pr-review-guide.md, in the same form the guide already uses:<!-- trigger: diff introduces a deliberate duplication -> read ../audits/… -->Without this line the payload does not exist for any practical purpose.pull-requestorticket-createguidance, or an explicit decision that review-time is the only enforcement point — recorded either way rather than left silent.Acceptance criteria
<!-- trigger: … -->form. This is the AC the original body got wrong by making it optional — a payload nothing routes to is write-only.SKILL.mdrouter entry. A skill implies a procedure with steps and a trigger of its own; this is a two-sentence decision rule and would carry its own retirement problem.Out of Scope
Avoided Traps
Decision Record impact
none— this documents an existing practice; it neither amends nor challenges an accepted ADR.Related
Assembled by
@neo-opus-grace, who supplied the inverse instance and the count, and who declined to file it herself. Live latest-open sweep: latest 20 open issues read created-descending at 2026-08-18T12:26Z, nearest neighbours #17344 and #17339, no equivalent found. A2A in-flight claim sweep: latest 30 messages, all read-states; no competing claim.Origin Session ID: 1baae1f2-97e4-418c-9119-c3112763f552
Retrieval Hint:
query_raw_memories("parity twin duplication pinned by test not comment cross-boundary import")