const trustedLiveProviders = new Set(["openai-responses", "codex-cli", "codex-readonly-runner", "codex-stdio"]); const trustedRunnerProviders = new Set(["codex-stdio"]); const partialRunnerProviders = new Set(["codex-readonly-runner"]); const trustedCodexSandboxes = new Set(["workspace-write", "danger-full-access"]); const readonlySessionCapabilityLevels = new Set(["read-only-tools", "read-only-session-tools"]); const untrustedProviderPattern = /\b(?:echo|mock|fixture|stub|sample)\b/iu; const blockedCodeAgentUiLabels = new Set([ "后端失败", "服务受阻", "等待超时", "Provider 不可用", "Runner 忙碌", "Session 受阻", "Runner 受阻", "API 错误", "需要配置", "能力未开放", "安全阻断", "仍是 fallback", "BLOCKED 凭证缺口" ]); const timeoutPattern = /\b(?:timeout|timed out|abort|aborted|超时|请求超过|无新事件)\b/iu; export function classifyCodeAgentChatReadiness(payload, { realDevLive = false, httpStatus = null } = {}) { const providerBlock = classifyCodeAgentProviderBlock(payload, { httpStatus }); if (providerBlock.blocked) { return { status: "blocked", level: providerBlock.level, blocker: providerBlock.blocker, devLiveReplyPass: false, reason: providerBlock.reason, ...(providerBlock.providerStatus != null ? { providerStatus: providerBlock.providerStatus } : {}) }; } const assistantReply = typeof payload?.reply?.content === "string" ? payload.reply.content.trim() : ""; if (payload?.status === "completed" && assistantReply) { const evidence = inspectRealCompletionEvidence(payload); if (!evidence.ok) { return { status: "blocked", level: realDevLive ? "BLOCKED/untrusted-completion" : "SOURCE", blocker: "untrusted-completion", devLiveReplyPass: false, reason: `completed response is missing real provider/model/trace/conversation evidence or looks like echo/mock/stub: ${evidence.reason}` }; } if (realDevLive) { return { status: "pass", level: "#143 DEV-LIVE reply pass", blocker: null, devLiveReplyPass: true, reason: "real DEV /v1/agent/chat completed with a non-empty assistant reply" }; } return { status: "blocked", level: "SOURCE", blocker: "not-dev-live", devLiveReplyPass: false, reason: "mock, fixture, local stub, or source-only completion cannot be counted as #143 DEV-LIVE reply pass" }; } const suffix = httpStatus ? ` (HTTP ${httpStatus})` : ""; return { status: "blocked", level: "BLOCKED", blocker: "runtime", devLiveReplyPass: false, reason: `Code Agent chat did not produce a completed non-empty assistant reply${suffix}` }; } export function classifyCodexRunnerCapability(payload, { httpStatus = null } = {}) { const providerBlock = classifyCodeAgentProviderBlock(payload, { httpStatus }); if (providerBlock.blocked) { return { status: "blocked", level: providerBlock.level, blocker: providerBlock.blocker, capabilityPass: false, reason: providerBlock.reason, ...(providerBlock.providerStatus != null ? { providerStatus: providerBlock.providerStatus } : {}) }; } const provider = stringOrNull(payload?.provider); const runnerKind = stringOrNull(payload?.runner?.kind); const capabilityLevel = stringOrNull(payload?.capabilityLevel); const workspace = stringOrNull(payload?.workspace ?? payload?.runner?.workspace); const sandbox = stringOrNull(payload?.sandbox ?? payload?.runner?.sandbox); const toolCalls = Array.isArray(payload?.toolCalls) ? payload.toolCalls : []; const runnerTrace = payload?.runnerTrace && typeof payload.runnerTrace === "object" ? payload.runnerTrace : null; const skills = payload?.skills && typeof payload.skills === "object" ? payload.skills : null; const sessionMode = stringOrNull(payload?.sessionMode ?? payload?.runner?.sessionMode ?? payload?.runner?.session); const implementationType = stringOrNull(payload?.implementationType ?? payload?.runner?.implementationType); const runnerLimitations = Array.isArray(payload?.runnerLimitations) ? payload.runnerLimitations.filter((item) => typeof item === "string") : Array.isArray(payload?.runner?.runnerLimitations) ? payload.runner.runnerLimitations.filter((item) => typeof item === "string") : []; const sessionReuse = payload?.sessionReuse && typeof payload.sessionReuse === "object" ? payload.sessionReuse : null; const session = payload?.session && typeof payload.session === "object" ? payload.session : null; const longLivedSessionGate = payload?.longLivedSessionGate && typeof payload.longLivedSessionGate === "object" ? payload.longLivedSessionGate : null; if (provider === "openai-responses" || runnerKind === "openai-responses-fallback") { return { status: "blocked", level: "BLOCKED/text-chat-only", blocker: "openai-fallback-not-runner", capabilityPass: false, reason: "OpenAI Responses fallback can answer text, but it has no workspace/tools/skills runner evidence." }; } const missing = []; if (payload?.status !== "completed") missing.push("completed status"); if (!trustedRunnerProviders.has(provider)) missing.push("runner provider"); if (runnerKind !== "codex-app-server-stdio-runner") missing.push("runner.kind=codex-app-server-stdio-runner"); if (capabilityLevel !== "long-lived-codex-stdio-session") missing.push("capabilityLevel=long-lived-codex-stdio-session"); if (!workspace) missing.push("workspace"); if (!trustedCodexSandboxes.has(sandbox)) missing.push("sandbox=workspace-write|danger-full-access"); if (sessionMode !== "codex-app-server-stdio-long-lived") missing.push("sessionMode=codex-app-server-stdio-long-lived"); if (implementationType !== "repo-owned-codex-app-server-stdio-session") missing.push("implementationType=repo-owned-codex-app-server-stdio-session"); if (!session) missing.push("session"); if (session && !["idle", "ready", "busy"].includes(session.status)) missing.push("session.status active/idle"); if (session && typeof session.idleTimeoutMs !== "number") missing.push("session.idleTimeoutMs"); if (session && !session.lastTraceId) missing.push("session.lastTraceId"); if (session && session.longLivedSession !== true) missing.push("session.longLivedSession=true"); if (session && session.codexStdio !== true) missing.push("session.codexStdio=true"); if (!sessionReuse) missing.push("sessionReuse"); if (toolCalls.length === 0) missing.push("toolCalls"); if (!runnerTrace) missing.push("runnerTrace"); if (!skills) missing.push("skills"); if (payload?.runner?.codexStdio !== true) missing.push("runner.codexStdio=true"); if (payload?.runner?.writeCapable !== true) missing.push("runner.writeCapable=true"); if (payload?.runner?.durableSession !== true) missing.push("runner.durableSession=true"); if (!longLivedSessionGate) missing.push("longLivedSessionGate"); if (longLivedSessionGate?.status !== "pass" || longLivedSessionGate?.pass !== true) missing.push("longLivedSessionGate=pass"); if (missing.length > 0) { if (partialRunnerProviders.has(provider) && runnerKind === "hwlab-readonly-runner") { return { status: "blocked", level: "BLOCKED/controlled-readonly-long-lived-session", blocker: "controlled-readonly-not-long-lived", capabilityPass: false, reason: "controlled-readonly-session-registry exposes a reusable read-only session, but it is not Codex stdio, a write-capable sandbox, or a full Code Agent capability pass." }; } return { status: "blocked", level: "BLOCKED/runner-capability", blocker: "runner-evidence-missing", capabilityPass: false, reason: `Codex runner capability evidence is incomplete: ${missing.join(", ")}` }; } if (toolCalls.some((tool) => tool.status !== "completed")) { return { status: "blocked", level: "BLOCKED/tool", blocker: "tool-unavailable", capabilityPass: false, reason: "At least one runner tool call is not completed." }; } return { status: "pass", level: "#275 long-lived Codex stdio session skeleton pass", blocker: null, capabilityPass: true, longLivedSession: true, reason: "completed repo-owned Codex stdio response includes reusable session, write-capable sandbox, toolCalls, skills, runnerTrace, and a passed long-lived session gate" }; } export function classifyCodeAgentProviderBlock(payload, { httpStatus = null } = {}) { const payloadStatus = stringOrNull(payload?.status); const errorCode = stringOrNull(payload?.error?.code); const availabilityStatus = stringOrNull(payload?.availability?.status); const missingEnv = Array.isArray(payload?.error?.missingEnv) ? payload.error.missingEnv.filter((item) => typeof item === "string") : []; const providerStatus = numericStatus(payload?.error?.providerStatus); const responseStatus = numericStatus(httpStatus); const providerHttpBlocked = isHttpNon2xxStatus(providerStatus); const responseHttpBlocked = isHttpNon2xxStatus(responseStatus); const httpBlocked = providerHttpBlocked || responseHttpBlocked; const blockingHttpStatus = providerHttpBlocked ? providerStatus : responseHttpBlocked ? responseStatus : providerStatus ?? responseStatus; const providerUnavailable = errorCode === "provider_unavailable" || availabilityStatus === "blocked" || payloadStatus === "blocked" || httpBlocked; if (!providerUnavailable) { return { blocked: false }; } if (httpBlocked) { return { blocked: true, level: "BLOCKED/provider", blocker: "provider-upstream", providerStatus: blockingHttpStatus, missingEnv, reason: `Code Agent HTTP non-2xx status ${blockingHttpStatus} means the upstream response is blocked, not completed` }; } if (missingEnv.includes("OPENAI_API_KEY")) { return { blocked: true, level: "BLOCKED/credential", blocker: "credential", providerStatus: blockingHttpStatus, missingEnv, reason: "provider_unavailable with missing OPENAI_API_KEY means the provider credential contract is incomplete" }; } if (missingEnv.includes("HWLAB_CODE_AGENT_OPENAI_BASE_URL")) { return { blocked: true, level: "BLOCKED/provider-config", blocker: "provider-config", providerStatus: blockingHttpStatus, missingEnv, reason: "provider_unavailable with missing HWLAB_CODE_AGENT_OPENAI_BASE_URL means the provider egress/base-url contract is incomplete" }; } return { blocked: true, level: "BLOCKED/provider", blocker: "provider-unavailable", providerStatus: blockingHttpStatus, missingEnv, reason: "provider_unavailable or availability.status=blocked means the provider path is blocked, not completed" }; } export function summarizeCodeAgentPayload(payload, { httpStatus = null, traceId = null } = {}) { const providerBlock = classifyCodeAgentProviderBlock(payload, { httpStatus }); const hasObjectPayload = payload && typeof payload === "object" && !Array.isArray(payload); if (!hasObjectPayload) { if (!providerBlock.blocked) return null; return { status: "failed", sourceKind: null, evidenceLevel: null, provider: "unknown", model: "unknown", backend: "unknown", traceId: traceId || "unknown", hasReply: false, error: { code: "provider_unavailable", missingEnv: [], missingCommands: [], providerStatus: providerBlock.providerStatus }, runner: null, workspace: null, sandbox: null, capabilityLevel: null, toolCalls: [], skills: null, runnerTrace: null, sessionMode: null, sessionLifecycleStatus: null, sessionSummary: null, sessionReuse: null, session: null, implementationType: null, runnerLimitations: [], codexStdioFeasibility: null, longLivedSessionGate: null, conversationFacts: null }; } const error = normalizeCodeAgentError(payload.error); const assistantReply = typeof payload.reply?.content === "string" ? payload.reply.content.trim() : ""; const provider = stringOrNull(payload.provider) ?? (providerBlock.blocked ? "unknown" : null); const model = stringOrNull(payload.model) ?? (providerBlock.blocked ? "unknown" : null); const backend = stringOrNull(payload.backend) ?? (providerBlock.blocked ? "unknown" : null); const observedTraceId = stringOrNull(payload.traceId) ?? traceId ?? (providerBlock.blocked ? "unknown" : null); if (providerBlock.blocked) { const blockedError = error ? { ...error, code: error.code ?? "provider_unavailable", providerStatus: error.providerStatus ?? providerBlock.providerStatus } : { code: "provider_unavailable", missingEnv: providerBlock.missingEnv ?? [], missingCommands: [], providerStatus: providerBlock.providerStatus }; return { status: "failed", sourceKind: stringOrNull(payload.sourceKind), evidenceLevel: stringOrNull(payload.evidenceLevel), provider, model, backend, traceId: observedTraceId, hasReply: false, error: blockedError, blocker: summarizeBlocker(payload.blocker ?? payload.error?.blocker), runner: summarizeRunner(payload), workspace: stringOrNull(payload.workspace), sandbox: stringOrNull(payload.sandbox), capabilityLevel: stringOrNull(payload.capabilityLevel), toolCalls: summarizeToolCalls(payload.toolCalls), skills: summarizeSkills(payload.skills), runnerTrace: summarizeRunnerTrace(payload.runnerTrace), sessionMode: stringOrNull(payload.sessionMode), sessionLifecycleStatus: stringOrNull(payload.sessionLifecycleStatus ?? payload.sessionSummary?.status ?? payload.session?.lifecycleStatus), sessionSummary: summarizeSessionLifecycle(payload.sessionSummary ?? payload.sessionLifecycle), sessionReuse: summarizeSessionReuse(payload.sessionReuse), session: summarizeSession(payload.session), implementationType: stringOrNull(payload.implementationType), runnerLimitations: summarizeStringList(payload.runnerLimitations), codexStdioFeasibility: summarizeCodexStdioFeasibility(payload.codexStdioFeasibility), longLivedSessionGate: summarizeLongLivedSessionGate(payload.longLivedSessionGate), conversationFacts: summarizeConversationFacts(payload.conversationFacts) }; } return { status: stringOrNull(payload.status), sourceKind: stringOrNull(payload.sourceKind), evidenceLevel: stringOrNull(payload.evidenceLevel), provider, model, backend, traceId: observedTraceId, hasReply: assistantReply.length > 0, error, blocker: summarizeBlocker(payload.blocker ?? payload.error?.blocker), runner: summarizeRunner(payload), workspace: stringOrNull(payload.workspace), sandbox: stringOrNull(payload.sandbox), capabilityLevel: stringOrNull(payload.capabilityLevel), toolCalls: summarizeToolCalls(payload.toolCalls), skills: summarizeSkills(payload.skills), runnerTrace: summarizeRunnerTrace(payload.runnerTrace), sessionMode: stringOrNull(payload.sessionMode), sessionLifecycleStatus: stringOrNull(payload.sessionLifecycleStatus ?? payload.sessionSummary?.status ?? payload.session?.lifecycleStatus), sessionSummary: summarizeSessionLifecycle(payload.sessionSummary ?? payload.sessionLifecycle), sessionReuse: summarizeSessionReuse(payload.sessionReuse), session: summarizeSession(payload.session), implementationType: stringOrNull(payload.implementationType), runnerLimitations: summarizeStringList(payload.runnerLimitations), codexStdioFeasibility: summarizeCodexStdioFeasibility(payload.codexStdioFeasibility), longLivedSessionGate: summarizeLongLivedSessionGate(payload.longLivedSessionGate), conversationFacts: summarizeConversationFacts(payload.conversationFacts) }; } export function classifyCodeAgentBrowserJourney({ responseSummary, httpOk = false, httpStatus = null, ui = null } = {}) { const providerBlock = classifyCodeAgentProviderBlock(responseSummary, { httpStatus }); const runtimeBlock = classifyCodeAgentRuntimeBlock(responseSummary, { httpStatus }); const uiCompleted = ui?.agentChatStatus === "DEV-LIVE 回复" || ui?.agentChatStatus === "已回复" || ui?.completedMessageVisible === true; const uiFailed = ui?.failedMessageVisible === true || blockedCodeAgentUiLabels.has(ui?.agentChatStatus); const evidence = inspectSanitizedCompletionEvidence(responseSummary); const backendCompleted = httpOk && responseSummary?.status === "completed" && responseSummary?.hasReply === true && responseSummary.error === null && evidence.ok; if (backendCompleted && uiCompleted && !uiFailed) { return { status: "pass", blocker: null, reason: "completed Code Agent payload over HTTP 2xx with real provider/backend/model/trace/reply evidence and completed UI state" }; } if (runtimeBlock.blocked) { return runtimeBlock; } if (providerBlock.blocked) { return { status: "blocked", blocker: providerBlock.blocker, reason: providerBlock.reason, ...(providerBlock.providerStatus != null ? { providerStatus: providerBlock.providerStatus } : {}) }; } if (responseSummary?.status === "completed") { return { status: "blocked", blocker: "untrusted-completion", reason: `Code Agent completed-looking payload was not paired with HTTP success, completed UI, and real provider evidence: ${evidence.reason}` }; } return { status: "blocked", blocker: "runtime", reason: "Code Agent browser journey did not produce a completed non-error response" }; } export function classifyCodeAgentRuntimeBlock(payload, { httpStatus = null } = {}) { const errorCode = stringOrNull(payload?.error?.code); const blockerCode = stringOrNull(payload?.blocker?.code ?? payload?.error?.blocker?.code); const layer = stringOrNull(payload?.error?.layer ?? payload?.blocker?.layer ?? payload?.error?.blocker?.layer); const category = stringOrNull(payload?.error?.category ?? payload?.blocker?.category ?? payload?.error?.blocker?.category); const payloadStatus = stringOrNull(payload?.status); if (["skill_cli_api_base_missing"].includes(errorCode ?? blockerCode)) { return { blocked: true, status: "blocked", blocker: "needs-config", category: "needs_config", layer, reason: "M3 Skill CLI is missing a safe HWLAB API base URL contract; do not show generic send failure." }; } if (["hwlab_api_unavailable"].includes(errorCode ?? blockerCode)) { return { blocked: true, status: "blocked", blocker: "retryable", category: "retryable", layer, reason: "HWLAB API is unavailable; the UI should show retryable blocker semantics." }; } if (["text_chat_only_fallback"].includes(errorCode ?? blockerCode) || category === "fallback") { return { blocked: true, status: "blocked", blocker: "text-chat-only-fallback", category: "fallback", layer, reason: "Code Agent response is still text chat fallback and does not satisfy runner/session/tool control." }; } if (["m3_readiness_blocked"].includes(errorCode ?? blockerCode) || layer === "m3-readiness") { return { blocked: true, status: "blocked", blocker: "capability-unavailable", category: category ?? "capability_unavailable", layer, reason: "M3 readiness is blocked; the UI must not treat this as generic send failure or completed control." }; } if (errorCode === "session_busy") { return { blocked: true, status: "blocked", blocker: "runner-busy", category: "runner_busy", reason: "Code Agent read-only runner session is already busy; the UI must keep the input retryable." }; } if (["session_expired", "session_reuse_conflict", "session_failed", "session_interrupted", "session_canceled", "session_timeout", "session_error"].includes(errorCode)) { return { blocked: true, status: "blocked", blocker: "session-blocked", category: "session_blocked", reason: `Code Agent session is blocked by ${errorCode}; fallback must not be reported as a Codex session.` }; } if ([ "runner_unavailable", "tool_unavailable", "skills_unavailable", "security_blocked", "codex_stdio_blocked", "codex_stdio_failed", "codex_stdio_protocol_blocked", "codex_stdio_empty_response", "codex_stdio_command_probe_failed" ].includes(errorCode)) { return { blocked: true, status: "blocked", blocker: "runner-blocked", category: "runner_blocked", reason: `Code Agent read-only runner returned ${errorCode}; this is blocked runner evidence, not a completed fallback.` }; } if (["invalid_params", "parse_error", "request_failed", "cloud_api_proxy_failed", "upstream_unavailable"].includes(errorCode)) { return { blocked: true, status: "blocked", blocker: "api-error", category: "api_error", reason: `Code Agent API returned ${errorCode}; the request is retryable and must remain distinguishable from provider failure.` }; } if (payloadStatus === "failed" && errorCode && errorCode !== "provider_unavailable") { return { blocked: true, status: "blocked", blocker: "api-error", category: "api_error", reason: `Code Agent returned failed status with ${errorCode}.` }; } return { blocked: false }; } export function classifyCodeAgentBrowserFailure(error, { traceId = null } = {}) { const message = error instanceof Error ? error.message : String(error ?? ""); const observedTraceId = traceId ?? error?.traceId ?? null; if (error?.userMessage) { return { status: "blocked", blocker: blockerForStructuredCategory(error.category, error.code), category: error.category ?? "runner_blocked", chineseSummary: `${error.userMessage}${observedTraceId ? `;traceId=${observedTraceId}` : ""}`, reason: message }; } if (timeoutPattern.test(message)) { return { status: "blocked", blocker: "timeout", category: "timeout", chineseSummary: `超时:Code Agent 在配置的活动时间边界内没有新事件${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message }; } if (/session[_ -]?busy|runner busy|already busy/iu.test(message)) { return { status: "blocked", blocker: "runner-busy", category: "runner_busy", chineseSummary: `Runner 忙碌:Code Agent 正在处理上一轮请求,可稍后重试${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message }; } if (/session[_ -]?(expired|blocked|reuse_conflict)|conversation.*session/iu.test(message)) { return { status: "blocked", blocker: "session-blocked", category: "session_blocked", chineseSummary: `Session 受阻:Code Agent 会话无法复用或已过期${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message }; } if (/provider|upstream|openai|codex|502|503|504|429|provider_unavailable/iu.test(message)) { return { status: "blocked", blocker: "provider-upstream", category: "provider", chineseSummary: `Provider 故障:Code Agent 上游或后端返回失败${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message }; } if (/api|http \d{3}|invalid_params|parse_error|request_failed|cloud_api_proxy_failed/iu.test(message)) { return { status: "blocked", blocker: "api-error", category: "api_error", chineseSummary: `API 错误:Code Agent 接口返回失败,输入应保留可重试${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message }; } return { status: "blocked", blocker: "browser-runtime", category: "browser", chineseSummary: `浏览器故障:Workbench 浏览器链路未完成${observedTraceId ? `;traceId=${observedTraceId}` : ""}。`, reason: message || "unknown browser error" }; } function blockerForStructuredCategory(category, code) { if (category === "needs_config") return "needs-config"; if (category === "security_blocked" || code === "security_blocked") return "security-blocked"; if (category === "fallback" || code === "text_chat_only_fallback") return "text-chat-only-fallback"; if (category === "capability_unavailable") return "capability-unavailable"; if (category === "retryable") return "retryable"; if (category === "runner_busy") return "runner-busy"; if (category === "session_blocked") return "session-blocked"; if (category === "timeout") return "timeout"; return "runtime"; } export function inspectRealCompletionEvidence(payload) { const provider = String(payload?.provider ?? "").trim().toLowerCase(); const backend = String(payload?.backend ?? "").trim().toLowerCase(); const missing = []; if (!payload?.conversationId && !payload?.sessionId) missing.push("conversationId"); if (!payload?.traceId) missing.push("traceId"); if (!payload?.messageId) missing.push("messageId"); if (!payload?.provider) missing.push("provider"); if (!payload?.model) missing.push("model"); if (!payload?.backend) missing.push("backend"); if (missing.length > 0) { return { ok: false, reason: `missing ${missing.join(",")}` }; } if (!trustedLiveProviders.has(provider)) { return { ok: false, reason: `provider ${payload.provider} is not an accepted real provider` }; } if (provider === "openai-responses" && payload?.capabilityLevel && payload.capabilityLevel !== "text-chat-only") { return { ok: false, reason: "openai-responses cannot claim runner capabilityLevel" }; } if (provider === "codex-readonly-runner" && payload?.longLivedSessionGate?.status === "pass") { return { ok: false, reason: "read-only runner cannot claim long-lived session gate pass" }; } if (provider === "codex-readonly-runner") { return { ok: false, reason: "controlled read-only runner is partial capability only and cannot be reported as full Code Agent completion" }; } if (provider === "openai-responses" && payload?.longLivedSessionGate?.status !== "pass") { return { ok: false, reason: "OpenAI Responses fallback is text-chat-only and cannot be reported as full Code Agent completion" }; } if (provider === "codex-stdio" && payload?.longLivedSessionGate?.status !== "pass") { return { ok: false, reason: "codex-stdio completion is missing long-lived session gate pass" }; } if (untrustedProviderPattern.test(`${provider} ${backend}`)) { return { ok: false, reason: `provider/backend looks non-real: ${payload.provider}/${payload.backend}` }; } return { ok: true, reason: "provider/model/trace/conversation evidence present" }; } export function normalizeCodeAgentError(error) { if (!error || typeof error !== "object") return null; return { code: stringOrNull(error.code), layer: stringOrNull(error.layer), category: stringOrNull(error.category), retryable: error.retryable === true, userMessage: stringOrNull(error.userMessage), traceId: stringOrNull(error.traceId), route: stringOrNull(error.route), toolName: stringOrNull(error.toolName), blocker: summarizeBlocker(error.blocker), missingConfig: Array.isArray(error.missingConfig) ? error.missingConfig.filter((item) => typeof item === "string") : [], missingEnv: Array.isArray(error.missingEnv) ? error.missingEnv.filter((item) => typeof item === "string") : [], missingCommands: Array.isArray(error.missingCommands) ? error.missingCommands.filter((item) => typeof item === "string") : [], providerStatus: numericStatus(error.providerStatus) }; } export function isHttpNon2xxStatus(value) { const status = numericStatus(value); return status !== null && (status < 200 || status > 299); } function inspectSanitizedCompletionEvidence(summary) { const provider = String(summary?.provider ?? "").trim().toLowerCase(); const backend = String(summary?.backend ?? "").trim().toLowerCase(); const missing = []; if (!summary?.provider) missing.push("provider"); if (!summary?.model) missing.push("model"); if (!summary?.backend) missing.push("backend"); if (!summary?.traceId) missing.push("traceId"); if (summary?.hasReply !== true) missing.push("reply"); if (missing.length > 0) { return { ok: false, reason: `missing ${missing.join(",")}` }; } if (!trustedLiveProviders.has(provider)) { return { ok: false, reason: `provider ${summary.provider} is not an accepted real provider` }; } if (untrustedProviderPattern.test(`${provider} ${backend}`)) { return { ok: false, reason: `provider/backend looks non-real: ${summary.provider}/${summary.backend}` }; } return { ok: true, reason: "real provider/backend/model/trace/reply evidence present" }; } function summarizeRunner(payload) { if (!payload?.runner || typeof payload.runner !== "object") return null; return { kind: stringOrNull(payload.runner.kind), backend: stringOrNull(payload.runner.backend), workspace: stringOrNull(payload.runner.workspace), sandbox: stringOrNull(payload.runner.sandbox), session: stringOrNull(payload.runner.session), sessionMode: stringOrNull(payload.runner.sessionMode), sessionId: stringOrNull(payload.runner.sessionId), implementationType: stringOrNull(payload.runner.implementationType), codexStdio: payload.runner.codexStdio === true, writeCapable: payload.runner.writeCapable === true, durableSession: payload.runner.durableSession === true, longLivedSession: payload.runner.longLivedSession === true, readOnly: payload.runner.readOnly === true, capabilityLevel: stringOrNull(payload.runner.capabilityLevel), runnerLimitations: summarizeStringList(payload.runner.runnerLimitations) }; } function summarizeToolCalls(value) { if (!Array.isArray(value)) return []; return value.map((tool) => ({ name: stringOrNull(tool?.name), type: stringOrNull(tool?.type), status: stringOrNull(tool?.status), route: stringOrNull(tool?.route), capabilityLevel: stringOrNull(tool?.capabilityLevel), blocker: summarizeBlocker(tool?.blocker), exitCode: numericStatus(tool?.exitCode), outputTruncated: tool?.outputTruncated === true })); } function summarizeSkills(value) { if (!value || typeof value !== "object") return null; return { status: stringOrNull(value.status), count: typeof value.count === "number" ? value.count : Array.isArray(value.items) ? value.items.length : null, totalCount: typeof value.totalCount === "number" ? value.totalCount : null, blockers: Array.isArray(value.blockers) ? value.blockers.map((blocker) => ({ code: stringOrNull(blocker.code), sourceIssue: stringOrNull(blocker.sourceIssue) })) : [] }; } function summarizeRunnerTrace(value) { if (!value || typeof value !== "object") return null; return { runnerKind: stringOrNull(value.runnerKind), route: stringOrNull(value.route), capabilityLevel: stringOrNull(value.capabilityLevel), blocker: summarizeBlocker(value.blocker), sandbox: stringOrNull(value.sandbox), sessionMode: stringOrNull(value.sessionMode), sessionStatus: stringOrNull(value.sessionStatus), sessionLifecycleStatus: stringOrNull(value.sessionLifecycleStatus), implementationType: stringOrNull(value.implementationType), sessionReused: value.sessionReused === true, turn: typeof value.turn === "number" ? value.turn : null, outputTruncated: value.outputTruncated === true, valuesPrinted: value.valuesPrinted === true }; } function summarizeBlocker(value) { if (!value || typeof value !== "object") return null; return { code: stringOrNull(value.code), layer: stringOrNull(value.layer), category: stringOrNull(value.category), retryable: value.retryable === true, userMessage: stringOrNull(value.userMessage), route: stringOrNull(value.route), toolName: stringOrNull(value.toolName) }; } function summarizeSessionReuse(value) { if (!value || typeof value !== "object") return null; return { conversationId: stringOrNull(value.conversationId), sessionId: stringOrNull(value.sessionId), mapped: value.mapped === true, reused: value.reused === true, turn: typeof value.turn === "number" ? value.turn : null, previousTurns: typeof value.previousTurns === "number" ? value.previousTurns : null, workspace: stringOrNull(value.workspace), status: stringOrNull(value.status), idleTimeoutMs: typeof value.idleTimeoutMs === "number" ? value.idleTimeoutMs : null, lastTraceId: stringOrNull(value.lastTraceId) }; } function summarizeSession(value) { if (!value || typeof value !== "object") return null; return { sessionId: stringOrNull(value.sessionId), conversationId: stringOrNull(value.conversationId), status: stringOrNull(value.status), lifecycleStatus: stringOrNull(value.lifecycleStatus ?? value.lifecycle?.status), workspace: stringOrNull(value.workspace), sandbox: stringOrNull(value.sandbox), runnerKind: stringOrNull(value.runnerKind), capabilityLevel: stringOrNull(value.capabilityLevel), implementationType: stringOrNull(value.implementationType), createdAt: stringOrNull(value.createdAt), updatedAt: stringOrNull(value.updatedAt), idleTimeoutMs: typeof value.idleTimeoutMs === "number" ? value.idleTimeoutMs : null, lastTraceId: stringOrNull(value.lastTraceId), turn: typeof value.turn === "number" ? value.turn : null, longLivedSession: value.longLivedSession === true, codexStdio: value.codexStdio === true, writeCapable: value.writeCapable === true, secretMaterialStored: value.secretMaterialStored === true }; } function summarizeConversationFacts(value) { if (!value || typeof value !== "object") return null; return { conversationId: stringOrNull(value.conversationId), sessionId: stringOrNull(value.sessionId), sessionStatus: stringOrNull(value.sessionStatus), sessionLifecycleStatus: stringOrNull(value.sessionLifecycleStatus), sessionMode: stringOrNull(value.sessionMode), capabilityLevel: stringOrNull(value.capabilityLevel), runnerKind: stringOrNull(value.runnerKind), workspace: stringOrNull(value.workspace), sandbox: stringOrNull(value.sandbox), turnCount: typeof value.turnCount === "number" ? value.turnCount : null, latestTraceId: stringOrNull(value.latestTraceId), traceIds: Array.isArray(value.traceIds) ? value.traceIds.map(stringOrNull).filter(Boolean).slice(-6) : [], latestSkills: value.latestSkills && typeof value.latestSkills === "object" ? { status: stringOrNull(value.latestSkills.status), count: typeof value.latestSkills.count === "number" ? value.latestSkills.count : null, totalCount: typeof value.latestSkills.totalCount === "number" ? value.latestSkills.totalCount : null, names: Array.isArray(value.latestSkills.names) ? value.latestSkills.names.map(stringOrNull).filter(Boolean).slice(0, 8) : [] } : null, recentToolCalls: Array.isArray(value.recentToolCalls) ? value.recentToolCalls.map((tool) => ({ name: stringOrNull(tool?.name), status: stringOrNull(tool?.status) })).filter((tool) => tool.name || tool.status).slice(-8) : [], valuesRedacted: value.valuesRedacted === true, secretMaterialStored: value.secretMaterialStored === true }; } function summarizeSessionLifecycle(value) { if (!value || typeof value !== "object") return null; return { status: stringOrNull(value.status), rawStatus: stringOrNull(value.rawStatus), label: stringOrNull(value.label), action: stringOrNull(value.action), reusable: value.reusable === true, reused: typeof value.reused === "boolean" ? value.reused : null, newSession: value.newSession === true, busy: value.busy === true, requiresNewSession: value.requiresNewSession === true, degraded: value.degraded === true, fallback: value.fallback === true, unsupported: value.unsupported === true, reasonCode: stringOrNull(value.reasonCode), userMessage: stringOrNull(value.userMessage) }; } function summarizeCodexStdioFeasibility(value) { if (!value || typeof value !== "object") return null; return { status: stringOrNull(value.status), canStartLongLivedCodexStdio: value.canStartLongLivedCodexStdio === true, currentImplementation: stringOrNull(value.currentImplementation), implementationRequired: stringOrNull(value.implementationRequired), binaryOnPath: value.binaryOnPath === true, binary: value.binary && typeof value.binary === "object" ? { status: stringOrNull(value.binary.status), present: value.binary.present === true, command: stringOrNull(value.binary.command), version: stringOrNull(value.binary.version), versionDetected: value.binary.versionDetected === true } : null, runtimeContract: value.runtimeContract && typeof value.runtimeContract === "object" ? { status: stringOrNull(value.runtimeContract.status), ready: value.runtimeContract.ready === true, binaryStatus: stringOrNull(value.runtimeContract.binary?.status), stdioProtocolStatus: stringOrNull(value.runtimeContract.stdioProtocol?.status), lifecycleStatus: stringOrNull(value.runtimeContract.lifecycleSupervisor?.status), workspaceStatus: stringOrNull(value.runtimeContract.workspaceMount?.status), tokenBoundaryStatus: stringOrNull(value.runtimeContract.tokenBoundary?.status), cancelReapTraceStatus: stringOrNull(value.runtimeContract.cancelReapTraceReadiness?.status) } : null, workspace: stringOrNull(value.workspace), sandbox: stringOrNull(value.sandbox), ready: value.ready === true, sessionLifecycle: value.sessionLifecycle && typeof value.sessionLifecycle === "object" ? { create: value.sessionLifecycle.create === true, reuse: value.sessionLifecycle.reuse === true, cancel: value.sessionLifecycle.cancel === true, reap: value.sessionLifecycle.reap === true, idleTimeout: value.sessionLifecycle.idleTimeout === true, traceCapture: value.sessionLifecycle.traceCapture === true, idleTimeoutMs: typeof value.sessionLifecycle.idleTimeoutMs === "number" ? value.sessionLifecycle.idleTimeoutMs : null } : null, blockers: Array.isArray(value.blockers) ? value.blockers.map((blocker) => ({ code: stringOrNull(blocker.code), sourceIssue: stringOrNull(blocker.sourceIssue) })) : [] }; } function summarizeLongLivedSessionGate(value) { if (!value || typeof value !== "object") return null; return { status: stringOrNull(value.status), pass: value.pass === true, requiredCapability: stringOrNull(value.requiredCapability), currentCapability: stringOrNull(value.currentCapability), sessionId: stringOrNull(value.sessionId), sessionStatus: stringOrNull(value.sessionStatus), runnerKind: stringOrNull(value.runnerKind), provider: stringOrNull(value.provider), blockers: Array.isArray(value.blockers) ? value.blockers.map((blocker) => ({ code: stringOrNull(blocker.code), sourceIssue: stringOrNull(blocker.sourceIssue) })) : [] }; } function summarizeStringList(value) { return Array.isArray(value) ? value.filter((item) => typeof item === "string") : []; } function stringOrNull(value) { return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; } function numericStatus(value) { if (typeof value !== "number" || !Number.isInteger(value)) return null; return value; }