Уточнить эффективный статус agent loop
This commit is contained in:
parent
15f1a57039
commit
d24f8476b4
|
|
@ -167,6 +167,8 @@ It stores the GUI review under `artifacts/domain_runs/stage_agent_loops/<stage_i
|
|||
|
||||
Use `python scripts/stage_agent_loop.py status --manifest docs/orchestration/<stage_loop>.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.
|
||||
|
||||
The status payload also exposes `effective_stage_status`, `effective_stage_status_source`, and `latest_gui_review_superseded_by_validation`. These fields prevent stale GUI failures from looking current after a later accepted repair validation or domain-loop replay has already superseded them. Keep the historic `latest_gui_business_status` visible for audit, but use the effective status to decide whether the next action is repair, validation, or manual confirmation.
|
||||
|
||||
Use `python scripts/stage_agent_loop.py continue --manifest docs/orchestration/<stage_loop>.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-<id>` when the next required step is post-repair rerun/ingest validation.
|
||||
|
||||
It also writes `stage_repair_handoff.md/json` next to the stage summary. That handoff is the preferred input for the next coder pass: it lists primary repair targets and sample user-facing failures without forcing the coder to reread the entire GUI conversation first.
|
||||
|
|
|
|||
|
|
@ -2119,6 +2119,46 @@ def handle_ingest_domain_loop_validation(args: argparse.Namespace) -> int:
|
|||
return 0
|
||||
|
||||
|
||||
def stage_validation_passed(validation: dict[str, Any]) -> bool:
|
||||
return bool(validation.get("accepted_after_repair")) and str(validation.get("validation_status") or "").strip() == "passed"
|
||||
|
||||
|
||||
def build_effective_stage_status(
|
||||
summary: dict[str, Any],
|
||||
latest_gui_review: dict[str, Any],
|
||||
latest_repair_validation: dict[str, Any],
|
||||
latest_replay_validation: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
gui_status = str(latest_gui_review.get("overall_business_status") or "").strip()
|
||||
gui_is_negative = bool(gui_status and gui_status not in {"pass", "accepted"})
|
||||
validation = latest_repair_validation if stage_validation_passed(latest_repair_validation) else {}
|
||||
if not validation and stage_validation_passed(latest_replay_validation):
|
||||
validation = latest_replay_validation
|
||||
if validation:
|
||||
return {
|
||||
"status": "accepted_after_validation" if summary.get("accepted_gate") else "validated_after_repair",
|
||||
"source": validation.get("validation_source") or "repair_validation",
|
||||
"validation_run_id": validation.get("validation_run_id"),
|
||||
"supersedes_latest_gui_review": gui_is_negative,
|
||||
"superseded_gui_run_id": latest_gui_review.get("run_id") if gui_is_negative else None,
|
||||
}
|
||||
if gui_status:
|
||||
return {
|
||||
"status": gui_status,
|
||||
"source": "latest_gui_review",
|
||||
"validation_run_id": None,
|
||||
"supersedes_latest_gui_review": False,
|
||||
"superseded_gui_run_id": None,
|
||||
}
|
||||
return {
|
||||
"status": summary.get("loop_final_status"),
|
||||
"source": "stage_summary",
|
||||
"validation_run_id": None,
|
||||
"supersedes_latest_gui_review": False,
|
||||
"superseded_gui_run_id": None,
|
||||
}
|
||||
|
||||
|
||||
def ingest_replay_validation(args: argparse.Namespace) -> dict[str, Any]:
|
||||
stage_manifest_path = repo_path(args.manifest)
|
||||
stage_manifest = load_stage_manifest(stage_manifest_path)
|
||||
|
|
@ -2307,6 +2347,12 @@ def build_stage_status(stage_manifest: dict[str, Any], stage_dir: Path) -> dict[
|
|||
if isinstance(summary.get("stage_closing_gate"), dict)
|
||||
else {}
|
||||
)
|
||||
effective_status = build_effective_stage_status(
|
||||
summary,
|
||||
latest_gui_review,
|
||||
latest_repair_validation,
|
||||
latest_replay_validation,
|
||||
)
|
||||
return {
|
||||
"schema_version": "stage_agent_loop_status_v1",
|
||||
"stage_id": stage_manifest["stage_id"],
|
||||
|
|
@ -2321,6 +2367,11 @@ def build_stage_status(stage_manifest: dict[str, Any], stage_dir: Path) -> dict[
|
|||
"stage_closing_gate": stage_closing_gate or None,
|
||||
"next_action": next_action,
|
||||
"next_step_guidance": next_step_guidance,
|
||||
"effective_stage_status": effective_status.get("status"),
|
||||
"effective_stage_status_source": effective_status.get("source"),
|
||||
"latest_gui_review_superseded_by_validation": effective_status.get("supersedes_latest_gui_review"),
|
||||
"superseding_validation_run_id": effective_status.get("validation_run_id"),
|
||||
"superseded_gui_run_id": effective_status.get("superseded_gui_run_id"),
|
||||
"latest_gui_run_id": latest_gui_review.get("run_id"),
|
||||
"latest_gui_business_status": latest_gui_review.get("overall_business_status"),
|
||||
"latest_business_audit": summary.get("latest_business_audit"),
|
||||
|
|
|
|||
|
|
@ -514,6 +514,11 @@ class StageAgentLoopTests(unittest.TestCase):
|
|||
self.assertTrue(summary["latest_repair_validation"]["accepted_after_repair"])
|
||||
self.assertEqual(status["latest_validation_source"], "domain_truth_harness.run-live")
|
||||
self.assertEqual(status["latest_replay_validation_status"], "passed")
|
||||
self.assertEqual(status["effective_stage_status"], "accepted_after_validation")
|
||||
self.assertEqual(status["effective_stage_status_source"], "domain_truth_harness.run-live")
|
||||
self.assertTrue(status["latest_gui_review_superseded_by_validation"])
|
||||
self.assertEqual(status["superseding_validation_run_id"], "accepted_replay")
|
||||
self.assertEqual(status["superseded_gui_run_id"], "assistant-stage1-before")
|
||||
|
||||
def test_domain_loop_validation_stage_summary_closes_after_accepted_pack_loop(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
|
@ -1023,6 +1028,9 @@ class StageAgentLoopTests(unittest.TestCase):
|
|||
self.assertEqual(status["stage_closing_gate"]["status"], "blocked_pending_repair_validation")
|
||||
self.assertEqual(status["latest_repair_coder_status"], "patched")
|
||||
self.assertEqual(status["latest_validation_status"], "failed_p0")
|
||||
self.assertEqual(status["effective_stage_status"], "fail")
|
||||
self.assertEqual(status["effective_stage_status_source"], "latest_gui_review")
|
||||
self.assertFalse(status["latest_gui_review_superseded_by_validation"])
|
||||
|
||||
def test_build_stage_status_derives_guidance_from_existing_next_action(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
|
|
|||
Loading…
Reference in New Issue