fix: classify D601 provider health signals

This commit is contained in:
Codex
2026-05-20 20:04:32 +00:00
parent d766875a39
commit 8a822c686e
7 changed files with 113 additions and 14 deletions
+48 -10
View File
@@ -24,6 +24,12 @@ export type ProviderBlockingDisposition =
| "service-degraded"
| "global-blocker";
export type ProviderTriageDecision =
| "healthy"
| "retryable-transient"
| "service-degraded"
| "global-offline";
export interface ProviderTriageSignal {
id: string;
scope: ProviderSignalScope;
@@ -36,11 +42,15 @@ export interface ProviderTriageSignal {
export interface ProviderTriageClassification {
scope: ProviderSignalScope;
decision: ProviderTriageDecision;
observedAt: string;
retryable: boolean;
recommendedCrossChecks: string[];
blockingDisposition: ProviderBlockingDisposition;
rationale: string[];
failedScopes: ProviderSignalScope[];
degradedScopes: ProviderSignalScope[];
healthyScopes: ProviderSignalScope[];
failedIndependentScopes: ProviderSignalScope[];
healthyIndependentScopes: ProviderSignalScope[];
}
@@ -193,8 +203,23 @@ function sshSignal(result: unknown, providerId: string): ProviderTriageSignal {
function registrySignal(result: unknown): ProviderTriageSignal {
const record = asRecord(result);
if (record === null) return signal("artifact-registry-health", "registry", "unknown", "artifact registry health returned non-object", result);
const status: ProviderSignalStatus = record.ok === true && record.healthy !== false ? "ok" : record.ok === false ? "failed" : "degraded";
return signal("artifact-registry-health", "registry", status, `artifact registry health ok=${String(record.ok)} healthy=${String(record.healthy)}`, {
const checks = asRecord(record.checks) ?? {};
const runtimeApiHealthy = checks.containerRunning === true && checks.loopbackOnly === true && checks.v2Ok === true;
const status: ProviderSignalStatus = record.ok === true && record.healthy !== false
? "ok"
: runtimeApiHealthy
? "degraded"
: record.ok === false
? "failed"
: "degraded";
return signal("artifact-registry-health", "registry", status, [
`artifact registry health ok=${String(record.ok)}`,
`healthy=${String(record.healthy)}`,
`unitActive=${String(checks.unitActive)}`,
`containerRunning=${String(checks.containerRunning)}`,
`loopbackOnly=${String(checks.loopbackOnly)}`,
`v2Ok=${String(checks.v2Ok)}`,
].join(" "), {
ok: record.ok,
installed: record.installed ?? null,
healthy: record.healthy ?? null,
@@ -273,9 +298,9 @@ export function providerTriageRecommendedCrossChecks(providerId: string): string
];
}
function uniqueScopes(signals: ProviderTriageSignal[], statuses: ProviderSignalStatus[]): ProviderSignalScope[] {
function uniqueScopes(signals: ProviderTriageSignal[], statuses: ProviderSignalStatus[], independentOnly = true): ProviderSignalScope[] {
return Array.from(new Set(signals
.filter((item) => item.independentPath)
.filter((item) => !independentOnly || item.independentPath)
.filter((item) => statuses.includes(item.status))
.map((item) => item.scope)))
.sort();
@@ -292,10 +317,11 @@ function primaryScope(signals: ProviderTriageSignal[]): ProviderSignalScope {
}
export function classifyProviderTriage(providerId: string, signals: ProviderTriageSignal[], observedAt = isoNow()): ProviderTriageClassification {
const failedScopes = uniqueScopes(signals, ["failed"]);
const degradedScopes = uniqueScopes(signals, ["degraded"]);
const failedScopes = uniqueScopes(signals, ["failed"], false);
const degradedScopes = uniqueScopes(signals, ["degraded"], false);
const healthyScopes = uniqueScopes(signals, ["ok"]);
const independentFailedScopes = failedScopes.filter((scope) => scope !== "runner-local");
const independentFailedScopes = uniqueScopes(signals, ["failed"]).filter((scope) => scope !== "runner-local");
const independentDegradedScopes = uniqueScopes(signals, ["degraded"]);
const failedCriticalScopes = independentFailedScopes.filter((scope) => criticalScopes.has(scope));
const runnerLocalObservedFailure = signals.some((signal) => signal.scope === "runner-local" && signal.status === "failed");
const serviceOnlyFailure = independentFailedScopes.length > 0 && independentFailedScopes.every((scope) => scope === "registry" || scope === "service-proxy" || scope === "microservice" || scope === "k3s");
@@ -312,7 +338,7 @@ export function classifyProviderTriage(providerId: string, signals: ProviderTria
} else if (serviceOnlyFailure && hasIndependentHealthy) {
blockingDisposition = "service-degraded";
rationale.push("service-scoped path failed while at least one provider-level path remains healthy");
} else if (failedCriticalScopes.length > 0 || degradedScopes.some((scope) => criticalScopes.has(scope))) {
} else if (failedCriticalScopes.length > 0 || independentDegradedScopes.some((scope) => criticalScopes.has(scope))) {
blockingDisposition = hasIndependentHealthy ? "provider-degraded" : "transient";
rationale.push(hasIndependentHealthy
? "provider-critical path is degraded but cross-checks still show independent healthy evidence"
@@ -327,15 +353,27 @@ export function classifyProviderTriage(providerId: string, signals: ProviderTria
if (runnerLocalObservedFailure) rationale.push("runner-local observation failed but is not counted as an independent global blocker by contract");
if (hasIndependentHealthy) rationale.push(`healthy independent scopes: ${healthyScopes.join(", ")}`);
if (failedScopes.length > 0) rationale.push(`failed independent scopes: ${failedScopes.join(", ")}`);
if (failedScopes.length > 0) rationale.push(`failed scopes: ${failedScopes.join(", ")}`);
const hasAnyIssueSignal = signals.some((item) => item.status === "failed" || item.status === "degraded");
const decision: ProviderTriageDecision = blockingDisposition === "global-blocker"
? "global-offline"
: blockingDisposition === "service-degraded"
? "service-degraded"
: hasAnyIssueSignal
? "retryable-transient"
: "healthy";
return {
scope: runnerLocalObservedFailure && failedScopes.length === 0 && degradedScopes.length === 0 ? "runner-local" : primaryScope(signals),
scope: runnerLocalObservedFailure && independentFailedScopes.length === 0 && independentDegradedScopes.length === 0 ? "runner-local" : primaryScope(signals),
decision,
observedAt,
retryable: blockingDisposition !== "global-blocker",
recommendedCrossChecks: providerTriageRecommendedCrossChecks(providerId),
blockingDisposition,
rationale,
failedScopes,
degradedScopes,
healthyScopes,
failedIndependentScopes: independentFailedScopes,
healthyIndependentScopes: healthyScopes,
};