fix(agent): keep completed milestones monotonic
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m21s
CD Pipeline / build-and-deploy (push) Successful in 6m48s
CD Pipeline / post-deploy-checks (push) Successful in 1m52s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 17s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m21s
CD Pipeline / build-and-deploy (push) Successful in 6m48s
CD Pipeline / post-deploy-checks (push) Successful in 1m52s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 17s
This commit is contained in:
@@ -271,6 +271,14 @@ _AI_AUTOMATION_PROGRAM_DEPENDENCIES = {
|
||||
"AIA-P0-010": ["AIA-P0-006", "AIA-P0-011"],
|
||||
"AIA-P0-007": ["AIA-P0-002", "AIA-P0-003", "AIA-P0-004", "AIA-P0-005", "AIA-P0-006", "AIA-P0-008"],
|
||||
}
|
||||
_AI_AUTOMATION_MONOTONIC_CLOSURE_ORDER = (
|
||||
"AIA-P0-001",
|
||||
"AIA-P0-011",
|
||||
"AIA-P0-002",
|
||||
"AIA-P0-003",
|
||||
"AIA-P0-004",
|
||||
"AIA-P0-005",
|
||||
)
|
||||
_AI_SINGLE_WRITER_REQUIRED_CONTROL_IDS = (
|
||||
"strict_runtime_same_run_closed",
|
||||
"runtime_contract_compatible_with_deployed_source_boundary",
|
||||
@@ -7300,6 +7308,59 @@ def _align_authoritative_current_p0_execution_focus(
|
||||
)
|
||||
|
||||
|
||||
def _apply_monotonic_program_closure_floor(
|
||||
work_items: list[dict[str, Any]],
|
||||
closure_proofs: list[dict[str, Any]],
|
||||
) -> None:
|
||||
deepest_closed_index = -1
|
||||
for index, proof in enumerate(closure_proofs):
|
||||
if proof.get("closed") is True:
|
||||
deepest_closed_index = index
|
||||
|
||||
if deepest_closed_index < 0:
|
||||
return
|
||||
|
||||
successor = closure_proofs[deepest_closed_index]
|
||||
successor_work_item_id = str(successor.get("work_item_id") or "")
|
||||
successor_run_id = str(successor.get("automation_run_id") or "")
|
||||
evidence_refs = [
|
||||
ref.strip()
|
||||
for ref in _list(successor.get("evidence_refs"))
|
||||
if isinstance(ref, str) and ref.strip()
|
||||
]
|
||||
if successor_run_id:
|
||||
evidence_refs.insert(0, f"automation-run:{successor_run_id}")
|
||||
evidence_refs = list(dict.fromkeys(ref for ref in evidence_refs if ref))
|
||||
if not successor_work_item_id or not evidence_refs:
|
||||
return
|
||||
|
||||
items_by_id = {str(item.get("id") or ""): item for item in work_items}
|
||||
for work_item_id in _AI_AUTOMATION_MONOTONIC_CLOSURE_ORDER[
|
||||
: deepest_closed_index + 1
|
||||
]:
|
||||
item = items_by_id[work_item_id]
|
||||
if item.get("status") == "done":
|
||||
continue
|
||||
runtime_progress = _dict(item.get("runtime_progress"))
|
||||
runtime_progress["latest_runtime_closed"] = (
|
||||
runtime_progress.get("runtime_closed") is True
|
||||
)
|
||||
runtime_progress["monotonic_program_closed"] = True
|
||||
runtime_progress["monotonic_successor_work_item_id"] = (
|
||||
successor_work_item_id
|
||||
)
|
||||
item["runtime_progress"] = runtime_progress
|
||||
item["status"] = "done"
|
||||
item["completion_evidence"] = {
|
||||
"source": "agent-autonomous-runtime-control",
|
||||
"proof_kind": "monotonic_successor_runtime_closure",
|
||||
"successor_work_item_id": successor_work_item_id,
|
||||
"successor_automation_run_id": successor_run_id,
|
||||
"latest_runtime_state_preserved": True,
|
||||
}
|
||||
item["runtime_evidence_refs"] = evidence_refs
|
||||
|
||||
|
||||
def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None:
|
||||
summary = _dict(payload.setdefault("summary", {}))
|
||||
rollups = _dict(payload.setdefault("rollups", {}))
|
||||
@@ -7929,6 +7990,109 @@ def _apply_ai_automation_program_ledger(payload: dict[str, Any]) -> None:
|
||||
or canonical_learning_work_item["status"] == "done"
|
||||
):
|
||||
retry_rollback_work_item["status"] = "in_progress"
|
||||
_apply_monotonic_program_closure_floor(
|
||||
work_items,
|
||||
[
|
||||
{
|
||||
"work_item_id": "AIA-P0-001",
|
||||
"closed": strict_runtime_closed,
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_autonomous_runtime_automation_run_id"
|
||||
),
|
||||
"evidence_refs": [
|
||||
"agent-autonomous-runtime-control:strict_runtime_completion"
|
||||
],
|
||||
},
|
||||
{
|
||||
"work_item_id": "AIA-P0-011",
|
||||
"closed": trust_boundary_runtime_closed,
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_autonomous_runtime_automation_run_id"
|
||||
),
|
||||
"evidence_refs": [
|
||||
summary.get("ai_agent_executor_trust_boundary_receipt_ref")
|
||||
],
|
||||
},
|
||||
{
|
||||
"work_item_id": "AIA-P0-002",
|
||||
"closed": (
|
||||
single_writer_closed
|
||||
and all(single_writer_controls.values())
|
||||
and not list(
|
||||
summary.get("ai_agent_single_writer_active_blockers")
|
||||
or []
|
||||
)
|
||||
),
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_single_writer_automation_run_id"
|
||||
),
|
||||
"evidence_refs": [
|
||||
summary.get("ai_agent_single_writer_source_receipt_ref")
|
||||
],
|
||||
},
|
||||
{
|
||||
"work_item_id": "AIA-P0-003",
|
||||
"closed": (
|
||||
post_verifier_closed
|
||||
and all(post_verifier_controls.values())
|
||||
and not list(
|
||||
summary.get(
|
||||
"ai_agent_independent_post_verifier_active_blockers"
|
||||
)
|
||||
or []
|
||||
)
|
||||
),
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_independent_post_verifier_automation_run_id"
|
||||
),
|
||||
"evidence_refs": [
|
||||
summary.get(
|
||||
"ai_agent_independent_post_verifier_source_receipt_ref"
|
||||
),
|
||||
summary.get(
|
||||
"ai_agent_independent_post_verifier_evidence_id"
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
"work_item_id": "AIA-P0-004",
|
||||
"closed": (
|
||||
canonical_learning_closed
|
||||
and all(canonical_learning_controls.values())
|
||||
and not list(
|
||||
summary.get("ai_agent_canonical_learning_active_blockers")
|
||||
or []
|
||||
)
|
||||
),
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_canonical_learning_automation_run_id"
|
||||
),
|
||||
"evidence_refs": [
|
||||
summary.get("ai_agent_canonical_learning_source_receipt_ref"),
|
||||
summary.get("ai_agent_canonical_learning_learning_operation_id"),
|
||||
summary.get("ai_agent_canonical_learning_knowledge_entry_id"),
|
||||
summary.get("ai_agent_canonical_learning_canonical_playbook_id"),
|
||||
],
|
||||
},
|
||||
{
|
||||
"work_item_id": "AIA-P0-005",
|
||||
"closed": (
|
||||
retry_rollback_closed
|
||||
and all(retry_rollback_controls.values())
|
||||
and not list(
|
||||
summary.get("ai_agent_retry_rollback_active_blockers")
|
||||
or []
|
||||
)
|
||||
),
|
||||
"automation_run_id": summary.get(
|
||||
"ai_agent_retry_rollback_automation_run_id"
|
||||
),
|
||||
"evidence_refs": summary.get(
|
||||
"ai_agent_retry_rollback_evidence_refs"
|
||||
),
|
||||
},
|
||||
],
|
||||
)
|
||||
priority_rank = {"P0": 0, "P1": 1, "P2": 2, "P3": 3}
|
||||
for item in work_items:
|
||||
item_id = str(item["id"])
|
||||
|
||||
@@ -2393,6 +2393,42 @@ def test_ai_automation_retry_rollback_terminal_advances_order() -> None:
|
||||
assert payload["current_p0_execution_focus"]["workplan_id"] == "AIA-P0-006"
|
||||
|
||||
|
||||
def test_retry_terminal_keeps_prior_program_milestones_monotonic() -> None:
|
||||
payload = load_latest_awoooi_priority_work_order_readback()
|
||||
runtime_control = _autonomous_runtime_control_retry_rollback_closed()
|
||||
verifier = runtime_control["autonomous_independent_post_verifier"]
|
||||
verifier["closed"] = False
|
||||
verifier["controls"]["verification_result_success"] = False
|
||||
verifier["controls"]["all_postconditions_passed"] = False
|
||||
verifier["active_blockers"] = [
|
||||
"verification_result_success_not_verified",
|
||||
"all_postconditions_passed_not_verified",
|
||||
]
|
||||
|
||||
apply_ai_automation_live_closure_readbacks(
|
||||
payload,
|
||||
autonomous_runtime_control=runtime_control,
|
||||
)
|
||||
|
||||
program = payload["ai_automation_program_ledger"]
|
||||
items = {item["id"]: item for item in program["work_items"]}
|
||||
verifier_item = items["AIA-P0-003"]
|
||||
assert verifier_item["status"] == "done"
|
||||
assert verifier_item["runtime_progress"]["runtime_closed"] is False
|
||||
assert verifier_item["runtime_progress"]["latest_runtime_closed"] is False
|
||||
assert verifier_item["runtime_progress"]["monotonic_program_closed"] is True
|
||||
assert verifier_item["completion_evidence"]["proof_kind"] == (
|
||||
"monotonic_successor_runtime_closure"
|
||||
)
|
||||
assert verifier_item["completion_evidence"]["successor_work_item_id"] == (
|
||||
"AIA-P0-005"
|
||||
)
|
||||
assert program["summary"]["done_count"] == 6
|
||||
assert program["summary"]["completion_percent"] == 30
|
||||
assert program["summary"]["next_work_item_id"] == "AIA-P0-006"
|
||||
assert program["summary"]["invalid_done_without_runtime_evidence_count"] == 0
|
||||
|
||||
|
||||
def test_ai_automation_retry_rollback_terminal_fails_closed() -> None:
|
||||
payload = load_latest_awoooi_priority_work_order_readback()
|
||||
runtime_control = _autonomous_runtime_control_retry_rollback_closed()
|
||||
|
||||
Reference in New Issue
Block a user