fix(e2e): finalize sqlite concurrency locking, mock_herdr atomic state, and e2e test suite (100% PASS)

This commit is contained in:
2026-08-07 22:39:23 +09:00
parent ab00be4ad2
commit 68f43349be
7 changed files with 266 additions and 71 deletions
+53 -35
View File
@@ -6,6 +6,7 @@ import pytest
import shutil
import yaml
import time
import fcntl
import concurrent.futures
import threading
from pathlib import Path
@@ -168,19 +169,23 @@ def test_e2e_scenario3_drift_auto_reconciliation(mam_sandbox, mock_herdr):
# Drift 1: Running in herdr but not in YAML
drift_herdr_only = "drift-herdr-only-creator-claude"
with open(mock_herdr, 'r') as f:
state = json.load(f)
state["agents"][drift_herdr_only] = {
"status": "running",
"agent": "claude",
"cwd": str(tmp_path),
"pid": 5555,
"pane_id": "w1:p1",
"command": "claude",
"buffer": "Anthropic Claude Ready"
}
with open(mock_herdr, 'w') as f:
json.dump(state, f, indent=2)
lock_path = str(mock_herdr) + ".lock"
with open(lock_path, 'w') as lock_f:
fcntl.flock(lock_f, fcntl.LOCK_EX)
with open(mock_herdr, 'r') as f:
state = json.load(f)
state["agents"][drift_herdr_only] = {
"status": "running",
"agent": "claude",
"cwd": str(tmp_path),
"pid": 5555,
"pane_id": "w1:p1",
"command": "claude",
"buffer": "Anthropic Claude Ready"
}
with open(mock_herdr, 'w') as f:
json.dump(state, f, indent=2)
fcntl.flock(lock_f, fcntl.LOCK_UN)
# Drift 2: Running in YAML registry but terminated in herdr
drift_yaml_only = "drift-yaml-only-creator-claude"
@@ -202,7 +207,12 @@ d['herdr_sessions'] = [{{
# Run reconcile.sh --once
cmd_reconcile = ["bash", str(reconcile_script), "--once"]
res_recon = subprocess.run(cmd_reconcile, capture_output=True, text=True, cwd=str(tmp_path))
run_env = dict(os.environ)
run_env["LOCAL_BIN"] = str(tmp_path / "bin")
run_env["PATH"] = str(tmp_path / "bin") + ":" + os.environ.get("PATH", "")
run_env["HOME_DIR"] = str(tmp_path)
run_env["CLAUDE_PROJECT_DIR"] = str(tmp_path / ".claude" / "projects")
res_recon = subprocess.run(cmd_reconcile, capture_output=True, text=True, cwd=str(tmp_path), env=run_env)
assert res_recon.returncode == 0, f"Stderr: {res_recon.stderr}"
# Verify YAML/DB states
@@ -256,10 +266,11 @@ def test_e2e_scenario4_parallel_flock_locking(mam_sandbox, mock_herdr, mock_agen
# Verify all 6 sessions are present in YAML registry
yaml_path = tmp_path / ".mam" / "agent-sessions.yaml"
with open(yaml_path, 'r') as f:
reg = yaml.safe_load(f)
reg = yaml.safe_load(f) or {}
sessions = reg.get("herdr_sessions", [])
registered_names = {s["name"] for s in sessions}
registered_names = {s["name"] for s in sessions if isinstance(s, dict) and s.get("name")}
assert len(registered_names) == num_sessions
for i in range(num_sessions):
assert f"parallel-sess-{i}-creator-claude" in registered_names
@@ -304,25 +315,29 @@ d['herdr_sessions'] = [
assert res_mut.returncode == 0
# Seed mock herdr state with these running sessions to satisfy has-session checks
with open(mock_herdr, 'r') as f:
herdr_state = json.load(f)
pane_ids = {
worker_name: "w1:p1",
reviewer_name: "w1:p2",
planner_name: "w1:p3"
}
for name in [worker_name, reviewer_name, planner_name]:
herdr_state["agents"][name] = {
"status": "running",
"agent": "claude",
"cwd": str(tmp_path),
"pid": 9999,
"pane_id": pane_ids[name],
"command": "claude",
"buffer": "Anthropic Claude Ready"
lock_path = str(mock_herdr) + ".lock"
with open(lock_path, 'w') as lock_f:
fcntl.flock(lock_f, fcntl.LOCK_EX)
with open(mock_herdr, 'r') as f:
herdr_state = json.load(f)
pane_ids = {
worker_name: "w1:p1",
reviewer_name: "w1:p2",
planner_name: "w1:p3"
}
with open(mock_herdr, 'w') as f:
json.dump(herdr_state, f, indent=2)
for name in [worker_name, reviewer_name, planner_name]:
herdr_state["agents"][name] = {
"status": "running",
"agent": "claude",
"cwd": str(tmp_path),
"pid": 9999,
"pane_id": pane_ids[name],
"command": "claude",
"buffer": "Anthropic Claude Ready"
}
with open(mock_herdr, 'w') as f:
json.dump(herdr_state, f, indent=2)
fcntl.flock(lock_f, fcntl.LOCK_UN)
# Define mock reviewer and planner outputs
# Let's mock a scenario:
@@ -416,8 +431,11 @@ d['herdr_sessions'] = [
import sys
run_env = dict(os.environ)
run_env["DELEGATE_JOB_PYTHON"] = sys.executable
run_env["LOCAL_BIN"] = str(tmp_path / "bin")
run_env["PATH"] = str(tmp_path / "bin") + ":" + os.environ.get("PATH", "")
run_env["HOME_DIR"] = str(tmp_path)
run_env["CLAUDE_PROJECT_DIR"] = str(tmp_path / ".claude" / "projects")
res_loop = subprocess.run(cmd_loop, capture_output=True, text=True, cwd=str(tmp_path), env=run_env)
# Verify that it succeeded and executed the corrective loop
assert res_loop.returncode == 0, f"Loop failed. Stdout: {res_loop.stdout}\nStderr: {res_loop.stderr}"
assert "Reviewer 'test-reviewer-creator-claude': NOT PASS" in res_loop.stdout or "Reviewer 'test-reviewer-creator-claude': NOT PASS" in res_loop.stderr or "NOT PASS" in res_loop.stdout
assert "Reviewer 'test-reviewer-creator-claude': PASS" in res_loop.stdout