import assert from "node:assert/strict"; import test from "node:test"; import { CODE_AGENT_M3_IO_ROUTE, codeAgentM3EvidenceContractSummary, extractCodeAgentM3Evidence, isCodeAgentM3SkillCompletion, m3EvidenceRows } from "./code-agent-m3-evidence.mjs"; test("renders accepted M3 Skill CLI operation/audit/evidence metadata", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "succeeded", accepted: true, operationId: "op_m3_cli_accepted", traceId: "trc_m3_cli_accepted", auditId: "aud_m3_cli_accepted_succeeded", evidenceId: "evd_m3_cli_accepted_succeeded", value: true, readbackValue: true })); assert.equal(evidence.verdict.key, "accepted"); assert.equal(evidence.responseType, "m3_io_result"); assert.equal(evidence.route, CODE_AGENT_M3_IO_ROUTE); assert.equal(evidence.target.resourceId, "res_boxsimu_1"); assert.equal(evidence.target.port, "DO1"); assert.equal(evidence.target.value, true); assert.equal(evidence.readback.resourceId, "res_boxsimu_2"); assert.equal(evidence.readback.port, "DI1"); assert.equal(evidence.readback.value, true); assert.equal(evidence.ids.operationId, "op_m3_cli_accepted"); assert.equal(evidence.ids.traceId, "trc_m3_cli_accepted"); assert.equal(evidence.ids.auditId, "aud_m3_cli_accepted_succeeded"); assert.equal(evidence.ids.evidenceId, "evd_m3_cli_accepted_succeeded"); assert.equal(isCodeAgentM3SkillCompletion(m3Message()), true); assert.equal(rowValue(evidence, "路径"), "Code Agent -> Skill CLI -> HWLAB API /v1/m3/io"); assert.equal(rowValue(evidence, "接线"), "res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1"); assert.match(rowValue(evidence, "DO1"), /res_boxsimu_1:DO1 value=true/u); assert.match(rowValue(evidence, "DI1"), /res_boxsimu_2:DI1 value=true/u); assert.equal(rowValue(evidence, "evidenceId"), "evd_m3_cli_accepted_succeeded"); }); test("renders blocker state from Skill CLI without trusted pass", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "blocked", accepted: false, operationId: "op_m3_blocked", blocker: { code: "m3_wiring_missing", zh: "hwlab-patch-panel 未确认 active DO1 -> DI1 接线" } })); assert.equal(evidence.verdict.key, "blocked"); assert.equal(evidence.responseType, "m3_io_blocker"); assert.equal(evidence.verdict.tone, "blocked"); assert.match(rowValue(evidence, "blocker"), /m3_wiring_missing/u); assert.equal(isCodeAgentM3SkillCompletion({ ...m3Message(), status: "failed" }), false); }); test("renders accepted but non-durable M3 IO result as degraded, not DEV-LIVE trusted", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "succeeded", accepted: true, value: false, readbackValue: false, trust: { trusted: false, durable: false, durableStatus: "degraded", durableBlocker: "runtime_durable_not_green" }, trustBlocker: { code: "runtime_durable_not_green", layer: "runtime-durable", zh: "runtime durable 未 green" } })); assert.equal(evidence.verdict.key, "accepted-untrusted"); assert.equal(evidence.verdict.tone, "degraded"); assert.equal(rowValue(evidence, "trusted"), "false"); assert.equal(rowValue(evidence, "durable"), "false"); assert.match(rowValue(evidence, "DI1"), /value=false/u); }); test("shows missing evidenceId as unavailable proof instead of fabricating one", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "succeeded", accepted: true, evidenceId: null })); assert.equal(evidence.verdict.key, "accepted-missing-proof"); assert.equal(rowValue(evidence, "evidenceId"), "未产生/不可证明"); assert.equal(row(evidence, "evidenceId").copyable, false); }); test("classifies DO1 target and DI1 readback mismatch as blocked proof", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "blocked", accepted: false, operationId: "op_m3_readback_mismatch", value: true, readbackValue: false, blocker: { code: "m3_readback_mismatch", zh: "DI1 回读值 false 与 DO1 写入值 true 不一致" } })); assert.equal(evidence.readbackMismatch, true); assert.equal(evidence.verdict.key, "readback-mismatch"); assert.match(rowValue(evidence, "DI1"), /res_boxsimu_2:DI1 value=false/u); }); test("classifies direct gateway/box/patch-panel path as invalid and never trusted", () => { const evidence = extractCodeAgentM3Evidence(m3Message({ status: "succeeded", accepted: true, operationId: "op_m3_direct_path", controlPath: { cloudApi: false, gatewaySimu: true, boxSimu: true, patchPanel: true, frontendBypass: true }, blocker: { code: "direct_hardware_target_blocked", zh: "Skill CLI target must be HWLAB cloud-api, not gateway/box/patch-panel." } })); assert.equal(evidence.directPathInvalid, true); assert.equal(evidence.verdict.key, "direct-path-invalid"); assert.equal(evidence.verdict.tone, "blocked"); }); test("contract summary documents operation/audit/evidence visibility", () => { assert.match(codeAgentM3EvidenceContractSummary(), /operationId/u); assert.match(codeAgentM3EvidenceContractSummary(), /auditId/u); assert.match(codeAgentM3EvidenceContractSummary(), /evidenceId/u); assert.match(codeAgentM3EvidenceContractSummary(), /direct gateway\/box\/patch-panel/u); }); function row(evidence, label) { const found = m3EvidenceRows(evidence).find((item) => item.label === label); assert.ok(found, `missing row ${label}`); return found; } function rowValue(evidence, label) { return row(evidence, label).value; } function m3Message(overrides = {}) { const operationId = overrides.operationId ?? "op_m3_cli_accepted"; const traceId = overrides.traceId ?? "trc_m3_cli_accepted"; const auditId = Object.hasOwn(overrides, "auditId") ? overrides.auditId : "aud_m3_cli_accepted_succeeded"; const evidenceId = Object.hasOwn(overrides, "evidenceId") ? overrides.evidenceId : "evd_m3_cli_accepted_succeeded"; const value = Object.hasOwn(overrides, "value") ? overrides.value : true; const readbackValue = Object.hasOwn(overrides, "readbackValue") ? overrides.readbackValue : value; const status = overrides.status ?? "succeeded"; const accepted = Object.hasOwn(overrides, "accepted") ? overrides.accepted : true; const responseType = overrides.responseType ?? (accepted && status !== "blocked" ? "m3_io_result" : "m3_io_blocker"); const trust = overrides.trust ?? { trusted: responseType === "m3_io_result", durable: responseType === "m3_io_result", durableStatus: responseType === "m3_io_result" ? "green" : "blocked", durableBlocker: responseType === "m3_io_result" ? null : "m3_io_blocked" }; const toolCall = { id: "tool_m3_fixture", type: "skill-cli", name: "hwlab-agent-runtime.m3-io", responseType, status: accepted ? "completed" : "blocked", route: CODE_AGENT_M3_IO_ROUTE, accepted, operationId, traceId, audit: { auditId }, evidence: { evidenceId, status: evidenceId ? "green" : "blocked", sourceKind: evidenceId ? "DEV-LIVE" : "BLOCKED" }, command: { action: "do.write", resourceId: "res_boxsimu_1", port: "DO1", value }, result: { value, targetReadback: { resourceId: "res_boxsimu_2", port: "DI1", value: readbackValue } }, blocker: overrides.blocker ?? null, trustBlocker: overrides.trustBlocker ?? null, blockers: [overrides.blocker, overrides.trustBlocker].filter(Boolean), controlPath: overrides.controlPath ?? { cloudApi: true, gatewaySimu: true, boxSimu: true, patchPanel: true, frontendBypass: false }, safety: { cloudApiRouteOnly: true, allowedRoute: CODE_AGENT_M3_IO_ROUTE, directGatewayCalls: false, directBoxCalls: false, directPatchPanelCalls: false, fallbackUsed: false }, stdout: JSON.stringify({ route: CODE_AGENT_M3_IO_ROUTE, status, accepted, traceId, operationId, audit: { auditId }, evidence: { evidenceId }, blocker: overrides.blocker ?? null, result: { value, targetReadback: { resourceId: "res_boxsimu_2", port: "DI1", value: readbackValue } } }) }; return { status: "completed", responseType, m3Io: { type: responseType, status, action: "do.write", accepted, do1: { resourceId: "res_boxsimu_1", port: "DO1", targetValue: value }, di1: { resourceId: "res_boxsimu_2", port: "DI1", observedValue: readbackValue }, wiring: { from: "res_boxsimu_1:DO1", via: "hwlab-patch-panel", to: "res_boxsimu_2:DI1", label: "res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1" }, path: { summary: "Code Agent -> Skill CLI -> HWLAB API /v1/m3/io", segments: ["Code Agent", "Skill CLI", "HWLAB API"], hwlabApi: { route: CODE_AGENT_M3_IO_ROUTE, method: "POST" } }, operation: { operationId, auditId, evidenceId }, trace: { traceId, route: CODE_AGENT_M3_IO_ROUTE, method: "POST" }, trust, blocker: overrides.blocker ?? null, blockers: [overrides.blocker, overrides.trustBlocker].filter(Boolean) }, provider: "hwlab-skill-cli", model: "controlled-m3-io", backend: "hwlab-cloud-api/hwlab-agent-runtime-skill-cli", traceId, conversationId: "conv_m3_fixture", sessionId: "sess_m3_fixture", messageId: "msg_m3_fixture", runner: { kind: "hwlab-m3-io-skill-cli" }, runnerTrace: { runnerKind: "hwlab-m3-io-skill-cli", route: CODE_AGENT_M3_IO_ROUTE, status, accepted, operationId, traceId }, providerTrace: { runnerKind: "hwlab-m3-io-skill-cli", skill: "hwlab-agent-runtime.m3-io", responseType, route: CODE_AGENT_M3_IO_ROUTE, status, accepted, operationId, traceId, fallbackUsed: false }, toolCalls: [toolCall], reply: { content: "M3 IO Skill CLI result fixture." } }; }