fix: correct durable readiness attribution

This commit is contained in:
unidesk-code-queue-runner
2026-05-23 15:29:57 +00:00
parent 6b7acb7159
commit 50256826d7
3 changed files with 420 additions and 17 deletions
@@ -0,0 +1,240 @@
{
"runtime": {
"durableReady": {
"runtime": {
"adapter": "postgres",
"durable": true,
"durableRequested": true,
"durableCapable": true,
"ready": true,
"status": "ready",
"blocker": null,
"liveRuntimeEvidence": true,
"connection": {
"queryAttempted": true,
"queryResult": "durable_readiness_ready"
},
"durabilityContract": {
"ready": true,
"status": "ready",
"blockedLayer": null,
"blocker": null,
"liveRuntimeEvidence": true,
"secretMaterialRead": false
},
"gates": {
"ssl": { "checked": true, "ready": true, "status": "ready", "blocker": null },
"auth": { "checked": true, "ready": true, "status": "ready", "blocker": null },
"schema": { "checked": true, "ready": true, "status": "ready", "blocker": null },
"migration": { "checked": true, "ready": true, "status": "ready", "blocker": null },
"durability": { "checked": true, "ready": true, "status": "ready", "blocker": null }
}
},
"readiness": {
"contractVersion": "v3",
"ready": true,
"status": "ok",
"blockerCodes": [],
"blockers": [],
"components": {
"db": "ready",
"codeAgent": "ready",
"runtime": "ready"
},
"durability": {
"status": "ready",
"ready": true,
"adapter": "postgres",
"durable": true,
"durableRequested": true,
"durableCapable": true,
"runtimeStatus": "ready",
"runtimeReady": true,
"liveRuntimeEvidence": true,
"dbLiveEvidenceObserved": true,
"dbLiveEvidenceIsDurabilityEvidence": false,
"blockedLayer": null,
"blocker": null,
"queryAttempted": true,
"queryResult": "durable_readiness_ready",
"secretMaterialRead": false
}
},
"blockerCodes": []
},
"durableQueryBlocked": {
"status": "degraded",
"ready": false,
"runtime": {
"adapter": "postgres",
"durable": true,
"durableRequested": true,
"ready": false,
"status": "blocked",
"blocker": "runtime_durable_adapter_query_blocked",
"liveRuntimeEvidence": false,
"connection": {
"queryAttempted": true,
"queryResult": "query_blocked"
},
"durabilityContract": {
"ready": false,
"status": "blocked",
"blockedLayer": "durability_query",
"blocker": "runtime_durable_adapter_query_blocked"
}
},
"readiness": {
"ready": false,
"status": "blocked",
"durability": {
"status": "blocked",
"ready": false,
"blocker": "runtime_durable_adapter_query_blocked",
"blockedLayer": "durability_query",
"queryResult": "query_blocked"
}
},
"blockerCodes": ["runtime_durable_adapter_query_blocked"]
},
"authBlocked": {
"status": "degraded",
"ready": false,
"runtime": {
"adapter": "postgres",
"durable": true,
"durableRequested": true,
"ready": false,
"status": "blocked",
"blocker": "runtime_durable_adapter_auth_blocked",
"liveRuntimeEvidence": false,
"connection": {
"queryAttempted": true,
"queryResult": "auth_blocked"
},
"durabilityContract": {
"ready": false,
"status": "blocked",
"blockedLayer": "auth",
"blocker": "runtime_durable_adapter_auth_blocked"
}
},
"readiness": {
"ready": false,
"status": "blocked",
"durability": {
"status": "blocked",
"ready": false,
"blocker": "runtime_durable_adapter_auth_blocked",
"blockedLayer": "auth",
"queryResult": "auth_blocked"
}
},
"blockerCodes": ["runtime_durable_adapter_auth_blocked"]
},
"schemaBlocked": {
"status": "degraded",
"ready": false,
"runtime": {
"adapter": "postgres",
"durable": true,
"durableRequested": true,
"ready": false,
"status": "blocked",
"blocker": "runtime_durable_adapter_schema_blocked",
"liveRuntimeEvidence": false,
"connection": {
"queryAttempted": true,
"queryResult": "schema_blocked"
},
"durabilityContract": {
"ready": false,
"status": "blocked",
"blockedLayer": "schema",
"blocker": "runtime_durable_adapter_schema_blocked"
}
},
"readiness": {
"ready": false,
"status": "blocked",
"durability": {
"status": "blocked",
"ready": false,
"blocker": "runtime_durable_adapter_schema_blocked",
"blockedLayer": "schema",
"queryResult": "schema_blocked"
}
},
"blockerCodes": ["runtime_durable_adapter_schema_blocked"]
},
"unknownMissingReadiness": {
"status": "unknown",
"ready": null
}
},
"codeAgent": {
"readOnlySessionTools": {
"endpoint": "POST /v1/agent/chat",
"status": "available",
"ready": true,
"provider": "codex-readonly-runner",
"backend": "hwlab-cloud-api/controlled-readonly-session-registry",
"capabilityLevel": "read-only-session-tools",
"sessionMode": "controlled-readonly-session-registry",
"implementationType": "controlled-readonly-session-registry",
"trackingIssue": "#317",
"runner": {
"kind": "hwlab-readonly-runner",
"ready": true,
"writeCapable": false,
"durableSession": false,
"codexStdio": false
},
"runnerLimitations": [
"not-codex-stdio",
"not-write-capable",
"not-durable-session"
],
"longLivedSessionGate": {
"status": "blocked",
"pass": false,
"sourceIssue": "pikasTech/HWLAB#317",
"blockers": [
{
"code": "stdio_protocol_not_wired",
"sourceIssue": "pikasTech/HWLAB#317"
}
]
}
}
},
"m3": {
"controlReady": {
"status": "available",
"readiness": {
"status": "ready",
"controlReady": true,
"sourceKind": "DEV-LIVE",
"evidenceLevel": "DEV-LIVE"
}
},
"trustedGreenSummary": {
"contractVersion": "m3-status-v1",
"status": "live",
"sourceKind": "DEV-LIVE",
"summary": "M3 trusted green fixture",
"patchPanel": {
"serviceId": "hwlab-patch-panel",
"connectionActive": true
},
"trust": {
"durableStatus": "green",
"blocker": null,
"operationId": "op_m3_fixture_green",
"traceId": "trc_m3_fixture_green",
"auditId": "aud_m3_fixture_green",
"evidenceId": "evd_m3_fixture_green"
}
}
}
}
+55 -16
View File
@@ -173,15 +173,6 @@ function classifyApiProbe(probe, context) {
const payload = probe.data;
const serviceId = payload?.serviceId ?? context.serviceId;
if (context.apiPath === "/v1" && payload?.codeAgent) {
const codeAgentProbe = classifyCodeAgentProbe({ restIndex: probe });
if (codeAgentProbe?.kind === "readonly") {
return {
...codeAgentProbe,
rawStatus: rawStatusFrom(payload)
};
}
}
const durableReason = durableRuntimeReason(payload);
if (durableReason) {
return readOnlyProbe({
@@ -194,6 +185,16 @@ function classifyApiProbe(probe, context) {
});
}
if (context.apiPath === "/v1" && payload?.codeAgent) {
const codeAgentProbe = classifyCodeAgentProbe({ restIndex: probe });
if (codeAgentProbe && codeAgentProbe.kind !== "pass" && codeAgentProbe.kind !== "unverified") {
return {
...codeAgentProbe,
rawStatus: rawStatusFrom(payload)
};
}
}
const blocker = firstBlocker(payload);
if (blocker) {
const reasonCode = String(blocker.code ?? blocker.reason ?? "blocked");
@@ -549,13 +550,23 @@ export function classifyRuntimeDurableReadiness(payload = {}, options = {}) {
durability?.queryResult,
dbRuntimeReadiness?.queryResult
);
const queryBlocker = runtimeDurableBlockerFromQueryResult(queryResult);
const readyQueryResult = isRuntimeDurableReadyQueryResult(queryResult);
const explicitDurabilityReady = durabilityReadySignal({
runtime,
durability,
dbRuntimeReadiness,
gateBlocker,
queryResult,
readyQueryResult,
queryBlocker
});
const directBlocker = firstNonEmpty(
runtime?.blocker,
explicitDurabilityReady ? "" : runtime?.blocker,
durability?.blocker,
dbRuntimeReadiness?.blocker,
blockerCodeStartingWith(payload, "runtime_durable_adapter_")
explicitDurabilityReady ? "" : blockerCodeStartingWith(payload, "runtime_durable_adapter_")
);
const queryBlocker = runtimeDurableBlockerFromQueryResult(queryResult);
const reasonCode = firstNonEmpty(directBlocker, gateBlocker?.blocker, queryBlocker);
const blockedLayer = firstNonEmpty(
runtime?.durabilityContract?.blockedLayer,
@@ -575,8 +586,6 @@ export function classifyRuntimeDurableReadiness(payload = {}, options = {}) {
durability?.liveRuntimeEvidence === true ||
dbRuntimeReadiness?.liveRuntimeEvidence === true;
const rawStatus = rawStatusFrom(payload);
const rawStatusBlocked = [...ERROR_STATUSES, ...BLOCKED_STATUSES, ...RAW_DEGRADED_STATUSES].includes(normalizedStatus(rawStatus));
const readyQueryResult = isRuntimeDurableReadyQueryResult(queryResult);
const postgresRequired = options.requirePostgresAdapter === true;
const adapterReady = !postgresRequired || adapter === "postgres";
const ready = adapterReady &&
@@ -585,7 +594,8 @@ export function classifyRuntimeDurableReadiness(payload = {}, options = {}) {
durabilityReady &&
liveRuntimeEvidence &&
!reasonCode &&
!rawStatusBlocked;
!blockedLayer &&
(!queryResult || readyQueryResult);
if (ready) {
return {
@@ -622,7 +632,7 @@ export function classifyRuntimeDurableReadiness(payload = {}, options = {}) {
runtimeDurable ? "" : "runtime_durable_adapter_missing",
runtimeReady ? "" : "runtime_durable_runtime_not_ready",
liveRuntimeEvidence ? "" : "runtime_durable_live_evidence_missing",
rawStatusBlocked ? rawStatus : "",
isBlockedRuntimeStatus(rawStatus) ? rawStatus : "",
"runtime_durable_adapter_not_ready"
);
const layer = firstNonEmpty(
@@ -658,6 +668,35 @@ export function classifyRuntimeDurableReadiness(payload = {}, options = {}) {
};
}
function durabilityReadySignal({
runtime,
durability,
dbRuntimeReadiness,
gateBlocker,
queryResult,
readyQueryResult,
queryBlocker
}) {
if (gateBlocker || queryBlocker) return false;
if (queryResult && !readyQueryResult) return false;
const ready = durability?.ready === true ||
dbRuntimeReadiness?.ready === true ||
runtime?.durabilityContract?.ready === true;
if (!ready) return false;
return !firstNonEmpty(
durability?.blocker,
dbRuntimeReadiness?.blocker,
runtime?.durabilityContract?.blocker,
durability?.blockedLayer,
dbRuntimeReadiness?.blockedLayer,
runtime?.durabilityContract?.blockedLayer
);
}
function isBlockedRuntimeStatus(status) {
return [...ERROR_STATUSES, ...BLOCKED_STATUSES, ...RAW_DEGRADED_STATUSES].includes(normalizedStatus(status));
}
function firstBlockedRuntimeGate(gates = {}) {
for (const layer of RUNTIME_DURABLE_GATE_LAYERS) {
const gate = gates?.[layer];
@@ -1,7 +1,17 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { classifyWorkbenchLiveStatus } from "../live-status.mjs";
import {
classifyRuntimeDurableReadiness,
classifyWorkbenchLiveStatus
} from "../live-status.mjs";
import { wiringPresentationFromSummary } from "../wiring-status.mjs";
const statusMatrix = JSON.parse(readFileSync(
new URL("../../../fixtures/cloud-web/durable-readiness-status-matrix.json", import.meta.url),
"utf8"
));
const okApi = Object.freeze({
ok: true,
@@ -609,6 +619,112 @@ test("keeps ready durable runtime green while attributing read-only mode to Code
assert.doesNotMatch(healthLiveProbe.reason, /blocked/u);
});
test("fixture matrix keeps durable_readiness_ready green and attributes read-only mode to Code Agent", () => {
const restPayload = {
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
...statusMatrix.runtime.durableReady,
codeAgent: statusMatrix.codeAgent.readOnlySessionTools
};
const durable = classifyRuntimeDurableReadiness(restPayload);
const status = classifyWorkbenchLiveStatus({
healthLive: jsonProbe({
serviceId: "hwlab-cloud-api",
status: "ok",
ready: true,
...statusMatrix.runtime.durableReady
}),
restIndex: jsonProbe(restPayload),
health: okApi,
adapter: okApi,
m3Control: jsonProbe(statusMatrix.m3.controlReady),
m3Status: jsonProbe(statusMatrix.m3.trustedGreenSummary)
});
assert.equal(durable.ready, true);
assert.equal(durable.evidence.blocker, null);
assert.equal(durable.evidence.blockedLayer, null);
assert.equal(durable.evidence.queryResult, "durable_readiness_ready");
assert.equal(status.kind, "readonly");
assert.equal(status.reasonCode, "code_agent_read_only_session_tools");
assert.equal(status.apiPath, "POST /v1/agent/chat");
assert.match(status.detail, /#317 full pass not complete/u);
assert.doesNotMatch(status.detail, /runtime durable blocked|blocked at durability/u);
});
test("fixture matrix preserves runtime durable blocked attribution when durability is actually blocked", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: jsonProbe(statusMatrix.runtime.durableQueryBlocked),
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
const durable = classifyRuntimeDurableReadiness(statusMatrix.runtime.durableQueryBlocked);
assert.equal(durable.ready, false);
assert.equal(durable.reasonCode, "runtime_durable_adapter_query_blocked");
assert.equal(durable.evidence.blockedLayer, "durability_query");
assert.equal(status.kind, "readonly");
assert.equal(status.reasonCode, "runtime_durable_adapter_query_blocked");
assert.match(status.detail, /runtime durable/u);
assert.match(status.detail, /query_blocked/u);
});
test("fixture matrix keeps auth and schema runtime blockers on their exact layers", () => {
for (const [name, expectedReason, expectedLayer, expectedQuery] of [
["authBlocked", "runtime_durable_adapter_auth_blocked", "auth", "auth_blocked"],
["schemaBlocked", "runtime_durable_adapter_schema_blocked", "schema", "schema_blocked"]
]) {
const durable = classifyRuntimeDurableReadiness(statusMatrix.runtime[name]);
const status = classifyWorkbenchLiveStatus({
healthLive: jsonProbe(statusMatrix.runtime[name]),
restIndex: okRest,
health: okApi,
adapter: okApi,
m3Control: okM3Control,
m3Status: okM3Status
});
assert.equal(durable.reasonCode, expectedReason);
assert.equal(durable.evidence.blockedLayer, expectedLayer);
assert.equal(durable.evidence.queryResult, expectedQuery);
assert.equal(status.kind, "readonly");
assert.equal(status.reasonCode, expectedReason);
}
});
test("fixture matrix treats unknown or missing readiness as unverified, not runtime durable blocked", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: jsonProbe(statusMatrix.runtime.unknownMissingReadiness)
});
assert.equal(status.kind, "unverified");
assert.equal(status.label, "等待验证");
assert.doesNotMatch(`${status.reasonCode} ${status.detail}`, /runtime durable blocked|blocked at durability/u);
});
test("fixture matrix keeps M3 trusted green summary aligned with live status and wiring presentation", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: okApi,
restIndex: codexStdioRest,
health: okApi,
adapter: okApi,
m3Control: jsonProbe(statusMatrix.m3.controlReady),
m3Status: jsonProbe(statusMatrix.m3.trustedGreenSummary)
});
const wiring = wiringPresentationFromSummary(statusMatrix.m3.trustedGreenSummary);
const m3Probe = status.probes.find((probe) => probe.apiPath === "/v1/m3/status");
assert.equal(status.kind, "pass");
assert.equal(m3Probe.kind, "pass");
assert.equal(wiring.m3Live, true);
assert.equal(wiring.stateLabel, "实况已验证");
assert.equal(wiring.badgeTone, "dev-live");
});
test("classifies M3 control blockers by cloud-api/gateway/box/patch-panel layer", () => {
const status = classifyWorkbenchLiveStatus({
healthLive: okApi,
@@ -673,3 +789,11 @@ test("includes trusted M3 evidence identifiers in probe attribution", () => {
assert.match(m3Probe?.evidenceSummary ?? "", /audit=aud_m3_live/u);
assert.match(m3Probe?.evidenceSummary ?? "", /evidence=evd_m3_live/u);
});
function jsonProbe(data, status = 200) {
return {
ok: true,
status,
data
};
}