diff --git a/docs/orchestration/domain_scenario_loop_repo_adapter.md b/docs/orchestration/domain_scenario_loop_repo_adapter.md index 1ff04cc..1601e81 100644 --- a/docs/orchestration/domain_scenario_loop_repo_adapter.md +++ b/docs/orchestration/domain_scenario_loop_repo_adapter.md @@ -143,7 +143,7 @@ It stores the GUI review under `artifacts/domain_runs/stage_agent_loops/.json` as the cheap read-only checkpoint before continuing a stage. It prints the current next action, closing gate, latest GUI run, latest repair coder status, and latest repair validation status without modifying artifacts. +Use `python scripts/stage_agent_loop.py status --manifest docs/orchestration/.json` as the cheap read-only checkpoint before continuing a stage. It prints the current next action, closing gate, latest GUI run, latest repair coder status, latest repair validation status, and cold-start continuation artifacts such as `domain_pack_loop.command.txt` without modifying artifacts. Use `python scripts/stage_agent_loop.py continue --manifest docs/orchestration/.json` as the safe one-command continuation layer. From a cold start it materializes `domain_pack_loop.command.txt` without launching the long live loop; after a GUI review it can prepare a repair iteration and materialize `run-repair --dry-run` automatically; it will not run the real coder pass unless `--execute-repair` is passed, and it waits for a `--run-id assistant-stage1-` when the next required step is post-repair rerun/ingest validation. diff --git a/scripts/stage_agent_loop.py b/scripts/stage_agent_loop.py index f061f20..e5fa33d 100644 --- a/scripts/stage_agent_loop.py +++ b/scripts/stage_agent_loop.py @@ -1128,6 +1128,13 @@ def handle_plan(args: argparse.Namespace) -> int: def build_stage_status(stage_manifest: dict[str, Any], stage_dir: Path) -> dict[str, Any]: summary_path = stage_dir / "stage_loop_summary.json" summary = load_json_object(summary_path, "Existing stage summary") if summary_path.exists() else {} + continue_result_path = stage_dir / "stage_continue_result.json" + continue_result = ( + load_json_object(continue_result_path, "Stage continue result") + if continue_result_path.exists() + else {} + ) + domain_command_path = stage_dir / "domain_pack_loop.command.txt" next_action = str(summary.get("next_action") or "run_stage_loop_or_ingest_gui_run") latest_gui_review = summary.get("latest_gui_review") if isinstance(summary.get("latest_gui_review"), dict) else {} latest_repair_execution = ( @@ -1166,6 +1173,11 @@ def build_stage_status(stage_manifest: dict[str, Any], stage_dir: Path) -> dict[ "latest_validation_status": latest_repair_validation.get("validation_status"), "accepted_after_repair": latest_repair_validation.get("accepted_after_repair"), "summary_path": repo_relative(summary_path) if summary_path.exists() else None, + "domain_pack_loop_command_exists": domain_command_path.exists(), + "domain_pack_loop_command_path": repo_relative(domain_command_path) if domain_command_path.exists() else None, + "last_continue_action": continue_result.get("performed_action"), + "last_continue_next_action": continue_result.get("next_action"), + "last_continue_result_path": repo_relative(continue_result_path) if continue_result_path.exists() else None, } diff --git a/scripts/test_stage_agent_loop.py b/scripts/test_stage_agent_loop.py index 99ecae4..53a32f8 100644 --- a/scripts/test_stage_agent_loop.py +++ b/scripts/test_stage_agent_loop.py @@ -817,6 +817,33 @@ class StageAgentLoopTests(unittest.TestCase): self.assertEqual(result["performed_action"], "materialize_stage_run_dry_run") self.assertIn("run-pack-loop", command_text) + def test_build_stage_status_reports_cold_start_continue_artifacts(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + stage_dir = root / "stage_runs" / "agent_loop" + write_json( + stage_dir / "stage_continue_result.json", + { + "schema_version": "stage_agent_loop_continue_result_v1", + "performed_action": "materialize_stage_run_dry_run", + "next_action": "run_stage_loop_or_ingest_gui_run", + }, + ) + (stage_dir / "domain_pack_loop.command.txt").write_text("python run-pack-loop\n", encoding="utf-8") + + status = stage_loop.build_stage_status( + { + "stage_id": "agent_loop", + "module_name": "Agent Loop", + "title": "Agent Loop", + }, + stage_dir, + ) + + self.assertTrue(status["domain_pack_loop_command_exists"]) + self.assertEqual(status["last_continue_action"], "materialize_stage_run_dry_run") + self.assertEqual(status["last_continue_next_action"], "run_stage_loop_or_ingest_gui_run") + def test_resolve_stage_repair_iteration_auto_prepares_from_handoff(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp)