fix(loop): resolve B-13 by implementing runtime freeze snapshot and dual-root isolation

- Add Stage 2 runtime freeze snapshot at run_loop.sh bootstrap to prevent in-flight tooling mutations
- Implement dual-root architecture separating code execution (frozen snapshot) and workspace state (real repo)
- Ensure original argv preservation and safe cleanup of freeze directories in exit traps
- Add 5 regression guards in tests/test_o3_scoped_guard.py (271/271 PASS)
- Update IMPROVEMENTS.md, VERSIONS.md, and include peer review report
This commit is contained in:
2026-08-17 11:49:37 +09:00
parent 40576c44ab
commit 8cee9374b1
5 changed files with 332 additions and 30 deletions
+102
View File
@@ -367,3 +367,105 @@ def test_z14_run_loop_records_lstart(mam_sandbox):
content = lock_script.read_text()
assert "mam_lstart" in content
assert "lstart=" in content
# ===========================================================================
# B-13 Stage 2: Self-hosting loop runtime freeze snapshot regression guards
# ===========================================================================
def test_b13_reexec_preserves_original_argv(tmp_path):
"""B-13/P1: the freeze re-exec must forward the original arguments.
The arg parser consumes "$@" (shift), so capturing argv beforehand is mandatory.
"""
run_loop_sh = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-loop" / "scripts" / "run_loop.sh"
res = subprocess.run(
["bash", str(run_loop_sh), "--target-agent", "nonexistent-agent", "--task", "test goal with spaces"],
capture_output=True,
text=True,
cwd=str(REPO_ROOT),
)
combined = res.stdout + res.stderr
assert "mandatory fields" not in combined
def test_b13_freeze_survives_broken_wrapper(tmp_path):
"""B-13: a wrapper broken mid-loop must not break an already-frozen runtime."""
skills_src = REPO_ROOT / ".agents" / "skills"
skills_dst = tmp_path / ".agents" / "skills"
shutil.copytree(skills_src, skills_dst)
freeze_dir = tmp_path / "freeze"
freeze_skills = freeze_dir / ".agents" / "skills"
shutil.copytree(skills_dst, freeze_skills)
wrapper_orig = skills_dst / "multi-agent-mux-delegate-job" / "multi-agent-mux-delegate-job"
wrapper_orig.write_text('echo "broken wrapper syntax" "\nunexpected EOF\n')
r_orig = subprocess.run(["bash", str(wrapper_orig)], capture_output=True, text=True)
assert r_orig.returncode != 0
wrapper_frozen = freeze_skills / "multi-agent-mux-delegate-job" / "multi-agent-mux-delegate-job"
r_frozen = subprocess.run(["bash", str(wrapper_frozen), "--help"], capture_output=True, text=True)
assert r_frozen.returncode == 0
def test_b13_freeze_dir_is_outside_the_skill_tree(tmp_path):
"""B-13 must not reintroduce B-6: nothing may be written under .agents/skills/."""
run_loop_sh = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-loop" / "scripts" / "run_loop.sh"
subprocess.run(["bash", str(run_loop_sh), "--help"], capture_output=True, text=True, cwd=str(REPO_ROOT))
assert list((REPO_ROOT / ".agents" / "skills").rglob("*.tmp")) == []
assert "mam-loop-freeze" not in str(list((REPO_ROOT / ".agents").rglob("*")))
def test_b13_release_guard_cleans_up_and_releases_lock(tmp_path):
"""B-13 cleanup must extend _mam_release_guard, releasing lock and removing snapshot."""
loop_lock_sh = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-loop" / "scripts" / "loop_lock.sh"
marker = tmp_path / ".mam" / "loop-guard-active"
freeze_dir = tmp_path / "mam-loop-freeze.TEST1234"
freeze_dir.mkdir(parents=True)
(freeze_dir / "dummy").write_text("test")
script = f"""#!/usr/bin/env bash
set -euo pipefail
MAM_REAL_ROOT="{tmp_path}"
MAM_LOOP_MARKER="{marker}"
MAM_LOOP_FREEZE_DIR="{freeze_dir}"
MAM_LOOP_FREEZE_OWNED="1"
source "{loop_lock_sh}"
_mam_release_guard() {{
mam_release_loop_lock "$MAM_LOOP_MARKER" || true
if [ -n "${{MAM_LOOP_FREEZE_DIR:-}}" ] && [ "${{MAM_LOOP_FREEZE_OWNED:-0}}" = "1" ]; then
case "$MAM_LOOP_FREEZE_DIR" in
*/mam-loop-freeze.*) rm -rf "$MAM_LOOP_FREEZE_DIR" ;;
*) : ;;
esac
fi
}}
mam_acquire_loop_lock "$MAM_LOOP_MARKER"
trap _mam_release_guard EXIT INT TERM HUP
[ -f "$MAM_LOOP_MARKER" ]
[ -d "$MAM_LOOP_FREEZE_DIR" ]
"""
res = subprocess.run(["bash", "-c", script], capture_output=True, text=True)
assert res.returncode == 0
assert not marker.exists(), "loop lock marker was not released"
assert not freeze_dir.exists(), "freeze snapshot dir was not cleaned up"
def test_b13_no_freeze_switch_disables_reexec(tmp_path):
"""MAM_LOOP_NO_FREEZE=1 must skip the snapshot and re-exec entirely."""
run_loop_sh = REPO_ROOT / ".agents" / "skills" / "multi-agent-mux-loop" / "scripts" / "run_loop.sh"
env = os.environ.copy()
env["MAM_LOOP_NO_FREEZE"] = "1"
res = subprocess.run(
["bash", str(run_loop_sh), "--target-agent", "nonexistent-agent", "--task", "test goal"],
capture_output=True,
text=True,
env=env,
cwd=str(REPO_ROOT),
)
assert "mam-loop-freeze" not in res.stderr