Files
pikasTech-HWLAB/docs/reference/spec-hwpod-harness.md
T
2026-06-08 11:25:54 +08:00

310 lines
32 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.
# HWPOD Harness 规格
> **hwpod-node 运维操作见 `hwpod-ops` skill**`~/.agents/skills/hwpod-ops/SKILL.md`),包含 G14 serve 模式、D601 Windows connect 模式启停、cloud-api 注册状态检查、源码同步、日志路径和故障排查。
本文是 HWLAB `v0.2` 的 HWPOD Harness 长期规格。概念体系和实施跟踪见 [pikasTech/HWLAB#897](https://github.com/pikasTech/HWLAB/issues/897)。当前实现只打通单线程核心业务闭环,不把鉴权、安全、并发、计量、复杂调度或 Evidence 体系作为前置条件。
本规格不保留旧设备执行路径作为迁移对照;新任务只按 HWPOD 单通道实现和验收。
## 快速迭代阶段
快速迭代阶段把业务翻译权放在 Code Agent workspace 内:
```text
Code Agent workspace
.hwlab/hwpod-spec.yaml
hwpod-cli
hwpod-ctl
hwpod-compiler-cli
hwpod-cli / hwpod-ctl
-> hwpod-compiler-cli
-> hwpod-node-ops plan
-> hwlab-api
-> hwpod-node
```
核心边界:
- `hwpod-spec` 存放在 Code Agent workspace 内,是当前 hwpod 的本地声明式定义。
- `hwpod-cli` 是用户和 Code Agent 执行研发动作的入口。
- `hwpod-ctl` 是和 `hwpod-cli` 平级的管理入口,用于初始化、修改、检查 `hwpod-spec`,以及 smoke/node 状态类操作。
- `hwpod-compiler-cli` 是 workspace-local 编译器,把高层 intent 和 `hwpod-spec` 编译为 `hwpod-node-ops`
- `hwlab-api` 只接收 `hwpod-node-ops` plan,负责转发和返回结果,不承担业务翻译。
- `hwpod-node` 是靠近硬件的薄执行节点,只维护少量稳定 op handler,不保存完整 `hwpod-spec`,也不解释高层 hwpod intent。
## 云端平台阶段
快速闭环跑通后,再逐步迁移为云端平台能力:
- 将 workspace-local `hwpod-spec` 注册或同步到云端,形成云端 hwpod source of truth。
-`hwpod-ctl spec` 从本地文件管理迁移为云端 hwpod/spec 管理,同时保留本地导入、导出和调试能力。
-`hwpod-compiler-cli` 服务化为云端 `hwpod-compiler`,供 Web、Code Agent、batch harness 和 CI/HIL gate 共用。
-`hwlab-api` 从薄转发面扩展为 hwpod run 管理面,承载 run 状态、计划版本、结果归档和后续 Evidence。
- 只在多个任务反复需要同一类基础动作时扩展 `hwpod-node-ops`,避免把业务变化下沉到 node。
## 核心概念
| 概念 | 定义 | 当前阶段含义 |
| --- | --- | --- |
| `hwpod` | 硬件研发执行逻辑实体 | 由 target device、workspace、debug probe、io probe 四要素组成 |
| `hwpod-spec` | hwpod 的声明式定义 | 先存放在 Code Agent workspace 内,后续迁移到云端维护 |
| `hwpod-cli` | 用户和 Code Agent 的任务入口 | 发起 inspect、workspace、build、download、reset、UART、JSON-RPC 和 closeout |
| `hwpod-ctl` | workspace 内的管理入口 | 初始化/检查/修改 spec、绑定 node、执行 smoke 和临时维护动作 |
| `hwpod-compiler-cli` | workspace-local HWPOD 编译器 | 把高层 intent + spec 编译为 `hwpod-node-ops` plan |
| `hwpod-compiler` | 云端化后的编译服务 | 由 `hwpod-compiler-cli` 成熟后服务化而来 |
| `hwpod-node-ops` | node 最小操作协议 | `hwlab-api``hwpod-node` 之间的稳定执行契约 |
| `hwpod-node` | 靠近硬件的薄执行节点 | PC host、AI 网关、调试器边缘设备或实验室控制盒上的 executor |
| `hwlab-api` | HWPOD node-ops 转发面 | 快速阶段只转发 node-ops plan 并返回 result |
`hwpod` 的四个本体要素固定为:
- target device:被研发或调试的目标设备。
- workspace:项目源码、工程、构建工具链和 artifact 边界。
- debug probe:下载、复位、chip-id、调试连接等能力。
- io probeUART、JSON-RPC、GPIO/relay 或其他 I/O 观测与交互能力。
`nodeBinding``hwpod-spec` 的部署字段,不属于 hwpod 四个本体要素。
## hwpod-spec
快速迭代阶段的默认 spec 路径是 `.hwlab/hwpod-spec.yaml`。CLI 也可以通过 `--spec <path>` 显式指定。第一版 spec 保持轻量:
```yaml
apiVersion: hwlab.dev/v0alpha1
kind: Hwpod
metadata:
uid: hwpod-local-demo
name: demo
spec:
targetDevice:
board: D601-F103-V2
mcu: STM32F103
workspace:
path: /workspace/project
toolchain: keil-mdk
keilProject: firmware/demo.uvprojx
keilTarget: Debug
debugProbe:
type: daplink
adapter: keil
probeUid: 3FD750C63E342E24
programBackend: keil
ioProbe:
uart:
id: uart/1
port: COM9
baudrate: 115200
nodeBinding:
nodeId: node-d601-pc-host
nodeType: pc-host
```
最低校验要求:
- `kind` 必须为 `Hwpod`
- `spec.targetDevice``spec.workspace``spec.debugProbe``spec.ioProbe` 必须存在。
- `spec.nodeBinding.nodeId` 必须存在。
- `spec.workspace.path` 必须存在。
Keil MDK 装配规则:当 `spec.workspace.toolchain``keil-mdk``keil``mdk``uv4` 时,`hwpod-compiler-cli` 可以直接从 `hwpod-spec` 生成 `debug.build` / `debug.download` 的 node-side command。`spec.workspace.keilProject``spec.workspace.projectPath` 指向 `.uvprojx`,相对路径按 `spec.workspace.path` 解析;`spec.workspace.keilTarget``spec.workspace.targetName` 指向 Keil target。`spec.debugProbe.probeUid` 用于固定 DAP-Link/CMSIS-DAP 选择,`spec.debugProbe.programBackend` 默认按 Keil UV4 工程链路下载。标准下载语义必须由 compiler 生成 Keil `flash` 命令,让 build+program 留在同一个 Keil 异步 job 中;不得依赖预先存在的 artifact、手工 uvoptx 状态或旧 profile 副作用。只有 `spec.debugProbe.autoBindUvoptx` / `autoBindProbe` 显式打开时,compiler 才生成 probe-binding 写回步骤。自动生成的 Keil 计划必须使用已有 `cmd.run` op,并用 `command` + `argv` 传递参数;`probeName`、Windows 路径和 target 名称必须作为独立 argv 元素,不得依赖 `cmd.exe /c`、PowerShell 或 `&&` 拼接来保真带空格参数。Keil 长任务默认异步启动,后续用 `hwpod-cli job status <jobId>` 查询;该入口仍编译为 `cmd.run` 调已有 Keil CLI,不新增 node op。
`spec.workspace.buildCommand``spec.debugProbe.downloadCommand``spec.debugProbe.resetCommand` 仍是调试覆盖出口;标准 case 和 Code Agent runner 不应依赖这些字段长期手写 Keil 主流程。旧 `device-host-cli` / device pod profile 不再作为 compiler 输入权威,相关工程、target、probe 和下载 backend 信息必须迁入 `hwpod-spec`
## hwpod-node-ops
`hwpod-node-ops` 不表达用户意图,只表达 node 可执行的基础动作。当前新增能力边界收敛为文件读写/patch 类 op 加 `cmd.run`:有 `cmd.run` 就能覆盖 host 上成熟 CLI、编译器、下载器、串口工具和维护命令,再加上受控文件读写即可支撑源码修改 case。后续新增 case 不应因为 build、download、job status、UART、reset 或某个调试工具需要而新增专用 node op;这些业务翻译必须优先落在 `hwpod-compiler-cli` / `hwpod-cli` 组合层。
基础 op 集合:
| op | 用途 |
| --- | --- |
| `node.health` | 查询 node 存活和基础状态 |
| `node.version` | 查询 node runtime 版本 |
| `node.inventory` | 查询 workspace/probe/io 能力 |
| `workspace.ls` | 列目录 |
| `workspace.cat` | 读文件 |
| `workspace.rg` | 搜索文件内容 |
| `workspace.apply-patch` | 应用 Codex apply_patch envelope 源码补丁 |
| `workspace.write` | 带 `expectedSha`、换行策略和 diff 摘要的整文件写入 |
| `workspace.replace` | 带 `expectedSha`、唯一匹配检查和 diff 摘要的精确文本替换 |
| `workspace.insert-after` | 按精确 anchor 插入文本,避免 PowerShell/cmd quoting |
| `cmd.run` | 通用 host 命令透传,用于组合 Keil、serial-monitor、job status、下载、复位和临时维护动作 |
若历史实现中仍存在 `debug.*``io.*` 这类专用 op,它们只能作为兼容存量观察对象,不再作为新 case 或新 harness 业务的扩展方向。标准路径是:compiler 根据 spec 生成 `cmd.run``command` + `argv`,node 只负责在目标 host 上忠实执行并返回 stdout/stderr/exit code。
`hwpod-node` 是 HWPOD 的唯一受控节点执行器。第一阶段的业务扩展优先落在 `hwpod-compiler-cli` / `hwpod-cli`,通过已有文件读写 op 和 `cmd.run` 组合 Keil、serial-monitor 等成熟工具;不要因为某个 case 需要 build、job status、download、UART 或临时维护动作就新增专用 node op。`cmd.run` 的命令解析、PATH 稳定性和跨平台差异必须在 `hwpod-node` 本体内处理;当 Windows service、后台进程或 D601 host 的环境变量与交互 shell 不一致时,不得用 gateway shell、手工 PowerShell、预先手工创建 worktree 或其他旁路代替 `hwpod-node-ops -> hwpod-node`。D601/Windows 实地调试应使用 UniDesk SSH 透传 `D601:win` 观察进程、PATH、工具安装位置和日志,但修复必须回到 `hwpod-node` 源码、配置或启动入口,并用 `/v1/hwpod-node-ops` 原链路复测。只有 `cmd.run` 自身的执行语义、环境继承或可见性不满足真实 host 执行时,才修改 `hwpod-node`;否则优先改 compiler/CLI。
Windows subject worktree 文本修改优先使用 `workspace.apply-patch``workspace.replace``workspace.insert-after``workspace.write`,不要把 `cmd.run` 的 PowerShell/cmd quoting 当成标准编辑路径。文本编辑结果必须返回编辑前后 SHA、文件字节数、换行类型、diff 摘要和 dry-run 状态;`apply-patch` 匹配失败时必须返回 normalized preview、候选行号、CRLF/LF 统计、文件 SHA/bytes 和 hwpod-node implementation version,便于判断是上下文不匹配、CRLF 问题还是远端实现版本问题。`workspace.apply-patch` 应保留原文件换行风格,尤其不能把 CRLF subject 文件静默改写成 LF。
UART read 默认由 compiler 把 `hwpod-cli uart read` 编译为已有 `cmd.run` 内的一段短序列,调用节点本地 `serial-monitor` CLI 的 `monitor start``fetch --session-only`。两步必须在同一个 `cmd.run` 内顺序执行:`monitor start` 的 JSON 若返回 `success:false`,该 `cmd.run` 必须以非 0 退出并停止,不得继续 fetch 旧会话数据。默认绑定路径是 `C:\Users\liang\.agents\skills\serial-monitor`,也可通过 `spec.tooling.serialMonitorDir``spec.ioProbe.serialMonitorDir` 或 CLI 参数覆盖;`spec.ioProbe.uart.port``spec.ioProbe.uart.baudrate` 是物理串口和波特率权威。串口采集失败时必须把 serial-monitor 的 stdout/stderr、exit code 和 command argv 原样留在 `cmd.run` result 中;不得静默伪造空读数,也不得要求 Agent 改走手写 PowerShell/串口脚本旁路。
标准 plan 形态:
```json
{
"contractVersion": "hwpod-node-ops-v1",
"planId": "plan_xxx",
"hwpodId": "hwpod-local-demo",
"nodeId": "node-d601-pc-host",
"intent": "workspace.ls",
"ops": [
{ "opId": "op_001", "op": "workspace.ls", "args": { "path": "." } }
]
}
```
每个 op 的结果第一版保持简单:
```ts
type HwpodNodeOpResult = {
opId: string;
op: string;
ok: boolean;
status: "completed" | "blocked" | "failed";
exitCode?: number;
stdout?: string;
stderr?: string;
summary?: string;
blocker?: { code: string; summary: string } | null;
};
```
## CLI 入口
快速阶段的源码入口使用 Bun 直接运行 TypeScript 文件;runner 或 skill 可以把这些入口暴露为短命令:
```bash
bun tools/hwpod-ctl.ts spec init --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-ctl.ts spec validate --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-compiler-cli.ts compile --spec .hwlab/hwpod-spec.yaml --intent workspace.ls --args '{"path":"."}'
bun tools/hwpod-cli.ts inspect --spec .hwlab/hwpod-spec.yaml --dry-run
bun tools/hwpod-cli.ts workspace read --spec .hwlab/hwpod-spec.yaml projects/01_baseline/User/main.c
bun tools/hwpod-cli.ts workspace replace --spec .hwlab/hwpod-spec.yaml --path projects/01_baseline/User/main.c --find "old text" --replace "new text" --expected-sha <sha>
bun tools/hwpod-cli.ts workspace insert-after --spec .hwlab/hwpod-spec.yaml --path projects/01_baseline/User/main.c --anchor "while (1)" --line " /* marker */"
bun tools/hwpod-cli.ts download --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts job status <jobId> --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts uart read --spec .hwlab/hwpod-spec.yaml --port uart1
bun tools/hwpod-node.ts serve --host 127.0.0.1 --port 19678
```
`hwpod-cli` 的正常任务路径是:读取 spec、调用 compiler、把 node-ops plan 交给 `hwlab-api`,最后输出 closeout/result。`hwpod-ctl` 的管理路径可以在本地直接修改 spec,也可以生成 smoke plan 交给 `hwlab-api` 验证 node 链路。
## HWPOD CLI 调试入口分层
HWPOD 调试固定保留两种入口,二者必须调用同一套 `hwpod-cli` / `hwpod-ctl` / `hwpod-compiler-cli` 组合层,并最终走 `/v1/hwpod-node-ops` 到目标 `hwpod-node`。不要因为入口不同而复制下载、编译、串口或 job status 逻辑,也不要为 build、download、UART 或 job status 新增 node 专用 op。
### 人工单步直调 hwpod-cli
人工或维护 agent 定位 CaseRun 卡点时,优先在 G14 v0.2 workspace 直接调用 `hwpod-cli` 的单步命令。调用前必须加载 v0.2 CLI API key 和 runtime endpoint,并显式选择 run-local spec 或 case registry specspec 是 DAPLink、Keil target、COM 口、波特率和 subject worktree 的唯一输入权威。
```bash
. /root/.config/hwlab-v02/master-server-admin-api-key.env
export HWLAB_RUNTIME_API_URL=http://74.48.78.17:19667
export HWLAB_RUNTIME_WEB_URL=http://74.48.78.17:19666
export HWLAB_RUNTIME_ENDPOINT_LOCKED=1
bun tools/hwpod-ctl.ts spec validate --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts inspect --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts workspace cat --spec .hwlab/hwpod-spec.yaml --path projects/01_baseline/User/main.c
bun tools/hwpod-cli.ts build --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts download --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts job status <jobId> --spec .hwlab/hwpod-spec.yaml
bun tools/hwpod-cli.ts uart read --spec .hwlab/hwpod-spec.yaml --port uart1 --max-bytes 4096
```
直调入口只用于单步定位和原链路复测:`build` / `download` 返回 Keil async job accepted 只能证明命令已投递,不能等同于编译或下载成功;必须继续用独立短命令 `hwpod-cli job status <jobId>` 轮询终态,不要把轮询包进 `sleep &&``timeout``watch``head`、pipe 或 shell loop。解释结果时结合 `uart read`、Keil result 或目标串口日志。串口被人工工具占用时,应先释放 COM 口或读取已有 serial-monitor 数据解释现象,不得把 COM 口占用误判成 DAPLink、目标板或 API 不可用。
### CaseRun 让 code agent 调 hwpod-cli
CaseRun 验证 code agent 能力时,runner 的职责是布置舞台,而不是代替 agent 完成源码修改或硬件动作。标准流程是:CaseRun 从 case registry 读取 `case.json``hwpod-spec.yaml`,创建 subject 隔离 worktree,生成 run-local `.hwlab/hwpod-spec.yaml` 并把 `spec.workspace.path` 改写到该 worktree,再把当前 HWPOD CLI/skill 文件随 AgentRun workspace 一起提供给 code agent。
code agent 必须在自己的 AgentRun workspace 内调用同一套入口,例如:
```bash
hwpod-ctl spec validate --spec .hwlab/hwpod-spec.yaml
hwpod inspect --spec .hwlab/hwpod-spec.yaml
hwpod workspace cat --spec .hwlab/hwpod-spec.yaml --path projects/01_baseline/User/main.c
hwpod workspace replace --spec .hwlab/hwpod-spec.yaml --path projects/01_baseline/User/main.c --find <old> --replace <new> --expected-sha <sha>
hwpod build --spec .hwlab/hwpod-spec.yaml
hwpod download --spec .hwlab/hwpod-spec.yaml
hwpod job status <jobId> --spec .hwlab/hwpod-spec.yaml
hwpod uart read --spec .hwlab/hwpod-spec.yaml --port uart1 --max-bytes 4096
```
对 Code Agent 而言,Keil/HWPOD 长任务同样遵循 cli-spec 短连接组合:`build``download` 只负责返回 async job id`job status` 必须作为独立短命令少量轮询;若仍处于 running,应报告 job id、status、diagnostics 和当前判断,不要用长 shell 等待把 agent 子阶段拖成黑盒。
CaseRun prompt 只能描述任务、边界、允许修改的文件、必须尝试的 HWPOD 命令和需要回报的 raw output/job id/串口尾部;不得把具体源码补丁、预期答案或自动评价逻辑写成 prompt。CaseRun result 负责归档 agent session id、trace id、agent message、final response、workspace diff、HWPOD command trace 和 registry run 产物;不做 evidence 自动评价、不做门禁、不把 runner 后置命令伪装成 agent 命令。若某个步骤卡住,先用人工单步直调入口复测同一 spec 和同一 subject worktree,确认是 HWPOD CLI/Keil/serial-monitor/hwpod-node 业务问题后再修复对应组合层或 node 本体。
## CaseRun 无服务阶段
第一阶段 CaseRun 不引入常驻调度服务,由 `hwlab-cli case` 组合 case registry repo、本地 `.state``hwpod-cli``hwpod-compiler-cli``hwlab-api` 和在线 `hwpod-node` 完成单次运行。标准 case registry repo 是 `pikasTech/hwlab-case-registry`,本地默认 checkout 路径是 `/root/hwlab-case-registry`;历史 `pikasTech/hwpod-cases` 只作为迁移前来源。case registry repo 提供 `cases/<caseId>/case.json` 与同目录 `hwpod-spec.yaml`;每次运行会先在 subject repo 本地 checkout 下创建隔离 Git worktree,再把 spec 复制到 `.state/hwlab-cli/caserun/<runId>/.hwlab/hwpod-spec.yaml` 并把 `spec.workspace.path` 改写到该隔离 worktree,形成 run-local spec。
CaseRun 的 case registry repo 与 subject repo 必须分离。标准 registry repo 是 `pikasTech/hwlab-case-registry`G14 标准 checkout 是 `/root/hwlab-case-registry`;历史 `pikasTech/hwpod-cases``/root/hwpod-cases` 只作为迁移前来源,不再作为新 CaseRun 入口或写入目标。case registry repo 只保存 `case.json`、HWPOD spec 或 spec 引用、`subject` 引用、期望结果和 `runs/<caseId>/<runId>/` 审计产物;它不保存或替代实际固件、工程、测试样例或产品代码库。subject repo 是被开发、被测试、被编译或被下载验证的真实源码仓库,`case.json.subject` 必须明确写入 `repoLocalPath``commitId`,其中 `repoLocalPath` 是绑定 HWPOD node 上的本地 Git checkout`commitId` 是完整 40 字符 subject commit id。`case run` 准备阶段只能从 `repoLocalPath` 执行 `git worktree add --detach <worktree> <commitId>`,不得 clone/fetch GitHub,也不得把 branch、tag 或当前 HEAD 作为执行依据或 fallback。若 HWPOD spec 声明 Keil MDK 工程,准备阶段还必须把同名 `.uvoptx` / `.uvopt` sidecar 从 `repoLocalPath` 同步到 isolated worktree,并在 prepare 结果里暴露 copied/missing 诊断;这些 sidecar 承载 CMSIS-DAP/UV4 探头绑定、flash sequence 和 reset/run 配置,不能被 git worktree 的 tracked-file 视角静默丢失。`subdir` 只描述 subject repo 内的 case 关注区域,不能替代 `spec.workspace.path` 的隔离 worktree。`evidence.json` 必须记录 subject repo 本地路径、subject commit、subdir 和 run-local worktree,避免把 floating ref 或外部脏 workspace 当作可审计证据。
标准 `case.json` 的 subject 字段形态如下:
```json
{
"subject": {
"repoLocalPath": "F:\\Work\\HWLAB-CASE-F103",
"commitId": "df7a4e6e551fa90d64bde5537cc000f89d63dd20",
"subdir": "projects/01_baseline"
}
}
```
每个 case 必须按任务难度独立配置 agent 阶段等待窗口,避免用单一全局 timeout 误判长任务或拖慢短任务。优先在 `agentTask.timeoutMs` 写入该 case 的 Code Agent 预期窗口;需要统一组织多个阶段 timeout 时,也可以写顶层 `timeouts.agentTimeoutMs`,但 CLI 显式参数 `--agent-timeout-ms` / `--timeout-ms` 仍作为人工单次覆盖。`timeoutMs` 只控制 CaseRun 等待 agent terminal/result 的窗口,不是 evidence 自动评价、门禁或成功判定。未配置时 CLI 兜底为 600000ms;case 可按难度显式收紧或放宽,当前 CLI 上限为 3600000ms。
### CaseRun 当前实现边界
当前 `d601-f103-v2-compile` 是 compile-only smoke,用于验证 case registry repo 与 subject repo 分离、`repoLocalPath``commitId` 的 subject provenance、隔离 subject worktree、run-local spec rewrite 和 D601 Keil 编译证据。它不创建 HWLAB Code Agent session,不调用 DS/DeepSeek/provider,不向 Code Agent 下发任务 prompt,不等待 agent trace,也不验证 agent 在源码仓库内完成修改。因此,compile-only CaseRun 是 HWPOD runner 和 Keil 编译底座 smoke,不是 Code Agent 能力评测。
### CaseRun 目标边界:布置舞台与任务 prompt
目标形态中,`case run` 的职责是布置 subject worktree、HWPOD spec、工具入口、上下文包和任务 prompt,再创建或调用 HWLAB Code Agent / AgentRun session,让 Code Agent 在隔离 worktree 内完成源码修改、分析或调试任务。`case run` 可以等待 agent terminal state、读取 workspace diff、执行 build/download/UART smoke、收集 evidence 和判定验收;不得替 Code Agent 生成补丁、直接修改 subject source 或把 deterministic runner 实现当作任务答案。对于“增加一行打印代码”这类 case,源码 diff 必须来自 Code Agent sessionrunner 只能验收该 diff。边界跟踪见 [pikasTech/HWLAB#976](https://github.com/pikasTech/HWLAB/issues/976)。
agent-task CaseRun 的 evidence 必须至少记录:subject repo 本地路径、subject commit、隔离 worktree、任务 prompt 来源、Code Agent session/trace/provider/model、agent 产生的 workspace diff、验证动作和验证结果。compile-only smoke 的 evidence 不得伪造或补写 agent provenance。
Agent compile-only 阶段必须走 HWLAB Code Agent / AgentRun 的成熟入口:CaseRun 负责生成 prompt/context、创建或调用显式 Code Agent session,并通过 `case run start/status/result/logs` 轮询终态;prompt 必须要求 agent 在自己的 AgentRun workspace 内使用 gitbundle 装配出的标准 `hwpod` / `hwpod-ctl` 工具执行 compile-only 验证。CaseRun 可以保留 runner 后置 compile 作为收尾或对照证据,但 evidence 必须把 agent trace 中的 HWPOD commandExecution 与 runner 后置 `hwpod-cli build` 分开记录,不得把 runner 直接编译伪装成 agent 编译。
CaseRun 是强化学习 Harness 的最小执行单元,但它本身不是完整 epoch。完整 epoch 还需要样本选择、策略生成、奖励/评价、批量调度、跨 run 归因和自动训练闭环;第一阶段只要求一个 `caseId` 能从 case registry repo 进入真实 HWPOD 编译闭环,并把可审计产物稳定落盘。
最小入口:
用法详见 `hwlab-caserun` skill,包含同步运行、异步 start/status/result/logs、分步 prepare/build/collect 和 provider profile 选择等完整用法。
`case run` 在当前版本只负责编排流程和记录原始证据,不做 evidence 自动评价、自动打分或门禁判断。流程是:prepare 先在 subject repo 本地 checkout 下创建 `.worktree/caserun-<runId>` 隔离 worktree并写入 run-local spec,然后生成 Code Agent prompt/context,创建或调用 HWLAB Code Agent session,把 isolated worktree、run-local HWPOD spec、任务目标和约束交给 Code Agent;agent 阶段结束或超时后,CaseRun 记录 agent identity、terminal result 里已有的终态字段、trace lookup hint、subject worktree 的 `git status` / `git diff --stat` / `git diff --binary`,再按 case 定义执行 runner 后置 `hwpod-cli build``cmd.run` Keil 异步 job-status 查询,最后把原始证据和可读归档写入 case registry repo 的 `runs/<caseId>/<runId>/`。固定归档包括 `evidence.json``summary.md``run.json``result.json``agent-prompt.md``agent-diff.patch`、run-local `.hwlab/hwpod-spec.yaml`、worker stdout/stderr、`artifact-manifest.json`,以及 `agent-messages.json``agent-trace.md``agent-transcript.md``final-response.md``agent-trace.md` / `agent-transcript.md` 必须包含 trace lookup hint、renderer 标识和 subject diff 区块;如果归档了完整 rendered rows,其语义必须来自共享 Web/CLI trace renderer,不能由 CaseRun 自行发明。`final-response.md` 在 terminal result 存在权威 finalResponse 时保存正文,不存在时显式记录 `finalResponse=null`、terminal/error rows 和缺失原因。下载不作为 compile-only CaseRun 的隐式步骤;后续需要下载时,应作为独立 action 显式加入 case 定义和流程记录。
CaseRun 下发给 HWLAB Code Agent 的请求不得再携带 ad hoc `workspaceFiles` 或 source tree 工具种子;当前工具和 skills 必须由 AgentRun `ResourceBundleRef.kind="gitbundle"` 装配,固定把 repo `tools/` 复制到 workspace `tools/`,把 repo `skills/` 复制到 workspace `.agents/skills`。这不是把 prompt 写成答案,而是保证 Code Agent 看到的 `hwpod` 能力、help、wrapper 和 `cmd.run` 组合语义与当前 `v0.2` 源码一致。若 agent 报告标准 `hwpod` 命令缺失或 help 明显过时,优先修 gitbundle runtime assembly 或 HWPOD CLI/skill 装配,不新增 hwpod-node 专用 op,也不把业务动作旁路到 shell 脚本。
CaseRun 的 trace 处理必须遵循 [spec-v02-code-agent-trace.md](spec-v02-code-agent-trace.md) 的组合优先原则:CaseRun 只负责稳定返回和归档 `traceId``sessionId``conversationId``threadId`、AgentRun 执行线索以及 `traceLookup.commands.*`,完整 trace/result/session 读取继续使用已有 `hwlab-cli client agent trace/result/inspect`。CaseRun 不应在自身内部再实现一套 `/v1/agent/chat/trace/{traceId}` 查询器、row renderer、session 反查或 final response 归因逻辑;如果已有 agent CLI 的 trace 可见性不足,先改进 `client agent trace/result/inspect`,再让 CaseRun 输出新的 ID 或 hint。归档中的 `agent-trace.json` 可以是 `lookupOnly=true` 的 identity manifest,表示“用这些 ID 调既有 CLI 查完整 trace”,不能伪装成完整 trace dump。
长时间 CaseRun 必须优先使用 `case run start/status/result/logs` 短连接形态,而不是用 shell/nohup 包装同步 `case run``start` 只负责创建 `.state/hwlab-cli/caserun/<runId>/`、启动后台 worker 并立即返回 `runId`、PID、stdout/stderr 路径和下一条查询命令;`status``result``logs` 都是短查询。`run.json` 是阶段状态权威,阶段开始时就要刷新 `status``stage``traceId/sessionId/conversationId/threadId`、AgentRun/trace 轮询信息、stdout/stderr byte count 和下一条轮询命令;长等待期间不得出现无输出、无 trace、无状态文件更新的黑洞窗口。
当前标准 smoke case 是 `d601-f103-v2-compile`。它绑定已发现并预装的 `D601-F103-V2` HWPOD spec,目标是让 CaseRun 通过 Web 等价入口或 AgentRun runner 布置 Code Agent 舞台,再调用 `hwlab-cli case run d601-f103-v2-compile` 跑完整流程,而不是由操作员手工编译后代替运行。当前版本的结果只要求记录:subject provenance、agent prompt/session/trace/conversation/provider、subject worktree diff 文件、HWPOD build invocation、Keil job/status/artifact 字段、`compileOnly=true``downloadSkipped=true`;不得把这些 evidence 自动归纳为 Code Agent 通过/失败。
产物归属按两条线分开:
- case registry repo 的 `runs/<caseId>/<runId>/` 是 CaseRun 审计产物权威入口;`.state/hwlab-cli/caserun/<runId>/` 只保留短连接控制和轮询所需状态,不作为长期产物入口。registry run 目录必须包含 trace manifestmanifest 只记录文件哈希、agent trace/session、subject provenance、diff 和 Keil job 字段,不引入自动评价或门禁结论。
- `case run`、异步 worker 完成收口和 `case run result` 刷新归档后,默认必须把当前 `runs/<caseId>/<runId>/` 目录自动 `git add``git commit``git push origin HEAD` 到 case registry repo;只允许提交当前 run 目录,不得顺带提交 registry 里其他历史未跟踪 run。`registrySync` 必须写入 result/summary,说明 `pushed``unchanged` 或失败阶段。`--no-case-repo-record` 是完全不记录 registry 的诊断出口;`--no-case-repo-git-sync` / `--no-registry-git-sync` 只用于特殊本地调试,不能作为正常 CaseRun 产物收口方式。
- HWLAB repo 的 harness、`hwpod-cli``hwpod-ctl``hwpod-compiler-cli` 或文档改进可以按风险进入 `v0.2` 分支;单纯文档和轻量 CLI/helper 变更可直接提交,业务代码、运行面或发布链路变更走 PR 工作流。
当前边界:CaseRun 仍是无服务化短连接 CLI 编排,不负责排队、并发、评分、自动合并、长期 run retention 或 epoch 汇总;这些能力属于后续强化学习 Harness 层。CaseRun 也不负责代替 HWLAB Code Agent 完成研发任务,后续 agent-task CaseRun 必须把 prompt/session/trace/diff/evidence 作为一等输出。AgentRun 私有 GitHub repo git transport 必须具备有界失败和可观测性后,才能把单次 CaseRun 扩展为批量 runner 或 epoch 系统。
## 验收标准
快速阶段最小验收:
1. Code Agent workspace 内存在 `.hwlab/hwpod-spec.yaml`,并能通过 `hwpod-ctl spec validate`
2. `hwpod-compiler-cli compile` 能把同一个 spec 和高层 intent 编译为稳定 `hwpod-node-ops-v1` plan。
3. `hwpod-cli --dry-run` 输出的 plan 不需要云端 spec,也不读取其他本地旧 profile authority。
4. `hwlab-api` 的 node-ops 入口能接收 plan,返回 JSON result;无可用 node 时必须返回结构化 blocker,而不是静默伪造 DEV-LIVE。
5. 真实 CLI 验收必须证明 `hwpod-cli -> hwpod-compiler-cli -> hwlab-api /v1/hwpod-node-ops -> hwpod-node` 全链路走通。
6. CaseRun 流程必须能用 `hwlab-cli case run <caseId>` 从 case registry repo 读取 case 定义,按 `subject.repoLocalPath``subject.commitId` 创建隔离 subject worktree,生成 Code Agent prompt/context,记录 agent session/trace/conversation/provider,采集 subject worktree diff,执行 compile-only smoke,并产出 isolated run state 和 case registry repo 全量产物归档;当前版本只记录流程证据和 trace manifest,不设置通过条件、不自动评价 evidence,并明确记录 downloadSkipped。
7. 长任务验收必须覆盖 `hwlab-cli case run start <caseId>` 立即返回,以及 `status/result/logs <runId>` 在 worker 运行中能短查询到阶段、耗时、stdout/stderr byte count、trace/session/conversation/thread 信息和下一条轮询命令;不得把同步命令长时间无输出视为有效 CaseRun 操作体验。
8. `d601-f103-v2-compile` 的真实流程只覆盖当前编排链路和 compile-only smoke;操作员直接运行 `hwpod-cli build`、直接调用 Keil 或只检查 node 侧 job,不等同于 CaseRun 流程跑完。
9. agent-task CaseRun 的真实流程必须证明 `case run` 已创建或调用 Code Agent / AgentRun session,任务 prompt 已进入 agent 上下文,CaseRun 已采集隔离 subject worktree diff,并已继续执行编译、下载或 I/O smoke 等后续动作;当前版本只记录这些事实,不自动判断 agent 是否完成任务。
10. Windows subject worktree 文本编辑必须能在 CRLF 文件中通过 `workspace.insert-after``workspace.replace` 完成一行源码修改,返回 before/after SHA 与 diff 摘要,并保留原文件 CRLF;`workspace.apply-patch` 在 context 不匹配时必须返回可诊断 payload,而不是只给 `context not found`
11. Keil `debug.download` 自动装配必须输出结构化 `cmd.run` argv 步骤;带空格的 `probeName` 在 plan 中必须是单独 argv 元素。`io.uart.read` 必须通过节点本地 `serial-monitor` 读取正在监控的 COM/baud;未监控或工具失败时必须返回包含 `ioProbe`/COM 口/baud/monitor status/启动建议的结构化 blocker details。