Planning bug: a card filed MID-RUN carried a criterion the FILING run then satisfied itself, and pinned both repositories — the next run claimed half-done work behind a repo set that could never close
Found by: motir run MOTIR-4233 (2026-09-02), at the guard-#4 prior-art read, before a worktree existed. · About: MOTIR-4233, filed 01:02Z by the run executing MOTIR-4103. · Repo: none — the fix is a plan/authoring rule, not product code.
What happened
MOTIR-4103's run, sweeping content/legal/'s referrers, correctly noticed that deleting the directory would silently retire the assertion coupling ACCOUNT_ERASURE_WINDOW_DAYS to the Privacy Policy's §6, and filed MOTIR-4233 for it — a good catch, filed as a card rather than as a paragraph, exactly as a recorded deviation that names an open defect is a card requires.
It then went on to fix the motir-core half itself, in the same working tree, as part of MOTIR-4103's own diff — re-pointing tests/users/dataSubjectRequests.test.ts to a pinned PUBLISHED_ERASURE_WINDOW_DAYS = 30 quoting https://motir.co/legal/privacy §6, and even writing MOTIR-4233's key into the new comment as the card that owes the other half. That work is correct and belongs where it is: the deletion is what removes the old assertion, so replacing it in the same diff is what keeps motir-core green.
What was never done is the other half of the same thought: the card was not amended to stop asking for it. MOTIR-4233 was left carrying:
- acceptance criterion 2, the
motir-corere-point — by then already written on MOTIR-4103's branch; and targetRepos: ["motir-marketing", "motir-core"], with a body reading "TWO PRs".
Why it is a planning bug and not a near-miss
Two independent failures were queued, and every readiness signal was green in front of both. At claim time MOTIR-4233 read status: todo, readiness.ready: true, openBlockers: [], validate_work_item.valid: true.
- Duplicate, conflicting work. A run following the card literally branches off
origin/mainand re-writestests/users/dataSubjectRequests.test.ts— the exact file a live sibling had 47 uncommitted changes across, including that one. Two independently-authored versions of one guard, colliding on merge. This is the never rebuild the sibling's half prohibition, reached by obeying the card rather than by carelessness. - A card that could never close.
targetReposis a completion GATE: the item does not complete until every listed repository has a merged pull request linked to it.motir-core's half ships under MOTIR-4103's key, so nomotir-corepull request would ever be linked to MOTIR-4233 — leaving it deferred at In Review indefinitely on a merge nobody was ever going to make.
Nothing mechanical reports either one. The prior-art advisory family (subsumption / likely-already-shipped) keys on a MERGED pull request; this work was not merged, not pushed, not even committed, which is the one window in which a duplicate can actually be created. The advisories array came back with three plain reference entries and one shape entry, none of them about this. What found it was reading the sibling's worktree by hand.
Root cause
A card filed mid-run is filed at the moment of DISCOVERY, and its scope is then never re-read at the moment of DELIVERY — even when the same run delivers part of it minutes later. The filing rule (log-bug.md) is about where a bug is parented and what it relates to; it has nothing to say about the filing run subsequently absorbing part of the card it just wrote. So the card ages by the length of one run and nobody re-opens it.
The repository set makes it expensive rather than merely untidy: a scope that shrinks by one repository is not a cosmetic overstatement, it is a completion gate pointed at a pull request that will not exist.
Fix direction
A rule, in log-bug.md beside the filing protocol (and echoed in run.md's findings section), of roughly this shape:
Before you finish a run that FILED a bug, re-read that bug against your own final diff. Anything your diff delivered is a criterion to CUT on the record, and if that removes a repository from the card's scope,
update_work_itemthetargetReposin the same action — a repository on the list with no pull request coming does not degrade, it strands the card.
It is the close-out twin of the re-read the container's CURRENT child set before opening the parent PR rule: both are about state the run itself created after t=0 and never looked at again.
Reproduce
# MOTIR-4233 as filed, before the amendment:
# targetRepos: ["motir-marketing", "motir-core"]
# AC 2: motir-core's tests/users/dataSubjectRequests.test.ts asserts …
git -C motir-core-subtask-4103 diff -- tests/users/dataSubjectRequests.test.ts
# → AC 2, already written, uncommitted, on the filing card's own branch
What this run did about it
Applied on the record to MOTIR-4233 rather than left as prose: criterion 2 struck with the sibling's diff quoted as evidence, targetRepos narrowed to ["motir-marketing"], size 3 pts / 45 min → 2 pts / 30 min, a coordination comment on MOTIR-4103, and the surviving motir-marketing half built and shipped. The corpus lesson "Verifying that something is broken is not verifying that nobody has already fixed it" (c30hny9…, global) covered this exactly and was reinforced against MOTIR-4233 rather than duplicated — its howToApply already says to read the siblings' working copies as a prior-art check, which is the step that caught it.
Acceptance criteria
log-bug.mdcarries a close-out rule requiring a run that FILED a bug to re-read that bug against its own final diff before reporting, cutting on the record any criterion the diff delivered.- That rule names
targetReposexplicitly: a repository dropped from a card's scope is anupdate_work_itemfield edit, never a sentence in a body or a PR. - The rule states why a merged-PR-keyed prior-art advisory cannot cover this case, so a later reader does not try to mechanise it there.
run.md's runbook-vs-dispatched table gains a row, or an existing row is widened, saying whether a dispatched agent owes the same re-read (it files bugs under the in-flight card's parent, so it can hit the same shape).