(motir-core) Provision the worker process group on Fly — `fly scale count`, read back from the platform
⚠️ AMENDED 2026-08-25 (second amendment) — CRITERION 2 IS REMOVED FROM THIS CARD
"The pilot job's runs appear in the operator dashboard, proving the worker is claiming" is struck, and MOTIR-3467 now owns it. The criterion is left standing in the list below with a marker, so the correction is visible as a correction rather than as a criterion that quietly disappeared.
Why it was never this card's to meet. This card provisions a process group. Its title, its steps and its other three criteria are all one thing: bring a machine up and read it back from the platform. Criterion 2 asserts something provisioning cannot cause — it assumed a job would already be routed to the engine, and none ever was.
lib/jobs/engine/cutover.tsdefaults every job to Inngest, andMOTIR_POSTGRES_JOB_IDSreadsnullon the running worker machine (verified 2026-08-25 19:27Z from inside the process). So the worker is up, correct, and claiming an empty queue by design, and no action inside this card's scope could change that.And leaving it here DEADLOCKED the pair. MOTIR-3467 is
blocked_bythis card, while this card's only outstanding criterion could be satisfied only by MOTIR-3467 — a cycle. It is the same shape as MOTIR-3429, the planning bug that re-parented this card out of MOTIR-3414 in the first place: work that cannot start until a card closes, and a card that cannot close until that work happens. Recognised before it cost anything, and cut here.The substantive precondition MOTIR-3467 actually needs from this card — a
startedmachine in theworkergroup — is met and verified from the platform's own API.Nothing else below is changed. The three remaining criteria are all met; see the platform read-back comment of 2026-08-25 19:27Z for the evidence.
⚠️ AMENDED by
motir run MOTIR-3414(2026-08-23) — this card must LEAVE the storyIt is a POST-DEPLOY child sitting inside the container it exists to outlive. Step 1 below says so outright: "Deploy the branch carrying the
[processes]worker entry (this happens via CI on merge)". So it cannot begin until MOTIR-3414's pull request has merged — while the parent-run rule opens that pull request only once every child has landed. The story deadlocks on itself.And opening the PR anyway would be worse, not a workaround. Completing a container CASCADES
doneonto every child, from any status, by a direct write no interactive edge allows. This card would close green and unverified with no machine ever scaled — the MOTIR-3010 shape exactly (planning bug MOTIR-3153), and the reason the runbook's own remedy is to re-parent such a child OUT of the container before the PR is opened.⚠️ THE RE-PARENT IS THE APPROVER'S TO MAKE — a plan cannot express it.
add_plan_items'modify.patchcarries body, sizing, repo pin and dependency edges, and NOTparentRef. So the two commands are:move_to_parent MOTIR-3425 → MOTIR-3413 (the epic; a sibling of the story, not its child) link_work_items MOTIR-3414 blocks MOTIR-3425After that the story can complete on its own children, its merge deploys the
[processes]entry, and this card runs against a deployment that exists — which is the only state in which its own acceptance criteria are checkable.What it is waiting for, precisely:
fly.tomlalready declares theworkerprocess group (landed onparent/MOTIR-3414-postgres-job-engine), and the Dockerfile already stages the worker bundle at/app/worker/worker.mjs. Nothing further is needed from the story — only the merge and the deploy that follows it.Planning bug: MOTIR-3429. Amended on the record; no step or criterion below is changed.
Bring the worker process group up on Fly. No PR — this is an operator action, marked done on Yue's confirmation.
The worker subtask declares the [processes] entry in fly.toml; declaring a process group does not create machines for it. Fly requires an explicit scale command, exactly as MOTIR-2386 did for the app group when motir-core moved off Vercel.
⚠️ The paragraph above is FALSE for a NEW process group, measured 2026-08-25.
flyctl deployreconciles process groups: a group declared infly.tomlwith zero machines gets one created for it. Release v131 carried theworkerentry and the machine appearedstartedwith nofly scale countever run. MOTIR-2386's precedent was about RAISING the count of an existing group (app, 1 → 2), which is a different operation. Growing a group is an operator action; introducing one is not. Step 2 below was therefore never executed, and the card's own verified-no-change exit is what discharged it.
The steps
- Deploy the branch carrying the
[processes]worker entry (this happens via CI on merge). fly scale count worker=1 -a motir-core— one worker to start. The engine claims withFOR UPDATE SKIP LOCKED, so raising this later is safe by construction, but one is enough to prove the pilot job and keeps the first production exposure small. — NOT RUN; not needed. See the note above.- Read the result back from the platform:
fly status -a motir-core(orGET https://api.machines.dev/v1/apps/motir-core/machines) and confirm a machine exists in theworkergroup and isstarted. - Confirm the worker is claiming: a pilot-job run row appears in
/settings/workspace/jobs. — MOVED to MOTIR-3467.
Hypotheses to verify rather than assume
This card describes a system outside the agent's reach, so its claims about that system's current state are unverifiable at authoring time and are written as hypotheses with a verified-no-change exit:
- The
workerprocess group does not exist yet. Verify withfly status -a motir-corebefore scaling; if it is already running at the intended count, the card is done and says so. — THIS EXIT FIRED. - The app currently runs 2 machines in the
appgroup (min_machines_running = 2, bothstartedas of 2026-08-23). Adding a worker group should not disturb them — confirm it did not. — Confirmed: still 2, bothstarted. - Cost: one additional small machine. If the machine size the process group inherits is larger than intended, stop and re-scope rather than absorbing the spend silently. — Held:
shared-cpu-1x/1 GB, the measured size, not the inherited one.
Acceptance criteria
- A machine exists in the
workerprocess group and readsstarted, verified from the platform's own API — never fromfly.toml, which is a claim about the deployment rather than a reading of it. The pilot job's runs appear in the operator dashboard, proving the worker is claiming.— STRUCK 2026-08-25; owned by MOTIR-3467. See the second amendment at the top for why it was never achievable inside this card's scope, and why leaving it here deadlocked the pair.- The
appprocess group is unaffected and still at its previous count. - The machine size and the resulting cost are recorded on this card.
Context refs
fly.toml— the[processes]entry the worker subtask addsdocs/decisions/application-hosting.mdQ6 — the precedent: machine count is an operator action owned by a card, never byfly.toml/settings/workspace/jobs— where the proof appears (now MOTIR-3467's)