"""Integration test for decentralized-rework P5: peer cross-review (#11). >=2 independent peer reviewers replace the single-critic Master gate: disagreement is recorded, the arbitrated verdict reopens rework targets, and each rework is attributed (root cause + who introduced it). Hermetic, no model key. Run from agent_swarm_v6 (install deps first — needs fakeredis): pip install -r orchestrator/requirements.txt -r agent/requirements.txt REDIS_FAKE=1 ENABLE_CROSS_REVIEW=1 python scripts/test-swarm-cross-review.py """ import asyncio import os import sys from pathlib import Path os.environ["REDIS_FAKE"] = "1" os.environ["ENABLE_CROSS_REVIEW"] = "1" sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from orchestrator.redis_client import redis_client from orchestrator import swarm_runtime as sr_mod from orchestrator.swarm_runtime import swarm_runtime from orchestrator.task_queue import task_queue, TaskStatus from orchestrator import main as orch failures = [] def check(name, cond): print(("PASS" if cond else "FAIL"), "-", name) if not cond: failures.append(name) async def _noop(self, *a, **k): return None async def completed_task(run, tid, agent): t = await task_queue.create_task(task_id=f"{run.swarm_id}-{tid}", description=tid, agent_role=tid.split("-")[-1], enqueue=False) t.status = TaskStatus.COMPLETED t.assigned_agent_id = agent await task_queue._save_task(t) await swarm_runtime.attach_task(run, t.task_id) return t async def main(): await redis_client.connect() sr_mod.SwarmRuntime._post_callback = _noop body = {"mode": "swarm", "requirement": {"objective": "cross review test"}, "callback": {"url": "http://127.0.0.1:9/cb", "subscribed_events": []}, "metadata": {"manager_deployment_id": "m-cr"}} run, _ = await swarm_runtime.get_or_create_run(body=body, idempotency_key=None, correlation_id="cr") impl = await completed_task(run, "t-implementation", "agent-impl") await completed_task(run, "t-documentation", "agent-doc") # two peers submit INDEPENDENT reviews of the implementation; they DISAGREE await orch.handle_review_decision("reviewer-1", { "task_id": impl.task_id, "verdict": "pass", "summary": "looks correct"}) r = await orch.handle_review_decision("reviewer-2", { "task_id": impl.task_id, "verdict": "fail", "failed_criteria": ["implementation raises wrong exception"], "recommended_rework": [impl.task_id], "summary": "wrong exception on bad input"}) check("two independent reviews recorded", r.get("review_count") == 2) # aggregate (called by the run lifecycle with a fresh run) fresh = await swarm_runtime.get_run(run.swarm_id) tasks = [await task_queue.get_task(tid) for tid in fresh.task_ids] reopened = await orch.run_cross_review(fresh, tasks) check("cross-review reopened rework target (rejected on split)", reopened is True) after = await swarm_runtime.get_run(run.swarm_id) cr = after.metadata.get("cross_review") or {} check("verdict recorded with disagreement", cr.get("disagreement") is True and cr.get("accepted") is False) check("split arbitrated by majority → reject (safety bias)", cr.get("method") == "majority" and cr.get("pass_votes") == 1 and cr.get("fail_votes") == 1) impl_after = await task_queue.get_task(impl.task_id) check("flagged task reopened to PENDING", impl_after.status == TaskStatus.PENDING) attrs = after.metadata.get("rework_attributions") or [] check("rework attributed (root cause + detector)", attrs and attrs[0]["target_task_id"] == impl.task_id and attrs[0]["root_cause"] in {"implementation", "collaboration"} and attrs[0]["detected_by_agent_id"] == "reviewer-2") check("reviews consumed after the cycle", not after.metadata.get("reviews")) check("review cycle counter advanced", after.metadata.get("review_cycles") == 1) # --- unanimous pass → accept, no reopen --- run2, _ = await swarm_runtime.get_or_create_run( body={**body, "metadata": {"manager_deployment_id": "m-cr2"}}, idempotency_key=None, correlation_id="cr2") a2 = await completed_task(run2, "t-implementation", "agent-impl") for rid in ("reviewer-1", "reviewer-2"): await orch.handle_review_decision(rid, {"task_id": a2.task_id, "verdict": "pass", "summary": "ok"}) fresh2 = await swarm_runtime.get_run(run2.swarm_id) reopened2 = await orch.run_cross_review(fresh2, [await task_queue.get_task(t) for t in fresh2.task_ids]) check("unanimous pass → not reopened", reopened2 is False) a2_after = await task_queue.get_task(a2.task_id) check("accepted task stays COMPLETED", a2_after.status == TaskStatus.COMPLETED) # --- single reviewer is NOT a cross-review (needs >=2) --- run3, _ = await swarm_runtime.get_or_create_run( body={**body, "metadata": {"manager_deployment_id": "m-cr3"}}, idempotency_key=None, correlation_id="cr3") a3 = await completed_task(run3, "t-implementation", "agent-impl") await orch.handle_review_decision("reviewer-1", {"task_id": a3.task_id, "verdict": "fail", "recommended_rework": [a3.task_id]}) fresh3 = await swarm_runtime.get_run(run3.swarm_id) reopened3 = await orch.run_cross_review(fresh3, [await task_queue.get_task(t) for t in fresh3.task_ids]) check("single reviewer → no cross-review (needs >=2)", reopened3 is False) print() if failures: print(f"{len(failures)} cross-review (P5) check(s) FAILED: {failures}") sys.exit(1) print("all swarm cross-review (P5) checks passed") if __name__ == "__main__": asyncio.run(main())