Type: planning bug — an inference stated as fact, then promoted into an acceptance criterion. Discovered in: motir run MOTIR-3371 (2026-08-21). Lesson: notes.html #357, shipped as motir-meta#312 (locate by title; append collisions shift the number). The product bug the falsification produced: MOTIR-3398.
MOTIR-3371 diagnoses a real defect in stallDiagnosis, correctly: it measures a burst's span from our own send-acks while the debounce window opens and closes on the scheduler's clock, so a span under PERIOD_MS does not prove the burst fit. The run confirmed that against the dev server's own records and shipped the fix (motir-core#2255).
The card then explains the OCCURRENCE it was filed from with that same defect, in one sentence:
toHaveLength(1)passed, so event 6 opened a second window whose run landed afterSETTLE_MSand was never observed.
The so is the defect. Exactly one run carrying a non-last event is equally consistent with a burst that coalesced perfectly and did not keep the last event. The two mechanisms are indistinguishable in a CI log; the only thing that separates them is a span measured on the scheduler's clock — which is precisely the instrument the card was proposing to build, and therefore did not have.
Instrumenting burst() to read the dev server's own received_at per event, ten consecutive local runs of tests/jobs/debounce-burst.test.ts (8 passed, 2 failed):
# the card's OWN case, the assertion at :308, the card's OWN error string
{"fn":"coalesce","recvRel":[0,0,0,0,0,0],"lastIsMax":true,"ourSpan":16,"schedulerSpanMs":0}
AssertionError: expected 5 to be 6
Six events inside zero milliseconds on the scheduler's clock, against a 3 000 ms window. Nothing overran. The presentation the card reasoned from was produced by a mechanism the card never considered, and that mechanism reproduces at 2 in 10 on this box.
The inference did not stay in the prose. It became acceptance criterion 1 — "a burst that misses the scheduler's window is NAMED … the case that produced this occurrence" — so the run was asked to certify the diagnosis as part of delivering the fix. And criterion 4 ("no change to any assertion's meaning in the spec") fenced off the only edit that could have addressed the other mechanism. A card that is wrong about WHY can still be right about WHAT, and this one was; the cost is that its criteria made the wrongness non-falsifiable from inside the card.
This is the fourth expected N to be 6 filed against this file and the third card built on the timing reading (MOTIR-3125, MOTIR-3276, and this one). The base rate is why the reading felt safe.
notes.html carries the lesson — already shipped as #357 / motir-meta#312: an acceptance criterion may bind the DEFECT the card fixes, never the card's unverified explanation of the OCCURRENCE that prompted it, with the grep-able tell (a so / therefore / which means between an observed signal and an unobserved mechanism, in a card whose reason to exist is that the mechanism was not observable). This criterion is discharged by confirming that entry is on main and reading it, not by writing it again.plan-rules/ packs and lands where it belongs — plan-rules/kind-bug.md (bug-card authoring) is the candidate home, beside the reproduce-first limb. If the pack already carries an equivalent obligation, say which line and close on that rather than duplicating it.SHARED_PLANNING_RULES in motir-ai is its second home and gets the mirrored wording in the same change (the two-homes rule, notes.html #338). If it lands as a lesson only, say so explicitly and why.notes.html #357 (this lesson) · #309 (a bug card that named a MECHANISM its own quoted evidence already excluded — the nearest sibling) · #308 (a diagnosis measured on one member of a batch, applied to the batch) · #319 (a mechanism written as prose hypothesis, then encoded as fact) · #339 (prescribed remedy taken as the goal, symptom never reproduced)plan-rules/kind-bug.md · plan-rules/phase-deepen.md (the NEGATIVE limb, the nearest existing obligation)Open. The correction is already applied to the run's output: the fix shipped as specified (motir-core#2255), the falsification is in the pull-request body and on the card, the lesson is motir-meta#312, and MOTIR-3398 owns the product half. This card owns the RULE half.