"""U-010's real-call coverage: "手工依次触发 planner/coder/validator 三个 Org Agent" (05 §5.5) with actual `claude --agent -p` calls for all three, not just planner (which U-004 already validated). Artifact-validation preconditions are seeded directly -- no real Work Graph exists yet to produce them (U-011+), same as the mocked tests. Gated behind RUN_REAL_AGENT_E2E=1 (CLAUDE.md Testing constraint). Run: RUN_REAL_AGENT_E2E=1 python3 -m unittest src.test_org_node_lifecycle_e2e -v """ import subprocess import tempfile import unittest import uuid from src import agent_profile, org_node_lifecycle, project_scaffold, schema, task_create from src.test_support import skip_unless_env _PROMPT = "In one short sentence, confirm you're ready and state your role. Take no other action." @skip_unless_env("RUN_REAL_AGENT_E2E") class RealChainedTriggerTest(unittest.TestCase): def test_all_three_org_agents_trigger_for_real_and_status_advances_each_time(self): with tempfile.TemporaryDirectory() as tmp: subprocess.run(["git", "init"], cwd=tmp, check=True, capture_output=True) conn = schema.connect(":memory:") schema.create_schema(conn) project_scaffold.create_project(conn, tmp, init_git_if_missing=False) agent_profile.deploy_agent_definitions(tmp) task_id = task_create.create_task(conn, self._project_id(conn), "实现贪吃蛇游戏")["task_id"] planner_result = org_node_lifecycle.trigger_org_node_full(conn, "planner", task_id, tmp, _PROMPT) self.assertEqual(planner_result["status"], "planning_brd_prd_sdd") self._seed_passing_artifacts(conn, task_id, ("brd", "prd", "sdd", "benchmark")) coder_result = org_node_lifecycle.trigger_org_node_full(conn, "coder", task_id, tmp, _PROMPT) self.assertEqual(coder_result["status"], "coding") self._seed_passing_artifacts(conn, task_id, ("code_diff", "test_report")) validator_result = org_node_lifecycle.trigger_org_node_full(conn, "validator", task_id, tmp, _PROMPT) self.assertEqual(validator_result["status"], "validating") @staticmethod def _project_id(conn): return conn.execute("SELECT project_id FROM project").fetchone()[0] @staticmethod def _seed_passing_artifacts(conn, task_id, artifact_types): run_id = str(uuid.uuid4()) conn.execute( "INSERT INTO work_graph_run (run_id, task_id, graph_manifest, status) VALUES (?, ?, '{}', 'done')", (run_id, task_id), ) for artifact_type in artifact_types: conn.execute( "INSERT INTO artifact (artifact_id, artifact_type, task_id, produced_by_run_id, " "file_path, git_commit_sha, validation_status) VALUES (?, ?, ?, ?, 'f.md', ?, 'passed')", (str(uuid.uuid4()), artifact_type, task_id, run_id, artifact_type), ) conn.commit() if __name__ == "__main__": unittest.main()