Skip to content

feat(agent-mux): tear down docker when a cmux workspace closes - #32

Open
mhardingjones-lupa wants to merge 9 commits into
mainfrom
docker-cleanup-on-close
Open

feat(agent-mux): tear down docker when a cmux workspace closes#32
mhardingjones-lupa wants to merge 9 commits into
mainfrom
docker-cleanup-on-close

Conversation

@mhardingjones-lupa

Copy link
Copy Markdown
Collaborator

What

Automatically tears down a worktree's docker compose stack when its cmux workspace is closed, and re-ups it on reattach. Closing a workspace previously left containers running indefinitely (observed: 23 running, several idle 20–45h) because closing a cmux tab only detaches the tmux session — neither the session-closed hook nor docker-start.sh's Ctrl+C teardown fires.

How

  • Generalises the existing singleton daemon dev-tmux-titled.sh — each ~15s tick it now also tails cmux's ~/.cmuxterm/events.jsonl for workspace.closed events (non-blocking file read, no socket auth needed) and cleans up.
  • All logic lives in a new sourceable lib dev-close-cleanup.sh (unit-tested with stubs + fixtures, 24 asserts).
  • dev.sh writes a workspace_id → worktree registry (on create + reattach) and re-ups torn-down docker on reattach.

Key behaviours

  • docker compose down only — never --volumes (data preserved; reopening re-ups fast).
  • tmux session kept alive on close (docker-only cleanup); reattach reattaches the live agent and re-ups docker.
  • Project discovered from the container's working_dir label, not the worktree basename (handles branch-named projects, e.g. eng-7925-3 → project matt-eng-7925-2-batches-at-conversion).
  • Bulk-close guard with one-tick debounce: a cmux quit (many workspaces closing together, even split across tick boundaries) accumulates to ≥3 and is skipped — only deliberate individual closes tear down.
  • Safety rails: only worktrees under ~/workspace; explicit denylist for lupa-proxy / supabase_* / buildx_buildkit_*; collision-free marker keys (full-path hash) for case-insensitive FS + nested worktrees; no event-history replay (boot-aware cursor).

Testing

agent-mux/tests/test-close-cleanup.sh — 24 asserts, failed 0. Reviewed per-task and via a whole-branch review; the critical marker-collision bug, the bulk-guard tick-split gap, and an infra-denylist hardening were caught in review and fixed.

🤖 Generated with Claude Code

mhardingjones-lupa and others added 9 commits July 2, 2026 16:50
Previously, the marker was written unconditionally even when the `docker compose down`
command failed (the failure was suppressed by `|| true`). Now the marker is only written
inside an `if` guard that ensures the teardown succeeded.

Regression test added: verifies that when cd into the docker directory fails (missing
directory), no marker is written.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant