Files
pikasTech-HWLAB/docs/reference/code-agent-chat-readiness.md
T

319 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.<namespace>.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
forwarderforwarder 再直连 `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 版本和 workspaceD601 只能作为 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 transporthyueapi 仍由 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:<port>`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 transportCI/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 <ms> --powershell-stdin <<'PS1'
<bounded PowerShell script>
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=<status> op=<operationId> exit=<exitCode> s=<duration>`,正文展示 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/<traceId>` 获取终态,并用 `/v1/agent/chat/trace/<traceId>` 刷新可视 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/<traceId>` 是终态摘要接口,不是完整 trace 下载接口。它可以携带压缩后的 `runnerTrace` 窗口用于传输保活,但 Workbench 用户界面不得把该窗口显示为“压缩窗口”或“显示全部”。只要结果或轮询快照声明 `eventsCompacted=true`,前端必须自动请求 `/v1/agent/chat/trace/<traceId>` 并用完整 trace 替换可视事件线;回放完成前只能显示“完整 trace 回放中/当前已载入”状态。result 响应仍必须保留 `eventCount``lastEvent``providerTrace``threadId/sessionId` 和终态 reply/blocker;完整 trace 只能从 `/v1/agent/chat/trace/<traceId>`、复制 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/<traceId>` 做 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 <windows path>` 或脚本内 `Set-Location -LiteralPath <path>` 表达,不要在 prompt 里拼 `cmd /c "cd ... && ..."`
- 命令参数在 PowerShell 脚本里用数组或显式变量传递,例如 `$args = @("subcommand", "-p", $projectPath)``& $exe @args`,避免让模型手动嵌套引号。
- 对所有 Windows skill 都先复用 `C:\Users\liang\.agents\skills\<skill>\SKILL.md` 和该 skill 自带 CLICode Agent 只负责通过 repo wrapper 调用,不把 skill 行为复制到 cloud-api 或 wrapper。
- 一次探测命令失败后,只做一次更窄、更结构化的修正;若仍失败,返回失败 `operationId`、stderr 摘要和下一步,而不是连续试错。
Windows 文件系统探测必须是有界小输出:
-`F:\work``F:\work\ConStart` 或同类目录先做顶层目录/项目标记探测,不要读取 Secret、env、kubeconfig、DB URL 或完整源码内容。
- 使用 `-LiteralPath``Select-Object -First <N>``ConvertTo-Json -Compress -Depth <N>`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 <project.uvprojx> -t <target>
py -3 keil-cli.py job-status <job_id>
```
多 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 <COMx> -b <baud>
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` 证据分级。