# Code Agent Chat Readiness Runbook 本文定义 Cloud Workbench `POST /v1/agent/chat` 的 readiness 判定。它只处理 Code Agent 回复链路是否具备复测条件,不修复、不读取、不打印、不创建也不修改任何 Secret 或 token。 ## 运行边界 - DEV Cloud Web 入口是 `http://74.48.78.17:17666/`,同源代理到 `/v1/agent/chat`。 - DEV API/edge 入口是 `http://74.48.78.17:17667/`;它不能替代 Workbench 同源聊天入口的真实回复证据。 - `internal/cloud/code-agent-chat.ts` 是 `/v1/agent/chat` 的后端处理入口。 - `scripts/code-agent-chat-smoke.mjs` 是 Code Agent chat schema 与 readiness 合同检查。 - `scripts/dev-cloud-workbench-smoke.mjs --static` 只验证 Workbench 源码合同和 `/v1/agent/chat` 前端接线;它不是 DEV-LIVE 回复证明。 ## Provider 前置条件 当前 DEV 部署合同中 `hwlab-cloud-api` 的 Code Agent provider 是 `HWLAB_CODE_AGENT_PROVIDER=codex-stdio`。运行时必须具备 repo-owned Codex app-server stdio session supervisor,并证明 `/workspace/hwlab` 可读写、`CODEX_HOME=/codex-home` 可写、`/app/node_modules/.bin/codex --version` 可执行、`codex app-server --listen stdio://` 可创建和复用同一个 Codex thread/session。 Codex token boundary 仍由授权路径把 `OPENAI_API_KEY` 注入到 DEV runtime。DEV Pod 不能直接指向 public `api.openai.com`。G14 默认 `deepseek` profile 指向 `http://hwlab-deepseek-proxy..svc.cluster.local:4000/v1/responses`;该 Service 必须先进入 `hwlab-deepseek-responses-bridge`,由 bridge 解压 Codex Responses 的 zstd request body、规范化 `/v1/models` 返回、丢弃非 `function` tool, 再转发到同 Pod 内 Moon Bridge 4001。Moon Bridge 是 DeepSeek profile 的真实 Responses 转换和 prompt cache 保留层;不要在 HWLAB 中手写完整转换器替代它。 `codex-api` profile 是独立的 Codex/OpenAI-compatible Responses 通道。G14 上 `hwlab-cloud-api` 应把 `codex-api` base URL 指向同 Pod 的 `127.0.0.1` loopback forwarder;forwarder 再直连 `hyueapi.com` / `.hyueapi.com`,并把这两个域名显式保留在 `NO_PROXY` / `no_proxy`。这不是 DeepSeek bridge,也不是公网 `api.openai.com`,不能把 hyueapi 流量改成 HTTP/SOCKS proxy。`http://172.26.26.227:17680/v1/responses` 只能作为 D601 legacy Code Queue runner 或历史 egress 的对照线索;迁移到 G14 后不得把它当作 G14 默认 `codex-api` base URL,也不得用 DeepSeek bridge 伪装 `codex-api` 通过。 Runner 不得尝试修补、读取、回显或替换该 Secret。若 DEV runtime 缺少该授权凭证注入, `provider_unavailable` 且 `error.missingEnv` 包含 `OPENAI_API_KEY` 必须判为 `BLOCKED/credential`。 部署前和部署后的自动化只允许证明 env 名称、`secretKeyRef` 的 Secret 名和 key 名、以及 DEV egress/base-url 合同是否声明和保留;不得读取 Secret data,也不得把 Secret 值写入 report、issue、PR 或截图。 ## Provider 切换排查方法论 Provider/profile 切换故障必须先在目标 pod/host 上打通最小真实闭环,再进入完整 CI/CD、 GitOps render 或正式发布。`deepseek`、`codex-api` 和未来 provider 共享 cloud-api 会话与 Workbench UI,但排查时必须把 profile overlay、认证、网络、模型、Codex CLI/app-server 逐层拆开,避免用一个 profile 的成功掩盖另一个 profile 的退化。 最小闭环按以下顺序分层,任何一层失败都不能跳到正式 CI/CD 试错: 1. 运行面确认:在 G14 `/root/hwlab` 与 G14 k3s 目标 pod 内确认当前分支、镜像、env overlay、 `CODEX_HOME`、Codex 版本和 workspace;D601 只能作为 legacy 对照,不作为 G14 source truth。 2. 凭证边界:只检查 Secret 引用、`auth.json` 顶层 key 和值长度,不打印 secret。Codex CLI 的 `auth.json` 应能暴露 `OPENAI_API_KEY` 顶层 key;形如 `auth` 的不明结构必须先按 blocker 处理。 3. 直连边界:`hyueapi.com` / `.hyueapi.com` 必须在 `NO_PROXY` 与 `no_proxy` 内。需要同时检查 shell env 和 Codex/Rust trace;若 trace 显示 `network_proxy: None` 且直接连接 `hyueapi.com:443`, 不能再把问题归类为 proxy 污染。 4. 裸 Responses API:在同一个目标 pod 内用同一份 auth、同一模型、同一 base host 发 `/responses` 或 `/v1/responses` 流式请求,确认网络、认证和模型是否可用。裸 API 通过只证明 upstream 可达,不等于 Workbench 或 Codex runner 通过。 5. Codex CLI 对照:用同一模型、同一 `CODEX_HOME`、同一 prompt 运行 `codex exec --json`;同时在 D601 Code Queue runner 上做同模型对照,记录版本、config 形态、NO_PROXY、proxy env 和 transport 摘要。D601 对照只用于定位差异,不能把 D601 路径写回 G14 默认运行态。 6. Loopback forwarder 对照:如果裸 Responses API 通过、Codex CLI 直连失败,并且 trace 已确认 `network_proxy: None`,必须在同一个目标 Pod 内增加只监听 `127.0.0.1` 的临时 forwarder,使用同一份 auth、同一模型和同一 prompt 复测 `codex exec` 与 `/v1/agent/chat`。forwarder 只能把流量转到可配置的 hyueapi upstream,不能硬编码 D601 IP,也不能复用 DeepSeek bridge。 7. App-server 闭环:最终证据必须来自 repo-owned Codex app-server stdio 或明确批准的等价 long-lived runner,返回 `completed` 且 `reply.content` 非空。Node/raw HTTPS、stub、bridge、 source-only smoke、前端状态都不能升级成 DEV-LIVE reply pass。 排查记录应保留稳定结论和判定方法,不写 Secret、一次性 trace 全文或日期化流水账。遇到 “裸 API 通过但 Codex CLI/app-server 失败”时,优先抓 Codex/Rust transport 日志并与 D601 成功 路径比对:模型、service tier、`auth.json` 结构、base URL、是否直连、实际连接 IP、请求体大小、 SSE 是否 completed。只有这些证据归一后,才修改源码、render、SecretRef 或发布配置。 ## Codex API 转发根因 `codex-api` 在 G14 上采用 pod-local loopback forwarder 是一个受控传输边界修复,不是为了规避 hyueapi 直连要求。根因判定按以下证据链成立: - 同一目标 Pod 内,使用同一份 auth、同一模型、同一 Responses payload,通过 Node HTTPS 直接请求 `hyueapi.com` 能获得完整 SSE `response.completed`;这排除了模型、Secret、请求体、基本网络可达性和 hyueapi 账号本身不可用。 - 同一目标 Pod 内,Codex CLI/Rust 传输直连 `https://hyueapi.com/responses` 会在 streaming 阶段断开; Rust trace 显示 `network_proxy: None` 且连接目标是 `hyueapi.com:443`,这排除了全局 proxy 污染和 `NO_PROXY` 未生效作为主因。 - 把 Codex CLI 的 base URL 改为同 Pod `127.0.0.1`,再由 Node forwarder 使用直连 HTTPS 转发到 hyueapi,`codex exec` 与 `/v1/agent/chat` 均能完成并返回非空 assistant 回复;这把失败边界收敛到 Codex CLI 的 Rust HTTPS/SSE transport 与 G14->hyueapi 边缘路径组合,而不是 Workbench、DeepSeek、 模型或 auth。 - D601 Code Queue runner 使用同模型可成功,只能证明 D601 legacy 路径可作为对照;不能把 `172.26.26.227:17680` 写回 G14 默认配置。 因此,在不修改 Codex CLI 二进制、不要求 hyueapi 改边缘行为、也不把 hyueapi 流量送进 HTTP/SOCKS proxy 的前提下,pod-local Node forwarder 是当前可控的最小修复。它的职责只是替换 Codex CLI 失败的 直接 HTTPS/SSE transport;hyueapi 仍由 forwarder 进程直连,`hyueapi.com` / `.hyueapi.com` 仍必须在 `NO_PROXY` 和 `no_proxy` 中。 ## 转发器迁移与隔离 Codex API forwarder 必须是 Pod 内部能力,推荐作为 `hwlab-cloud-api` 同 Pod sidecar 或等价的同 Pod 受控进程运行。`hwlab-cloud-api` 只连接 `http://127.0.0.1:`;forwarder 通过 env 配置 upstream, 默认 upstream host 为 `hyueapi.com`。以下约束保证它可迁移且不会污染其他运行面: - 禁止硬编码 provider host IP、D601 `172.26.26.227`、G14 节点 IP、namespace 名或 NodePort。可配置项只应是 loopback listen port、upstream base URL、模型 profile env 和 Secret 引用。 - forwarder 不创建 Kubernetes Service、Ingress、NodePort 或 host port;它只监听 Pod network namespace 内的 `127.0.0.1`。同一 k3s 集群内 `hwlab-dev`、`hwlab-prod` 或其他 namespace 可以同时各自运行一个 `hwlab-cloud-api` Pod 和同端口 forwarder,因为每个 Pod 都有独立 loopback。 - 不要给 `hwlab-cloud-api` Pod 启用 `hostNetwork` 来承载 forwarder。若某个迁移目标必须使用 hostNetwork, 必须重新评估端口冲突和隔离边界,不能沿用“Pod 内同端口无冲突”的结论。 - 迁移到其他 k3s 时,只需要保证目标 Pod 能直连 `hyueapi.com:443`、SecretRef 仍以 `OPENAI_API_KEY` 注入、 `CODEX_HOME/auth.json` 形态正确、`NO_PROXY/no_proxy` 包含 `hyueapi.com` 与 `.hyueapi.com`,以及 loopback forwarder 进程跟 `hwlab-cloud-api` 在同一 Pod network namespace。 - DEV、PROD 和临时 smoke Pod 的证据必须分开记录。DEV forwarder 通过不能自动证明 PROD 通过;PROD 需要在 PROD namespace 的目标 Pod 内复跑最小 `/v1/agent/chat` 闭环。 ## 自动化兼容性 Forwarder 不需要人工维护长驻进程。正式固化后,它应由 Kubernetes Deployment 管理生命周期:Pod 创建时随 `hwlab-cloud-api` 启动,Pod 删除时一起退出,异常退出由 kubelet 按 Pod/容器 restart policy 重启。人工只允许在 临时 smoke Pod 中手动启动 forwarder 做分层诊断;运行态不应依赖手动 `kubectl exec` 后台进程。 自动化门禁只需要做合同级检查,不需要读取 Secret 或调用外部模型: - desired state 中 `codex-api` profile base URL 指向 Pod-local loopback,不指向 D601 IP 或 `api.openai.com`。 - forwarder 的 upstream base URL 由 env 配置,默认 host 为 `hyueapi.com`,并且 `NO_PROXY/no_proxy` 包含 `hyueapi.com` 与 `.hyueapi.com`。 - `hwlab-cloud-api` Pod 模板包含 forwarder sidecar 或明确等价的同 Pod 受控进程;forwarder 不暴露 Service、NodePort、Ingress 或 hostPort。 - `deepseek` profile 仍指向 DeepSeek bridge/Moon Bridge;`codex-api` profile 不依赖 DeepSeek bridge。 完整 CI/CD、GitOps render 或发布流水线只能在目标 Pod 最小闭环已经通过、且当前 CI/CD 基础设施可用时继续。 最小闭环没有通过时,不要通过反复推送 CI/CD 来探索 provider transport;CI/CD 只能固化已经在目标运行面证明可行的 配置和代码。 ## 判定标准 | 观测结果 | readiness | | --- | --- | | `status: "failed"`,`error.code: "provider_unavailable"`,且 `error.missingEnv` 包含 `OPENAI_API_KEY` | `BLOCKED/credential`;provider 凭证缺失,不能标真实回复通过。 | | `provider: "codex-readonly-runner"` 或 `sessionMode: "controlled-readonly-session-registry"` | 历史只读状态,只能作为 `BLOCKED/not-codex-stdio` 诊断;不能满足当前自然语言单一路由或 DEV-LIVE reply pass。 | | `codexStdioFeasibility.status: "blocked"`,或 blocker 包含 `codex_cli_binary_missing`、`codex_cli_not_executable`、`codex_cli_native_dependency_missing`、`runner_lifecycle_missing`、`stdio_protocol_not_wired`、`workspace_mount_missing`、`workspace_write_boundary_blocked`、`codex_home_missing`、`codex_home_write_blocked`、`provider_token_boundary` | 真实 Codex stdio / 等价 long-lived runner 未具备;必须按 blocker 处理,不能表述为完整 Codex session。 | | `status: "completed"`,但来自 mock、fixture、本地 stub、source-only smoke、浏览器本地回显或人工拼接 | 不是 DEV-LIVE reply pass。 | | 真实 DEV `POST /v1/agent/chat` 返回 `status: "completed"`,且 `reply.content` 是非空 assistant 回复 | 可标 DEV-LIVE reply pass。 | | 传输失败、schema 不完整、HTTP 非预期、`reply.content` 为空或缺失 | `BLOCKED`,按 runtime/schema/transport 分析。 | 只有“真实 DEV 路由 + `completed` + 非空 assistant reply”能作为 DEV-LIVE 回复通过依据。 不得把 mock、fixture、本地 echo、source report、静态检查或前端状态当作通过。 ## 自然语言单一路由 `/v1/agent/chat` 的自然语言请求唯一执行路径是 repo-owned Codex stdio long-lived session。cloud-api 不再把自然语言预分类到 M3 Skill CLI、`/v1/m3/io`、 `external.network.check`、`session_context`、`security.hardware-boundary`、 `hardware.invoke.shell` shortcut 或 OpenAI text fallback。 自然语言里即使出现 M3、DO/DI、DAP、PWM、gateway、box-simu、patch-panel、Keil、 serial-monitor、Windows skill、串口、下载、烧录、启动日志等词,也必须把完整请求交给 Codex stdio turn。Codex turn 自己根据仓库、skill 文档和可用工具决定调用 repo wrapper、 Windows skill CLI、项目脚本或其他真实可达路径;cloud-api 只负责 session 生命周期、trace、 result 轮询和 schema 化返回。 如果 Codex stdio 不具备运行条件,`/v1/agent/chat` 只能返回 Codex stdio readiness blocker,不能降级到 M3 Skill CLI、受控硬件 shortcut、外网专用检查或普通 OpenAI 文本回复。 显式 `/v1/m3/io` 控制面可以作为独立 API 或 UI 控制面继续存在,但聊天自然语言不得自动路由 到该 API,也不得保留要求自然语言先满足 M3 白名单的源码检查或测试。该显式控制面也不得在 进入 gateway 前保留固定 `DO1/DI1` 或固定 gateway 身份白名单预拦截;真实下游执行失败可以 返回执行失败,但不能由 cloud-api 用旧白名单提前拒绝。 持久 session 是默认合同:同一个 `conversationId/sessionId` 必须映射到 repo-owned Codex thread 和固定 workspace,刷新前端、重新打开页面或短连接 result 轮询不得创建新的短期 runner。 除非 Pod 重建或 Codex supervisor 明确重启,workspace、thread/session 绑定和可见 trace 应持续 存在。Workbench 前端必须把这些会话标识和最近消息持久化到浏览器本地状态;用户显式清空 对话或登出时才清除该本地状态。刷新后下一轮自然语言请求必须携带已保存的 `conversationId/sessionId/threadId`,不能只因为 JS 内存重建就显示“首轮请求”或重新分配 Codex workspace。 ## PC Gateway Windows Skill 调用 Code Agent 通过已登记 PC gateway 执行 Windows 侧命令时,必须让 Codex turn 自己调用仓库 wrapper,不能由 cloud-api 字符串匹配短路到 gateway: ```sh node /app/tools/hwlab-gateway-shell.mjs --json --timeout-ms --powershell-stdin <<'PS1' PS1 ``` PowerShell 默认使用 wrapper 的 `-EncodedCommand` 路径;不要手写 `cmd /c powershell ...` 的管道、引号或中文转义。简单 `cmd` 命令仍可用 `--command "cmd /d /s /c ..."`,但涉及目录枚举、Unicode、管道、排序或 JSON 输出时优先用 `--powershell-stdin`。 Workbench 会把“Gateway 命令超时”控件的毫秒值随 `/v1/agent/chat` 传入 `gatewayShellTimeoutMs`。Codex prompt 必须把该值落实到 wrapper 的 `--timeout-ms`,cloud-api `hardware.invoke.shell` dispatch timeout 必须取环境配置、请求 `input.timeoutMs` 和 120s 默认值中的较大值并加 grace;不得让 20s/30s 的旧默认提前返回 `dispatchStatus=timed_out`。wrapper 自身 HTTP request timeout 要比 shell timeout 稍长,确保用户看到的是 gateway/cloud 返回的结构化 `status/operationId/dispatch`,不是 wrapper 先超时丢失结果。 调大 timeout 不能替代正确的长任务控制语义。Gateway poll loop 必须支持后台 in-flight 执行,长 Keil/UV4 命令运行期间仍能处理短 `job-status`、state/log 读取和健康探测;如果 trace 出现 `shellExecuted=false` 的 dispatch timeout,优先检查 gateway 是否队头阻塞或离线,而不是把所有 wrapper 调用改成长等待。 Workbench trace 对已知 JSON-RPC gateway 响应应按普通 tool call 展示:前端首行用中性 `tool gateway.shell status= op= exit= s=`,正文展示 request、gateway/resource/capability、dispatch、command、audit/evidence 以及有界 stdout/stderr。不要把整段 JSON 原样刷屏;复制/下载完整 trace 仍保留原始 JSON。 ## 短连接 result 轮询 Workbench 与 Code Agent 的用户请求必须是短连接 submit + 短连接 result/trace 轮询;浏览器或 cloud-web 不应持有一次长 HTTP 请求等待整个 Codex turn 结束。`POST /v1/agent/chat` 返回 `202` 后,前端轮询 `/v1/agent/chat/result/` 获取终态,并用 `/v1/agent/chat/trace/` 刷新可视 trace。 Code Agent backend 的 completed 语义只能来自真实 Codex app-server `turn/completed` 成功事件。`item/agentMessage/delta`、`item/completed`、已有 assistant 文本、transport close 或 activity idle timeout 都不能单独升级成 `status: "completed"`。如果已经收到部分 assistant 文本但没有收到 `turn/completed`,终态必须是 timeout/partial blocker,并保留 trace、session、thread、partial output 摘要和可重试提示;Workbench 只能显示“部分回复/超时”,不能标 DEV-LIVE reply pass。 `Codex app-server transport closed after partial assistant output but before turn/completed` 不能单独判定为 CI/CD 滚动中断。排查必须同时看三类证据:失败 trace 的 `providerTrace`/`runnerTrace`、对应 `hwlab-cloud-api` Pod 的 restart/age、以及同一时间窗口内的 Kubernetes rollout/kill 事件。若 Pod 在 trace 开始前已经稳定且 `RESTARTS=0`,应归类为 Codex app-server transport/session 失败,提示用户用新 session 重试;只有 trace 时间窗口内存在当前会话所在 Pod 的删除、重建或 restart 证据时,才归类为滚动导致的中断。失败响应也必须尽量保留 `providerTrace`,即使 `terminalStatus=failed`,避免前端把“providerTrace 缺失”误报成未知降级。 cloud-web 同源代理必须把短连接语义原样转发给 cloud-api,至少包括 `Prefer: respond-async`、`X-HWLAB-Short-Connection` 和 `X-Trace-Id`。如果这些 header 在 cloud-web 层被过滤,cloud-api 会把同一个请求当成长同步请求处理,用户入口会表现为 `17666` 卡住或代理超时,而 `17667` 直连 cloud-api 正常。此类问题应先比对同一 trace 在 `17666` 与 `17667` 的 submit 行为,再修代理 header 透传,而不是调大前端等待时间。 `/v1/agent/chat/result/` 是终态摘要接口,不是完整 trace 下载接口。它可以携带压缩后的 `runnerTrace` 窗口用于传输保活,但 Workbench 用户界面不得把该窗口显示为“压缩窗口”或“显示全部”。只要结果或轮询快照声明 `eventsCompacted=true`,前端必须自动请求 `/v1/agent/chat/trace/` 并用完整 trace 替换可视事件线;回放完成前只能显示“完整 trace 回放中/当前已载入”状态。result 响应仍必须保留 `eventCount`、`lastEvent`、`providerTrace`、`threadId/sessionId` 和终态 reply/blocker;完整 trace 只能从 `/v1/agent/chat/trace/`、复制 JSON 或下载 trace 入口取得。默认 result trace 窗口上限由 `HWLAB_CODE_AGENT_RESULT_TRACE_EVENT_LIMIT` 控制;不要把数百个大 chunk 原样塞进 result 响应,避免 cloud-web 代理层或浏览器 fetch 把“正常执行中的大响应”表现成 503、非 JSON 或空响应。 result 轮询的 408/425/429/5xx、浏览器 timeout、非 JSON 或空响应应按“可恢复传输抖动”处理:前端先拉取一次 trace 刷新活性,再带退避继续轮询,只有后端返回结构化 terminal blocker、真实终态失败,或 trace 按无新事件 idle timeout 超时,才向用户显示失败。只要 `/trace` 仍显示新事件或 `waitingFor` 仍在推进,就不能把一次 result poll 失败标成“Code Agent API 错误”并停止。 Workbench 的 trace 展示不是终态真相。只要 trace 中出现 `result:completed`、`result:failed`、`result:canceled`、`session:session_busy` 这类 terminal event,或浏览器从本地状态恢复出带 `traceId` 的非终态消息,前端必须再请求 `/v1/agent/chat/result/` 做 result reconciliation,并用 result 的 reply/blocker/session/providerTrace 替换消息卡片。仅回放 `/trace` 不能把旧 running 消息改成完成,也不能把 `Code Agent result is ready for short-connection polling.` 当作用户可见最终回复。 长耗时和前后端协同缺陷必须优先用 mock/fixture 复现,不得把真实 token 调用作为日常回归测试。后端单元测试使用 fake Codex app-server JSON-RPC client 模拟 `thread/started`、`turn/started`、assistant delta、command output、`turn/completed` 缺失、transport close 和 idle timeout;前端测试使用固定 `/result`、`/trace`、EventSource、localStorage fixture 验证 result reconciliation、刷新恢复、transient poll error 和 compact trace 回放。真实 `--live` Code Agent smoke 只作为显式授权的 DEV 验证,不进入默认 PR 单元测试路径。 Windows 侧 skill、编译器、脚本工具和多参数命令都应走同一个通用传输模式,不新增某个工具的专用 wrapper 子命令: - 工作目录优先用 wrapper 的 `--cwd ` 或脚本内 `Set-Location -LiteralPath ` 表达,不要在 prompt 里拼 `cmd /c "cd ... && ..."`。 - 命令参数在 PowerShell 脚本里用数组或显式变量传递,例如 `$args = @("subcommand", "-p", $projectPath)` 后 `& $exe @args`,避免让模型手动嵌套引号。 - 对所有 Windows skill 都先复用 `C:\Users\liang\.agents\skills\\SKILL.md` 和该 skill 自带 CLI;Code Agent 只负责通过 repo wrapper 调用,不把 skill 行为复制到 cloud-api 或 wrapper。 - 一次探测命令失败后,只做一次更窄、更结构化的修正;若仍失败,返回失败 `operationId`、stderr 摘要和下一步,而不是连续试错。 Windows 文件系统探测必须是有界小输出: - 对 `F:\work`、`F:\work\ConStart` 或同类目录先做顶层目录/项目标记探测,不要读取 Secret、env、kubeconfig、DB URL 或完整源码内容。 - 使用 `-LiteralPath`、`Select-Object -First `、`ConvertTo-Json -Compress -Depth `,stdout 目标控制在约 12 KB 内。 - wrapper 的 PowerShell prologue 已设置 UTF-8 console/output,并提供 `Read-HwlabText`、`Select-HwlabText`、`ConvertTo-HwlabJson`。读取中文 `SKILL.md`、Keil 日志或 manifest 时优先用这些 helper,避免 `Get-Content`/`Select-String` 的扩展对象字段和系统代码页造成乱码。 - 不要先输出完整目录 JSON 再依赖终端截断;需要更多信息时按明确候选项目二次查询。 - 如果命令已经到达 gateway 但因脚本语法或输出大小失败,只允许简化修正一次;最终回复要记录失败 `operationId`、修正后的成功 `operationId` 和有界输出摘要。 Keil 编译、下载或探测请求必须优先使用 Windows 侧 skill,而不是在 prompt 中重写 Keil 调用逻辑: ```sh cd C:\Users\liang\.agents\skills\keil py -3 keil-cli.py build -p -t py -3 keil-cli.py job-status ``` 多 probe、烧录和 reset-run 的具体参数以 Windows 侧 `C:\Users\liang\.agents\skills\keil\SKILL.md` 为准;Code Agent 只负责通过 repo wrapper 调用该 skill CLI 并返回 trace、operation/evidence 和 bounded stdout/stderr 摘要。 对 build/download 这类长任务,Code Agent 应优先使用 skill 自带的异步 job 语义:启动命令用短 wrapper timeout 拿到 job id 或明确的启动失败,再用短 `job-status`、state 文件和日志读取轮询进展。除非用户明确要求同步等待并设置了足够大的 Gateway 命令超时,不要通过 gateway 执行 `--wait` 长轮询;同步等待会占用一个 in-flight 槽位,旧 gateway 还会造成队头阻塞。 串口启动日志请求必须优先使用 Windows 侧 `serial-monitor` skill,而不是在 cloud-api 新增串口专用 route: ```sh cd C:\Users\liang\.agents\skills\serial-monitor npm run cli -- server status npm run cli -- server start npm run cli -- monitor start -p -b npm run cli -- fetch --session-only --no-dedup ``` Keil 下载后的启动日志抓取应和 build/download 共用同一个 Codex stdio session 与 gateway wrapper trace。71-FREQ 类项目的串口参数以 Windows 侧 `serial-monitor\SKILL.md` 和实时设备枚举为准;需要轮询时用短 wrapper 调用读取 session/state/log,而不是新增聊天层白名单或 blocker。 ## Smoke Checks 本地合同检查: ```sh node scripts/code-agent-chat-smoke.mjs ``` 该命令验证 schema、`provider_unavailable` provider gap、`OPENAI_API_KEY` missing-env 分类,以及本地 stub completion 不能升级为 DEV-LIVE pass。 Workbench 静态接线检查: ```sh node scripts/dev-cloud-workbench-smoke.mjs --static node scripts/dev-cloud-workbench-smoke.mjs --dom-only --url http://74.48.78.17:17666/ ``` 该命令验证 Workbench 默认页、同源只读边界和 `/v1/agent/chat` 前端主流程接线。它只产出 `SOURCE` 级证据。`--dom-only` 会保留部署 runtime/web-asset identity preflight, 但只做真实 DEV DOM/help 只读观察;它不会发送 `/v1/agent/chat`,Code Agent journey 必须记录为 `not_applicable`,不能冒充真实 DEV-LIVE reply。 授权凭证注入后的真实 DEV 复测: ```sh node scripts/code-agent-chat-smoke.mjs --live node scripts/code-agent-chat-smoke.mjs --live --url http://74.48.78.17:17667/ --timeout-ms 45000 ``` `--live` 会向真实 DEV `/v1/agent/chat` 发送一条最小聊天请求。输出只包含 readiness、provider/model/backend、assistant 回复是否非空和长度、错误分类等摘要;不打印 assistant 回复正文,不读取或打印任何 Secret 值。 默认 `--live` 应指向当前 G14 DEV API/edge 入口 `17667`,而不是历史 D601 端口。 健康的 Codex stdio 冷启动首个 assistant token 可能需要数十秒;10 秒级 transport timeout 会把健康环境误报为 transport blocker。把 timeout 提高到 45 秒左右只是在真 实 DEV 路由上减少误报,不能替代 `completed` + 非空 assistant reply 的最终判定标 准。 ## 复测结果解释 - 若输出 `readiness.level: "BLOCKED/credential"`,后续动作是由授权路径注入 `hwlab-code-agent-provider/openai-api-key`,不是由 runner 临时补 Secret。 - 若输出 `readiness.level: "#143 DEV-LIVE reply pass"`,只说明真实回复链路通过; 它不自动证明 M3、M4、M5 或硬件闭环通过。 - 若 `scripts/dev-cloud-workbench-smoke.mjs --static` 通过,而 `--live` 未通过,结论是 Workbench 接线和源合同通过,但真实 provider readiness 仍 blocked。 ## 稳定来源 - [docs/reference/cloud-workbench.md](cloud-workbench.md):Cloud Workbench 默认页和同源边界。 - [docs/reference/dev-runtime-boundary.md](dev-runtime-boundary.md):DEV 端口、k3s 与运行态边界。 - [docs/reference/architecture.md](architecture.md):`SOURCE`、`LOCAL`、`DRY-RUN`、 `DEV-LIVE`、`BLOCKED` 证据分级。