fix(issue-45): MAM herdr servers start with restore-on-restart off; resume closes its own restored empty shell (v4.8.5) #48

Merged
Godopu merged 14 commits from fix/issue-45 into main 2026-10-05 09:56:40 +00:00
14 Commits
Author SHA1 Message Date
GodopuandClaude Opus 5.5 bf8a583afb docs(v4.8.5): archive PR #48 reviews (three rounds) and record the merge-workspace review
PR #48 already carries the 4.8.5 lockstep bump. Merge-workspace review:
round 1 (@35935f9) claude agy grok NOT PASS (test portability: tomllib on
Python 3.9, /proc and /tmp on macOS), codex no verdict (model at capacity,
budget spent); fixed in 36f0b8d and e8d9151. Round 2 (@e8d9151) codex NOT
PASS (unrunnable config check passed an unchecked merge, odd pids closed a
pane, nan dropped the user's settings); fixed in ab93776. Round 3
(@ab93776) 4/4 PASS. Full suite at ab93776 on macOS / Python 3.9: 1456
passed / 0 failed / 38 skipped. Reports and the round-3 identity sidecars
go to .agents/reports/<session>/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-05 18:56:38 +09:00
GodopuandClaude Opus 5.5 ab93776d6d fix(issue-45): review round 2 - an unrunnable config check is not a pass, odd pids never close a pane, nan does not drop settings
codex round 2 (PR #48).

- R1: when `herdr config check` could not run (timeout, OSError), the
  merged config was handed to the server as checked. A merge with a schema
  error makes herdr drop the whole file, restore back on - the #45 failure.
  The merged body is no longer used unchecked: _write_checked falls to the
  fixed MINIMAL config with a warning. When the check cannot run on MINIMAL
  either, MINIMAL is still used (with its own warning) rather than no
  config: returning none would leave restore on, and MINIMAL is a fixed
  two-line file the real-herdr test accepts. Unknown non-zero exits stay as
  they were - herdr exits non-zero for harmless warnings (an unknown
  section) that do not drop the file.
- R2: _shell_in_foreground compared shell_pid and the foreground group with
  ==, so 0/0, False/False, ""/"" or -1/-1 closed the pane. Both must now be
  positive ints (bool excluded) before they are compared.
- R3: the re-parse check used ==, and nan != nan, so a valid TOML nan threw
  away every other user setting even on Python 3.11. _same_doc compares
  documents recursively with nan equal to nan.

Tests: R1 (timeout, OSError) and R3 (top-level, array, nested nan) in
test_issue45_herdr_config.py; R2 in the new tests/test_issue45_restore_unit.py
(a herdr stub: zero, false, empty, negative, null, string, true, float;
missing info; a real shell closed; a busy pane kept). On the previous code
12 of them fail. Python 3.11: 67 passed; Python 3.9: 33 passed / 34 skipped
(tomllib-only). Real-herdr restore tests and related files on 3.9: 197
passed / 1 skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-05 17:50:15 +09:00
GodopuandClaude Opus 5.5 e8d9151226 test(issue-45): review - the real-server tests run on macOS, and the bootstrap config check follows the bootstrap's python3
claude round 1, B2 and B3 (B1 was the previous commit).

- B2, tests/test_issue45_restore.py: the throwaway root is resolved, because
  on macOS /tmp links to /private/tmp and herdr reports real paths (two B
  tests compared /tmp/... with /private/tmp/...). The server's environment
  is read from /proc on Linux and from `ps -E` elsewhere (macOS has no /proc;
  two A tests failed with FileNotFoundError).
- B3, tests/test_issue9_server_env.py: the bootstrap builds the config with
  the python3 on PATH, which here is 3.9 without tomllib, so the test's
  merged-settings expectation could not hold and its own `import tomllib`
  failed. The test now parses the result with that same python3; when it
  has no tomllib, it expects the key-only config and the bootstrap's
  "no tomllib" warning instead.

macOS, Python 3.9 venv: test_issue45_restore, test_issue9_server_env and
test_issue45_herdr_config 42 passed / 29 skipped (the tomllib-only checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-05 15:59:26 +09:00
GodopuandClaude Opus 5.5 36f0b8dfd6 test(issue-45): the herdr-config tests collect on Python < 3.11; the docs say what that Python loses
tests/test_issue45_herdr_config.py imported tomllib at module level. On
Python 3.9 - macOS's /usr/bin/python3, which the venvs and the bootstrap's
python3 use here - the import failed during collection and pytest ran no
test of the whole suite.

The import is optional now, and the 29 tests that parse a result with
tomllib or expect the user's settings kept are marked needs_tomllib: on
Python < 3.11 herdr_config deliberately writes the key-only config (restore
still off, the other settings dropped, a warning on stderr), which
test_without_tomllib_restore_is_still_off covers on every Python.
Python 3.9: 22 passed / 29 skipped; Python 3.11: 51 passed.

create SKILL.md (same line, so the #42 inventory is unchanged) and the
4.8.5 entry state that building the server config needs tomllib (Python
3.11+) in the python3 on PATH, and what an older python3 loses. Checked
with Python 3.9 in a throwaway HOME: the warning reaches stderr (the
bootstrap captures only stdout) and the user's file is untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
2026-10-05 15:56:27 +09:00
GodopuandClaude Opus 5.5 35935f9e8a fix(issue-45): review round 2 R3 - the .mam fallback obeys the same no-overwrite rules
The fallback wrote <.mam>/herdr-server-config.toml unchecked, so it could
replace a foreign file there, the source itself, or a link to it. It now goes
through output_path like the normal path (source identity incl. aliases,
generated-for-this-source ownership, then a per-source name) and writes
nothing when no name is safe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:49:08 +00:00
GodopuandClaude Opus 5.5 7c544c06ab test(issue-45): S11 base follows the review-R1 heredoc change; VERSIONS notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:18:09 +00:00
GodopuandClaude Opus 5.5 811b080966 fix(issue-45): review R1-R3 - herdr checks the config, any TOML spelling kept, source never overwritten
R1: tomllib accepting a file is not herdr accepting it (a schema error makes
herdr drop the whole file, restore included). The shim passes REAL_HERDR and
the written file must pass `herdr config check` ("parse error"/"using defaults"
reject; unknown keys and sound-file notices do not), else the key-only file is
written and checked. A non-table `session` and a source that is not UTF-8 reach
that fallback instead of raising.

R2: the line edit is replaced by parse -> set -> serialize; the result must
parse back to the source plus the key, so dotted keys and inline tables keep
the user's other settings.

R3: the output is never the source (aliases included) nor a file not generated
for the same source; then a per-source name beside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:17:59 +00:00
GodopuandClaude Opus 5.5 ce91cc11b9 release(v4.8.5): bump framework and eight skills to 4.8.5 in lockstep
Issue #45 A+B: MAM's isolated herdr servers start with restore-on-restart off,
and resume closes the session's own restored empty shell. Not reviewed yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:53:14 +00:00
GodopuandClaude Opus 5.5 eedcebcc12 fix(issue-45): restore stays off when python3 has no tomllib
The shim runs a bare python3. Before 3.11 the module failed to import and the
server started with restore on; now it gets the key alone, with a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:34:27 +00:00
GodopuandClaude Opus 5.5 feceddf49f docs(issue-45): isolation and resume notes; block inventory line shifts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:49 +00:00
GodopuandClaude Opus 5.5 fb1380fdc1 fix(issue-45): resume closes the session's own restored empty shell
After a restart with restore off, the session's saved pane comes back as an
empty shell (in $HOME when its directory is gone) holding the agent_session it
reported. A resume with a CP_PREFIX cannot reuse it, so it stayed next to the
new pane. Just before spawning, resume closes panes whose agent_session is the
id being resumed, with no live agent and only the shell in the foreground; the
registry is not consulted, since a session whose server died stays running.

tests/test_issue45_restore.py drives a real herdr server under a throwaway HOME
and session with a fake claude: restore stays off through the MAM bootstrap
(with a restore-on control), the close conditions, and create -> crash ->
resume leaving one pane.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:49 +00:00
GodopuandClaude Opus 5.5 933af344c2 test(issue-45): S11 compares the shim heredoc with the Issue #45 bootstrap commit
S11 keeps the generated .mam/shim/herdr from changing by accident; #45 changes
it on purpose, so its base moves to ed73f67.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:49 +00:00
GodopuandClaude Opus 5.5 ed73f67a4f fix(issue-45): the shim bootstrap starts MAM servers with restore-on-restart off
The headless bootstrap regenerates the server config on every start and hands
it to the server as HERDR_CONFIG_PATH. Without a file the server still starts,
with a warning. mam_sandbox unsets HERDR_CONFIG_PATH/XDG_CONFIG_HOME so the
file lands in the sandbox HOME.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:35 +00:00
GodopuandClaude Opus 5.5 a640b0f072 feat(issue-45): herdr config for MAM servers with restore-on-restart off
lib_py/herdr_config.py builds the user's herdr config (HERDR_CONFIG_PATH, else
XDG_CONFIG_HOME, else ~/.config, as herdr reads it) with only
[session] resume_agents_on_restore forced to false, written next to the source
so relative paths resolve the same. The text merge is re-parsed; a merge that
does not leave the rest equal falls back to the key alone, since herdr drops a
config that does not parse and would restore again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:32:35 +00:00