fix(reset): never take another live reset's fence, and fence absent row registries (#78)

Review round 4 (codex):
- R1: fence_registries reads an existing marker under the registry lock and
  refuses the reset, changing nothing, when another live (or undecidable)
  reset holds it - registries may be shared between workspaces; only a stale
  marker is replaced, and the reset's exit removes only its own fences.
- R2: the registries to fence come from update.jobs_dirs, the enumeration
  open_jobs now uses too, whether or not they exist; an absent row registry
  is created and fenced (a registration would create it), and one that cannot
  be created refuses the reset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
GodopuandClaude Opus 5.5 committed 2026-10-30 08:21:40 +09:00
1 parent 568385c77a
commit b49314c3d0
6 files changed
+213 -74

No files matched your search

+30 -24
View File
@@ -147,34 +147,40 @@ def _is_open(rec: dict) -> bool:
return rec.get("status") not in TERMINAL_STATUSES and rec.get("dry_run") is not True
def open_jobs(workspace: str, state: dict, env: Mapping[str, str]) -> List[dict]:
"""Every open record (not completed/error/cancelled, not dry_run) in this
workspace's .mam/jobs and MAM_JOBS_DIR; in another row's
control_plane.mam_jobs_dir only those addressed to a row of this registry.
A record, or a directory, that cannot be read is open (path only)."""
own, seen = [], set()
for c in (os.path.join(workspace, ".mam", "jobs"), env.get("MAM_JOBS_DIR") or ""):
if c and _is_jobs_dir(c) and _real(c) not in seen:
def jobs_dirs(workspace: str, state: dict, env: Mapping[str, str]) -> List[Tuple[str, bool]]:
"""(dir, addressed_only) per registry an open-job check reads, once per
real path, whether or not it exists yet: this workspace's .mam/jobs and
MAM_JOBS_DIR, then another row's control_plane.mam_jobs_dir, where only
records addressed to a row of this registry count (addressed_only)."""
rows = state.get("herdr_sessions") or []
cands = [(c, False) for c in (os.path.join(workspace, ".mam", "jobs"), env.get("MAM_JOBS_DIR") or "")]
cands += [((s.get("control_plane") or {}).get("mam_jobs_dir") or "", True) for s in rows]
out, seen = [], set()
for c, addressed_only in cands:
if c and _real(c) not in seen:
seen.add(_real(c))
own.append(c)
out.append((c, addressed_only))
return out
def open_jobs(workspace: str, state: dict, env: Mapping[str, str]) -> List[dict]:
"""Every open record (not completed/error/cancelled, not dry_run) in the
registries jobs_dirs names; in another row's control-plane registry only
those addressed to a row of this registry. A record, or a directory, that
cannot be read is open (path only)."""
rows = state.get("herdr_sessions") or []
names = {"herdr:%s" % s.get("name") for s in rows if s.get("name")}
other = []
for s in rows:
c = (s.get("control_plane") or {}).get("mam_jobs_dir") or ""
if c and _is_jobs_dir(c) and _real(c) not in seen:
seen.add(_real(c))
other.append(c)
out = []
for dirs, addressed_only in ((own, False), (other, True)):
for d in dirs:
for path, rec in _job_records(d):
if rec is None:
out.append({"path": path, "unreadable": True, "dir": path == d})
elif _is_open(rec) and (not addressed_only or rec.get("agent_session") in names):
out.append({"path": path, "job_id": rec.get("job_id") or "",
"agent_session": rec.get("agent_session") or "",
"status": rec.get("status"), "registry_dir": d})
for d, addressed_only in jobs_dirs(workspace, state, env):
if not _is_jobs_dir(d):
continue
for path, rec in _job_records(d):
if rec is None:
out.append({"path": path, "unreadable": True, "dir": path == d})
elif _is_open(rec) and (not addressed_only or rec.get("agent_session") in names):
out.append({"path": path, "job_id": rec.get("job_id") or "",
"agent_session": rec.get("agent_session") or "",
"status": rec.get("status"), "registry_dir": d})
return out