feat: update admission gate - entries refuse while an update runs (Issue #72, decision 8, U2)

The update skill publishes .mam/update-in-progress (pid + lstart, the
loop_lock.sh rules) while it holds .mam/update-admission.lock exclusively.
create, resume, run_loop.sh and delegate submit (decision 8) and stop and
orc-onboard (U2: a rollback would restore the registry without their write)
take that lock shared (lib.sh mam_update_admit, fd 7), refuse while the marker
is live or unknown, and hold the lock until their record is written. A stale
marker refuses nothing. lib_py.pane_lock acquire gains --shared and
--wait-env (MAM_UPDATE_ADMISSION_WAIT_S, default 120); create's wrapper path
closes fd 7 for the long-lived child. The exit-1 rows of create/resume/stop
name the refusal; skill_code_blocks.json pins follow the shifted lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-27 04:06:42 +00:00
1 parent 179473e5d5
commit 6359d65999
13 files changed
+311 -25

No files matched your search

@@ -257,6 +257,11 @@ if [ "$DRY_RUN" = true ]; then
exit 0
fi
# Issue #72 (U2): no registry write while an update runs - a rollback would
# restore the registry without it. Held until the write is done (lib.sh
# mam_update_admit).
mam_update_admit || exit 1
# Issue #13: the orchestrator has no herdr_sessions row, so stop_session.sh
# --purge-conversation can never reach its conversation. Purge FIRST, through
# the adapter (`lib_py.agents purge`): a refusal because the conversation is
@@ -304,6 +309,7 @@ elif op == "remove":
uuids = [u for u in uuids if u != target]
d["orchestrator_uuids"] = uuids
PYEOF
mam_update_admit_release
case "$MODE" in
add) verb="added" ;;