Skip to content

fix(down): preserve slot on ecluse down --keep-worktree - #32

Merged
hefgi merged 13 commits into
mainfrom
fix/stopped-slot-on-keep-worktree
Oct 2, 2026
Merged

hefgi merged 13 commits into
mainfrom
fix/stopped-slot-on-keep-worktree

Conversation

@hefgi

@hefgi hefgi commented Jul 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Bug: ecluse down --keep-worktree removed the session from state.json. On the next ecluse up from inside that worktree, slot allocation ran fresh and picked the lowest available slot (e.g. slot 1 instead of slot 3), changing all ports.
  • Fix: adds a Stopped SessionStatus. With --keep-worktree (and shutdown --keep-worktrees) the session stays in state as stopped, runtime fields cleared, slot reserved. ecluse up from the kept worktree resumes at the same slot; ports are re-probed at that slot.
  • env, status, shell, and sync reject stopped sessions with an actionable error; ls, flush, and shutdown handle the new status.
  • Stopped sessions hold their slot until the worktree is deleted. SlotsExhausted, the --keep-worktree(s) help, SKILL.md, and README now say so and point at ecluse down <slug> --delete-worktree.
  • Also: new_op_id is unique within a process, and a race test is de-flaked.
  • state.json files with stopped sessions can't be read by older ecluse versions (noted in CHANGELOG).

Test plan

  • Integration test reproducing the bug: 3 sessions, keep-down slot 3, free slot 1, bare ecluse up from the kept worktree resumes at slot 3 (fails on main, passes here)
  • Integration tests for the stopped lifecycle (keep/resume, delete-worktree, shutdown --keep-worktrees, rejected commands)
  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test (unit + integration)

hefgi added 13 commits October 2, 2026 15:56
Add a Stopped variant to SessionStatus for sessions whose services are
down but whose worktree is kept on disk. The entry stays in state so its
slot remains reserved. Adds find_session_mut and mark_stopped, which
clears runtime and provisioning fields while keeping the identity fields
(slug, slot, branch, worktree_path, mode).
Two op ids minted in the same process within the same nanosecond could
collide. Append a process-local atomic counter so ids are always
distinct, keeping pid and timestamp for readability.
down --keep-worktree and shutdown --keep-worktrees used to drop the
session from state, so the next up allocated a new slot and every port
changed. They now mark the session Stopped instead.

- up auto-detects a Stopped session (by slug or from inside the kept
  worktree) and resumes it at the same slot, re-probing ports
- down/shutdown/flush skip service teardown for Stopped sessions but still
  remove the worktree when it is not kept
- a failed teardown restores the entry without duplicating it and keeps a
  pre-existing Stopped status
- ls shows Stopped sessions as '<slug> (stopped)'
- the shutdown summary counts sessions kept as stopped
…e error

A Stopped session has no running services, so reading its env or status
would report ports nothing is listening on. ensure_session_settled now
rejects Stopped sessions and points to `ecluse up <slug>`.
mark_pending commits the state entry before the worktree is created, so
waiting only for the entry let down --delete-worktree run before the
worktree existed and fail teardown intermittently.
Integration tests for down --keep-worktree marking the session stopped
and resuming at the same slot, down --delete-worktree on a stopped
session, shutdown --keep-worktrees, and resuming a stopped session whose
worktree was deleted by hand.
Stopped sessions keep their slot, so a plain down --keep-worktree no
longer frees one. The message now names down --delete-worktree and
notes that stopped sessions in ecluse ls hold slots.
Tell agents to prefer --delete-worktree when a task is done, and how to
recover from SlotsExhausted when stopped sessions hold the slots.
Bring up three sessions, keep the third's worktree, fully tear down the
first, then run a bare up from inside the kept worktree. It must resume
at slot 3 rather than drift onto the freed slot 1. Fails on main.
@hefgi
hefgi force-pushed the fix/stopped-slot-on-keep-worktree branch from e27053c to 3c56d1e Compare October 2, 2026 14:57
@hefgi
hefgi merged commit 0467600 into main Oct 2, 2026
2 checks passed
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