Repository navigation
Description
Parent
Part of #154 (remote agent sessions). Phase 4. Design doc docs/designs/remote-workrooms.md: Constraints ("One provider-specific component is sanctioned on the far side"), Provider Decision, Phase 3 "A lifecycle shim", Distribution Plan ("Two artifacts ship to the far side"), OQ19 and OQ22, and Next Steps item 5 ("Apply the measured wakefulness policy through the far-side shim").
What to build
The agent already decides whether a workroom is busy or idle (#215, policy from OQ19). A sleeping Mac can tell a provider nothing, so a small per-driver shim on the box turns that verdict into the provider's own control-plane call, and a long job survives the provider's idle timer with the Mac asleep.
- The boxd shim. On boxd the in-VM
boxdCLI is self-scoped:boxd machine config set auto-hibernate.timeout 0targets only its own machine and needs no Workroom-managed credential (Phase 0 results, item 1). The shim holds auto-hibernate off while the agent says busy and restores it when idle. - The awake ceiling (OQ22). Advisory by default: a box busy past the ceiling is reported, not hibernated. With the ask-the-user setting on, an unanswered prompt stops the agent asserting busy, so the provider's own idle timer can hibernate the box. The shim never hibernates a box itself.
- The bootstrap pushes a set keyed by driver (agent, shim, supervisor unit), not the agent alone as Remote bootstrap: push the Linux agent on first connect, hand off on version mismatch #231 does today, and each driver's shim has its own Linux build target.
- Small enough to audit by reading. It dies with the instance, including on failure paths, and its credential scope is a declared driver trait.
Acceptance criteria
- On boxd, a job longer than the provider's idle window finishes with no client attached, where an unprotected control box is hibernated during the same wait.
- Once the workroom goes idle, the box hibernates within the provider's normal idle window.
- With the default policy, a box busy past the awake ceiling is reported in the app and stays awake; with ask mode on, an unanswered prompt lets it hibernate.
- Connecting a newer app pushes the updated shim with the agent, and connecting the same version pushes nothing.
- The shim holds no credential that outlives the instance.
Blocked by
#256 (boxd driver).
Filed by Claude Code at the owner's request, 2026-09-27.
Activity
fix: address the adversarial review of #252, and record it as built
joelmoss commentedon Oct 6, 2026
🤖 Left by Claude Code
Built as an agent heartbeat, not a shim (PR #353). The eng review's D5 replaced the far-side lifecycle shim: boxd's suspend and hibernate timers count only idle network time, so while its published verdict (after the awake ceiling) is BUSY,
wr-agentsends one 1-byte UDP datagram a minute to the box's IPv4 default gateway. An idle box, an unanswered ceiling prompt or a dead agent sends nothing, and the provider's own timer sleeps the box. There is noboxdCLI call, no timer change, no separate artifact to push, and no credential on the box. The agent is pushed by hash as before, so an older machine gets the heartbeat with its next agent update.Live acceptance on boxd (2026-10-06). Three fresh machines, 120 s timers, the same 6-minute job with no network use and nothing attached:
Against the acceptance criteria above:
HostDriverTraits.keepAwakeHoldsCredentialis false for every driver).Still open:
BoxdIntegrationTestsis a P1 TODO.I haven't closed this; your call.
feat(vcs): wr-agent keeps a busy box awake with a heartbeat (#257)
feat(macapp): hand remote agents the ceiling settings and show their …
docs: record #257 as built, and its review follow-ups
joelmoss commentedon Oct 6, 2026
🤖 Left by Claude Code
Shipped in #353 (merged as
b8809ab0). A busy remote box now stays awake with the Mac asleep and nothing attached, and it sleeps on the provider's own timer once it goes idle.What shipped
wr-agentsends one 1-byte UDP datagram to the IPv4 default gateway every 60 s. That replaces the planned far-side lifecycle shim: no boxd CLI, no timer changes, no credential on the box. An idle box, an unanswered ceiling prompt or a dead agent sends nothing.settingsrequest sets the ceiling, prompt timeout and ask mode, bounded to 30 s – 30 days. The agent keeps them in<socket>.settings, and they win over flags at the next start.statusalso reportskeep_awake(the last send and any error) andstalled(no tick for 30 s).HostDriverTraits.sleepsWhenIdle).Left as P1 TODOs (
TODOS.md)Put the acceptance run in
BoxdIntegrationTests. The live run above was done by hand, and nothing reruns it. It should be a gated case, so a boxd metering change or a new provider (exe.dev, exe.dev driver: the second real provider #259) gets the same proof.Remove the lifecycle shim's leftovers. That means the
<socket>.wakeverdict file,verdict_written,net_maskedandwr-wakeshimfrom the exclusion list. The verdict file is written on the service thread each tick, so a stalled disk can delay the next heartbeat and let a busy box sleep.Gate before wiring boxd into the app (boxd live-fork derivation, as an accelerator behind deriveFromBase #258, Phase 4 gate: the success criteria on two real providers #260).
None of these is exposed today: boxd isn't wired in, and containers never sleep.
P2 follow-ups (settings hardening, several Macs, a crashed wakefulness thread) are in
TODOS.mdtoo.refactor(vcs): remove what the never-built lifecycle shim left in the…
docs(remote-workrooms): mark #254, #255 and #257 as merged
fix(wr-agent): a wake after an unanswered prompt asks again (#356)
test(macapp): gated live boxd runs for the app's wiring and sleep (#356)
docs: record boxd in the app (#356) and drop the TODOs it closes
feat: the box decides its own wakefulness (#380)