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

Planning bug: MOTIR-3634's own TEST asserts a property of sibling MOTIR-3635's output, and the split left the two edge-free

Done
Description

Found by motir run MOTIR-3634 (2026-08-28), which halted at guard #4 before cutting a worktree.

The defect

The motir run MOTIR-3626 split (2026-08-26) authored three children and wired the order as MOTIR-3633 → MOTIR-3635, leaving MOTIR-3634 deliberately edge-free. The stated reason is in MOTIR-3626's own body and is a runtime argument: MOTIR-3634 "changes no running row", so it cannot participate in the outage the ordering exists to prevent. That reasoning is correct as far as it goes.

It does not reach the card's test. MOTIR-3634 AC 3 asks for a Go test that "fails when no channel in the residency group serves the planner's default model". AC 2 puts DeepSeek out of the residency group. The planner's default is deepseek-v4-pro (motir-ai src/llm/gatewayClient.ts:23 on origin/main; PLANNER_MODEL unset on both production machines, per MOTIR-3626's own platform read). So the assertion is red on merge day, and the only thing that makes it green is MOTIR-3635 repointing the default to o3.

The card's TEST depends on a sibling's output even though the card's CODE does not. That is the axis the split's ordering argument did not cover.

Why it sealed clean

Nothing signalled it. readiness.ready: true, openBlockers: [], validate_work_item on the parent returned only the already-dispositioned subsumption advisory. The reference advisory family scans a card's description for not-done MOTIR-<n> references — and MOTIR-3634's description never names MOTIR-3635. The dependency is expressed as the phrase "the planner's default model", which carries no key, so the detector has nothing to key on. run.md guard #4 names this gap explicitly: "Where the dependency was written as a prose PHRASE carrying no MOTIR-<n> … the detector has nothing to key on, returns nothing … That half is an AUTHORING rule."

The correction already applied

  • link_work_items MOTIR-3634 blocked_by MOTIR-3635 (same parent, acyclic, gate 7 clean).
  • MOTIR-3634Blocked, with the full finding as a comment.
  • Lesson Every prose precondition must be a real dependency edge (global, cmr11gsxh0003kdqzv7e5mc1l) reinforced against occurrence MOTIR-3634. Its howToApply already carries the operative sentence — "any test depends on what it tests" — and also carries the limb that misdirects here: "A non-UI task … blocks ONLY on what it needs to BUILD: if it compiles and ships on its own, do not block it on a sibling whose output it merely consumes at run time." MOTIR-3634 compiles and ships on its own; only its assertion does not hold. The two limbs are in tension for a card whose deliverable IS a test, and the split resolved the tension the wrong way.

What a fix would change

The takeaway worth carrying into the rule corpus, if it recurs: when a card's deliverable is a TEST or a GUARD, the edge is owed to whatever makes the asserted property TRUE, not to whatever makes the code COMPILE. The existing lesson's build-vs-runtime split reads as licence to leave the edge off precisely in this case, because a guard card is exactly the card that compiles alone and asserts about elsewhere. That is a candidate sharpening of an existing global lesson rather than a new one, so it is recorded here rather than written into the store on this run.

Acceptance criteria

  1. A reader of this card can tell whether the build-vs-runtime limb of lesson cmr11gsxh0003kdqzv7e5mc1l needs the guard-card carve-out above, or whether one occurrence is not enough to widen a global row.
  2. If it does: the lesson is widened at its authoring source (motir-ai src/seed/lessons.base.ts + pnpm lessons:generate-migration), since the takeaway survives stripping every local identifier.
  3. No change to MOTIR-3634 or MOTIR-3635 is owed by this card — the edge is already wired.

Context refs

  • motir-meta/prompts/run.md guard #4, the empty-array limb.
  • plan-rules/core.md gate 4 and gate 8 (the file-time half: a new sibling's author wires the edge at creation).
  • The run comment on MOTIR-3634 carries the full evidence.