Planning bug: a `notes.html` #27 filing writes `relates_to` where gate 4 also owes `blocked_by` — when the found-in card IS the consumed card, one edge hides the other
Repo: motir-meta. One PR. Telemetry, filed by motir run MOTIR-2969 (2026-08-18) per run.md's planner-bug-home rule. The correction is already applied — MOTIR-2969 blocked_by MOTIR-2966 is wired — so this holds nothing up and carries no sprint. It exists to make the recurrence countable.
Timeline footnote, because it changes what this card is NOT about. MOTIR-2969 was moved to Blocked at
10:24:38Z; PR #237 had merged at10:23:58Z, forty seconds earlier and mid-run. The run re-read the tenant, saw MOTIR-2966done, unblocked, and shipped MOTIR-2969 as motir-meta PR #238. The edge stays — it is the correct edge and is now satisfied. The missing-edge defect is not retroactively excused by the merge landing early: the card satready: true,valid: true,openBlockers: []and fully claimable for the eight hours before it, and any run that had claimed it in that window would have branched off anorigin/mainwhere three of its six criteria were unreachable.
What happened
MOTIR-2969 was authored at 01:44:40Z by the motir run MOTIR-2966 session, under notes.html #27 (an out-of-scope defect found mid-card is logged, never absorbed). It was wired relates_to MOTIR-2966 and nothing else. Every one of its six acceptance criteria then read on substrate that existed only in that same session's worktree — which became PR #237, opened at 01:48:33Z, four minutes after the card was filed.
Dispatch caught it: validate_work_item returned severity: likely-missing-edge naming MOTIR-2966 at in_review, and run.md guard #4's advisory limb disposed of it correctly. But the card had by then been sealed, ranked and made claimable with readiness.ready: true, valid: true, openBlockers: [].
The generator — why the edge went missing here specifically
Two rules fired on the same key and only one wrote an edge:
notes.html#27 says: log the out-of-scope defect,relates_tothe card you found it in. That edge is provenance — this is where it was seen.plan-rules/core.mdgate 4 says: an acceptance criterion naming a not-donecard is a missingblocked_byuntil proven otherwise. That edge is consumption — this is what it needs.
Normally these point at different cards and both get written. When the defect is found in the very card whose unmerged output the new card will consume, they point at the SAME key — and relates_to is already there, so the card reads as wired. It is wired, for the wrong relation. The two edges are not alternatives and the graph cannot infer one from the other.
The narrower trigger inside that: the filing run measured on its own worktree and wrote the numbers into the new card's criteria as properties of origin/main. MOTIR-2969 says so in plain text — "Measured on the MOTIR-2966 worktree, after its fixture spans landed" — and then AC 1 asks for that verdict "on a pristine origin/main worktree". Measured on origin/main @ f01f5c4 it was 3 packs, not 2, and kind-story.md showed 7 violation ops rather than the single insert the card's whole diagnosis rests on. Both numbers became correct the moment #237 merged — which is the point: they were properties of a branch, quoted as properties of a base.
Acceptance criteria
notes.html#27's entry (or theplan-rules/limb that restates it) says that a #27 filing owes gate 4 in addition to therelates_to— and that when the found-in card and the consumed card are the SAME key, BOTH edges are written, becauserelates_todoes not discharge gate 4.- The same edit states the narrower trigger: a measurement taken on the filing run's own worktree is not a property of
origin/main, so a criterion quoting it names the branch it was measured on, or is written to read on the base it will actually run against. git grepshows the addition lands in the corpus tier that a card AUTHOR reads at file time, not only inrun.md's dispatch guard — the dispatch half already exists and already worked here (notes.html#210(b)); the missing half is authoring-side.- No rule text elsewhere is re-worded — the diff is an addition, and
python3 prompts/plan-rules/COMPRESSION.conserve.pyis quoted before and after if anyplan-rules/pack is touched.
Context refs
MOTIR-2969— the card whose edge was missing; its dispatch comment carries the full rung-2 evidence and the measuredorigin/mainverdict. Shipped as motir-meta PR #238.MOTIR-2966/ motir-meta PR #237 — the substrate. Open and mergeable at filing; merged10:23:58Z.notes.html#210 — logs both halves of the generic shape already; (b) the run half, (d) the authoring half. This card is the #27-specific generator that #210(d) does not name, not a re-log of #210, and writing that entry is THIS card's deliverable rather than PR #238's.plan-rules/core.mdgate 4 — the rule that was owed at file time.