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
MOTIR-3768's acceptance criterion 3 handed the runner two figures as evidence:
"(
sandbox-imageslegs ran 0.1–5.8 min andrunner-image1.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.
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").
sandbox-profiles is 5.8 min. Applying the ~3× headroom the card asks for gives 18.sandbox-profiles leg on record is 16.68 min (aider, tier 2, run 33214411817, conclusion: success).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.
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.
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 astatus: completedfilter and all three drag a range's floor toward zero. Filter on the SUCCESS predicate, and say in the card which one you used —select(.conclusion=="success"), notselect(.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.
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.gh api … select(.conclusion=="success") form, because the failure was a filter, not an attitude.motir-meta/prompts/run.md — the enumeration and predicate limbs this sits beside.Resolution: open.