Filed by: motir run MOTIR-2761 (2026-08-17), run.md guards #4 + #5. About: MOTIR-2761. Correction already applied — this is the telemetry record, not scheduled work.
MOTIR-2761 was authored 2026-08-12 as a well-diagnosed bug: a four-row evidence table, a named root cause, a fix direction with file paths. It read ready: true, openBlockers: [], validate_work_item → valid: true. It was not runnable, for two independent reasons the card itself had already written down in prose.
1. It named its own blocker and never wired it. The § Related section says of the sibling defect MOTIR-2758: "Two defects, both on the predicate set of the same two reads — worth fixing in one pass, and worth reading together before the fix is planned." That is a dependency stated in words. blockedBy was []. By the time the card was claimed, MOTIR-2758 was in_review on open PR #2083, which:
browsableProjectIds → browsableProjectScopes and changes all four Home reads from projectIds: string[] to HomeProjectScope[];tests/integration/home/personal-reads.test.ts.So MOTIR-2761's fix direction — "The repository layer needs no change … already accept projectIds … pass [activeProject.id]" — was already false on an open branch. A run that trusted ready: true would have branched off origin/main and rebuilt the sibling's half: two PRs each green alone, composing badly (notes.html — the fixes cancel on merge family).
2. It named its own open decisions and then wrote one into an acceptance criterion. The card carries a section headed "Two open decisions the fix card must carry (Yue's, not the implementer's)", and then AC 5 reads "The no-project state resolves per the decision above". A criterion that defers to a decision the same card declares is not the implementer's cannot be evaluated by whoever claims the card — it is a placeholder wearing a checkbox. The card also called itself "a fix subtask, not this card" while carrying type: code, targetRepo: motir-core, 5 points and a full AC set: it was both the record and the fix and had not decided which.
Both halves are the same failure mode: a correct observation written as PROSE instead of as STRUCTURE. The card knew about its blocker and knew about its unmade decisions. Neither fact reached a field any tool reads — not blocked_by, not a decision card, not the status. Readiness is computed from edges, so a dependency that exists only in a paragraph makes a card look more ready than one that admits it, and an open decision recorded only in prose makes an AC look complete. The planner's own prose is not a channel; only the graph is.
validate_work_item's advisory channel did fire — {referenced: MOTIR-2758, referencedStatus: in_review, severity: advisory} — at the correct tier, naming the correct blocker. Severity was advisory rather than likely-missing-edge only because the reference sat in § Related rather than inside the acceptance criteria. It changed nothing, because nothing between authoring and dispatch read it. Same shape as MOTIR-2075.
link_work_items — MOTIR-2761 blocked_by MOTIR-2758 (the edge the author owed).create_work_item — MOTIR-2904, the type: decision card carrying both open decisions (the no-project state + post-auth landing; whether a cross-project "my work" survives), executor: coding_agent, deliverable docs/decisions/home-scope.md. link_work_items — MOTIR-2761 blocked_by it.update_work_item — MOTIR-2761 amended IN PLACE (never cancel-and-recreate): a BLOCKED block naming both blockers and the run order; fix-direction step 2 corrected against the #2083 branch with the real HomeProjectScope shape; the "a fix subtask, not this card" contradiction retired; AC 5 re-pointed at the decision RECORD; a new AC added so the lifecycle predicate #2083 introduces is not silently dropped when the project axis narrows.transition_status — MOTIR-2761 → Blocked.notes.html lesson appended in motir-meta (the LESSONS corpus; this card is the CARD half).No sprint — MOTIR-1465 carries none, MOTIR-2761 is itself in the backlog, and there is no active sprint in the project.
A card that can articulate its own blocker or its own open decision has done the hard part and must not stop there — the sentence is the trigger to write the edge. Concretely, at authoring time: grep the finished card body for a sibling MOTIR-<n> that is not done and not in blockedBy, and for any phrase of the "X must decide" / "open decision" / "per the decision above" family. The first is a missing edge; the second is a missing decision card plus an AC that is not yet a criterion. Both are cheap to fix while writing and expensive at dispatch — this one cost a full claim-and-stop and left a stale fix direction on the card for five days.
plan-rules/kind-bug.md § the repeat-defect trigger.