Friction (hit while dogfooding the hourly loop)
rivet next-id allocates the next ID by scanning only the current working tree, so in any multi-branch / parallel-PR workflow it silently hands out IDs that are already claimed by in-flight branches — producing two different artifacts with the same ID.
Reproduced just now (verified)
This loop has three open PRs that each added a requirement: #474 (REQ-201), #475 (REQ-202), #477 (REQ-203) — none merged yet, so none are on main. A fresh agent branching off main asks for the next ID:
$ git checkout main # main's requirements.yaml ends at REQ-200
$ rivet next-id --type requirement
REQ-201 # ← already live in open PR #474
So the agent files its REQ-201, and now two PRs define different REQ-201s. They don't even textually conflict if they land in different files — validate would later flag a duplicate ID, or worse, one silently shadows the other after a merge. I only avoided it this iteration by manually tracking that 201–203 were taken and jumping to REQ-204.
Why this is distinct from #422
#422 is about textual merge conflicts (same EOF lines in CHANGELOG.md / requirements.yaml). This is about ID allocation: next-id confidently returns a colliding ID with no warning, even when there would be no textual conflict (e.g. the two artifacts live in different files). Fixing #422 (per-artifact files, a merge driver) would not fix this — next-id would still hand out REQ-201 to a second branch.
Related: #447 (next-id must scan all files) fixed the intra-tree half; this is the cross-branch half.
Suggested fixes (pick per appetite)
- Warn loudly:
rivet next-id and rivet add could check unmerged refs — e.g. git log --all -G'id: <PREFIX>-' or the IDs present on origin/* PR branches — and print note: REQ-201 is also claimed on branch fix/...; next free across all refs is REQ-205.
--across-refs flag (opt-in, git-aware): compute the max ID across git for-each-ref blobs, not just the working tree.
- Reservation ledger: a tiny append-only
.rivet/reserved-ids (or a rivet reserve REQ) that agents bump atomically; cheap and merge-friendly (append-only with union merge).
- Documentation stopgap: AGENTS.md could tell parallel agents to allocate disjoint ID ranges per worktree.
Option 1 (a warning) is the cheapest high-value step — it turns a silent collision into a visible one. Reported from the hourly dogfooding loop; verified against rivet next-id at 970cea1.
Friction (hit while dogfooding the hourly loop)
rivet next-idallocates the next ID by scanning only the current working tree, so in any multi-branch / parallel-PR workflow it silently hands out IDs that are already claimed by in-flight branches — producing two different artifacts with the same ID.Reproduced just now (verified)
This loop has three open PRs that each added a requirement: #474 (REQ-201), #475 (REQ-202), #477 (REQ-203) — none merged yet, so none are on
main. A fresh agent branching offmainasks for the next ID:So the agent files its REQ-201, and now two PRs define different REQ-201s. They don't even textually conflict if they land in different files —
validatewould later flag a duplicate ID, or worse, one silently shadows the other after a merge. I only avoided it this iteration by manually tracking that 201–203 were taken and jumping to REQ-204.Why this is distinct from #422
#422 is about textual merge conflicts (same EOF lines in
CHANGELOG.md/requirements.yaml). This is about ID allocation:next-idconfidently returns a colliding ID with no warning, even when there would be no textual conflict (e.g. the two artifacts live in different files). Fixing #422 (per-artifact files, a merge driver) would not fix this —next-idwould still hand out REQ-201 to a second branch.Related: #447 (next-id must scan all files) fixed the intra-tree half; this is the cross-branch half.
Suggested fixes (pick per appetite)
rivet next-idandrivet addcould check unmerged refs — e.g.git log --all -G'id: <PREFIX>-'or the IDs present onorigin/*PR branches — and printnote: REQ-201 is also claimed on branch fix/...; next free across all refs is REQ-205.--across-refsflag (opt-in, git-aware): compute the max ID acrossgit for-each-refblobs, not just the working tree..rivet/reserved-ids(or arivet reserve REQ) that agents bump atomically; cheap and merge-friendly (append-only with union merge).Option 1 (a warning) is the cheapest high-value step — it turns a silent collision into a visible one. Reported from the hourly dogfooding loop; verified against
rivet next-idat970cea1.