MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-3275

Planning bug: MOTIR-2853 read `ready: true` with two unexecutable preconditions — an external credential and a post-deployment soak window, neither expressible as an edge

Done
Description

Planner telemetry, filed into the planner-bug home. It blocks nothing and is in no sprint. The correction to the tree was submitted as plan cmt22mrq0001yi5ph29cvkod0 at the time of filing.

Discovered in

motir run MOTIR-2853 (2026-08-20, 21:58–22:10Z), which halted at run.md guard #4 before creating a worktree.

The defect — one shape, two instances

MOTIR-2853 presented as maximally startable: status: todo, readiness.ready: true, openBlockers: [], validate_work_itemvalid: true with a single advisory (a subsumption entry naming its own blocker's merged PR — correct, and not a warning about this). Its one blocked_by, MOTIR-2852, was genuinely done and genuinely deployed.

It was nevertheless unexecutable, for two reasons the graph has no way to hold:

  1. An external credential nobody planned. Acceptance criterion 1 requires GET https://console.neon.tech/api/v2/projects/{id}. No Neon API key is reachable from a run session — verified absent from the shell environment, the repos' .env files, flyctl secrets list for all three Fly apps, the running motir-core machine's own environment, and there is no neonctl installed. This is notes.html mistake #30 exactly: every external-service or secret/dashboard prerequisite a code subtask needs is its OWN planned subtask, wired via depends_on so it is visible at PLAN time and never ambushes a motir run. The remedy — a type: manual / executor: human card — is proposed on the plan above.

  2. A post-deployment soak window that no edge can express. Criterion 1 also requires "a window of at least six hours with no human traffic", and the card's own Precondition section correctly insists on deployment, not merge. Both are right. But readiness is computed from blocked_by edges alone, so the card flipped to ready: true the moment MOTIR-2852 went donehours before the measurement it asks for could exist. MOTIR-2852 merged 19:59:25Z and first deployed at v92 ≈ 20:23Z; the card was claimable immediately and the earliest legal window closes ≈ 02:23Z the next day.

The unifying statement is the useful one: readiness measures what the graph can hold, and this card's real preconditions were a credential and a duration. Neither is a work item reaching done, so both were invisible to every signal a dispatcher consults — which is why all of them agreed the card was startable.

Instance 2 is the novel half. Instance 1 has a named lesson and a known remedy; a post-deployment soak does not, and it will recur: MOTIR-3264 asks for the same shape against motir-gateway, and §21 invites re-measurement whenever an interval changes. Every card of the form "measure X in production after Y ships" has it.

A third, minor finding — the enumeration was wrong when written

The card's description says "motir-core registers eleven scheduled jobs." Measured on a ref (git grep at fca2c9f, the last main commit before the card's createdAt) there were 12 cron jobs across 11 files: the count read FILES, and ciRunnerFleet.ts declares two — the sweep and the reaper — which the card's own text names separately. Today it is 14 across 13 files, and the two additions (planTargetLockSweep 2026-08-18, abandonedPlanSweep 2026-08-19) postdate the card, so that part is genuine drift. Recorded because the off-by-one and the drift look identical in a diff and are opposite findings (run.md's count that comes back HIGHER rule).

Acceptance criteria

  1. plan-rules/ gains, or sharpens, a rule for a card whose precondition is a duration after a blocker DEPLOYS rather than a blocker reaching done — stating that the card must say so in its own words, name the earliest legal start, and not rely on readiness to hold it. Whether that also warrants a mechanism (a blocked_by onto a manual "confirm the soak window has elapsed" card, or something else) is decided here rather than left open.
  2. The mistake is recorded in motir-meta/notes.html with its lesson and prompt-hint, matching the existing .mistake markup and bumping the count. (Written by the filing run; this criterion records that it is owed, and closes on it being present.)
  3. The credential half is NOT re-litigated here — it is notes.html mistake #30 and its remedy is the card proposed on plan cmt22mrq0001yi5ph29cvkod0. Criterion 1 covers only the soak-window half, plus whatever the two share.
  4. The rule change names this card and MOTIR-2853 as its fixture, so the next reader can see the shape rather than only the rule.

Context refs

  • MOTIR-2853 — the card, and the run comment on it carrying the full evidence.
  • Plan cmt22mrq0001yi5ph29cvkod0 — the submitted correction (the manual credential card + the blockedByAdd edge).
  • motir-meta/prompts/run.md — guard #4, and the count that comes back HIGHER rule.
  • motir-meta/prompts/plan-rules/phase-deepen.md — the precondition-verification rule this is the run-time backstop for.
  • MOTIR-3264 — the next card that will hit the same soak-window shape.