Add ward agent <name> headless <issue> (detached) + fix detached asset-cleanup race #125

Closed
opened 2026-06-18 00:36:58 +00:00 by coilysiren · 0 comments
Owner

ward agent <name> headless <issue> - detached, fire-and-forget

Follows #123 (the work surface). Adds a sibling headless surface so an issue can be dispatched into a container AFK:

ward agent claude headless coilyco-flight-deck/ward#98
  • Always detaches (docker run -d); no --detach flag (implied).
  • Runs the in-container agent in print mode (claude -p) via a new WARD_HEADLESS=1 env the entrypoint reads, so it works to completion non-interactively, then exits into the reaper. Read progress with docker logs / ward container exec.
  • Mirrors the ward dispatch interactive vs headless split, but in-container.

Bundled bugfix: detached asset-cleanup race

ward container up --detach (and the new headless path) were broken: docker run -d returns immediately, then defer cleanupAssets() deleted the host tmp dir bind-mounted as /opt/ward, so the container's entrypoint vanished mid-startup (entrypoint.sh: No such file or directory). Latent because no detached container had been run with the daemon up (unit tests never hit it).

Fix: detached runs leave their asset dir for a TTL-based sweep (sweepStaleContainerAssets, 1h) instead of deleting it on return; attached runs still clean up on exit. Verified live: detached codex run now completes the full entrypoint.

Known gap (not this issue): #108

The in-container reaper backstop still can't re-exec ward (sandbox EPERMs in the container's restricted namespace) - tracked in #108. Happy path is unaffected (the agent self-pushes via bare git per doctrine); only residual uncommitted work isn't auto-salvaged. Documented in docs/agent.md.

Done

cmd/ward/agent.go (work+headless surfaces), WARD_HEADLESS threaded through upPlan/entrypoint, detached-cleanup sweep, tests, docs/agent.md.

## `ward agent <name> headless <issue>` - detached, fire-and-forget Follows #123 (the `work` surface). Adds a sibling `headless` surface so an issue can be dispatched into a container AFK: ``` ward agent claude headless coilyco-flight-deck/ward#98 ``` - Always detaches (`docker run -d`); no `--detach` flag (implied). - Runs the in-container agent in print mode (`claude -p`) via a new `WARD_HEADLESS=1` env the entrypoint reads, so it works to completion non-interactively, then exits into the reaper. Read progress with `docker logs` / `ward container exec`. - Mirrors the `ward dispatch interactive` vs `headless` split, but in-container. ### Bundled bugfix: detached asset-cleanup race `ward container up --detach` (and the new headless path) were broken: `docker run -d` returns immediately, then `defer cleanupAssets()` deleted the host tmp dir bind-mounted as `/opt/ward`, so the container's entrypoint vanished mid-startup (`entrypoint.sh: No such file or directory`). Latent because no detached container had been run with the daemon up (unit tests never hit it). Fix: detached runs leave their asset dir for a TTL-based sweep (`sweepStaleContainerAssets`, 1h) instead of deleting it on return; attached runs still clean up on exit. Verified live: detached codex run now completes the full entrypoint. ### Known gap (not this issue): #108 The in-container reaper backstop still can't re-exec ward (sandbox EPERMs in the container's restricted namespace) - tracked in #108. Happy path is unaffected (the agent self-pushes via bare git per doctrine); only *residual* uncommitted work isn't auto-salvaged. Documented in docs/agent.md. ### Done `cmd/ward/agent.go` (work+headless surfaces), `WARD_HEADLESS` threaded through `upPlan`/entrypoint, detached-cleanup sweep, tests, docs/agent.md.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#125
No description provided.