The Deploy to Fly job's last step asserts the machine count against Fly's API. It reads vars.FLY_EXPECTED_MACHINE_COUNT, which MOTIR-2408 set to 2 when the pool WAS two app machines. MOTIR-3425 then created the worker process group — two machines, 8576143c4ee538 and the † standby 891e16eb021e28, both created 2026-08-25T19:24Z — and nothing updated the variable.
Run 32963471131 (c203f815, trunk), job 98166691997:
4 success Build the image and release it
5 success Assert the release answers
6 success Register the deployed functions with Inngest
7 failure Assert the machine count, read from Fly's API
machine_count=4, expected=2
##[error]motir-core runs 4 machine(s); 2 expected. Either the pool changed
under us, or FLY_EXPECTED_MACHINE_COUNT is stale — read the platform before
changing the variable.
The deploy SUCCEEDED. Step 4 built and released, step 5 asserted the release answers, step 6 synced Inngest. Production went to v147, all four machines, and the three pending migrations applied at 11:55:59Z — including 20260825220000_job_queue_idempotency_key, which is MOTIR-3415's. Only the post-hoc guard failed.
So the check is red, CI complete is red, and the trunk's red says nothing about whether the trunk is deployed — the two have come apart. Anyone reading the check to answer "did it ship?" gets the wrong answer, in the direction that costs the most: they conclude it did NOT ship and go looking for why.
The worker machines existed from 2026-08-25T19:24Z, so the guard has been wrong ever since. It never fired because every main run between then and now failed EARLIER — Playwright E2E (bulk-5) — which SKIPS the deploy job (needs:). Confirmed on runs 32946540460, 32949186960, 32951721187: all Deploy to Fly -> skipped. MOTIR-3563 cleared bulk-5, the deploy job ran for the first time in 16 hours, and the latent guard fired immediately.
Two defects stacked, and the first one masked the second. That is also why origin/main sat 7 commits ahead of production without anyone reading it as an incident.
The repo variable was set to 4 and read back:
FLY_EXPECTED_MACHINE_COUNT=4 updated=2026-08-26T12:02:29Z
That unblocks the next deploy. It does not fix the bug — it re-arms a guard that will drift again the next time anyone scales a process group, which is exactly what happened here.
The guard's premise is wrong, not its number. A count is the wrong assertion for an app whose pool is now a SUM over process groups, each scaled independently for its own reasons. The guard should assert the shape it actually cares about — per-group counts derived from fly.toml's [processes] and the min_machines_running policy — so that adding a group updates the expectation by construction rather than by someone remembering a repo variable.
At minimum, if the count survives as a count: it must be derived, not stored, and fly.toml's [processes] block must carry a ⚠️ pointing at it — the same treatment that block already gives http_service.processes.
Deploy to Fly run on motir-core completes green with the pool at 4 machines across 2 process groups — read from the run, not asserted locally.fly.toml's [processes] block names the deploy guard among the things a new group changes..github/workflows/ci.yml:1275-1299 — the guard, its comment naming MOTIR-2408, and vars.FLY_EXPECTED_MACHINE_COUNTfly.toml [processes] — the block whose ⚠️ already warns that declaring a group does not create a machine; it should warn about this too2 came from