You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was rewritten on 2026-08-15. The original description claimed dispatch state was "dropped before enqueue". That diagnosis was wrong. The corrected mechanism is below. If you began work against the original text, re-scope against this.
Summary
Dispatch is not atomic. A dispatch consists of at least three effects — spawn the implementer, spawn the reviewer, and record the claim on GitHub (the factory:in-progress label plus the dispatch comment). If the Factory process dies partway through, the dispatch is left half-committed: the implementer runs, the reviewer never spawns, and GitHub shows the issue as untouched.
A repair path exists, but it only runs at startup. So a half-committed dispatch stays broken for as long as Factory keeps running — indefinitely.
Evidence
Six issues were dispatched on 2026-08-14. They split cleanly by which Factory instance dispatched them:
Issue
Dispatched
Claim written to GitHub
Latency
factory#242
15:33:12Z
15:33:25Z
13s
factory#243
15:35:33Z
15:36:33Z
~60s
factory#244
~15:39Z
15:39:19Z
seconds
factory#240
~14:01Z
21:47:02Z
7h 45m
factory#241
~14:01Z
21:46:14Z
7h 45m
relayfile#419
~14:01Z
21:45:29Z
7h 44m
The discriminator is not load, repo, or issue shape. The first group was dispatched by a healthy instance and wrote back in seconds. The second group was dispatched at ~14:01Z by an instance that subsequently died. Their claims were never written.
For those 7¾ hours, all three were half-committed:
implementer running (ar-240-impl-factory et al., verified via ps)
no reviewer — ar-240-review-factory, ar-241-review-factory, ar-419-review-relayfile did not exist
no label, no dispatch comment on GitHub
At 21:45Z the daemon was upgraded 0.1.20 → 0.1.58 and restarted. Within ~2 minutes all three claims were written and all three missing reviewers spawned. The same restart also adopted two entirely unrelated stale issues (cloud#2185, cloud#2872), taking the fleet from 15 to 23 agents.
So the startup reconcile in 0.1.58 does repair this. Nothing repairs it while Factory is running.
Why the original diagnosis was wrong
relayfile writeback status reported pending: 0, failed: 0, dead-lettered: 0, which I read as "the write was dropped before enqueue". It was not: the write never reached relayfile's queue because it died inside Factory, between effects. Anyone debugging this should not expect evidence in relayfile's writeback subsystem.
Why it matters
The factory:in-progress label is the dispatch claim, and it fails closed. A half-committed dispatch is the worst of both states: an agent is consuming resources and editing a repo, while every observer — an operator, a human reading the issue, any tooling keyed on the label — sees unclaimed work. Re-triggering it duplicates the dispatch onto work already in flight.
During this incident that ambiguity produced a chain of confident wrong conclusions: that intake was stalled, that the event pipeline had stopped, and that creating an issue with the label pre-applied does not dispatch. All three were false, and all three followed from trusting GitHub state while agents were already running.
Asked-for behaviour
Make dispatch atomic, or explicitly recoverable. Either record a durable intent before spawning anything and drive it to completion, or treat a partial dispatch as a first-class state that is detected and repaired. A crash mid-dispatch must not leave a running agent with no claim.
Do not depend on a restart to repair it. The 0.1.58 startup reconcile is the right idea firing at the wrong time. A half-committed dispatch must be detected on a periodic sweep while the daemon runs.
Reconcile must cover all three effects, not just the label — a dispatch missing only its reviewer is still broken, and that is exactly what happened here for 7¾ hours.
Surface it. A dispatch that could not complete its claim must produce an error-level log naming the issue and the missing effect.
Verification — required, against the built CLI
Do not close this on green unit tests. Build the repo and exercise the real CLI.
npm ci && npm run build
node bin/factory.mjs --help # sanity
node bin/factory.mjs dispatch <ISSUE_KEY> --config <path>
node bin/factory.mjs status --config <path>
Prove all of the following, with real terminal output:
Kill Factory mid-dispatch (after implementer spawn, before the claim is written). On restart and on a running-daemon sweep, the claim is completed and the reviewer is spawned.
A dispatch whose GitHub write fails is retried and surfaced, not silently abandoned.
factory status reports in-flight work accurately.
Note on factory status: it currently returns "inFlight": [] while 23 agents are running. I have not established whether that is a reporting defect or simply a fresh CLI process holding no state — separate those two before treating it as a bug.
Context you need
The daemon in production was @agent-relay/factory@0.1.20 (installed Jul 17) while this repo was 0.1.57. It has since been upgraded to 0.1.58. All symptoms above were observed on 0.1.20. Confirm the defect still reproduces on a build of current main before writing a fix.
If it does not reproduce, say so and close the PR — that is a successful outcome, not a failure. Do not invent a change to justify the dispatch.
Branch from origin/main; the local checkout sits on codex/222-routed-pr-babysitter-v2 with unrelated WIP (b2ad725).
Summary
Dispatch is not atomic. A dispatch consists of at least three effects — spawn the implementer, spawn the reviewer, and record the claim on GitHub (the
factory:in-progresslabel plus the dispatch comment). If the Factory process dies partway through, the dispatch is left half-committed: the implementer runs, the reviewer never spawns, and GitHub shows the issue as untouched.A repair path exists, but it only runs at startup. So a half-committed dispatch stays broken for as long as Factory keeps running — indefinitely.
Evidence
Six issues were dispatched on 2026-08-14. They split cleanly by which Factory instance dispatched them:
factory#242factory#243factory#244factory#240factory#241relayfile#419The discriminator is not load, repo, or issue shape. The first group was dispatched by a healthy instance and wrote back in seconds. The second group was dispatched at ~14:01Z by an instance that subsequently died. Their claims were never written.
For those 7¾ hours, all three were half-committed:
ar-240-impl-factoryet al., verified viaps)ar-240-review-factory,ar-241-review-factory,ar-419-review-relayfiledid not existAt
21:45Zthe daemon was upgraded0.1.20 → 0.1.58and restarted. Within ~2 minutes all three claims were written and all three missing reviewers spawned. The same restart also adopted two entirely unrelated stale issues (cloud#2185,cloud#2872), taking the fleet from 15 to 23 agents.So the startup reconcile in
0.1.58does repair this. Nothing repairs it while Factory is running.Why the original diagnosis was wrong
relayfile writeback statusreportedpending: 0, failed: 0, dead-lettered: 0, which I read as "the write was dropped before enqueue". It was not: the write never reached relayfile's queue because it died inside Factory, between effects. Anyone debugging this should not expect evidence in relayfile's writeback subsystem.Why it matters
The
factory:in-progresslabel is the dispatch claim, and it fails closed. A half-committed dispatch is the worst of both states: an agent is consuming resources and editing a repo, while every observer — an operator, a human reading the issue, any tooling keyed on the label — sees unclaimed work. Re-triggering it duplicates the dispatch onto work already in flight.During this incident that ambiguity produced a chain of confident wrong conclusions: that intake was stalled, that the event pipeline had stopped, and that creating an issue with the label pre-applied does not dispatch. All three were false, and all three followed from trusting GitHub state while agents were already running.
Asked-for behaviour
0.1.58startup reconcile is the right idea firing at the wrong time. A half-committed dispatch must be detected on a periodic sweep while the daemon runs.Verification — required, against the built CLI
Do not close this on green unit tests. Build the repo and exercise the real CLI.
Prove all of the following, with real terminal output:
factory statusreports in-flight work accurately.Note on
factory status: it currently returns"inFlight": []while 23 agents are running. I have not established whether that is a reporting defect or simply a fresh CLI process holding no state — separate those two before treating it as a bug.Context you need
@agent-relay/factory@0.1.20(installed Jul 17) while this repo was0.1.57. It has since been upgraded to0.1.58. All symptoms above were observed on 0.1.20. Confirm the defect still reproduces on a build of current main before writing a fix.origin/main; the local checkout sits oncodex/222-routed-pr-babysitter-v2with unrelated WIP (b2ad725).mergePolicy: never— stop at review.