Merge remote-tracking branch 'gitea-ssh/main' into codex/p0-product-manifest-standard-20260629
This commit is contained in:
@@ -146,6 +146,29 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
|
||||
},
|
||||
],
|
||||
operation_latest_rows=[
|
||||
{
|
||||
"op_id": "candidate-op",
|
||||
"parent_op_id": None,
|
||||
"operation_type": "ansible_candidate_matched",
|
||||
"status": "dry_run",
|
||||
"actor": "decision_manager",
|
||||
"incident_id": incident_id,
|
||||
"catalog_id": "ansible:188-momo-backup-user",
|
||||
"playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml",
|
||||
"execution_mode": "check_mode",
|
||||
},
|
||||
{
|
||||
"op_id": "check-mode-op",
|
||||
"parent_op_id": "candidate-op",
|
||||
"operation_type": "ansible_check_mode_executed",
|
||||
"status": "success",
|
||||
"actor": "ansible_check_mode_worker",
|
||||
"incident_id": incident_id,
|
||||
"catalog_id": "ansible:188-momo-backup-user",
|
||||
"playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml",
|
||||
"execution_mode": "check_mode",
|
||||
"returncode": "0",
|
||||
},
|
||||
{
|
||||
"op_id": apply_op_id,
|
||||
"parent_op_id": "check-mode-op",
|
||||
@@ -156,10 +179,28 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
|
||||
"catalog_id": "ansible:188-momo-backup-user",
|
||||
"playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml",
|
||||
"execution_mode": "controlled_apply",
|
||||
"source_candidate_op_id": "candidate-op",
|
||||
"check_mode_op_id": "check-mode-op",
|
||||
"returncode": "0",
|
||||
"duration_ms": 7727,
|
||||
},
|
||||
],
|
||||
auto_repair_count_rows=[
|
||||
{"result_status": "success", "total": 1, "recent": 1},
|
||||
],
|
||||
auto_repair_latest_rows=[
|
||||
{
|
||||
"id": "auto-repair-1",
|
||||
"incident_id": incident_id,
|
||||
"catalog_id": "ansible:188-momo-backup-user",
|
||||
"playbook_name": "infra/ansible/playbooks/188-momo-backup-user.yml",
|
||||
"result_status": "success",
|
||||
"executed_steps_text": f'["apply:{apply_op_id}"]',
|
||||
"triggered_by": "ansible_controlled_apply",
|
||||
"risk_level": "low",
|
||||
"execution_time_ms": 7727,
|
||||
},
|
||||
],
|
||||
verifier_count_rows=[
|
||||
{"verification_result": "success", "total": 1, "recent": 1},
|
||||
],
|
||||
@@ -207,6 +248,7 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
|
||||
assert readback["db_read_status"] == "ok"
|
||||
assert readback["writes_on_read"] is False
|
||||
assert readback["ansible_apply_executed"]["total"] == 1
|
||||
assert readback["auto_repair_execution_receipt"]["by_status"]["success"] == 1
|
||||
assert readback["post_apply_verifier"]["by_status"]["success"] == 1
|
||||
assert readback["km_writeback"]["by_status"]["review"] == 1
|
||||
assert readback["telegram_receipt"]["by_status"]["sent"] == 1
|
||||
@@ -223,6 +265,28 @@ def test_runtime_receipt_readback_summarizes_live_executor_closure_rows():
|
||||
"latest_controlled_apply_closed_success"
|
||||
)
|
||||
assert readback["controlled_retry_package"]["status"] == "not_required_for_latest_apply"
|
||||
ledger = readback["autonomous_execution_loop_ledger"]
|
||||
assert ledger["schema_version"] == "ai_agent_autonomous_execution_loop_ledger_v1"
|
||||
assert ledger["operation_id"] == apply_op_id
|
||||
assert ledger["root_candidate_op_id"] == "candidate-op"
|
||||
assert ledger["check_mode_op_id"] == "check-mode-op"
|
||||
assert ledger["apply_op_id"] == apply_op_id
|
||||
assert ledger["execution_state"] == "closed_success"
|
||||
assert ledger["closed"] is True
|
||||
assert ledger["missing_stage_ids"] == []
|
||||
assert ledger["next_executor_action"] == "keep_receipt_chain_closed"
|
||||
assert [stage["stage_id"] for stage in ledger["stages"]] == [
|
||||
"candidate",
|
||||
"check_mode",
|
||||
"controlled_apply",
|
||||
"auto_repair_execution_receipt",
|
||||
"post_apply_verifier",
|
||||
"km_playbook_writeback",
|
||||
"telegram_receipt",
|
||||
]
|
||||
assert {stage["present"] for stage in ledger["stages"]} == {True}
|
||||
assert ledger["safety_contract"]["backfill_may_send_telegram"] is False
|
||||
assert ledger["safety_contract"]["live_apply_may_send_telegram_gateway_receipt"] is True
|
||||
|
||||
|
||||
def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():
|
||||
@@ -241,6 +305,18 @@ def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():
|
||||
},
|
||||
],
|
||||
operation_latest_rows=[
|
||||
{
|
||||
"op_id": "8b555f41-e81f-4d8e-956b-fb20d358db63",
|
||||
"parent_op_id": "candidate-op-2",
|
||||
"operation_type": "ansible_check_mode_executed",
|
||||
"status": "success",
|
||||
"actor": "ansible_check_mode_worker",
|
||||
"incident_id": incident_id,
|
||||
"catalog_id": "ansible:188-ai-web",
|
||||
"playbook_path": "infra/ansible/playbooks/188-ai-web-readonly.yml",
|
||||
"execution_mode": "check_mode",
|
||||
"returncode": "0",
|
||||
},
|
||||
{
|
||||
"op_id": apply_op_id,
|
||||
"parent_op_id": "8b555f41-e81f-4d8e-956b-fb20d358db63",
|
||||
@@ -251,10 +327,28 @@ def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():
|
||||
"catalog_id": "ansible:188-ai-web",
|
||||
"playbook_path": "infra/ansible/playbooks/188-ai-web.yml",
|
||||
"execution_mode": "controlled_apply",
|
||||
"source_candidate_op_id": "candidate-op-2",
|
||||
"check_mode_op_id": "8b555f41-e81f-4d8e-956b-fb20d358db63",
|
||||
"returncode": "2",
|
||||
"duration_ms": 4797,
|
||||
},
|
||||
],
|
||||
auto_repair_count_rows=[
|
||||
{"result_status": "failed", "total": 1, "recent": 1},
|
||||
],
|
||||
auto_repair_latest_rows=[
|
||||
{
|
||||
"id": "auto-repair-2",
|
||||
"incident_id": incident_id,
|
||||
"catalog_id": "ansible:188-ai-web",
|
||||
"playbook_name": "infra/ansible/playbooks/188-ai-web.yml",
|
||||
"result_status": "failed",
|
||||
"executed_steps_text": f'["apply:{apply_op_id}"]',
|
||||
"triggered_by": "ansible_controlled_apply",
|
||||
"risk_level": "medium",
|
||||
"execution_time_ms": 4797,
|
||||
},
|
||||
],
|
||||
verifier_count_rows=[
|
||||
{"verification_result": "failed", "total": 1, "recent": 1},
|
||||
],
|
||||
@@ -344,3 +438,54 @@ def test_runtime_receipt_readback_classifies_closed_failed_apply_as_ai_repair():
|
||||
"telegram_receipt_required": True,
|
||||
}
|
||||
assert retry["next_ai_action"] == "run_no_write_check_mode_replay"
|
||||
ledger = readback["autonomous_execution_loop_ledger"]
|
||||
assert ledger["closed"] is True
|
||||
assert ledger["execution_state"] == "closed_failed_apply_repair_ready"
|
||||
assert ledger["next_executor_action"] == "run_no_write_check_mode_replay"
|
||||
assert ledger["missing_stage_ids"] == []
|
||||
assert ledger["stages"][3]["stage_id"] == "auto_repair_execution_receipt"
|
||||
assert ledger["stages"][3]["status"] == "failed"
|
||||
|
||||
|
||||
def test_runtime_execution_loop_ledger_does_not_mix_unrelated_check_mode_rows():
|
||||
apply_op_id = "db3f12ce-08fc-4289-8c93-338305d5850c"
|
||||
readback = build_runtime_receipt_readback_from_rows(
|
||||
project_id="awoooi",
|
||||
db_read_status="ok",
|
||||
operation_latest_rows=[
|
||||
{
|
||||
"op_id": "unrelated-check-mode-op",
|
||||
"parent_op_id": "unrelated-candidate",
|
||||
"operation_type": "ansible_check_mode_executed",
|
||||
"status": "success",
|
||||
"actor": "ansible_check_mode_worker",
|
||||
"incident_id": "INC-OTHER",
|
||||
"catalog_id": "ansible:110-devops",
|
||||
"playbook_path": "infra/ansible/playbooks/110-devops.yml",
|
||||
"execution_mode": "check_mode",
|
||||
"returncode": "0",
|
||||
},
|
||||
{
|
||||
"op_id": apply_op_id,
|
||||
"parent_op_id": "expected-check-mode-op",
|
||||
"operation_type": "ansible_apply_executed",
|
||||
"status": "success",
|
||||
"actor": "ansible_controlled_apply_worker",
|
||||
"incident_id": "INC-20260629-LEDGER",
|
||||
"catalog_id": "ansible:188-momo-backup-user",
|
||||
"playbook_path": "infra/ansible/playbooks/188-momo-backup-user.yml",
|
||||
"execution_mode": "controlled_apply",
|
||||
"returncode": "0",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
ledger = readback["autonomous_execution_loop_ledger"]
|
||||
assert ledger["operation_id"] == apply_op_id
|
||||
assert ledger["check_mode_op_id"] == "expected-check-mode-op"
|
||||
assert ledger["root_candidate_op_id"] is None
|
||||
assert ledger["incident_id"] == "INC-20260629-LEDGER"
|
||||
assert ledger["stages"][1]["stage_id"] == "check_mode"
|
||||
assert ledger["stages"][1]["ref_id"] == "expected-check-mode-op"
|
||||
assert ledger["stages"][1]["status"] == "inferred_from_apply_parent"
|
||||
assert "candidate" in ledger["missing_stage_ids"]
|
||||
|
||||
Reference in New Issue
Block a user