fix(agent): hydrate complete runtime receipt chain
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m19s
CD Pipeline / build-and-deploy (push) Successful in 8m12s
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 51s
CD Pipeline / post-deploy-checks (push) Has been cancelled

This commit is contained in:
ogt
2026-07-10 18:12:34 +08:00
parent 4e9615c2c3
commit fb32c27e1b
2 changed files with 211 additions and 5 deletions

View File

@@ -3228,6 +3228,58 @@ def _operation_by_id(
return None
def _missing_runtime_operation_chain_ref_ids(
rows: Iterable[Mapping[str, Any] | Any],
) -> list[str]:
"""Return exact apply/check/candidate receipt ids missing from a bounded read."""
operation_rows = [_row_mapping(row) for row in rows]
latest_apply = _first_operation(operation_rows, "ansible_apply_executed")
if latest_apply is None:
return []
check_mode_op_id = str(
latest_apply.get("check_mode_op_id")
or latest_apply.get("parent_op_id")
or ""
)
latest_check = _operation_by_id(operation_rows, check_mode_op_id)
candidate_op_id = str(
(latest_check or {}).get("parent_op_id")
or (latest_check or {}).get("source_candidate_op_id")
or latest_apply.get("source_candidate_op_id")
or ""
)
present_ids = {
str(row.get("op_id") or "")
for row in operation_rows
if str(row.get("op_id") or "")
}
refs = [
str(latest_apply.get("op_id") or ""),
check_mode_op_id,
candidate_op_id,
]
return list(dict.fromkeys(ref for ref in refs if ref and ref not in present_ids))
def _merge_runtime_operation_rows(
primary_rows: Iterable[Mapping[str, Any] | Any],
supplemental_rows: Iterable[Mapping[str, Any] | Any],
) -> list[dict[str, Any]]:
merged: list[dict[str, Any]] = []
seen_ids: set[str] = set()
for raw_row in (*list(primary_rows), *list(supplemental_rows)):
row = _row_mapping(raw_row)
op_id = str(row.get("op_id") or "")
if op_id and op_id in seen_ids:
continue
if op_id:
seen_ids.add(op_id)
merged.append(row)
return merged
def _stage_status(row: Mapping[str, Any] | None, *, fallback_status: str | None = None) -> str:
if row is None:
return fallback_status or "missing"
@@ -5297,6 +5349,30 @@ async def _load_ai_agent_autonomous_runtime_receipt_readback_uncached(
"operation_latest",
_RUNTIME_OPERATION_LATEST_SQL,
)
for chain_pass in range(2):
missing_chain_refs = _missing_runtime_operation_chain_ref_ids(
operation_latest
)
if not missing_chain_refs:
break
padded_refs = [*missing_chain_refs[:3], "", ""][:3]
params.update(
{
"operation_chain_ref_1": padded_refs[0],
"operation_chain_ref_2": padded_refs[1],
"operation_chain_ref_3": padded_refs[2],
}
)
operation_chain_rows = await _safe_rows(
f"operation_chain_{chain_pass + 1}",
_RUNTIME_OPERATION_CHAIN_SQL,
)
if not operation_chain_rows:
break
operation_latest = _merge_runtime_operation_rows(
operation_latest,
operation_chain_rows,
)
auto_repair_counts = await _safe_rows(
"auto_repair_counts",
_RUNTIME_AUTO_REPAIR_COUNTS_SQL,
@@ -5518,17 +5594,37 @@ async def _load_core_runtime_receipt_rows_direct(
)
return []
operation_latest = await _fetch(
"operation_latest",
_RUNTIME_OPERATION_LATEST_DIRECT_SQL,
20,
)
for chain_pass in range(2):
missing_chain_refs = _missing_runtime_operation_chain_ref_ids(
operation_latest
)
if not missing_chain_refs:
break
padded_refs = [*missing_chain_refs[:3], "", ""][:3]
operation_chain_rows = await _fetch(
f"operation_chain_{chain_pass + 1}",
_RUNTIME_OPERATION_CHAIN_DIRECT_SQL,
*padded_refs,
)
if not operation_chain_rows:
break
operation_latest = _merge_runtime_operation_rows(
operation_latest,
operation_chain_rows,
)
return {
"operation_counts": await _fetch(
"operation_counts",
_RUNTIME_OPERATION_COUNTS_DIRECT_SQL,
lookback_hours,
),
"operation_latest": await _fetch(
"operation_latest",
_RUNTIME_OPERATION_LATEST_DIRECT_SQL,
20,
),
"operation_latest": operation_latest,
"auto_repair_counts": await _fetch(
"auto_repair_counts",
_RUNTIME_AUTO_REPAIR_COUNTS_DIRECT_SQL,
@@ -5836,6 +5932,78 @@ _RUNTIME_OPERATION_LATEST_DIRECT_SQL = """
"""
_RUNTIME_OPERATION_CHAIN_SQL = """
SELECT
op_id::text AS op_id,
parent_op_id::text AS parent_op_id,
CASE
WHEN operation_type = 'km_linked'
AND input ->> 'semantic_operation_type' = 'log_controlled_writeback_dispatched'
THEN 'log_controlled_writeback_dispatched'
ELSE operation_type
END AS operation_type,
status,
actor,
CASE
WHEN operation_type = 'ansible_candidate_matched'
THEN op_id::text
ELSE input ->> 'automation_run_id'
END AS automation_run_id,
coalesce(incident_id::text, input ->> 'incident_id') AS incident_id,
input ->> 'catalog_id' AS catalog_id,
coalesce(input ->> 'apply_playbook_path', input ->> 'playbook_path') AS playbook_path,
input ->> 'execution_mode' AS execution_mode,
input ->> 'source_candidate_op_id' AS source_candidate_op_id,
input ->> 'check_mode_op_id' AS check_mode_op_id,
input ->> 'risk_level' AS risk_level,
input ->> 'controlled_apply_allowed' AS controlled_apply_allowed,
coalesce(output ->> 'returncode', dry_run_result ->> 'returncode') AS returncode,
duration_ms,
created_at
FROM automation_operation_log
WHERE op_id::text IN (
:operation_chain_ref_1,
:operation_chain_ref_2,
:operation_chain_ref_3
)
ORDER BY created_at DESC
"""
_RUNTIME_OPERATION_CHAIN_DIRECT_SQL = """
SELECT
op_id::text AS op_id,
parent_op_id::text AS parent_op_id,
CASE
WHEN operation_type = 'km_linked'
AND input ->> 'semantic_operation_type' = 'log_controlled_writeback_dispatched'
THEN 'log_controlled_writeback_dispatched'
ELSE operation_type
END AS operation_type,
status,
actor,
CASE
WHEN operation_type = 'ansible_candidate_matched'
THEN op_id::text
ELSE input ->> 'automation_run_id'
END AS automation_run_id,
coalesce(incident_id::text, input ->> 'incident_id') AS incident_id,
input ->> 'catalog_id' AS catalog_id,
coalesce(input ->> 'apply_playbook_path', input ->> 'playbook_path') AS playbook_path,
input ->> 'execution_mode' AS execution_mode,
input ->> 'source_candidate_op_id' AS source_candidate_op_id,
input ->> 'check_mode_op_id' AS check_mode_op_id,
input ->> 'risk_level' AS risk_level,
input ->> 'controlled_apply_allowed' AS controlled_apply_allowed,
coalesce(output ->> 'returncode', dry_run_result ->> 'returncode') AS returncode,
duration_ms,
created_at
FROM automation_operation_log
WHERE op_id::text IN ($1, $2, $3)
ORDER BY created_at DESC
"""
_RUNTIME_AUTO_REPAIR_COUNTS_SQL = """
SELECT
CASE WHEN success THEN 'success' ELSE 'failed' END AS result_status,