From 913745380fc792898aaf386851741f34f180df8c Mon Sep 17 00:00:00 2001 From: dctouch Date: Sat, 9 May 2026 13:34:56 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20dogfood-=D0=BC=D0=B0=D0=BD=D0=B8=D1=84=D0=B5=D1=81?= =?UTF-8?q?=D1=82=20stage-loop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._semantic_development_loop_stage_pack.json | 100 ++++++++++++++++++ .../domain_scenario_loop_repo_adapter.md | 2 +- ...oop_agentic_semantic_development_loop.json | 27 +++++ scripts/stage_agent_loop.py | 26 +++++ scripts/test_stage_agent_loop.py | 39 +++++++ 5 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 docs/orchestration/agentic_semantic_development_loop_stage_pack.json create mode 100644 docs/orchestration/stage_agent_loop_agentic_semantic_development_loop.json diff --git a/docs/orchestration/agentic_semantic_development_loop_stage_pack.json b/docs/orchestration/agentic_semantic_development_loop_stage_pack.json new file mode 100644 index 0000000..74bc19c --- /dev/null +++ b/docs/orchestration/agentic_semantic_development_loop_stage_pack.json @@ -0,0 +1,100 @@ +{ + "schema_version": "domain_scenario_pack_v1", + "pack_id": "agentic_semantic_development_loop_stage_pack", + "domain": "agentic_semantic_development_loop_control", + "title": "Agentic semantic development loop control pack", + "description": "Compact stage pack for dogfooding the agentic development loop against business-overview, VAT, stale-scope, and legacy-canary questions.", + "analysis_context": { + "as_of_date": "2026-05-09", + "source": "agentic_semantic_development_loop_stage_pack" + }, + "bindings": { + "main_organization": "ООО Альтернатива Плюс", + "control_year": "2020", + "svk_counterparty": "Группа СВК" + }, + "scenarios": [ + { + "scenario_id": "agentic_loop_business_overview_control", + "title": "Business overview and stale-scope control", + "description": "Checks direct business-answer shape, period carryover, all-time reset, VAT boundary, and organization scope hygiene.", + "steps": [ + { + "step_id": "step_01_business_overview", + "title": "Business overview for explicit period", + "question": "Дай взрослый бизнес-обзор {{bindings.main_organization}} за {{bindings.control_year}} год по данным 1С: обороты, входящие и исходящие деньги, нетто, НДС, долги, склад, клиенты, поставщики и что пока нельзя утверждать.", + "expected_intents": ["business_overview"], + "required_answer_shape": "direct_answer_first", + "forbidden_answer_patterns": [ + "(?i)capability_id", + "(?i)selected_chain_id", + "(?i)runtime_", + "(?i)business_overview_route_template_v1" + ] + }, + { + "step_id": "step_02_money_followup", + "title": "Money follow-up", + "question": "Раскрой деньги подробнее: сколько получили, сколько заплатили, какой чистый денежный поток, кто главный клиент и главный поставщик в {{bindings.control_year}}.", + "depends_on": ["step_01_business_overview"], + "required_answer_shape": "direct_answer_first" + }, + { + "step_id": "step_03_best_year_all_time", + "title": "All-time best operating-flow year", + "question": "А если смотреть за все доступное время, какой самый доходный год по подтвержденным оборотам и почему? Не называй это бухгалтерской прибылью, если чистой прибыли нет.", + "depends_on": ["step_02_money_followup"], + "required_answer_shape": "direct_answer_first" + }, + { + "step_id": "step_04_vat_explicit_period", + "title": "VAT explicit period", + "question": "Что с НДС за {{bindings.control_year}} год по {{bindings.main_organization}}: какая позиция видна, на чем она основана и чего не хватает для налогового вывода?", + "depends_on": ["step_03_best_year_all_time"], + "required_answer_shape": "direct_answer_first" + }, + { + "step_id": "step_05_all_time_no_vat_carryover", + "title": "All-time reset without stale VAT carryover", + "question": "Теперь за все доступное время дай обзор компании в целом, но не тащи НДС за {{bindings.control_year}} как подтвержденную общую налоговую позицию.", + "depends_on": ["step_04_vat_explicit_period"], + "required_answer_shape": "direct_answer_first" + } + ] + }, + { + "scenario_id": "agentic_loop_counterparty_pivot_control", + "title": "Counterparty pivot and legacy canaries", + "description": "Checks explicit counterparty arbitration after organization context and keeps technical/debug details out of the final answer.", + "steps": [ + { + "step_id": "step_01_svk_money", + "title": "Explicit counterparty money flow", + "question": "Теперь отдельно по контрагенту {{bindings.svk_counterparty}}: сколько денег прошло, что входящее, что исходящее и есть ли документы или движения, на которых это основано?", + "expected_intents": ["value_flow"], + "required_answer_shape": "direct_answer_first", + "forbidden_answer_patterns": [ + "(?i)capability_id", + "(?i)selected_chain_id", + "(?i)runtime_", + "(?i)mcp_discovery" + ] + }, + { + "step_id": "step_02_svk_documents", + "title": "Counterparty documents follow-up", + "question": "Покажи документы по этой цепочке и не смешивай {{bindings.svk_counterparty}} с организацией {{bindings.main_organization}}.", + "depends_on": ["step_01_svk_money"], + "required_answer_shape": "direct_answer_first" + }, + { + "step_id": "step_03_final_summary", + "title": "Final executive summary", + "question": "Собери короткий итог: что мы подтвердили по компании, что отдельно по {{bindings.svk_counterparty}}, какие выводы можно делать и какие нельзя.", + "depends_on": ["step_01_svk_money", "step_02_svk_documents"], + "required_answer_shape": "direct_answer_first" + } + ] + } + ] +} diff --git a/docs/orchestration/domain_scenario_loop_repo_adapter.md b/docs/orchestration/domain_scenario_loop_repo_adapter.md index d5e1508..1ff04cc 100644 --- a/docs/orchestration/domain_scenario_loop_repo_adapter.md +++ b/docs/orchestration/domain_scenario_loop_repo_adapter.md @@ -145,7 +145,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 continue --manifest docs/orchestration/.json` as the safe one-command continuation layer. 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. +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. 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. diff --git a/docs/orchestration/stage_agent_loop_agentic_semantic_development_loop.json b/docs/orchestration/stage_agent_loop_agentic_semantic_development_loop.json new file mode 100644 index 0000000..df72a36 --- /dev/null +++ b/docs/orchestration/stage_agent_loop_agentic_semantic_development_loop.json @@ -0,0 +1,27 @@ +{ + "schema_version": "stage_agent_loop_manifest_v1", + "stage_id": "agentic_semantic_development_loop", + "module_name": "Agentic Semantic Development Loop", + "title": "Agentic semantic development loop dogfood gate", + "architecture_phase": "turnaround_11_agentic_semantic_development_loop", + "agent_focus": "Automate stage implementation, semantic replay review, repair handoff, coder pass, rerun validation, and final human confirmation.", + "current_stage_status": "active_dogfood", + "global_plan_refs": [ + "docs/orchestration/domain_scenario_loop_repo_adapter.md", + "docs/ARCH/11 - architecture_turnaround/README.md", + "AGENTS.md codex_domain_loop and agent_semantic_runs" + ], + "pack_manifest": "docs/orchestration/agentic_semantic_development_loop_stage_pack.json", + "loop_id": "agentic_semantic_development_loop", + "target_score": 88, + "max_iterations": 6, + "acceptance_invariants": [ + "status command exposes next_action, repair state, validation state, and closing gate", + "continue command never runs the real coder pass without --execute-repair", + "patched repair cannot close the stage without successful rerun/ingest validation", + "business answers remain direct, context-aware, and free of internal route/debug ids", + "manual GUI confirmation remains required after accepted semantic replay" + ], + "save_autorun_on_accept": true, + "manual_confirmation_required_after_accept": true +} diff --git a/scripts/stage_agent_loop.py b/scripts/stage_agent_loop.py index 3d6fc0d..f061f20 100644 --- a/scripts/stage_agent_loop.py +++ b/scripts/stage_agent_loop.py @@ -1265,6 +1265,32 @@ def handle_continue(args: argparse.Namespace) -> int: ), } ) + elif next_action == "run_stage_loop_or_ingest_gui_run": + if getattr(args, "run_id", None): + ingest_summary = ingest_gui_run_review(args) + payload.update( + { + "performed_action": "ingest_gui_run_from_cold_start", + "ingest_summary": ingest_summary, + "next_action": ingest_summary.get("next_action"), + } + ) + else: + write_json(stage_dir / "stage_manifest.json", stage_manifest) + write_text(stage_dir / "stage_manifest_source.txt", repo_relative(stage_manifest_path) + "\n") + command = build_domain_pack_loop_command(args, stage_manifest, stage_dir) + write_text(stage_dir / "domain_pack_loop.command.txt", " ".join(command) + "\n") + payload.update( + { + "performed_action": "materialize_stage_run_dry_run", + "domain_pack_loop_command": command, + "next_action": next_action, + "suggested_command": ( + "python scripts/stage_agent_loop.py run " + "--manifest " + ), + } + ) else: payload.update( { diff --git a/scripts/test_stage_agent_loop.py b/scripts/test_stage_agent_loop.py index 2921b75..99ecae4 100644 --- a/scripts/test_stage_agent_loop.py +++ b/scripts/test_stage_agent_loop.py @@ -778,6 +778,45 @@ class StageAgentLoopTests(unittest.TestCase): self.assertEqual(result["performed_action"], "wait_for_rerun_ingest") self.assertEqual(result["next_action"], "rerun_same_stage_or_gui_and_ingest_result") + def test_handle_continue_materializes_stage_run_from_cold_start(self) -> None: + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + manifest_path = root / "stage.json" + output_root = root / "stage_runs" + stage_dir = output_root / "agent_loop" + write_json( + manifest_path, + { + "stage_id": "agent_loop", + "module_name": "Agent Loop", + "title": "Agent Loop", + "pack_manifest": "docs/orchestration/demo_pack.json", + }, + ) + + exit_code = stage_loop.handle_continue( + stage_args( + manifest=str(manifest_path), + output_root=str(output_root), + handoff=None, + iteration_id=None, + plan=None, + coder_schema=str(root / "coder.schema.json"), + execute_repair=False, + run_id=None, + session_file=None, + sessions_dir=str(root / "sessions"), + reports_dir=str(root / "reports"), + review_output_dir=None, + ) + ) + result = json.loads((stage_dir / "stage_continue_result.json").read_text(encoding="utf-8")) + command_text = (stage_dir / "domain_pack_loop.command.txt").read_text(encoding="utf-8") + + self.assertEqual(exit_code, 0) + self.assertEqual(result["performed_action"], "materialize_stage_run_dry_run") + self.assertIn("run-pack-loop", command_text) + def test_resolve_stage_repair_iteration_auto_prepares_from_handoff(self) -> None: with tempfile.TemporaryDirectory() as tmp: root = Path(tmp)