What happened
Two record-writing runs, live at the same time, both wrote their decision record as 0074:
origin/main ends at 0073, so both children scanned docs/decisions/ at write time and took "the next free number". Whichever merges second lands a second 0074 (decisions:check and every cross-reference then pick one at random), or has to be renumbered by another round — which is what #2195 gets now.
Both asks said the same thing, because that is the repo's record procedure: "the record (next free number in docs/decisions/, the repo's record shape …)". The number is assigned by the child at write time from a directory listing, so two children in flight always collide.
Product shape
The orchestrator reserves the record number at admission and hands it to the child as a parameter of the unit (a plan/ship parameter, like the branch), and the child never scans docs/decisions/ for a free number. The reservation lives with the plan record (the same place the unit branch is chosen), so a re-issue of the same text gets the same number and two different texts admitted a minute apart get consecutive numbers. decisions:check gains one rule: a record's number equals the one its plan reserved (or, for a record with no plan, the file is unique in its number on main).
Spec home: the tech-spec/record procedure (the "next free number" sentence becomes "the number the admission reserved") and docs/reference/specs/agent-ship.md (a unit that writes a record carries record: <number>).
Fixture
The two asks above, admitted 22:52 and 23:24 PDT on 2026-09-21, both with "next free number in docs/decisions/" in their text, both live at once, both writing 0074.
What happened
Two record-writing runs, live at the same time, both wrote their decision record as 0074:
plan/write-decision-record-00-60beb0/u1docs/decisions/0074-a-side-effect-crosses-one-typed-seam.mdfix/provider-failure-seamdocs/decisions/0074-one-typed-provider-failure-cause-decides-every-model-call-and-every-surface-renders-it-once.md79bec206-813d-4dc0-ba5c-d13a828b3a40(https://coreplanelabs.slack.com/archives/C0BRRHKFLCB/p1790060297539069)origin/mainends at 0073, so both children scanneddocs/decisions/at write time and took "the next free number". Whichever merges second lands a second 0074 (decisions:checkand every cross-reference then pick one at random), or has to be renumbered by another round — which is what #2195 gets now.Both asks said the same thing, because that is the repo's record procedure: "the record (next free number in docs/decisions/, the repo's record shape …)". The number is assigned by the child at write time from a directory listing, so two children in flight always collide.
Product shape
The orchestrator reserves the record number at admission and hands it to the child as a parameter of the unit (a plan/ship parameter, like the branch), and the child never scans
docs/decisions/for a free number. The reservation lives with the plan record (the same place the unit branch is chosen), so a re-issue of the same text gets the same number and two different texts admitted a minute apart get consecutive numbers.decisions:checkgains one rule: a record's number equals the one its plan reserved (or, for a record with no plan, the file is unique in its number on main).Spec home: the tech-spec/record procedure (the "next free number" sentence becomes "the number the admission reserved") and
docs/reference/specs/agent-ship.md(a unit that writes a record carriesrecord: <number>).Fixture
The two asks above, admitted 22:52 and 23:24 PDT on 2026-09-21, both with "next free number in docs/decisions/" in their text, both live at once, both writing 0074.