A marker left on the invoking session name by a killed create/resume was
pruned before herdr was asked, so a retry under the same name took it over
while the orphaned pane was still alive (and create's failure cleanup could
then kill it). It is now kept and blocks like any other orphan until its
row is registered for the attempt or herdr reports the session gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR #69 review round 3 (rebuttal overruled; codex r2 applied as written).
- A failed `agent list`, herdr's server_not_running included, is unknown and
keeps an orphaned marker; only a successful list without the name prunes.
- No probe floor: probes get only the time left until the wait deadline, so
MAM_ID_ORDER_WAIT_S=0 asks herdr nothing (unknown, kept) and the refusal
says so.
- The timeout message reports the last definite answer of this wait, so an
alive orphan whose final probe ran out of time still reads as alive.
- Tests follow: server_not_running and cap 0 keep the marker and refuse;
delayed-probe bound is the cap itself; probing tests use a small cap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PR #69 review round 2.
- The herdr probe is tri-state (present / absent / unknown) from a parsed
`_herdr agent list`: absent only when the list parses without the name or
herdr answers server_not_running. A failed, unparseable or timed-out lookup
is unknown and keeps the marker (codex P1: has-session's exit 1 meant both
"absent" and "lookup failed").
- Probes run with MAM_NO_AUTOSTART=1 so a check never starts a server (agy P2).
- Probe time is capped by max(deadline, start + PROBE_FLOOR_S=2 s), shared by
all markers, so a slow herdr cannot hold the wait or its lock past the cap
(codex P2); MAM_ID_ORDER_WAIT_S=0 still gets one bounded look.
- Tests: unknown probe keeps and refuses; delayed probe at caps 0/1/3 stays
within the bound; real probe via lib.sh mam_id_order_wait against mock herdr
(listed / unlisted / failing list / server_not_running).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A create/resume killed after spawning its pane but before registering its
row left a marker whose owner pid was dead; the next same-cwd waiter pruned
it on the pid alone and could start a second session that discovers the
same workspace conversation id (PR #69 review P1).
- Markers record the herdr server. A dead owner's marker is pruned only once
its row is registered for the attempt (running, newer epoch: the row
decides) or `_herdr has-session` reports the session gone; an unanswered
probe counts as alive. On timeout the kill-session command is printed.
- A live marker of another process for the waiter's own session name is kept
and blocks instead of being deleted; the waiter's own pid's markers go.
- Tests: orphan / registered / gone / same-session / missing pane pid cases,
and a create-level reproduction against mock herdr (fails before the fix).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- workspace_uuid.py: the unused sys import.
- stop_session.sh: the orphan CAPTURE_ID and the blank padding that kept
later line numbers; the inventory pins follow the move instead.
- lib.sh: capture_conversation_id, which nothing calls any more.
- resume SKILL.md: the flow names the session-id decision (session_ids.py),
not resolve_session_id.sh.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>