Skip to content

Persistent remote agent: supervised serve, stdio relay and the container fixture #228

Closed

Description

@joelmoss

Parent

Part of #154 (remote agent sessions). Phase 3. Design doc docs/designs/remote-workrooms.md, Phase 3 "A stream is not persistence", and Next Steps item 4.

What to build

The far-side half of the persistent remote transport, proven against a local container reached over real ssh. No Swift in this milestone.

  • A stream is not persistence. wr-agent serve --stdio creates a connection-scoped session store and calls kill_all() on EOF or error. It stays as a transport test entry point, but it is not what production openStream reaches. Production relays into one supervised agent that owns the remote socket and the ptys, and every reconnect must reach that same owner, never a second store.
  • A stdio relay subcommand (name to decide, e.g. wr-agent relay --socket <path>). It copies bytes between stdin/stdout and the supervised agent's unix socket, and does nothing else. ssh host wr-agent relay … is then the ssh implementation of the driver contract's bidirectional byte stream. It does not start an agent: on the far side that is the supervisor's job, and a relay that self-spawned would recreate the idle-exit agent the remote host must not have.
  • A remote agent must survive with no client attached, because the busy/idle reports that feed the far-side lifecycle shim must keep flowing while the Mac sleeps. So the supervised serve runs with no idle exit. Local keeps today's spawn-on-connect, flock and idle self-exit unchanged (design doc: "Local needs no supervisor at all. DECIDED").
  • The supervisor is per driver. For the container fixture that is whatever starts serve at container boot (a systemd unit or an entrypoint), and it restarts the agent if it dies.
  • The container fixture is the cheapest real driver and becomes permanent CI for the remote path: a Linux container with sshd, the Linux wr-agent from Linux wr-agent as a published build artifact #227, a pinned host key, and BatchMode=yes.

Acceptance criteria

  • A relay subcommand bridges stdio to the supervised agent's socket, and it fails fast with a clear error when no agent is listening.
  • serve can run with no idle exit, and the fixture's supervisor starts it at boot and restarts it after a crash.
  • Integration test over real ssh into the container: open a session and start a long-running job, forcibly drop the ssh transport, leave the job running with no client, reconnect, and verify it is the same child pid and the terminal state is repainted (the design doc's Phase 3 acceptance).
  • The same test passes through the full multiplexed protocol (VCS, File, Status and Forward services answer through the relay), not only through pty frames.
  • The fixture runs in CI on ubuntu-latest.

Blocked by

#227 (the fixture runs the published Linux artifact).

Filed by Claude Code at the owner's request, 2026-09-24.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions