Skip to content

[factory] Run Factory dispatch on a cloud node, not a laptop #268

Description

@khaliqgant

Goal

Factory dispatch runs on a cloud node, not on a laptop — so work expressed on any surface is picked up and executed without a human machine being awake.

This resumes chief/principals/khaliq/workstreams/factory-cloud-node-dispatch.md, which is status: active with owner: unassigned. It is the principal's stated priority 4 of four. It has never been started as a hosting change.

Read this before planning: the blocker is not hosting

The workstream's own conclusion, and the single most important line in it:

Moving the host first would only relocate the outage.

AGENT_RELAY_BIN means two different things in two repos:

  • in relay — the Rust broker binary
  • in relayfile's Go CLI — the agent-relay Node CLI

So Relayfile's automatic delegated-credential re-mint execs the Rust broker, fails, and reports a version error against a CLI that is already current:

relayfile status
  error: refresh delegated relayfile credentials: delegated relayfile credentials expired
  or revoked. Re-bootstrap with `agent-relay cloud login`; cloud re-mint fallback failed:
  agent-relay CLI >= 8.7.0 required with `agent-relay cloud session --help`
  (error: unrecognized subcommand 'cloud' / Usage: agent-relay-broker <COMMAND>)

Credential expiry is routine and self-healing by design. What makes it an outage is that the self-heal path can never run — it execs the wrong binary, then directs the operator to an upgrade that would change nothing.

Every relay-spawned agent inherits this variable, so it breaks Relayfile for the whole fleet, not one machine. Confirmed still set in the live environment as of 2026-08-15:

AGENT_RELAY_BIN = /Users/khaliqgant/.local/bin/agent-relay-broker

relayfile-sdk-auth-0814 owns the real fix, per the principal: use the SDK, do not shell out. Do not re-solve it here; coordinate.

What does NOT need changing — do not relitigate

The active dispatch contract is already correct. <chief>/factory.config.json has issueSource: "github", safety gated on the factory label plus [factory] title prefix, mergePolicy: "never", and a repo list spanning the org.

A cloud-node Factory needs its own resolved copy of factory.khaliq.config.json, with its exact path passed via --config on every command and runtime. Routing scope lives inside that file — never in file placement. A factory.config.json sitting in another repo is inert, not a fallback.

Prior art — do not re-derive

  • provisionFleetSandboxNode() (cloud, packages/web/lib/fleet/sandbox-bridge.ts:464) is a complete, tested function with zero production callers. It may be exactly the mechanism this needs; it was simply never wired to anything.
  • Architecture correction, stated directly by the principal 2026-08-13: Daytona should provision a fresh sandbox per agent, not reuse one long-lived box.
  • Therefore the existing "Done when" criteria in daytona-fleet-nodes.md are STALE. Phase 1's 24-hour continuous-uptime bar was designed for a persistent node and is the wrong criterion for an ephemeral-per-agent model. Rewrite the acceptance bar before trusting it.
  • A related consequence: the identity-reclaim gate (relay#1499, draft, unmerged) may be solving a problem that mostly disappears under fresh-per-agent — a brand-new sandbox has no stale identity to reclaim. Reason about it in writing rather than assuming either way.

Sequencing — three defects would follow Factory to the cloud unchanged

Moving hosts today buys "runs while the laptop sleeps" and inherits every current defect. Each of these reproduces identically on a cloud node:

blocker effect on a cloud Factory
relayfile-adapters#263 — issue _index.json omits labels Same 1,362-issue serial walk; readiness reconcile stalls identically
relayfile-cloud#155 — GitHub App writeback 403 PR publication fails the same way; work strands on branches
factory#267 — unbounded fail-open index fallback Same total dispatch outage with no operator-visible signal

Recommendation: land those three first, so the cloud node starts working rather than starting broken. This issue should plan for that ordering, not race it.

Scope

  1. Resolve the AGENT_RELAY_BIN collision — or confirm relayfile-sdk-auth-0814's SDK fix lands first and depend on it. State which.
  2. Provision a cloud node for Factory, using provisionFleetSandboxNode() if it fits rather than a parallel mechanism.
  3. Give it a resolved config copy and pass its exact path with --config.
  4. Rewrite the acceptance criteria for the fresh-sandbox-per-agent model before declaring anything done.
  5. Keep the laptop Factory able to run, so this is a migration rather than a cutover — two Factories dispatching the same issues would double-claim, so the handover needs an explicit stop/start order.

Definition of done

  • Factory dispatches an issue from a cloud node with the laptop asleep or offline, verified by an agent spawning and a PR opening.
  • The node survives credential expiry without operator intervention — that is the whole point of fixing the env-var collision, so exercise it rather than assuming.
  • Exactly one Factory is dispatching at any moment; prove the handover does not double-claim.
  • The acceptance bar is written for the ephemeral model, not inherited from the persistent-node one.

Verification — required, against the built CLI

Do not close this on a deployment succeeding.

node bin/factory.mjs status --config <resolved-path-on-node>
node bin/factory.mjs run-once --config <resolved-path-on-node> --dry-run

Then a real dispatch from the node with the laptop's Factory stopped, showing the agent spawn and the PR. Attach real output.

Constraints

  • Branch from origin/main. mergePolicy: never — open the PR and stop at review.
  • Do not restart the old daytona-fleet-proof-0811 sandbox; that is the model being moved away from.
  • PR publication is currently failing intermittently (relayfile-cloud#155). If this issue's PR does not publish, report it rather than working around it.
  • Related workstreams: factory-cloud-node-dispatch.md (this), daytona-fleet-nodes.md, cross-node-attach.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    factoryFactory automation triggerfactory:human-reviewFactory work is ready for human review.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions