修复 AgentRun unreachable 泛化与 YAML-lane GitOps 发布分叉 (#624)

* fix: expose web-probe diagnostic previews

* fix: classify agentrun unreachable root causes

---------

Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
Lyon
2026-06-22 03:26:28 +08:00
committed by GitHub
parent b1ae0b6408
commit d44e195ae8
2 changed files with 289 additions and 128 deletions
+52 -2
View File
@@ -822,6 +822,10 @@ function renderTraceTable(input: {
const row = asPlainRecord(item) ?? {};
return [shortenEnd(textValue(row.name), 64), textValue(row.count)];
});
const identity = asPlainRecord(input.result.identity) ?? {};
const identityRows = ["runId", "commandId", "runnerJobId", "runnerId", "backendProfile", "sourceCommit", "jobName", "podName"]
.map((key) => [key, joinValues(identity[key], 88)])
.filter((row) => row[1] !== "-");
const next = asPlainRecord(input.result.next);
const lines = [
`platform-infra observability trace (${input.ok ? "ok" : "not-ok"})`,
@@ -835,6 +839,9 @@ function renderTraceTable(input: {
joinValues(input.result.businessTraceIds, 34),
]]),
"",
"Identity:",
formatTable(["FIELD", "VALUE"], identityRows.length > 0 ? identityRows : [["-", "-"]]),
"",
"Key spans:",
formatTable(["NAME", "SERVICE", "DETAIL"], spanRows.length > 0 ? spanRows : [["-", "-", "-"]]),
"",
@@ -2125,6 +2132,7 @@ if not isinstance(parsed, dict):
spans = []
services = set()
business_trace_ids = set()
identity_values = collections.defaultdict(set)
name_counts = collections.Counter()
error_spans = []
matched_spans = []
@@ -2146,6 +2154,11 @@ for batch in batches_from_body(parsed):
attrs = item.get("attributes", {})
if isinstance(attrs.get("traceId"), str):
business_trace_ids.add(attrs.get("traceId"))
if isinstance(attrs, dict):
for key in ("runId", "commandId", "runnerJobId", "runnerId", "backendProfile", "sourceCommit", "jobName", "podName"):
value = attrs.get(key)
if value not in (None, ""):
identity_values[key].add(str(value))
name = str(item.get("name") or "")
name_counts[name] += 1
spans.append(item)
@@ -2172,6 +2185,7 @@ payload = {
"serviceCount": len(services),
"services": sorted(services),
"businessTraceIds": sorted(business_trace_ids)[:20],
"identity": {key: sorted(values)[:8] for key, values in identity_values.items() if values},
"errorSpanCount": len(error_spans),
"matchedSpanCount": len(matched_spans) if GREP is not None else None,
"grep": GREP,
@@ -3009,6 +3023,9 @@ def http_status_summary(spans):
def agentrun_summary(spans):
terminal_spans = []
latest_seq = None
failure_kind = None
failure_message = None
terminal_category = None
seq_keys = ("maxSeq", "traceLastSeq", "endSeq", "seq", "eventSeq", "sourceSeq", "sourceLatestSeq", "latestSeq", "lastSeq")
for item in spans:
service = str(item.get("service") or "")
@@ -3024,9 +3041,17 @@ def agentrun_summary(spans):
derived = terminal_status
if not derived and name.startswith("runner_terminal."):
derived = name.split(".", 1)[1]
if attrs.get("failureKind") not in (None, ""):
failure_kind = attrs.get("failureKind")
if attrs.get("failureMessage") not in (None, ""):
failure_message = attrs.get("failureMessage")
if attrs.get("terminalCategory") not in (None, ""):
terminal_category = attrs.get("terminalCategory")
terminal_spans.append({
"status": derived,
"eventType": attrs.get("eventType"),
"failureKind": attrs.get("failureKind"),
"terminalCategory": attrs.get("terminalCategory"),
"span": public_span(item),
})
terminal_status = terminal_spans[-1]["status"] if terminal_spans else None
@@ -3047,6 +3072,9 @@ def agentrun_summary(spans):
runner_classification = "unknown"
return {
"terminalStatus": terminal_status,
"failureKind": failure_kind,
"failureMessage": failure_message,
"terminalCategory": terminal_category,
"latestSeq": latest_seq,
"terminalEventType": terminal_event_type,
"terminalSpans": terminal_spans,
@@ -3176,6 +3204,19 @@ def root_cause_candidates(http_summary, agentrun, read_model, lag_summary, error
"summary": "HWLAB projection stale is suspected because AgentRun is terminal but HWLAB read-model evidence is incomplete.",
"evidence": lag_summary.get("reasons", []),
})
if agentrun.get("terminalStatus") in ("failed", "error", "timeout", "blocked", "cancelled"):
candidates.append({
"code": "agentrun_terminal_failed",
"label": "AgentRun terminal failed",
"confidence": 0.9,
"summary": "AgentRun reached a non-success terminal state; inspect result/events/runnerjob before retrying or continuing the session.",
"evidence": {
"terminalStatus": agentrun.get("terminalStatus"),
"failureKind": agentrun.get("failureKind"),
"terminalCategory": agentrun.get("terminalCategory"),
"runnerProviderClassification": agentrun.get("runnerProviderClassification"),
},
})
if agentrun.get("terminalStatus") == "completed":
candidates.append({
"code": "agentrun_completed_not_provider_blocked",
@@ -3451,11 +3492,18 @@ service_path["complete"] = all(service in services for service in expected_servi
facts = []
if http_summary.get("actorForbidden"):
facts.append("actor forbidden")
if agentrun.get("terminalStatus") == "completed":
terminal_status = agentrun.get("terminalStatus")
if terminal_status in ("failed", "error", "timeout", "blocked", "cancelled"):
failure_kind = agentrun.get("failureKind")
if failure_kind:
facts.append(f"AgentRun terminal failed ({failure_kind})")
else:
facts.append("AgentRun terminal failed")
if terminal_status == "completed":
facts.append("AgentRun completed")
if lag.get("status") in ("confirmed", "suspected"):
facts.append("HWLAB projection stale")
if idle_warning_spans and agentrun.get("terminalStatus") in (None, ""):
if idle_warning_spans and terminal_status in (None, ""):
facts.append("AgentRun runner idle warnings active")
if not facts:
facts.append("no dominant Code Agent root cause classified")
@@ -3466,6 +3514,8 @@ summary = {
"projectionLag": lag.get("status"),
"runnerProvider": agentrun.get("runnerProviderClassification"),
"actorForbidden": http_summary.get("actorForbidden"),
"terminalStatus": terminal_status,
"failureKind": agentrun.get("failureKind"),
},
}
evidence = {