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-3854

Planning bug: an acceptance criterion quoted durations from a run where the jobs were SKIPPED — a skipped job reports zero, not an absence, and the ceiling it implied would have failed a green run

To Do
Description

Type · chore (planner corpus) · Parent · MOTIR-1465, the planner-bug home · Discovered in · the run of MOTIR-3768, 2026-08-28 (PR moooon-B-V/motir-core#2443) · Repo · motir-meta

What the plan got wrong

MOTIR-3768's acceptance criterion 3 handed the runner two figures as evidence:

"(sandbox-images legs ran 0.1–5.8 min and runner-image 1.3 min on run 33167406878 …)"

On run 33167406878 both of those jobs were skipped.

$ gh api repos/moooon-B-V/motir-core/actions/runs/33167406878/jobs \
    -q '.jobs[] | select(.name|test("Sandbox|Runner image")) | "\(.name) \(.conclusion)"'
Runner image     skipped
Sandbox images   skipped

ci.yml's sandbox and runner-image jobs are path-gated on needs.changes.outputs.images, and MOTIR-3768's own description says so, two sections above the criterion that then quotes durations from a run that did not touch the image inputs.

Why it is a planning bug and not a typo

Following the criterion exactly produces a ceiling that fails a healthy run — which is the one outcome the card's own Out of scope section forbids ("no ceiling here may be tight enough to fail a slow-but-healthy run").

  • The card's stated upper bound for sandbox-profiles is 5.8 min. Applying the ~3× headroom the card asks for gives 18.
  • The slowest successful sandbox-profiles leg on record is 16.68 min (aider, tier 2, run 33214411817, conclusion: success).
  • 18 clears 16.68 by 1.08×. The next slow-but-healthy aider build goes red.

So the defect is not that a number was stale — it is that a false number was more dangerous than no number, because it looked like the measurement the criterion demanded and suppressed the re-measurement that would have caught it.

Root cause — the mechanism, not the carelessness

A skipped GitHub Actions job is not absent from /jobs. It is returned with conclusion: "skipped" and started_at / completed_at that yield a duration of 0.0 minutes (or null timestamps, depending on the shape). An aggregation that filters on nothing — or on status: completed, which a skipped job satisfies — silently folds zeros into its range, and a range whose floor is 0.1 reads as "a fast job" rather than "a job that did not run".

That is exactly what produced 0.1–5.8: the 0.1 is skipped legs, and the 5.8 is one of the few runs where the filter happened to let them through. run.md's existing rules do not reach this. Re-measure on a REF secures the ref; re-measure the PREDICATE secures the population. This is a third axis: the ref is right, the population is right, and the individual OBSERVATIONS are not observations.

The rule change this earns

motir-meta/prompts/run.md, beside A bug card's FIRST deliverable is the REPRODUCTION → the enumeration/predicate limb (steps 3–4 and the RE-MEASURE THE PREDICATE block). A new sibling limb, roughly:

⚠️ AND CHECK THAT EACH MEASUREMENT IS A MEASUREMENT — a skipped, cancelled or failed unit reports a NUMBER, not an absence. Where a card quotes an observed duration, size, count or rate taken from a platform, the reading is only evidence if the unit it came from actually DID the work. A skipped CI job returns conclusion: "skipped" with a ~0 duration; a cancelled one returns a partial; a failed one returns a duration that measures the failure. All three survive a status: completed filter and all three drag a range's floor toward zero. Filter on the SUCCESS predicate, and say in the card which one you usedselect(.conclusion=="success"), not select(.status=="completed"). A range whose low end is implausibly small for the work described is the tell, and it is the direction that makes a derived ceiling too TIGHT, so it fails green runs rather than missing red ones.

Acceptance criteria

  1. motir-meta/prompts/run.md carries the limb above, beside the existing enumeration/predicate rules, with this card's fixture (the 18-vs-16.68 arithmetic) as its evidence.
  2. The limb states the concrete gh api … select(.conclusion=="success") form, because the failure was a filter, not an attitude.
  3. A LESSON is written for the same takeaway, scope decided by the strip-the-identifiers test and stated in the PR body.
  4. ORDERING — every criterion reads on this card's own branch. Nothing depends on MOTIR-3768 merging.

Context refs

  • MOTIR-3768 — the card carrying the falsified criterion; its AC 3 is amended on the record.
  • moooon-B-V/motir-core#2443 — the run that found it; its PR body carries the full correction and the re-measured table.
  • motir-meta/prompts/run.md — the enumeration and predicate limbs this sits beside.

Resolution: open.