MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-3630

Planning bug: `motir run <id>` step 0a CLAIMED an archived card — `transition_status` does not reject one, and no gate before the worktree reads `archivedAt` or `readiness.ready`

Done
Description

Found by motir run MOTIR-3628 on 2026-08-26 at 23:11 UTC. Nothing was built; the finding is about the runbook's dispatch gate, not about that card.

What happened

run.md's motir run <id> step 0a is the explicit-id path's entire claim: "transition_status todo → in_progress — this IS your claim. A REJECTION IS A STOP". It is the first MCP call the path makes, and it runs before the shape read, before guards #2–#5, before any worktree.

MOTIR-3628 was archived at 23:07:50 by Yue, with a comment titled "ARCHIVED — redundant. Its one real deliverable moved to MOTIR-3418" naming where each remaining piece went. At 23:11:08 step 0a transitioned it todo → in_progress and the call succeeded: archive is orthogonal to workflow status, so there is no rejection to read. The run only discovered the retirement at step 0b (a merged PR on the card's own branch) and at the shape read (readiness.ready: false, blocker MOTIR-3418 blocked) — both of which come after the claim.

Two signals were available and neither is consulted before the flip:

signalwhere it iswhen the runbook reads it
archivedAt / archivedByon the get_work_item payloadnever — no step in run.md mentions the word
readiness.ready: false + openBlockerssame payloadat guard #4, after the claim

Why the existing safeguards do not cover it. Step 0b ("the WORKTREE is the claim and the card is not") catches a live sibling, and it worked here — it found the merged PR. But it is written for CONTENTION, and a retired card has no contender. The bare motir run path claims through claim_next_ready, which selects from the active sprint's ready set; whether that op excludes archived rows is not asserted here — it is the first thing to check, because if it does, the <id> path is the only hole and the fix is local to it.

Cost when it fires: low on this occurrence (three minutes, one status flip, restored) and unbounded in general — the flip is what a later session reads as "a sibling holds this", so an archived card claimed and abandoned reads to the next reader as live work.

Acceptance criteria

  • motir-meta/prompts/run.md's motir run <id> step 0 names ARCHIVE as a stop condition before the transition_status call: read the target once, and refuse a target whose archivedAt is non-null — report the archive comment and stop, rather than claim it and discover the retirement two steps later.
  • The same step states that readiness.ready: false on an explicit-id target is a REPORT, not a claim — the <id> path skips selection, and selection is the only thing that has ever consulted readiness. It must say what to do (name the open blockers and stop), not merely that readiness exists.
  • The rule is written so it cannot be read as "a rejection is the only stop" — that sentence is what made an accepted call look like permission. Both new conditions are stated in step 0a itself, not in a note elsewhere in the file.
  • Explicitly out of scope, and said so on the card: making transition_status or claim_next_ready refuse an archived item in motir-core. That is a product-behaviour decision with its own blast radius (an archived card is still legally transitionable today, and something may depend on that); this card changes the runbook only, and is one repo.
  • A grep -n "archiv" motir-meta/prompts/run.md returns the new step-0 condition — i.e. the word appears in the dispatch path, which it does not today.

Context refs

  • motir-meta/prompts/run.md — the ⚠️ STEP 0 on motir run <id> block (0a the claim, 0b the worktree pre-flight).
  • The occurrence: MOTIR-3628, archived 2026-08-26 23:07:50, claimed 23:11:08, restored 23:14:09 — the run's own comment on that card carries the full trail.