Docs-only. Two rules that were implied but not enforceable, both demonstrated by #649 being implemented twice in parallel to completion on 2026-07-26.
Subagents: explicitly permitted
The kickoff's HARD CONSTRAINTS already require parallelising disjoint slices, mandatory independent review from a cold brief, and a named model/effort per dispatch. None of that is satisfiable without delegation — but nothing said so outright, and a generic client preamble of the form "do not use the Agent tool unless the user requested it" reads as a prohibition.
Now stated plainly in bothCLAUDE.md (always loaded) and the kickoff (pasted per session), including what to delegate (bounded recon, mechanical slices against a documented contract, disjoint worktrees, every independent review) and what to keep inline (design decisions, review arbitration, anything cheaper to do than to brief).
Claiming: a check, not a label
process.parallel-session-claim already said a claim prevents duplicate pickup, not duplicate work. But step 3 told you to apply in-progress and nothing else — so the documented risk had no corresponding action.
Step 3 now requires four checks first, each failing differently and all cheap:
What select-queue.sh's CLAIM? flag raises and deliberately leaves unresolved
git fetch origin main
Reading current state, not your opening snapshot
Staleness: re-fetch before every push
The second half of the collision was reading origin/mainonce, at branch time, and not again across hours and four review rounds.
A branch on a stale base computes its diff against that base — so git diff origin/main shows other sessions' merged work as deletions, and pushing reverts them. In #649's case that would have reverted both #666 and #667. The tell is deletions you did not make.
What the record now carries
process.parallel-session-claim gains the incident, including the part worth keeping: the duplicate effort was not wasted. The merged implementation was better in one respect (it exports ETV_GITEA_URL as well as GITEA_BASE_URL, because pr-changed-files.sh reads the former at higher precedence), and the discarded branch's test coverage was salvaged onto the merged code as #673. So when you find a collision, diff the two implementations before discarding yours — the loser usually contains something the winner lacks.
Verification
decisions-validate: OK, catalog regenerated and in sync, scripts/tests 325 passed, no NUL/BOM in the changed set. No behaviour change.
Docs-only. Two rules that were implied but not enforceable, both demonstrated by **#649 being implemented twice in parallel to completion** on 2026-07-26.
## Subagents: explicitly permitted
The kickoff's HARD CONSTRAINTS already require parallelising disjoint slices, mandatory independent review from a **cold** brief, and a named model/effort per dispatch. None of that is satisfiable without delegation — but nothing said so outright, and a generic client preamble of the form *"do not use the Agent tool unless the user requested it"* reads as a prohibition.
Now stated plainly in **both** `CLAUDE.md` (always loaded) and the kickoff (pasted per session), including what to delegate (bounded recon, mechanical slices against a documented contract, disjoint worktrees, every independent review) and what to keep inline (design decisions, review arbitration, anything cheaper to do than to brief).
## Claiming: a check, not a label
`process.parallel-session-claim` already said a claim prevents duplicate *pickup*, not duplicate *work*. But step 3 told you to apply `in-progress` and nothing else — so the documented risk had no corresponding action.
Step 3 now requires four checks first, each failing differently and all cheap:
| Check | Catches |
|---|---|
| Open PRs whose body says `fixes #N` | The #649 case exactly |
| `git ls-remote --heads origin '*<N>*'` | A branch usually exists before the PR |
| Comments predating the label | What `select-queue.sh`'s `CLAIM?` flag raises and deliberately leaves unresolved |
| `git fetch origin main` | Reading current state, not your opening snapshot |
## Staleness: re-fetch before every push
The second half of the collision was reading `origin/main` **once**, at branch time, and not again across hours and four review rounds.
A branch on a stale base computes its diff against that base — so `git diff origin/main` shows other sessions' merged work as **deletions**, and pushing reverts them. In #649's case that would have reverted both #666 and #667. The tell is deletions you did not make.
## What the record now carries
`process.parallel-session-claim` gains the incident, including the part worth keeping: the duplicate effort was not wasted. The merged implementation was **better** in one respect (it exports `ETV_GITEA_URL` as well as `GITEA_BASE_URL`, because `pr-changed-files.sh` reads the former at higher precedence), and the discarded branch's test coverage was salvaged onto the merged code as #673. So when you find a collision, **diff the two implementations before discarding yours** — the loser usually contains something the winner lacks.
## Verification
`decisions-validate: OK`, catalog regenerated and in sync, `scripts/tests` 325 passed, no NUL/BOM in the changed set. No behaviour change.
Two rules that were implied but not enforceable, both demonstrated by ersatztv#649 being
implemented TWICE in parallel to completion on the same day.
Subagents. The kickoff's HARD CONSTRAINTS already require parallel disjoint slices, mandatory
independent review from a cold brief, and a named model/effort per dispatch — none of which is
satisfiable without delegation. But nothing said so outright, and a generic client preamble of the
form "do not use the Agent tool unless the user requested it" reads as a prohibition. Now stated
plainly in both CLAUDE.md (always loaded) and the kickoff (pasted per session), with what to
delegate and what to keep inline.
Claiming. `in-progress` prevents duplicate PICKUP, not duplicate WORK — the record already said so,
but step 3 told you to apply the label and nothing else. It now requires four checks first: an open
PR whose body says `fixes #N`, a remote branch naming the number, a claiming comment predating the
label (exactly what select-queue.sh's CLAIM? flag raises and deliberately leaves unresolved), and a
fresh git fetch. Each fails differently; all four are cheap.
Staleness. The second half of the #649 collision was reading origin/main once, at branch time, and
not again across hours and four review rounds. A branch on a stale base computes its diff against
that base, so `git diff origin/main` shows other sessions' merged work as DELETIONS and pushing it
reverts them. Re-fetch before every push, rebase when it moved.
process.parallel-session-claim carries the incident, including what worked: the merged
implementation was better in one respect and the discarded branch's test coverage was salvageable,
so diff the two before discarding yours.
The previous commit rewrote the rationale prose of process.parallel-session-claim (adding the
ersatztv#649 double-implementation incident) without this trailer, and CI's decisions-lifecycle
gate correctly rejected it.
Worth recording WHY it passed locally and failed in CI: I ran decisions_validate.py BEFORE
`git commit` in the same command chain, so it inspected the working tree. The trailer check reads
COMMITTED history, so the one rule that can only fail after committing was the one I validated
before committing. Run the decisions validator after the commit, not before it.
Decisions-Edit: yes
timothy
merged commit cb7da865b6 into main2026-07-27 18:04:14 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Docs-only. Two rules that were implied but not enforceable, both demonstrated by #649 being implemented twice in parallel to completion on 2026-07-26.
Subagents: explicitly permitted
The kickoff's HARD CONSTRAINTS already require parallelising disjoint slices, mandatory independent review from a cold brief, and a named model/effort per dispatch. None of that is satisfiable without delegation — but nothing said so outright, and a generic client preamble of the form "do not use the Agent tool unless the user requested it" reads as a prohibition.
Now stated plainly in both
CLAUDE.md(always loaded) and the kickoff (pasted per session), including what to delegate (bounded recon, mechanical slices against a documented contract, disjoint worktrees, every independent review) and what to keep inline (design decisions, review arbitration, anything cheaper to do than to brief).Claiming: a check, not a label
process.parallel-session-claimalready said a claim prevents duplicate pickup, not duplicate work. But step 3 told you to applyin-progressand nothing else — so the documented risk had no corresponding action.Step 3 now requires four checks first, each failing differently and all cheap:
fixes #Ngit ls-remote --heads origin '*<N>*'select-queue.sh'sCLAIM?flag raises and deliberately leaves unresolvedgit fetch origin mainStaleness: re-fetch before every push
The second half of the collision was reading
origin/mainonce, at branch time, and not again across hours and four review rounds.A branch on a stale base computes its diff against that base — so
git diff origin/mainshows other sessions' merged work as deletions, and pushing reverts them. In #649's case that would have reverted both #666 and #667. The tell is deletions you did not make.What the record now carries
process.parallel-session-claimgains the incident, including the part worth keeping: the duplicate effort was not wasted. The merged implementation was better in one respect (it exportsETV_GITEA_URLas well asGITEA_BASE_URL, becausepr-changed-files.shreads the former at higher precedence), and the discarded branch's test coverage was salvaged onto the merged code as #673. So when you find a collision, diff the two implementations before discarding yours — the loser usually contains something the winner lacks.Verification
decisions-validate: OK, catalog regenerated and in sync,scripts/tests325 passed, no NUL/BOM in the changed set. No behaviour change.