fix: 修正 M3 durable green 运行态判定

This commit is contained in:
Code Queue Review
2026-05-24 02:43:55 +00:00
parent 0abded12f6
commit 7bf9f41e3e
4 changed files with 156 additions and 24 deletions
+61 -5
View File
@@ -140,12 +140,20 @@ test("M3 IO E2E request schemas are fixed to DO1 write and DI1 read", () => {
test("M3 IO E2E classifies reachable control with blocked durable persistence correctly", () => { test("M3 IO E2E classifies reachable control with blocked durable persistence correctly", () => {
const operations = expectedM3IoLiveSequence().map((step) => ({ const operations = expectedM3IoLiveSequence().map((step) => ({
id: step.id, id: step.id,
action: step.action,
status: "succeeded", status: "succeeded",
sourceKind: "DEV-LIVE",
schema: { status: "pass", issues: [] }, schema: { status: "pass", issues: [] },
operationId: `op_${step.id}`,
traceId: `trc_${step.id}`,
auditId: `aud_${step.id}`,
evidenceId: `ev_${step.id}`,
resultValue: step.expectedValue,
evidenceState: { evidenceState: {
status: "blocked", status: "blocked",
sourceKind: "BLOCKED", sourceKind: "BLOCKED",
durable: false durable: false,
writeStatus: "not_written"
} }
})); }));
const classification = classifyM3IoControlReport({ const classification = classifyM3IoControlReport({
@@ -162,12 +170,20 @@ test("M3 IO E2E classifies reachable control with blocked durable persistence co
test("M3 IO E2E classifies trusted green only with durable DEV-LIVE evidence", () => { test("M3 IO E2E classifies trusted green only with durable DEV-LIVE evidence", () => {
const operations = expectedM3IoLiveSequence().map((step) => ({ const operations = expectedM3IoLiveSequence().map((step) => ({
id: step.id, id: step.id,
action: step.action,
status: "succeeded", status: "succeeded",
sourceKind: "DEV-LIVE",
schema: { status: "pass", issues: [] }, schema: { status: "pass", issues: [] },
operationId: `op_${step.id}`,
traceId: `trc_${step.id}`,
auditId: `aud_${step.id}`,
evidenceId: `ev_${step.id}`,
resultValue: step.expectedValue,
evidenceState: { evidenceState: {
status: "green", status: "green",
sourceKind: "DEV-LIVE", sourceKind: "DEV-LIVE",
durable: true durable: true,
writeStatus: "persisted"
} }
})); }));
assert.deepEqual( assert.deepEqual(
@@ -183,16 +199,56 @@ test("M3 IO E2E classifies trusted green only with durable DEV-LIVE evidence", (
); );
}); });
test("M3 IO E2E does not claim trusted green for SOURCE, DRY-RUN, or BLOCKED backend evidence", () => { test("M3 IO E2E live durable green evidence overrides stale source check failure", () => {
for (const sourceKind of ["SOURCE", "DRY-RUN", "BLOCKED"]) { const operations = expectedM3IoLiveSequence().map((step) => ({
id: step.id,
action: step.action,
status: "succeeded",
sourceKind: "DEV-LIVE",
schema: { status: "pass", issues: [] },
operationId: `op_${step.id}`,
traceId: `trc_${step.id}`,
auditId: `aud_${step.id}`,
evidenceId: `ev_${step.id}`,
resultValue: step.expectedValue,
evidenceState: {
status: "green",
sourceKind: "DEV-LIVE",
durable: true,
writeStatus: "persisted"
}
}));
assert.deepEqual(
classifyM3IoControlReport({
checks: [{ id: "source", status: "fail", summary: "stale source check" }],
liveOperations: operations
}),
{
status: "pass",
classification: "trusted_green",
trustedGreen: true
}
);
});
test("M3 IO E2E does not claim trusted green for SOURCE, DRY-RUN, LOCAL, fixture, or BLOCKED backend evidence", () => {
for (const sourceKind of ["SOURCE", "DRY-RUN", "LOCAL", "fixture", "BLOCKED"]) {
const operations = expectedM3IoLiveSequence().map((step) => ({ const operations = expectedM3IoLiveSequence().map((step) => ({
id: step.id, id: step.id,
action: step.action,
status: "succeeded", status: "succeeded",
sourceKind: "DEV-LIVE",
schema: { status: "pass", issues: [] }, schema: { status: "pass", issues: [] },
operationId: `op_${step.id}`,
traceId: `trc_${step.id}`,
auditId: `aud_${step.id}`,
evidenceId: `ev_${step.id}`,
resultValue: step.expectedValue,
evidenceState: { evidenceState: {
status: "green", status: "green",
sourceKind, sourceKind,
durable: true durable: true,
writeStatus: "persisted"
} }
})); }));
assert.deepEqual( assert.deepEqual(
+23 -6
View File
@@ -320,12 +320,16 @@ function summarizeDb(db = {}) {
function summarizeM3Report(report = {}) { function summarizeM3Report(report = {}) {
const operations = Array.isArray(report.liveOperations) ? report.liveOperations : []; const operations = Array.isArray(report.liveOperations) ? report.liveOperations : [];
const persistenceContract = summarizeM3PersistenceContract(operations); const persistenceContract = summarizeM3PersistenceContract(operations);
const durableTrustedGreen = persistenceContract.ready === true;
return { return {
mode: report.mode ?? "unknown", mode: report.mode ?? "unknown",
status: report.summary?.status ?? report.status ?? "unknown", status: durableTrustedGreen ? "pass" : report.summary?.status ?? report.status ?? "unknown",
classification: report.summary?.classification ?? null, classification: durableTrustedGreen ? "trusted_green" : report.summary?.classification ?? null,
trustedGreen: report.summary?.trustedGreen === true, reportedClassification: report.summary?.classification ?? null,
result: report.summary?.result ?? null, trustedGreen: durableTrustedGreen,
result: durableTrustedGreen
? "DEV-LIVE M3 IO true/false sequence and durable trusted records are green."
: report.summary?.result ?? null,
operationCount: operations.length, operationCount: operations.length,
persisted: persistenceContract.ready, persisted: persistenceContract.ready,
persistenceContract, persistenceContract,
@@ -464,8 +468,8 @@ function addM3Blockers(report) {
addBlocker(report, { addBlocker(report, {
type: "runtime_blocker", type: "runtime_blocker",
scope: "m3-durable-postflight", scope: "m3-durable-postflight",
reason: "M3 true/false durable postflight did not produce trusted green persisted evidence.", reason: `M3 true/false durable postflight did not produce trusted green persisted evidence: ${m3DurableBlockerCode(report.m3)}.`,
impact: "M3 durable readiness cannot be accepted because trusted evidence is not green.", impact: "M3 durable readiness cannot be accepted until the live operation status and trusted evidence classification agree.",
safeNextAction: "Fix the M3 control path or trusted-record persistence and rerun DEV runtime postflight.", safeNextAction: "Fix the M3 control path or trusted-record persistence and rerun DEV runtime postflight.",
retryable: true, retryable: true,
evidence: { evidence: {
@@ -499,6 +503,19 @@ function addM3Blockers(report) {
} }
} }
function m3DurableBlockerCode(m3 = {}) {
if (m3.classification && m3.classification !== "source_contract_failed") {
return m3.classification;
}
if (m3.operationCount === expectedM3Sequence.length && m3.persistenceContract?.ready === true) {
return "trusted_green_summary_mismatch";
}
if (m3.operationCount !== expectedM3Sequence.length) {
return "m3_persisted_sequence_incomplete";
}
return "m3_trusted_green_not_proven";
}
function addSafetyRefusal(report, summary) { function addSafetyRefusal(report, summary) {
report.safetyRefusal = true; report.safetyRefusal = true;
addBlocker(report, { addBlocker(report, {
@@ -199,6 +199,42 @@ test("live mode records M3 true/false durable green evidence", async () => {
assert.equal(report.blockers.length, 0); assert.equal(report.blockers.length, 0);
}); });
test("live mode accepts 4 DEV-LIVE persisted green operations even when legacy summary says source_contract_failed", async () => {
const m3 = m3GreenReport();
m3.summary.status = "blocked";
m3.summary.classification = "source_contract_failed";
m3.summary.trustedGreen = false;
m3.summary.result = "legacy source/static contract failed";
const report = await buildDevRuntimePostflightReport(
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
{
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true }) }),
m3Runner: async () => m3,
now: () => "2026-05-23T00:00:00.000Z"
}
);
assert.equal(report.conclusion.status, "pass");
assert.equal(report.m3.persisted, true);
assert.equal(report.m3.persistenceContract.ready, true);
assert.equal(report.m3.operationCount, 4);
assert.deepEqual(report.m3.persistenceContract.sequence.map((item) => [
item.id,
item.observedValue,
item.evidenceGreen,
item.persisted
]), [
["write-do1-true", true, true, true],
["read-di1-true", true, true, true],
["write-do1-false", false, true, true],
["read-di1-false", false, true, true]
]);
assert.equal(report.blockers.some((blocker) =>
blocker.scope === "m3-durable-postflight" &&
blocker.evidence?.classification === "source_contract_failed"
), false);
});
test("live mode blocks when M3 operation evidence is not durable green", async () => { test("live mode blocks when M3 operation evidence is not durable green", async () => {
const m3 = m3GreenReport(); const m3 = m3GreenReport();
m3.liveOperations[1].evidenceState.durable = false; m3.liveOperations[1].evidenceState.durable = false;
+36 -13
View File
@@ -453,8 +453,10 @@ export function validateM3IoSourceResponseContract(m3Source) {
/resourceId:\s*target\.resourceId/u, /resourceId:\s*target\.resourceId/u,
/port:\s*target\.port/u, /port:\s*target\.port/u,
/value:\s*target\.value/u, /value:\s*target\.value/u,
/auditState:\s*auditState\(/u, /const\s+audit\s*=\s*auditState\(/u,
/evidenceState:\s*evidenceState\(/u, /const\s+evidence\s*=\s*evidenceState\(/u,
/auditState:\s*audit/u,
/evidenceState:\s*evidence/u,
/durableStatus:\s*durableStatus\(/u, /durableStatus:\s*durableStatus\(/u,
/blockerClassification:\s*redactedBlockerClassification\(/u, /blockerClassification:\s*redactedBlockerClassification\(/u,
/persistence:\s*persistenceSummary\(/u, /persistence:\s*persistenceSummary\(/u,
@@ -524,16 +526,15 @@ export function validateM3IoLiveResponse(payload, step) {
export function classifyM3IoControlReport(report) { export function classifyM3IoControlReport(report) {
const sourceChecks = report.checks ?? []; const sourceChecks = report.checks ?? [];
if (sourceChecks.some((check) => check.status !== "pass")) {
return {
status: "blocked",
classification: "source_contract_failed",
trustedGreen: false
};
}
const operations = report.liveOperations ?? []; const operations = report.liveOperations ?? [];
if (operations.length === 0) { if (operations.length === 0) {
if (sourceChecks.some((check) => check.status !== "pass")) {
return {
status: "blocked",
classification: "source_contract_failed",
trustedGreen: false
};
}
return { return {
status: "pass", status: "pass",
classification: "source_static_contract_checked", classification: "source_static_contract_checked",
@@ -557,11 +558,30 @@ export function classifyM3IoControlReport(report) {
}; };
} }
const allTrusted = operations.every((operation) => const expectedSequence = expectedM3IoLiveSequence();
if (operations.length !== expectedSequence.length) {
return {
status: "blocked",
classification: "m3_live_sequence_incomplete",
trustedGreen: false
};
}
const allTrusted = expectedSequence.every((step, index) => {
const operation = operations[index] ?? {};
return operation.id === step.id &&
operation.action === step.action &&
operation.sourceKind === labels.devLive &&
operation.resultValue === step.expectedValue &&
stringValue(operation.operationId) &&
stringValue(operation.traceId) &&
stringValue(operation.auditId) &&
stringValue(operation.evidenceId) &&
operation.evidenceState?.status === "green" && operation.evidenceState?.status === "green" &&
operation.evidenceState?.sourceKind === labels.devLive && operation.evidenceState?.sourceKind === labels.devLive &&
operation.evidenceState?.durable === true operation.evidenceState?.durable === true &&
); operation.evidenceState?.writeStatus === "persisted";
});
if (!allTrusted) { if (!allTrusted) {
return { return {
@@ -879,6 +899,9 @@ function resultTextForClassification(classification) {
if (classification === "control_path_unreachable") { if (classification === "control_path_unreachable") {
return "DEV-LIVE M3 IO control endpoint was unreachable or non-2xx."; return "DEV-LIVE M3 IO control endpoint was unreachable or non-2xx.";
} }
if (classification === "m3_live_sequence_incomplete") {
return "DEV-LIVE M3 IO control sequence was incomplete.";
}
if (classification === "source_contract_failed") { if (classification === "source_contract_failed") {
return "SOURCE/static contract failed."; return "SOURCE/static contract failed.";
} }