Planning bug: a story ACCEPTANCE CRITERION had no child that owns it — MOTIR-3870 pre-dates MOTIR-3891 and was scoped against a different parent
A STORY acceptance criterion had no child that owns it, and every signal said the story was complete.
The shape
MOTIR-3891's sixth criterion reads:
"
motir-meta's pack tree carries the same selector and the same cuts, and its MANIFEST is regenerated rather than hand-edited."
Its only motir-meta child is MOTIR-3870, which was created at 2026-08-29T00:58 — ten and a half hours BEFORE the story at 11:34. It was authored against MOTIR-3866 and MOTIR-3869, and its own acceptance criteria describe exactly that smaller mirror: eleven per-type packs, three kind-*-deepen packs, kind-container / kind-story at both phases, the operation axis retired. It discharges every one of them.
The story then went on to re-cut the SELECTOR into a sum and to cut VERIFY_EVERY_PRECONDITION into eight limbs — and nothing extended MOTIR-3870 to cover the mirror of that. The criterion was written as though its child would grow with the story.
Why every gate passed
validate_work_itemon the story:valid: true, no blocker.- Every child:
implemented. - The parent rollup flipped the story to
implementedon its own. - The routing, conservation and register guards are all green — in the repository each of them measures.
Nothing reads a story's acceptance criteria against its children's. The advisory channel detects a card REFERENCING a not-done item; there is no detector for a criterion that no child DELIVERS, and the two failures look identical from the board: a green subtree under a story whose criteria nobody re-read.
The pre-dating is the aggravator rather than the cause. A child older than its parent is a normal, healthy shape — an existing card adopted into a new story is exactly what reconcile existing not-done work asks a planning pass to do. What that pass owes and did not do is the second half: re-read the adopted card's acceptance criteria against the story's, and widen the card or add a sibling where the story asks for more than the card promises.
The discriminator, and the fix
The tell is mechanical and cheap: a story child whose createdAt PRE-DATES the story's own is an ADOPTED card, and an adopted card was scoped against a different parent. That is a one-field check on data every get_work_item already returns, and it names the exact population where this failure can occur.
The rule the corpus needs is a limb on the reconcile rules (RECONCILE_EXISTING_NOT_DONE_WORK, core.md in both homes): when a plan pass ADOPTS an existing card under a new container, it re-reads that card's criteria against the container's and either widens the card or files the sibling that covers the difference — because the card was sealed against a parent that no longer exists, and its silence about the new parent's criteria is not agreement.
A mechanised half is available too and is worth pricing: validate_work_item already walks a container's subtree, so a coverage advisory family — a container criterion whose nouns appear in no child's body — would fire on exactly this. It is fuzzier than the reference detector and would need its own card.
Disposition on this run
The missing card is SUBMITTED as a proposal (plan cmteeo1nm008xhvn8ukqyh8ao, one add under MOTIR-3891, blocked_by MOTIR-3870) rather than created: a run creates no work item except a bug. MOTIR-3870 is unchanged and correct — it is not the defect, and the record should not read as though it were. The MANIFEST it generates now states the residual gap in words, so the next reader meets it as a fact rather than as a discovery.
Comments (0)
No comments yet — be the first to weigh in.