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:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user