fix(issue-17): resume closes herdr 0.9.3's placeholder for a removed directory
With the cwd premise fixed, test_b still failed on herdr 0.9.3: a pane whose
saved directory is gone is restored as a placeholder - `restore_error`
"Saved directory is unavailable...", no process - and `pane process-info`
answers pane_not_found. close_restored_shells raised on it and exited 1
before looking at the other panes, so the resumed session's removed-worktree
pane (the case #45 closes on herdr 0.9.1, where it is a shell in $HOME) was
left behind.
Such a pane has nothing running, so it now meets condition 4. Only that
exact answer counts - restore_error set AND pane_not_found; any other
process-info failure still stops the run with exit 1 as before.
Tests: test_issue45_restore.py passes on herdr 0.9.3 (5/5). Unit tests with a
stub herdr: the placeholder is closed (fails at 56d0bfd); pane_not_found
without restore_error, or restore_error with another error, still raises.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HCGpJXhSZasJLU38ksDghe
This commit is contained in:
1 parent
25c99704f2
commit
f19f94099f
2 files changed
+59
-3
No files matched your search
@@ -3,7 +3,8 @@
|
||||
With restore-on-restart off (lib_py/herdr_config.py) a restarted MAM server
|
||||
still brings every saved pane back - as an empty shell in its old cwd. When
|
||||
that directory is gone, herdr 0.9.1 opens the shell in $HOME and herdr 0.9.3
|
||||
keeps the old path; nothing below looks at the cwd. A pane keeps the
|
||||
keeps the old path with no shell in it (see 4.); nothing below looks at the
|
||||
cwd. A pane keeps the
|
||||
`agent_session` its agent
|
||||
reported before the server died. resume_session.sh calls this once, right
|
||||
before it spawns, with the id it is about to resume; a pane is closed only when
|
||||
@@ -13,7 +14,10 @@ all of these hold:
|
||||
2. herdr sees no live agent in it;
|
||||
3. its agent_session value is that id - so a user's pane, another session's
|
||||
pane and a freshly split pane (no agent_session yet) are never candidates;
|
||||
4. its foreground process is the shell itself (nothing running in it).
|
||||
4. its foreground process is the shell itself (nothing running in it) - or
|
||||
it has no process at all: herdr 0.9.3 restores a pane whose directory is
|
||||
gone as a placeholder (`restore_error` set) that `pane process-info`
|
||||
reports as pane_not_found.
|
||||
|
||||
The registry is not consulted: a session whose server died stays `running`
|
||||
there, so "running" cannot tell a live pane from a restored one.
|
||||
@@ -51,6 +55,16 @@ def _shell_in_foreground(herdr: str, session: str, pane_id: str) -> bool:
|
||||
return _is_pid(shell) and _is_pid(fg) and fg == shell
|
||||
|
||||
|
||||
def _nothing_running(herdr: str, session: str, pane: dict) -> bool:
|
||||
try:
|
||||
return _shell_in_foreground(herdr, session, pane["pane_id"])
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Only herdr's own placeholder counts: any other failure still stops the run.
|
||||
if pane.get("restore_error") and "pane_not_found" in (e.stderr or "") + (e.stdout or ""):
|
||||
return True
|
||||
raise
|
||||
|
||||
|
||||
def _is_pid(v) -> bool:
|
||||
return isinstance(v, int) and not isinstance(v, bool) and v > 0
|
||||
|
||||
@@ -68,7 +82,7 @@ def close_restored_shells(session_id: str, herdr: str = "herdr",
|
||||
continue
|
||||
if (p.get("agent_session") or {}).get("value") != session_id:
|
||||
continue
|
||||
if not _shell_in_foreground(herdr, session, pane_id):
|
||||
if not _nothing_running(herdr, session, p):
|
||||
continue
|
||||
_herdr(herdr, session, "pane", "close", pane_id)
|
||||
print(f"closed restored pane {pane_id} (cwd={p.get('cwd', '')}, agent_session={session_id})",
|
||||
|
||||
Reference in new issue
Block a user