export const CODE_AGENT_M3_IO_ROUTE = "/v1/m3/io"; export const CODE_AGENT_M3_TRUSTED_ROUTE = Object.freeze({ fromResourceId: "res_boxsimu_1", fromPort: "DO1", patchPanelServiceId: "hwlab-patch-panel", toResourceId: "res_boxsimu_2", toPort: "DI1" }); export const CODE_AGENT_M3_SKILL_PROVIDER = "hwlab-skill-cli"; export const CODE_AGENT_M3_SKILL_RUNNER_KIND = "hwlab-m3-io-skill-cli"; export const CODE_AGENT_M3_SKILL_NAME = "hwlab-agent-runtime.m3-io"; export const CODE_AGENT_M3_PATH_LABEL = "Code Agent -> Skill CLI -> HWLAB API"; const missingProofLabel = "未产生/不可证明"; const nonProofIds = new Set(["", "n/a", "none", "null", "undefined", "not_observed", "not-observed"]); const directPathFields = Object.freeze([ "directGatewayCalls", "directBoxCalls", "directPatchPanelCalls", "directGatewayCallsAllowed", "directBoxCallsAllowed", "directBoxSimuCallsAllowed", "directPatchPanelCallsAllowed" ]); const safeInternalLinkPattern = /^\/(?:v1\/(?:m3|audit|evidence|operations?)|json-rpc\b|gate\b|diagnostics\/gate\b)/u; export function codeAgentM3EvidenceContractSummary() { return [ "Code Agent M3 evidence renderer consumes Skill CLI / /v1/m3/io facts from providerTrace, runnerTrace, and toolCalls.", "It renders operation/audit/evidence metadata: operationId, traceId, auditId, evidenceId, route, target, readback, accepted/status/blocker, and direct-path validity.", "Missing proof IDs render as 未产生/不可证明; direct gateway/box/patch-panel paths never render as trusted pass." ].join(" "); } export function isCodeAgentM3SkillCompletion(value) { const evidence = extractCodeAgentM3Evidence(value); return Boolean( evidence && value?.status === "completed" && evidence.route === CODE_AGENT_M3_IO_ROUTE && evidence.directPathInvalid !== true && evidence.provider === CODE_AGENT_M3_SKILL_PROVIDER && evidence.runnerKind === CODE_AGENT_M3_SKILL_RUNNER_KIND ); } export function extractCodeAgentM3Evidence(message) { const toolCall = findM3ToolCall(message); const m3Io = objectOrNull(message?.m3Io); const source = toolCall ?? message?.providerTrace ?? message?.runnerTrace ?? null; if (!source && !m3Io && !isM3ProviderMessage(message)) return null; const providerTrace = objectOrNull(message?.providerTrace); const runnerTrace = objectOrNull(message?.runnerTrace); const route = firstNonEmpty(source?.route, m3Io?.trace?.route, m3Io?.path?.hwlabApi?.route, providerTrace?.route, runnerTrace?.route, CODE_AGENT_M3_IO_ROUTE); const provider = firstNonEmpty(message?.provider, source?.provider, providerTrace?.provider); const runnerKind = firstNonEmpty(message?.runner?.kind, source?.runnerKind, providerTrace?.runnerKind, runnerTrace?.runnerKind); const command = objectOrNull(source?.command) ?? objectOrNull(message?.command); const result = objectOrNull(source?.result) ?? objectOrNull(message?.result); const response = parseToolStdout(source?.stdout); const blocker = firstBlocker(source, response, providerTrace, runnerTrace, message); const trustBlocker = firstTrustBlocker(m3Io, source, response, providerTrace, runnerTrace, message); const target = normalizeTarget(source, response, command, m3Io); const readback = normalizeReadback(source, response, result, m3Io); const action = firstNonEmpty(m3Io?.action, source?.action, response?.action, command?.action); const trust = normalizeTrust(m3Io, source, response, trustBlocker); const ids = { operationId: firstNonEmpty(m3Io?.operation?.operationId, source?.operationId, response?.operationId, providerTrace?.operationId, runnerTrace?.operationId, message?.operationId), traceId: firstNonEmpty(m3Io?.trace?.traceId, source?.traceId, response?.traceId, providerTrace?.traceId, runnerTrace?.traceId, message?.traceId), auditId: firstNonEmpty(m3Io?.operation?.auditId, source?.audit?.auditId, response?.audit?.auditId, message?.auditId, message?.audit?.auditId), evidenceId: firstNonEmpty(m3Io?.operation?.evidenceId, source?.evidence?.evidenceId, response?.evidence?.evidenceId, message?.evidenceId, message?.evidence?.evidenceId) }; const directPathInvalid = classifyDirectPathInvalid(source, response, message); const readbackMismatch = classifyReadbackMismatch({ action, target, readback, blocker }); const accepted = normalizeBoolean(firstDefined(m3Io?.accepted, source?.accepted, response?.accepted, providerTrace?.accepted)); const status = firstNonEmpty(m3Io?.status, source?.status, response?.status, providerTrace?.status, runnerTrace?.status, message?.status); const links = normalizeEvidenceLinks(source, response, providerTrace, message); const path = normalizePath(m3Io, route); const wiring = normalizeWiring(m3Io); if (!isM3EvidenceShape({ route, provider, runnerKind, source, m3Io })) return null; return { kind: "m3-io", responseType: firstNonEmpty(m3Io?.type, source?.responseType, message?.responseType), provider, runnerKind, route, action, status, accepted, blocker, trustBlocker, trust, directPathInvalid, readbackMismatch, target, readback, path, wiring, ids, links, verdict: classifyM3Verdict({ accepted, status, blocker, trustBlocker, trust, directPathInvalid, readbackMismatch, ids }), source }; } export function m3EvidenceRows(evidence) { if (!evidence) return []; const idRows = [ evidenceValueRow("operationId", evidence.ids.operationId, { copyable: true, href: evidence.links.operationId }), evidenceValueRow("traceId", evidence.ids.traceId, { copyable: true, href: evidence.links.traceId }), evidenceValueRow("auditId", evidence.ids.auditId, { copyable: true, href: evidence.links.auditId }), evidenceValueRow("evidenceId", evidence.ids.evidenceId, { copyable: true, href: evidence.links.evidenceId }) ]; const target = evidence.target; const readback = evidence.readback; return [ evidenceValueRow("状态", evidence.verdict.label, { tone: evidence.verdict.tone }), evidenceValueRow("类型", evidence.responseType ?? evidence.kind, { tone: evidence.responseType === "m3_io_blocker" ? "blocked" : "source" }), evidenceValueRow("动作", evidence.action ?? missingProofLabel), evidenceValueRow("accepted", evidence.accepted === null ? "unknown" : String(evidence.accepted), { tone: evidence.accepted === true ? "source" : "blocked" }), evidenceValueRow("status", evidence.status ?? missingProofLabel, { tone: evidence.status === "blocked" ? "blocked" : "source" }), evidenceValueRow("路径", evidence.path.summary, { copyable: true }), evidenceValueRow("接线", evidence.wiring.label, { copyable: true }), evidenceValueRow("route", evidence.route ?? missingProofLabel, { copyable: true, href: evidence.links.route }), evidenceValueRow("DO1", resourcePortValueLabel(target), { copyable: false }), evidenceValueRow("DI1", resourcePortValueLabel(readback), { tone: evidence.readbackMismatch ? "blocked" : "source" }), evidenceValueRow("trusted", booleanStateLabel(evidence.trust.trusted), { tone: evidence.trust.trusted === true ? "dev-live" : evidence.trust.trusted === false ? "warn" : "source" }), evidenceValueRow("durable", booleanStateLabel(evidence.trust.durable), { tone: evidence.trust.durable === true ? "dev-live" : evidence.trust.durable === false ? "warn" : "source" }), ...idRows, evidenceValueRow("blocker", blockerLabel(evidence.blocker), { tone: evidence.blocker ? "blocked" : "source" }) ]; } export function m3EvidenceSummaryText(evidence) { if (!evidence) return ""; return `${evidence.verdict.label} / ${evidence.path.summary} / DO1=${formatValue(evidence.target.value)} / DI1=${formatValue(evidence.readback.value)} / operation=${proofLabel(evidence.ids.operationId)}`; } export function proofLabel(value) { const text = stringOrNull(value); return text && !nonProofIds.has(text.toLowerCase()) ? text : missingProofLabel; } function evidenceValueRow(label, value, options = {}) { const proofValue = label.endsWith("Id") ? proofLabel(value) : String(value ?? missingProofLabel); return { label, value: proofValue, tone: options.tone ?? (proofValue === missingProofLabel ? "blocked" : "source"), copyable: options.copyable === true && proofValue !== missingProofLabel, href: safeInternalHref(options.href) }; } function classifyM3Verdict({ accepted, status, blocker, trustBlocker, trust, directPathInvalid, readbackMismatch, ids }) { if (directPathInvalid) { return { key: "direct-path-invalid", tone: "blocked", label: "direct-path-invalid", summary: "直接 gateway/box/patch-panel 路径无效,不能显示为可信闭环通过。" }; } if (readbackMismatch) { return { key: "readback-mismatch", tone: "blocked", label: "readback-mismatch", summary: "DI1 readback 与 DO1 target value 不一致,不能证明闭环。" }; } if (blocker || accepted === false || String(status ?? "").toLowerCase() === "blocked") { return { key: "blocked", tone: "blocked", label: "blocked", summary: blockerLabel(blocker) }; } if (accepted === true && ["succeeded", "completed", "accepted"].includes(String(status ?? "").toLowerCase())) { if (trustBlocker || trust?.trusted === false) { return { key: "accepted-untrusted", tone: "degraded", label: "accepted / 可信持久化未通过", summary: trustBlocker ? blockerLabel(trustBlocker) : "受控路径已返回,但 trusted/durable 未 green。" }; } const missingIds = Object.entries(ids).filter(([, value]) => proofLabel(value) === missingProofLabel); if (missingIds.length > 0) { return { key: "accepted-missing-proof", tone: "degraded", label: "accepted / 缺少证据ID", summary: `accepted 但缺少 ${missingIds.map(([key]) => key).join(", ")},不能证明完整可信闭环。` }; } return { key: "accepted", tone: "dev-live", label: "accepted", summary: "受控 Skill CLI 已通过 HWLAB API /v1/m3/io 返回 operation/audit/evidence facts。" }; } return { key: "unknown", tone: "blocked", label: "未产生/不可证明", summary: "没有足够的 M3 IO 事实证明该回复执行了受控路径。" }; } function classifyReadbackMismatch({ action, target, readback, blocker }) { if (String(action ?? "").toLowerCase() !== "do.write") return false; if (target.value === undefined || target.value === null || readback.value === undefined || readback.value === null) return false; if (normalizeBoolean(target.value) === normalizeBoolean(readback.value)) return false; return true; } function classifyDirectPathInvalid(...sources) { for (const source of sources) { if (!source || typeof source !== "object") continue; const safety = objectOrNull(source.safety) ?? {}; const hwlabApi = objectOrNull(source.hwlabApi) ?? {}; const controlPath = objectOrNull(source.controlPath) ?? {}; const blockerText = [ source.blocker?.code, source.blocker?.message, source.blocker?.zh, source.capabilityBlocker?.code, source.capabilityBlocker?.message, source.capabilityBlocker?.zh, source.error?.code, source.error?.message ].filter(Boolean).join(" "); if (/direct[_-]?(?:hardware|gateway|box|patch)/iu.test(blockerText)) return true; if (controlPath.frontendBypass === true || hwlabApi.cloudApiOnly === false) return true; for (const field of directPathFields) { if (source[field] === true || safety[field] === true || hwlabApi[field] === true) return true; } } return false; } function normalizeTarget(source, response, command, m3Io = null) { const target = objectOrNull(source?.target) ?? objectOrNull(response?.target) ?? {}; const commandObject = objectOrNull(command) ?? objectOrNull(response?.command) ?? {}; return { resourceId: firstNonEmpty(m3Io?.do1?.resourceId, target.resourceId, commandObject.resourceId, source?.resourceId, response?.resourceId, CODE_AGENT_M3_TRUSTED_ROUTE.fromResourceId), port: firstNonEmpty(m3Io?.do1?.port, target.port, commandObject.port, source?.port, response?.port, CODE_AGENT_M3_TRUSTED_ROUTE.fromPort), value: firstDefined(m3Io?.do1?.targetValue, target.value, commandObject.value, source?.value, response?.value) }; } function normalizeReadback(source, response, result, m3Io = null) { const targetReadback = objectOrNull(result?.targetReadback) ?? objectOrNull(response?.result?.targetReadback) ?? objectOrNull(source?.result?.targetReadback) ?? objectOrNull(source?.targetReadback) ?? {}; return { resourceId: firstNonEmpty(m3Io?.di1?.resourceId, targetReadback.resourceId, CODE_AGENT_M3_TRUSTED_ROUTE.toResourceId), port: firstNonEmpty(m3Io?.di1?.port, targetReadback.port, CODE_AGENT_M3_TRUSTED_ROUTE.toPort), value: firstDefined(m3Io?.di1?.observedValue, targetReadback.value, result?.value) }; } function normalizePath(m3Io, route) { return { summary: firstNonEmpty(m3Io?.path?.summary, `${CODE_AGENT_M3_PATH_LABEL} ${route ?? CODE_AGENT_M3_IO_ROUTE}`), segments: Array.isArray(m3Io?.path?.segments) && m3Io.path.segments.length > 0 ? m3Io.path.segments : ["Code Agent", "Skill CLI", "HWLAB API"] }; } function normalizeWiring(m3Io) { return { from: firstNonEmpty(m3Io?.wiring?.from, `${CODE_AGENT_M3_TRUSTED_ROUTE.fromResourceId}:${CODE_AGENT_M3_TRUSTED_ROUTE.fromPort}`), via: firstNonEmpty(m3Io?.wiring?.via, CODE_AGENT_M3_TRUSTED_ROUTE.patchPanelServiceId), to: firstNonEmpty(m3Io?.wiring?.to, `${CODE_AGENT_M3_TRUSTED_ROUTE.toResourceId}:${CODE_AGENT_M3_TRUSTED_ROUTE.toPort}`), label: firstNonEmpty( m3Io?.wiring?.label, `${CODE_AGENT_M3_TRUSTED_ROUTE.fromResourceId}:${CODE_AGENT_M3_TRUSTED_ROUTE.fromPort} -> ${CODE_AGENT_M3_TRUSTED_ROUTE.patchPanelServiceId} -> ${CODE_AGENT_M3_TRUSTED_ROUTE.toResourceId}:${CODE_AGENT_M3_TRUSTED_ROUTE.toPort}` ) }; } function normalizeTrust(m3Io, source, response, trustBlocker) { const trust = objectOrNull(m3Io?.trust) ?? {}; const durableValue = firstDefined( trust.durable, source?.durable?.durable, response?.durable?.durable ); const trustedValue = firstDefined(trust.trusted, source?.trusted, response?.trusted); const durable = normalizeBoolean(durableValue); const trusted = normalizeBoolean(trustedValue); return { trusted: trusted === null ? (trustBlocker ? false : null) : trusted, durable: durable === null ? null : durable, blocker: trustBlocker, sourceKind: firstNonEmpty(trust.evidenceSourceKind, source?.evidence?.sourceKind, response?.evidence?.sourceKind), durableStatus: firstNonEmpty(trust.durableStatus, source?.durable?.status, response?.durable?.status) }; } function resourcePortValueLabel(item) { const value = item.value === undefined || item.value === null ? "value=未产生/不可证明" : `value=${String(item.value)}`; return `${item.resourceId ?? missingProofLabel}:${item.port ?? missingProofLabel} ${value}`; } function firstBlocker(...sources) { for (const source of sources) { if (!source || typeof source !== "object") continue; const candidate = objectOrNull(source.blocker) ?? objectOrNull(source.capabilityBlocker) ?? objectOrNull(source.error?.blocker); if (candidate) return candidate; if (Array.isArray(source.blockers)) { const blocker = source.blockers.find((item) => (item?.code || item?.message || item?.zh) && !isTrustOnlyBlocker(item)); if (blocker) return blocker; } } return null; } function firstTrustBlocker(...sources) { for (const source of sources) { if (!source || typeof source !== "object") continue; const candidate = objectOrNull(source.trustBlocker) ?? objectOrNull(source.trust?.trustBlocker); if (candidate) return candidate; if (Array.isArray(source.blockers)) { const blocker = source.blockers.find((item) => (item?.code || item?.message || item?.zh) && isTrustOnlyBlocker(item)); if (blocker) return blocker; } } return null; } function isTrustOnlyBlocker(blocker) { const text = `${blocker?.code ?? ""} ${blocker?.layer ?? ""} ${blocker?.category ?? ""}`; return /durable|runtime|trust|evidence/i.test(text); } function blockerLabel(blocker) { if (!blocker) return "none"; return [blocker.code, blocker.zh ?? blocker.message ?? blocker.reason].filter(Boolean).join(": "); } function normalizeEvidenceLinks(...sources) { const links = {}; for (const source of sources) { if (!source || typeof source !== "object") continue; const candidates = [ source.links, source.urls, source.detailUrls, source.internalRoutes, source.evidence?.links, source.audit?.links ].filter((item) => item && typeof item === "object"); for (const candidate of candidates) { for (const key of ["operationId", "traceId", "auditId", "evidenceId", "route"]) { links[key] ??= safeInternalHref(candidate[key] ?? candidate[key.replace(/Id$/u, "")]); } } } return links; } function safeInternalHref(value) { const text = stringOrNull(value); if (!text || !safeInternalLinkPattern.test(text)) return null; return text; } function parseToolStdout(stdout) { const text = stringOrNull(stdout); if (!text) return null; try { const payload = JSON.parse(text); return payload && typeof payload === "object" ? payload : null; } catch { return null; } } function isM3EvidenceShape({ route, provider, runnerKind, source, m3Io }) { if (route !== CODE_AGENT_M3_IO_ROUTE) return false; if (m3Io?.type === "m3_io_result" || m3Io?.type === "m3_io_blocker") return true; if (provider === CODE_AGENT_M3_SKILL_PROVIDER) return true; if (runnerKind === CODE_AGENT_M3_SKILL_RUNNER_KIND) return true; if (source?.name === CODE_AGENT_M3_SKILL_NAME) return true; return false; } function findM3ToolCall(message) { const calls = Array.isArray(message?.toolCalls) ? message.toolCalls : []; return calls.find((tool) => tool?.name === CODE_AGENT_M3_SKILL_NAME || tool?.route === CODE_AGENT_M3_IO_ROUTE || tool?.runnerKind === CODE_AGENT_M3_SKILL_RUNNER_KIND || tool?.type === "skill-cli" && tool?.hwlabApi?.route === CODE_AGENT_M3_IO_ROUTE ) ?? null; } function isM3ProviderMessage(message) { return message?.provider === CODE_AGENT_M3_SKILL_PROVIDER || message?.runner?.kind === CODE_AGENT_M3_SKILL_RUNNER_KIND || message?.providerTrace?.route === CODE_AGENT_M3_IO_ROUTE || message?.runnerTrace?.route === CODE_AGENT_M3_IO_ROUTE; } function firstNonEmpty(...values) { for (const value of values) { const text = stringOrNull(value); if (text) return text; } return null; } function firstDefined(...values) { return values.find((value) => value !== undefined && value !== null); } function normalizeBoolean(value) { if (typeof value === "boolean") return value; if (typeof value === "number") return value === 1 ? true : value === 0 ? false : null; const text = stringOrNull(value)?.toLowerCase(); if (text === "true") return true; if (text === "false") return false; return null; } function objectOrNull(value) { return value && typeof value === "object" && !Array.isArray(value) ? value : null; } function stringOrNull(value) { const text = String(value ?? "").trim(); return text ? text : null; } function formatValue(value) { return value === undefined || value === null ? missingProofLabel : String(value); } function booleanStateLabel(value) { if (value === true) return "true"; if (value === false) return "false"; return "unknown"; }