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-2848

Planning bug: a cross-parent dependency was recorded in PROSE because the planner believed a different parent means no `blocked_by` edge is available (MOTIR-2768 → MOTIR-2764)

Done
Description

Found by motir run MOTIR-2765 (2026-08-13) at guard #4, on the run's first shape resolution.

What the plan said

MOTIR-2768's own Context refs close with:

The sibling bug — ships the refusal this card recognises. It is in a different parent, so there is no blocked_by edge; the dependency is real and the ADR records it.

That premise is false. link_work_items places a blocked_by edge between any two items in the same project — parentage is irrelevant, and the tool description says so explicitly ("Targets may be in another project in the same workspace"). The planner had the edge available and declined it on a belief about the tool.

Why it mattered

MOTIR-2768 consumes a typed error code from lib/acceptanceEvidence/errors.ts that MOTIR-2764 has not yet shipped. Verified on origin/main @ fca2c9f3:

  • errors.ts defines ACCEPTANCE_EVIDENCE_NOT_FOUND / NOT_A_STORY / NOT_IN_REVIEW / INVALID_PATHNAME / BLOB_MISSING — no already-approved refusal.
  • acceptanceEvidenceRepository.markSupersededByWorkItem is still updateMany({ where: { workItemId, isCurrent: true } }) — no status predicate, i.e. MOTIR-2764's defect is live.

So MOTIR-2768 read as ready with openBlockers: [], and validate_work_item MOTIR-2765 returned valid: true with an EMPTY advisories array. A run that trusted either signal would have branched off origin/main and invented the typed error itself — a parallel constant in the client, which the card's own Context refs forbid ("must not invent a parallel constant") — or gone red against a refusal that does not exist.

Why the advisory channel did not catch it

The reference advisory family scans a card's description for work-item references (MOTIR-<n> / item links) that carry no blocked_by edge. MOTIR-2768 names its dependency as the prose phrase "the sibling bug" and never once writes MOTIR-2764. The card is maximally clear to a human reader and completely invisible to the scanner — the one shape the safety net cannot see.

This is the generalisable finding, and it is a rule candidate rather than a one-off correction: a dependency stated in prose is not a dependency. The edge is the machine-readable form; prose that a reader would call unambiguous still leaves the card in the ready set.

What the run did

  • link_work_items MOTIR-2768 blocked_by MOTIR-2764 — the edge the author owed.
  • transition_status MOTIR-2768blocked.
  • MOTIR-2771 (integration test over the freeze seam) is transitively held behind it and was left alone.
  • The run continued on MOTIR-2765's other four children, which are genuinely ready.

Acceptance criteria

  • The notes.html lesson is appended (a prose dependency is not a dependency; name the key or wire the edge).
  • Assessed: whether the reference-advisory scanner should also flag a blocked_by-less card whose description contains a dependency PHRASE (the sibling bug, the sibling card, ships the X this card consumes) — recorded as either a follow-up card or an explicit decision not to, with the reason.
  • The planning rule, if adopted, lands in BOTH homes (plan-rules/ pack + motir-ai SHARED_PLANNING_RULES) per the two-homes rule.