PLANNING BUG — MOTIR-2279 was filed twice wrong: a deliberate omission called an oversight, and a cross-story dependency hung off the epic instead of a story-level edge
RECORD card — both fixes shipped in the same session. This exists so two planning defects on one card are countable, not because work remains.
One card (11.5.13), filed mid-run by motir run MOTIR-1855, wrong in two independent ways. The first was caught by the session that filed it; the second by Yue.
Defect 1 — a DELIBERATE omission called an oversight
The card asserted that readyItemSchema had narrowed away the ready row's assignee.name and targetRepo — "the same class as 11.7's three projections: the data exists, a service computes it, MCP returns it, and the v1 mapper drops it."
Forty minutes later the same session opened lib/api/v1/ready/schema.ts to make the change and found, at lines 31–45, a block headed "What is deliberately NOT on the row" naming both fields with reasons:
assignee.avatarUrl/name— "a public API must not acquire a second, accidental user resource."runCommand/contextRefs/sessionBranch/targetRepo— "those live onReadyItemDispatchDto, the payload for Motir's OWN CLI dispatch path."
The card had read presentReadyItem (line 119) and the schema object (line 97), and not the prose immediately above both — in the file it named as its own first context ref.
Why it matters: a widening of an oversight is a one-line schema edit any agent can make; overturning a recorded decision needs rung-1 evidence, an ADR entry, and a rule stated for every v1 collection row. Run as filed it would have widened the public API against a written decision and left the schema's comment contradicting its own code — passing CI throughout, because nothing tests a comment. One of the two turned out not to need overturning at all.
notes.html #33's shape (verify, don't cite), with an unusually short walk to the evidence.
Defect 2 — filed outside the story that owned it, as a cross-story edge
The card was filed as an epic-direct task and wired blocked_by directly into two subtasks in two different stories — 11.5.4 and 11.6.3.
That made both stories valid: false:
MOTIR-1855 → blockers: [{ item: MOTIR-2212, blockedBy: MOTIR-2279 }]
MOTIR-1856 → blockers: [{ item: MOTIR-2229, blockedBy: MOTIR-2279 }]
A subtask gated by work outside its own subtree: neither story was independently completable, and 11.6 — which a parallel session was actively finishing — was invalidated by a card that had nothing to do with it.
The correction, and the second correction. The first repair created a STORY for the finding (copying how 11.7 was born) and moved the edges up to story level. That fixed the tree but was over-structure: 11.7 was ten endpoints and nine cards, and this is one decision. A one-card story is not a review unit.
Where it actually belongs is inside 11.5 — the story whose own run found the gap. It is now 11.5.13, an ordinary subtask, with an in-story 11.5.4 blocked_by 11.5.13 edge. Both stories report valid: true. The interim story was archived.
And 11.6 gets no edge at all. list_ready / next_ready / claim_next_ready are already on 11.6.3's own exemption list, so the default behaviour is safe while this is outstanding; the constraint is recorded as a comment on that card instead of an edge that would invalidate its story.
The rule each defect lands under
- Defect 1: when a card's premise is "X is missing", the check is not "is X absent?" but "is there a recorded REASON X is absent?" — and it lives in the file's prose, not its expressions.
- Defect 2: a finding belongs to the story whose work exposed it, as an ordinary subtask with an in-story edge. Reach for a new story only when the finding is story-SIZED; reach for a cross-story edge only when the other story genuinely cannot proceed — and prefer a comment when its own mechanism (here, an exemption list) already makes the default safe.
Corrective actions — all complete
- 11.5.13 re-scoped (decision-first), re-parented into 11.5, re-kinded
subtask,type: decision. 11.5.4 blocked_by 11.5.13restored as an in-story edge; both storiesvalid: true.- 11.5's scope boundary amended: the "does NOT change the server" rule now names this one exception and says why (11.7 shipped, so gaps found by 11.5's run have no other owner).
notes.html#229 (defect 1) and #230 (defect 2).
Acceptance criteria
- No code change. Closed by its own existence plus the artifacts above.
Context refs
lib/api/v1/ready/schema.ts:31–45— the block defect 1 did not read.notes.html#33, #229, #230.
Close-out verification — motir run MOTIR-2280, 2026-08-06
Every corrective action re-checked against the live tenant and origin/main. Nothing had drifted in the record itself; every citation is exact. That is worth stating plainly rather than implying a drift that was looked for and not found.
| Claim | Verified against | Result |
|---|---|---|
11.5.13 re-parented into 11.5, re-kinded subtask, type: decision | get_work_item MOTIR-2279 | ✅ kind: subtask, parent MOTIR-1855, type: decision |
11.5.4 blocked_by 11.5.13 is an in-story edge | MOTIR-2279 blocks: [MOTIR-2212]; both under MOTIR-1855 | ✅ |
Both stories valid: true | validate_work_item | ✅ MOTIR-1855 valid: true; MOTIR-1856 valid: true, blockers: [], advisories: [] |
| 11.6 gets no edge | MOTIR-2279 blockedBy: [], no link to MOTIR-2229 | ✅ |
| The interim story was archived | MOTIR-2281 | ✅ archivedAt: 2026-08-06T09:06:01Z |
| 11.5's boundary amendment | MOTIR-1855 descriptionMd | ✅ "⚠️ Amended 2026-08-06 — the 'does NOT change the server' boundary has ONE exception, and why" |
lib/api/v1/ready/schema.ts:31–45 | git show origin/main:… | ✅ exact — the block opens at line 31, closes at line 45 |
presentReadyItem line 119 · schema object line 97 | same | ✅ both exact — no line rot |
notes.html #229 / #230 | git show origin/main:notes.html | ✅ both exact, no collision renumber; corpus head is #230, "Across the 230 mistakes" |
The prediction in the body held. "One of the two turned out not to need overturning at all" — 2279's Q2 CONFIRMED the targetRepo rationale (checkout-bound dispatch metadata, served by GET …/dispatch-prompt); only the assignee's display name was overturned, now ADR Amendment 9 Q1, with MOTIR-2283 applying it to the comment author.
The one thing that HAD drifted — and it was this card's own chosen remedy
The body says the 11.6 constraint "is recorded as a comment on that card instead of an edge." Reading that comment thread — rather than the record's paraphrase of it — showed its last word pointed at a story that no longer exists: comment 2 (09:00Z) announced that 2279 now lived under 11.8 / MOTIR-2281 with 11.6 blocked_by 11.8, and MOTIR-2281 was archived six minutes later. Comment 1 also over-claimed, saying 2279 "widens readyItemSchema with both fields" when Q2 confirmed targetRepo stays off.
No readiness impact — MOTIR-2229 and MOTIR-1856 are both done — but a reader of the thread would have been misdirected. Corrected with a third comment on MOTIR-2229 recording the final state. A remedy that is a comment has to be re-read at close-out; unlike an edge, nothing in the graph keeps it true.
Promote question: none is owed, and the answer would be LESSON
This card poses no lesson-vs-rule question, so settling one is not its deliverable — but the check is cheap and the result is worth recording so the next reader does not re-open it.
Defect 2's rule is already written in plan-rules.md, in the most literal terms available: "Every blocked_by edge is between two SIBLINGS of the SAME KIND … none crosses a PARENT." The ORDER test says it landed 2026-06-25 (4e7ea23), 42 days before the defect; the adjacent bug-parent gate — which names "re-creates the cross-story dependency the boundary rule exists to prevent" — landed 2026-08-04 (8f9668a), ~30 hours before MOTIR-2279 was created.
So the rule existed and was not applied. One nuance in the other direction, recorded and rejected: the rule's parenthetical enumeration ("a subtask under story A never blocks a subtask under story B") does not literally name an epic-direct task blocking a story's subtask, which is what this was — a trigger that stops one item short. But the governing sentence covers it completely: a task-under-epic and a subtask-under-story are neither siblings nor the same kind. A rule whose general clause covers the case and whose example does not is a diligence miss, not a trigger gap → LESSON, and the lesson (#230) is already authored and merged.
No rule card filed, no promotion argued. Recorded per the standing caution that a family resemblance narrated after the fact is not evidence.