fix(launch): reclaim stopped clean-exit container slots on name claim#184
Merged
Conversation
Replace the blanket `list_managed_agent_names` scan in `claim_container_name` with per-candidate `inspect_container_state` checks. Stopped containers with exit 0 and no OOM flag are removed best-effort, then their slot (and the state dir containing gh credentials) is reclaimed. Running containers and crashed/OOM-killed containers are skipped: the latter are preserved so `jackin hardline` can restart them in place. Also adds a doc comment on the `docker run` block explaining why `--rm` is intentionally absent: crashed containers need to persist for `jackin hardline` crash recovery, and clean-exit removal is handled by the naming loop (which can inspect the exit code) rather than Docker auto-removal (which cannot). Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave
added a commit
that referenced
this pull request
Apr 26, 2026
Brings in main's fix(workspace) #185, fix(launch) #184, and a large documentation roadmap addition (#183 + several smaller PRs covering codebase readability, project structure gates, etc.). Adds the `isolation` field to MountConfig literals introduced by main in test fixtures inside `src/app/context.rs` and `src/workspace/resolve.rs` (2 + 3 sites, all `MountIsolation::Shared` since they're not testing isolation behavior). These literals predate this branch's `isolation`-field addition; main couldn't anticipate the new required field, so the merge picks them up unmodified and we backfill the field here. No conflicts in the merge itself. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com>
donbeave
added a commit
that referenced
this pull request
May 6, 2026
…#184) Replace the blanket `list_managed_agent_names` scan in `claim_container_name` with per-candidate `inspect_container_state` checks. Stopped containers with exit 0 and no OOM flag are removed best-effort, then their slot (and the state dir containing gh credentials) is reclaimed. Running containers and crashed/OOM-killed containers are skipped: the latter are preserved so `jackin hardline` can restart them in place. Also adds a doc comment on the `docker run` block explaining why `--rm` is intentionally absent: crashed containers need to persist for `jackin hardline` crash recovery, and clean-exit removal is handled by the naming loop (which can inspect the exit code) rather than Docker auto-removal (which cannot). Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com> Co-authored-by: Claude <noreply@anthropic.com>
donbeave
added a commit
that referenced
this pull request
May 7, 2026
…#184) Replace the blanket `list_managed_agent_names` scan in `claim_container_name` with per-candidate `inspect_container_state` checks. Stopped containers with exit 0 and no OOM flag are removed best-effort, then their slot (and the state dir containing gh credentials) is reclaimed. Running containers and crashed/OOM-killed containers are skipped: the latter are preserved so `jackin hardline` can restart them in place. Also adds a doc comment on the `docker run` block explaining why `--rm` is intentionally absent: crashed containers need to persist for `jackin hardline` crash recovery, and clean-exit removal is handled by the naming loop (which can inspect the exit code) rather than Docker auto-removal (which cannot). Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com> Co-authored-by: Codex <codex@openai.com>
donbeave
added a commit
that referenced
this pull request
May 7, 2026
…#184) Replace the blanket `list_managed_agent_names` scan in `claim_container_name` with per-candidate `inspect_container_state` checks. Stopped containers with exit 0 and no OOM flag are removed best-effort, then their slot (and the state dir containing gh credentials) is reclaimed. Running containers and crashed/OOM-killed containers are skipped: the latter are preserved so `jackin hardline` can restart them in place. Also adds a doc comment on the `docker run` block explaining why `--rm` is intentionally absent: crashed containers need to persist for `jackin hardline` crash recovery, and clean-exit removal is handled by the naming loop (which can inspect the exit code) rather than Docker auto-removal (which cannot). Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com> Co-authored-by: Claude <noreply@anthropic.com>
donbeave
added a commit
that referenced
this pull request
May 7, 2026
…#184) Replace the blanket `list_managed_agent_names` scan in `claim_container_name` with per-candidate `inspect_container_state` checks. Stopped containers with exit 0 and no OOM flag are removed best-effort, then their slot (and the state dir containing gh credentials) is reclaimed. Running containers and crashed/OOM-killed containers are skipped: the latter are preserved so `jackin hardline` can restart them in place. Also adds a doc comment on the `docker run` block explaining why `--rm` is intentionally absent: crashed containers need to persist for `jackin hardline` crash recovery, and clean-exit removal is handled by the naming loop (which can inspect the exit code) rather than Docker auto-removal (which cannot). Signed-off-by: Alexey Zhokhov <alexey@zhokhov.com> Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
claim_container_namecalledlist_managed_agent_names, which runsdocker ps -a— including stopped containers. Becausedocker runintentionally omits--rm(see below), containers persist after exit as stopped entries. These two facts combined to permanently block every name slot that had ever been used: the nextjackin loadclimbed toclone-2,clone-3, etc., each with a brand-new empty state directory. The user had to re-authenticate withgh auth loginon every reload.Why
--rmwas not the fixAdding
--rmtodocker runwould auto-remove containers on exit, including crashed ones. That would:jackin hardlinecrash-restart impossible — it restarts the existing stopped container in place; if Docker already removed it, there is nothing to restart--rmis intentionally absent. The doc comment added to thedocker runblock in this PR makes that explicit.The three-way decision
Instead of a blanket scan,
claim_container_namenow callsinspect_container_stateper candidate:docker rmbest-effort, then reclaim the slotjackin hardlineterritoryWhy state survives
The state directory (
~/.jackin/data/<name>/) lives on disk independently of the Docker container. It holds.config/gh/with the gh credentials. Reclaiming a slot mounts the same directory into the new container — credentials are intact, no re-auth needed.The name-to-state-dir invariant
Each unique container name maps permanently to one state directory. This fix preserves that invariant exactly: it does not reassign names or move state directories. It only allows a slot to be reused when the previous container exited cleanly and has been removed.
Tests added
Five new unit tests for
claim_container_name:docker rmclone-1) claimeddocker rmissued, same slot reclaimed🤖 Generated with Claude Code