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

(motir-core) Provision the worker process group on Fly — `fly scale count`, read back from the platform

Done
Description

⚠️ 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.ts defaults every job to Inngest, and MOTIR_POSTGRES_JOB_IDS reads null on 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_by this 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 started machine in the worker group — 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 story

It 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 done onto 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.patch carries body, sizing, repo pin and dependency edges, and NOT parentRef. 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-3425

After 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.toml already declares the worker process group (landed on parent/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 deploy reconciles process groups: a group declared in fly.toml with zero machines gets one created for it. Release v131 carried the worker entry and the machine appeared started with no fly scale count ever 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

  1. Deploy the branch carrying the [processes] worker entry (this happens via CI on merge).
  2. fly scale count worker=1 -a motir-core — one worker to start. The engine claims with FOR 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.
  3. Read the result back from the platform: fly status -a motir-core (or GET https://api.machines.dev/v1/apps/motir-core/machines) and confirm a machine exists in the worker group and is started.
  4. 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 worker process group does not exist yet. Verify with fly status -a motir-core before 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 app group (min_machines_running = 2, both started as of 2026-08-23). Adding a worker group should not disturb them — confirm it did not. — Confirmed: still 2, both started.
  • 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 worker process group and reads started, verified from the platform's own API — never from fly.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 app process 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 adds
  • docs/decisions/application-hosting.md Q6 — the precedent: machine count is an operator action owned by a card, never by fly.toml
  • /settings/workspace/jobs — where the proof appears (now MOTIR-3467's)