Planning bug: MOTIR-2797 declared a sibling's 423-file substrate "landed" when it sits on an unmerged branch with no PR — and MOTIR-2734's placement makes the two stories deadlock
Filed by the motir run MOTIR-2797 that could not start. The correction is already applied — this card is telemetry, not scheduled work.
Defect A — an unverified precondition, stated as fact in the card body
MOTIR-2797's second sentence read "the fixtures (the 20 batches under MOTIR-2755, landed)". Against origin/main @ 4318ae07:
| claim | reality |
|---|---|
| the 20 fixture batches landed | all twenty at In Review, committed on parent/MOTIR-2755-motir-app-adoption — 33 commits ahead of main, 423 test files changed |
| that branch is in review | no PR exists for it in any state; the repository has zero open PRs |
tests/rls/singletonReadScan.ts, singleton-read-guard.test.ts, __fixtures__/scanner/ are available to mirror | absent from origin/main — they are MOTIR-2784's deliverable, on that same branch |
the batch directories carry adminDb fixtures | tests/integration/work-items 0 on main (48 on the branch), sprints 0 (16), boards 0 (21), mcp 0 (28), publicProjects 0 (10) |
Not one blocked_by edge recorded any of it. MOTIR-2797.blockedBy was [] and readiness.ready was true, so the story read as fully dispatchable. The thirteen children referenced their fixture predecessors as relates_to and as Context refs — a reference, which gates nothing — where the edge owed was blocked_by.
validate_work_item fired correctly and nothing consumed it. The advisory channel returned MOTIR-2817 → MOTIR-2784 plus eight likely-missing-edge entries. This is the MOTIR-2075 shape again, and the near-identical MOTIR-2433 ("acceptance criteria consume unmerged substrate ... so the card read ready", closed 2026-08-08) is its most recent prior instance.
What a run that skipped the check would have done: branched off origin/main and rebuilt 423 files of a sibling story's half, then produced an unresolvable conflict the moment MOTIR-2755's branch merged.
Defect B — the two stories DEADLOCK, and the loop closes through a child placement
This is the part no edge repair can fix, because the cycle is structural:
- MOTIR-2734 is a child of MOTIR-2755 and is
blocked_byall twenty fixture batches. Under the parent-run contract (run.mdstep 6) a parent→main PR opens only when every child is committed — so 2755's PR cannot open while 2734 is outstanding. - 2734 cannot run until MOTIR-2797 and MOTIR-2796 are done — its own body says so.
- MOTIR-2797 cannot start until 2755's branch is on
main.
Each edge is individually correct; together they are a cycle, and the graph cannot show it because leg 1 is a parent-run completion rule rather than a link. Note the graph even records MOTIR-2797 blocks MOTIR-2755, which is why the honest blocked_by had to be wired at the card tier (2817 → 2784, each batch → its fixture batch): a story-tier edge would have been rejected as a cycle. The card model made the truthful edge unrepresentable at the tier where the dependency actually lives.
Recommended cut (the user's call, not applied here)
MOTIR-2734 and MOTIR-2789 leave MOTIR-2755's completion set — re-parent them, or split them into a successor container downstream of 2755 / 2796 / 2797. MOTIR-2755's parent→main PR then opens on the 33 commits already landed, the substrate reaches main, and both MOTIR-2796 and MOTIR-2797 unblock. Not applied by this run: MOTIR-2755 has a live parent branch and re-parenting children out from under an in-flight parent-run is a sibling session's ground.
What this run DID apply
blocked_bywired:2817 → 2784;2818 → 2738,2819 → 2739,2820 → 2747,2821 → 2740,2822 → 2753,2823 → 2751,2824 → 2749 + 2752,2825 → 2743 + 2745,2826 → 2751,2827 → 2750,2828 → 2754.- MOTIR-2797 and MOTIR-2817 → Blocked; MOTIR-2797's
targetRepopinned tomotir-core(it was unset). - MOTIR-2797's body amended on the record — the false claim corrected, the evidence kept, nothing re-scoped or dropped.
- A first acceptance criterion added to MOTIR-2797: the substrate is verified on
origin/mainbygit cat-file, not inferred from a sibling card readingin_review. notes.htmllesson logged.
The lesson
in_review is not merged, and a card's status says nothing about where its files are. Twenty cards at In Review with a live branch and no PR read, at every automated tier, exactly like twenty cards whose work is on main. The only signal that separates them is git cat-file -e origin/main:<path> — which is why that is now the story's first acceptance criterion rather than a step someone remembers.