Skip to content

Milestone-close direct-push — OBJ-1911 post-mortem

A reference card for why fixing a rule in two docs isn't the same as fixing it — a third doc quoting the exact forbidden command kept firing for weeks after OBJ-1421 supposedly closed this gap.

Incident: master's tip failed scripts/check-release-integrity.mjs commits (the release-integrity-guard.yml commit-attribution check), blocking Vicki from cutting the OBJ-1911 hotfix production tag. The flagged commit, 7eba9fdfb ("docs(planning): close v4.25 Release-Build Safety Gates milestone"), was authored by Dori, landed directly on master's first-parent chain (parent = PR #1893's merge SHA 30cddb29), and had no merged PR covering it.

Root cause

Two crew-facing docs already forbade the unsafe command — docs/operations/planning-canon.md's do-not-run list and .claude/skills/generating-project-roadmaps/SKILL.md, both corrected under OBJ-1421 (2026-07-13) to stop recommending /gsd-complete-milestone in this repo (it archives .planning/ROADMAP.md as if it were a live phase list, which it never is here — see the canon doc for the full mechanism).

A third doc never got the memo. docs/guides/multica-agent-crew.md's Dori section — "Final action — milestone closed" — still literally instructed:

# 2. Run the completion workflow (archives phases, marks .planning/ROADMAP.md shipped)
/gsd-complete-milestone

the exact command the other two docs forbade. OBJ-1421's fix touched the skill and the canon doc but missed this crew-brief runbook, which is the doc an actual Dori run follows at milestone close.

Independent of the content-corruption risk planning-canon.md warns about (which didn't manifest — 7eba9fdfb's diff was well-formed), /gsd-complete-milestone's upstream implementation (~/.claude/get-shit-done/workflows/complete-milestone.md) is built for a solo-dev trunk workflow: its handle_branches step commits directly against whatever branch is currently checked out, with no PR step anywhere in that workflow file. At milestone-close time in this repo, the integration branch has already been squash-merged to master, so the branch checked out when this step runs is master. Following the stale runbook literally means committing straight to master.

Compounding gap: neither the stale runbook nor the corrected skill's "hand-edit .planning/ROADMAP.md directly" alternative specified cutting a branch for this step. Every other Dori action piggybacks on Codi's still-open branch ("commit to the same branch Codi worked on" — her Core behavior rule), but milestone-close runs after that branch is already merged and gone — there was no natural branch to attach to, and no instructed fallback other than the currently-checked-out master.

This was systemic, not a one-off

The same check was run against a second, independent "close milestone" commit: a7ec26b87 ("docs: close v4.24 Dependency Convergence & Upgrade milestone", authored by Orion, also direct on master's first-parent chain, no PR, landed 2026-07-29 21:58). Same violation, different milestone, different crew identity — confirming the defect lived in the shared runbook, not in one agent's execution.

Why it wasn't caught sooner

release-integrity-guard.yml is push-triggered + daily-cron — it can only report after a bad commit has already landed, and there was no PR for either commit to gate on before merge. Releases v4.3.0/v4.3.1/v4.3.2 all shipped fine before a7ec26b87 landed (21:58 that day); OBJ-1911 was the first release attempt since, so it was the first time anyone actually tried to tag from a post-milestone-close master tip and hit the collision — even though the underlying defect had already fired twice.

Fix (shipped, OBJ-1912)

  • docs/guides/multica-agent-crew.md's Dori "Final action — milestone closed" step (and every other literal occurrence of /gsd-complete-milestone in the file) now matches the canon: hand-edit .planning/ROADMAP.md's milestone entry, never run /gsd-complete-milestone.
  • Auditing the doc tree for the literal string turned up a fourth doc carrying the same stale instruction, outside Dave's original scope: docs/guides/multica-workspace-skills.md's gsd-workflow-quickref skill body listed /gsd-complete-milestone in Vicki's command map and in Dori's close-lifecycle line. Fixed in the same pass — this is exactly the "grep the whole doc tree, not just the docs that prompted the fix" lesson below, demonstrated on itself.
  • Both that doc and .claude/skills/generating-project-roadmaps/SKILL.md now specify an explicit branch step for milestone-close: cut a short-lived branch off master before making any edits, commit the closure work there, and hand off to Riley for a normal PR — never push milestone-close changes straight to master.
  • Retroactive remediation of 7eba9fdfb (getting it covered by a merged PR so the guard goes green on master) is separate git-mutation work, out of Dori's Agent Identity — routed to Codi/Riley as its own time-critical sub-task on OBJ-1911. a7ec26b87 (v4.24) is the same defect, non-blocking, tracked as follow-up cleanup.
  • A CI regression guard against docs/guides/multica-agent-crew.md reintroducing a literal /gsd-complete-milestone invocation is tracked as a separate task (Codi), mirroring scripts/check-planning-canon.mjs's existing enforcement style.

General rule

Correcting a forbidden command in "the skill" and "the canon doc" isn't the same as correcting it everywhere it's quoted. When a rule gets fixed under one issue, grep the whole doc tree for the literal string being forbidden — not just the two docs that prompted the fix — before declaring the gap closed. A crew-brief runbook is the doc an agent actually executes at the moment of action; if it disagrees with the "canonical" doc, the runbook wins in practice, silently, until something downstream (here, a release-integrity check weeks later) surfaces the collision.

Last updated: 2026-07-30

Loading…