Planning bug: a story was authored with a DEPLOYED-tenant verification card inside it, gating three siblings that ship at merge — so the story's own pull request could never open
Filed by motir run MOTIR-3780, which stopped without dispatching a child. The corrected shape is already submitted as plan cmtd9r21v012hhwn8drucjr37; this card is the telemetry, and it holds nothing up.
What was authored
MOTIR-3780 was laid out with eleven leaf children, one of which — MOTIR-3784, type: verification — has acceptance criteria that read the DEPLOYED tenant: "tools/list against app.motir.co/api/mcp returns an entry named publish_design_result", plus one real publish round-trip through it. Three sibling retirement subtasks were wired blocked_by it — MOTIR-3785 (motir-core), MOTIR-3786 (starter), MOTIR-3787 (motir-marketing) — with MOTIR-3790 and MOTIR-3791 behind MOTIR-3785 in turn.
The defect — a cycle, not an untidiness
Six of the eight motir-core children land on ONE parent/MOTIR-3780-* branch and ONE pull request. MOTIR-3785 / 3790 / 3791 cannot be written until MOTIR-3782's tool is deployed, and the deploy is triggered by the merge of the very pull request they would have to be committed on. run.md's parent-run step 6 forbids opening that pull request while any child is un-landed, and applyStatusTransition refuses the container's status flip with CONTAINER_HAS_OPEN_CHILDREN, naming them.
So the container had no exit. The run could neither land the retirements nor open the pull request that would have let them land. There is no ordering of the eleven children that finishes the story.
The gate that already forbids it
plan-rules/core.md gate 14 names both halves in its own words, and neither fired at authoring time:
- 14(c)'s placement clause — "hang a post-merge card OUTSIDE the container — a sibling the story
blocks— never inside it", because completing a container cascadesdoneonto every child from any status, and the parent-run's own pull request is what completes the container. Its LOOK-FOR is exact: "a child whose criteria read the DEPLOYMENT — a live-tenant read, a pulled artifact, a platform API — under a parent whose own merge is what closes the parent." - 14(d)'s ordering consequence — "a card whose criteria read the DEPLOYMENT may not be an IN-PARENT BLOCKER of a card that ships at merge."
⚠️ Why a careful author walked into it — the part worth keeping
This was not a card written carelessly; it was written unusually well, and that is what hid the defect. MOTIR-3784 exists at all because its author had already seen the problem: its own explanation argues that "a sentence in a body carries no readiness semantics and cannot hold anything out of the ready set, whereas an edge can", and it carries an EARLIEST-LEGAL-START section warning that the card flips ready at the moment the measurement is least likely to succeed. Each of the three retirement cards states the ordering again in its own "⚠️ Ordering" section. The story's AC 5 states it a fifth time.
Every one of those five statements is correct. The author reasoned all the way to the edge and stopped one question short of asking WHERE the card that carries it should hang. Gate 14(c)'s answer to that question is one clause inside a long gate whose first two axes (ACTOR, SURFACE) are about a single criterion, so a reader who has just satisfied himself that the ordering is expressible has no reason to keep reading into the placement clause.
The tell that a reviewer can actually use: a container that needs TWO merges separated by a deploy. Count the merges the story's own criteria imply. One is a story; two is two stories. That question is cheap, is asked of the story rather than of a criterion, and it is the one that was never asked here.
Acceptance criteria
plan-rules/kind-container.md(orkind-story.md) carries a skeleton-time check on the STORY, not only gate 14's per-criterion one — "how many merges do this story's own criteria imply? More than one, separated by a deployment, is more than one story" — citing this instance.- The check names the shape rather than the type — a
verificationcard is the usual carrier, but the trigger is criteria that read a deployed environment, whatever the card's type. An enumeration of types would have missed achoreordeploycard carrying the same criteria. run.md's parent-run step 0 gains the refusal it lacks — its two refusals are anepicby kind and a grandchild by depth; a container whose own merge is a precondition of one of its own children is a third, and the run that meets it should report it rather than deriving it as this one did.- THE TWO HOMES are both written (
plan-rules/core.mdgate 19) — the pack underprompts/plan-rules/, andSHARED_PLANNING_RULESinmotir-aiwhere the shipped planner reads the mirror. A narrowing is legitimate; silence is not. If the clause is excluded from the mirror, the card says so with the grep that excluded it. - The
git log/git showevidence for each edit is quoted in the pull-request body, and the card names the lesson row this bug is paired with.
Context refs
- MOTIR-3780 — the story this was found on, and the survivor the plan re-scopes.
motir-meta/prompts/plan-rules/core.md— gate 14(c) and 14(d), the clauses that already forbid the shape.motir-meta/prompts/plan-rules/kind-container.md·kind-story.md— the skeleton-time home for the merge-count check.motir-meta/prompts/run.md— the parent-run section: step 0's refusals, step 5's stoppers, step 6's post-deploy-child warning.motir-ai/src/lib/planning/sharedRules.ts(SHARED_PLANNING_RULES) — the second home gate 19 requires.- Plan
cmtd9r21v012hhwn8drucjr37— the corrected shape submitted by the run that filed this.
Comments (0)
No comments yet — be the first to weigh in.