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

Planning bug: guard #4 says an advisory's reference is "a `blocked_by` to WIRE" — followed literally on a CROSS-STORY reference it produces a cross-parent edge, which gate 7 forbids

Done
Description

Discovered 2026-08-21 by Yue, reading MOTIR-3295 immediately after it was planned: "story 3295 not valid".

What happened

Planning MOTIR-3293, the pass ran validate_work_item on the epic and got seven reference advisories. It disposed of them as guard #4 instructs:

a reference entry naming an item that is not done is a blocked_by to WIRE (link_work_items), never a note to leave

Two were wired: MOTIR-3302 blocked_by MOTIR-3300 and MOTIR-3304 blocked_by MOTIR-3299. Both cross parents — 3302 is a child of 3295 while 3300 is a child of 3294; 3304 is a child of 3296 while 3299 is a child of 3294.

core.md gate 7 says the opposite:

Edges a same-level DAG — every blocked_by a same-kind sibling under the same parent

So the pass satisfied one rule by breaking another, and produced a subtree that validate_work_item then reported as not finishable for a reason that was partly its own doing.

Why it is the instruction and not carelessness

The five advisories the pass did NOT wire were disposed of correctly, with the right reason written down"covered by the story edge". The same reasoning applies verbatim to the two it wired. What separated them was not judgement: the two wired ones were the ones where the reference looked most like a genuine consumption (a parameter passed, a column read), and guard #4's sentence is unconditional, so the more real the dependency felt the more the literal instruction applied.

The correct disposition for a CROSS-CONTAINER reference is an edge at the CONTAINER level, or nothing if one already exists. Both were already ordered: 3295 blocked_by 3294 and 3296 blocked_by 3294. Readiness confirms the container edge does the work — 3302 reads ready: false, openBlockers: [], blockedByAncestor: MOTIR-3295, so the subtask edge added no gating and only violated the DAG rule.

The fix

Guard #4's disposition sentence needs the qualification gate 7 already implies: wire the blocked_by when the referenced item is a SIBLING under the same parent; when it is in another container, the edge belongs between the containers — and if that edge already exists, nothing is owed. Same for the identical sentence in the create-time half (log-bug.md step 3 / the guard #5 validate block), which carries the same wording.

Acceptance criteria

  • run.md guard #4's reference-disposition sentence states the same-parent condition and names the container-level edge as the cross-container disposition.
  • Every other copy of that sentence in the corpus is found by grep and corrected or explicitly left, with the grep and its hit count quoted.
  • The correction names readiness.blockedByAncestor as the mechanism that makes a container edge sufficient, so a reader does not re-add the subtask edge for safety.
  • Lands via a branch + PR; no direct commit to main.

Context refs

  • motir-meta prompts/run.md — guard #4's advisory-disposition block, and the identical wording in the guard #5 / create-time validate note.
  • motir-meta prompts/plan-rules/core.md — gate 7, edges a same-level DAG… under the same parent.
  • motir-meta prompts/log-bug.md — step 3's validate post-condition, same sentence.
  • MOTIR-3295 — the story that read invalid; the two offending edges have been removed.