R2: glob() hid a listing error, so an unreadable .mam/jobs (or MAM_JOBS_DIR,
or another row's jobs dir) counted as empty and the update installed over an
open job. Records are now listed with os.listdir; a directory that cannot be
listed, or stat'ed, is a blocker with its path.
R3: a discovered agent with no row was told to run stop with --session only;
stop then looked on the workspace's server, not the one the agent was found
on. The hint now carries --herdr-session <server>, quoted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A v4.11.0 workspace's .mam_deploy/update.sh installs the new version - the
skill present, no updater left - and the skill run after it converts the
registry. An update-backup in an unknown state now restarts the monitor it
stopped: nothing was changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The update is a skill (decision 4); deploy/update.sh and the installed
.mam_deploy/update.sh are gone.
- Phase 1 (installed code, update.sh): publish the update marker under the
exclusive admission lock; refuse before any change while a running row, a
live herdr agent in the workspace on any running server, an open job
(unreadable JSON included, dry_run not), a live loop marker or a
monitor.lock held by a monitor the skills did not start (U3) is there - the
calling agent (server + pane, its row and one running job) excepted
(lib_py/update.py precheck, decisions 1 and 7). Stop the monitor (TERM, then
KILL and restart it if it does not end; decision 2), handle a leftover
backup by its state (U4), back up .agents, .mam_deploy, root files, .venv,
the installer's .mam files and the registry (SQLite backup API under the
registry lock) into .mam/update-backup/, then exec a copy of
install_phase.sh outside the tree (decision 5).
- The copy (no lib.sh/lib_py, bash 3.2) runs the installer in place; on
failure it restores the backup and restarts the monitor from the restored
tree; on success it runs phase 2, post_update.sh of the new tree, which
converts the registry with lib_py.registry_format and restarts the monitor
if it ran. The backup and the marker are removed at the end.
- install.sh updates in place (decisions 3, 4, 9): install_state keys are set,
one line each; no updater is installed and an old one (.mam_deploy/update.sh,
or a root update.sh the manifest lists) is removed; framework files the new
version no longer ships are deleted when unmodified, kept and listed when
modified, and dropped from base/, the manifest and asset_hashes.txt; a local
source's .mam is not staged. remove.sh knows the new skill; CI shellchecks
its scripts; docs point at the skill.
- test_issue8_update_state and test_deploy_layout td6/td27 run the skill.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>