Files
pikasTech-HWLAB/docs/reference/spec-hwpod-harness.md
T
2026-06-08 12:51:42 +08:00

334 lines
37 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)HWPOD 集中服务式管理和 `hwpod-id` source-of-truth 收敛见 [pikasTech/HWLAB#1043](https://github.com/pikasTech/HWLAB/issues/1043)。当前实现只打通单线程核心业务闭环,不把鉴权、安全、并发、计量、复杂调度或 Evidence 体系作为前置条件。
本规格不保留旧设备执行路径作为迁移对照;新任务只按 HWPOD 单通道实现和验收。
## 默认运行通道
当前 Code Agent / CaseRun runner 的默认 HWPOD 合同是 `hwpod-id` 加本次任务的 workspace binding,不再要求 runner workspace 预装 `.hwlab/hwpod-spec.yaml`
```text
Code Agent workspace
hwpod-cli
hwpod-ctl
hwpod-compiler-cli
task context: hwpodId + workspacePath
hwpod-cli / hwpod-ctl
-> runtime HWPOD registry (/v1/hwpod/specs?hwpodId=...)
-> HWPOD document + run workspace override
-> hwpod-compiler-cli / in-process compiler
-> hwpod-node-ops plan
-> hwlab-api
-> hwpod-node
```
核心边界:
- `hwpod-id` 是 WebUI、CLI、CaseRun、Code Agent 和 runner 的默认运行时引用。
- HWPOD 定义由 runtime service 解析;runner-local YAML 只作为显式 debug/import/export,不作为默认合同。
- `hwpod-cli` 是用户和 Code Agent 执行研发动作的入口。
- `hwpod-ctl` 是和 `hwpod-cli` 平级的管理入口,用于校验 `hwpod-id` 解析结果、检查四要素/node binding,以及 smoke/node 状态类操作。
- `hwpod-compiler-cli` / in-process compiler 把高层 intent 和 runtime-resolved HWPOD document 编译为 `hwpod-node-ops`
- `hwlab-api` 只接收 `hwpod-node-ops` plan,负责转发和返回结果,不承担业务翻译。
- `hwpod-node` 是靠近硬件的薄执行节点,只维护少量稳定 op handler,不保存完整 `hwpod-spec`,也不解释高层 hwpod intent。
## 云端平台阶段
完整服务式 registry/source-of-truth 仍按 #1043 收敛;当前已具备最小 discovery/resolve 能力:
- `GET /v1/hwpod/specs` 可列出已知 HWPOD,并可按 `hwpodId` 查询用于 CLI/runner resolve。
- `hwpod-ctl spec validate --hwpod-id <id> --workspace-path <run-worktree>` 校验 runtime-resolved document 和四要素。
- `hwpod-cli ... --hwpod-id <id> --workspace-path <run-worktree>` 生成并提交 node-ops plan。
- 将本地 YAML 文件管理降级为显式导入、导出和调试能力,不再作为 AgentRun runner 默认合同。
-`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 的声明式定义 | 由 runtime service 解析;本地 YAML 仅用于显式 debug/import/export |
| `hwpod-cli` | 用户和 Code Agent 的任务入口 | 发起 inspect、workspace、build、download、reset、UART、JSON-RPC 和 closeout |
| `hwpod-ctl` | HWPOD 管理入口 | 检查 `hwpod-id`、四要素、node binding、执行 smoke 和临时维护动作 |
| `hwpod-compiler-cli` | HWPOD 编译器 | 把高层 intent + resolved document 编译为 `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 identity and document
默认入口通过 `--hwpod-id <id>` 解析 HWPOD document。`--workspace-path <run-worktree>` 是 CaseRun/单步调试绑定本次 subject worktree 的运行时 override。`--spec <path>` 只保留为显式 debug/import/export path,不允许作为 Code Agent runner 缺少 service resolve 时的 fallback。
第一版 HWPOD document 保持轻量:
```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` | 递归搜索文件内容,标准别名还有 `grep` / `search` |
| `workspace.apply-patch` | 应用 Codex apply_patch envelope 源码补丁 |
| `cmd.run` | 通用 host 命令透传,用于组合 Keil、serial-monitor、job status、下载、复位和临时维护动作 |
`workspace.rg` 是查找符号、结构体、函数签名和错误文本的标准入口。它在 node 侧直接做受限递归文本搜索,不依赖目标 host 预装 `rg`,并支持 `--context``--before-context``--after-context``--max-matches``--max-files``--max-bytes-per-file``--max-line-bytes`。输出会保留结构化 `matches``scannedFiles``truncated``limits`,用于在不爆炸输出的前提下追踪上下文。需要精准读整文件时才用 `workspace.cat`;查找 ARM-2D 头文件、函数原型或 Demo 入口时,优先用 `workspace.rg` / `workspace.search`,不要再把 `cat` 管道给 shell `grep`
若历史实现中仍存在 `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`,不要把 `cmd.run` 的 PowerShell/cmd quoting 当成标准编辑路径,也不要把旧 `workspace.write` / `workspace.replace` / `workspace.insert-after` 当成新 case 的推荐入口。文本编辑结果必须返回编辑前后 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 validate --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-compiler-cli.ts compile --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --intent workspace.ls --args '{"path":"."}'
bun tools/hwpod-cli.ts inspect --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --dry-run
bun tools/hwpod-cli.ts workspace read projects/01_baseline/User/main.c --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts workspace rg arm_2d_init projects/01_baseline/Middlewares/Arm-2D --context 3 --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
cat patch.txt | bun tools/hwpod-cli.ts workspace apply-patch --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --reason "edit subject workspace through hwpod-node"
bun tools/hwpod-cli.ts download --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts job status <jobId> --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts uart read --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --port uart1
bun tools/hwpod-node.ts serve --host 127.0.0.1 --port 19678
```
`hwpod-cli` 的正常任务路径是:按 `hwpod-id` 从 runtime service resolve HWPOD document、应用 workspace override、编译 node-ops plan、交给 `hwlab-api`,最后输出 closeout/result。`hwpod-ctl` 的管理路径用于校验 resolved document 和 node 链路;本地 YAML 修改只用于显式 debug/import/export。
## 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,并显式传入 `--hwpod-id` 和本次 subject worktree 的 `--workspace-path`resolved HWPOD document 是 DAPLink、Keil target、COM 口和波特率的输入权威,workspace path 是本次运行的覆盖参数。
```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 --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts inspect --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts workspace cat projects/01_baseline/User/main.c --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts workspace rg arm_2d_init projects/01_baseline/Middlewares/Arm-2D --context 3 --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts build --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts download --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts job status <jobId> --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
bun tools/hwpod-cli.ts uart read --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --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 引用,创建 subject 隔离 worktree,把 `hwpodId``hwpodWorkspaceArgs` 写入 agent prompt/context,再把当前 HWPOD CLI/skill 文件随 AgentRun gitbundle workspace 一起提供给 code agent。runner 不再要求 `.hwlab/hwpod-spec.yaml` 进入 AgentRun workspace。
code agent 必须在自己的 AgentRun workspace 内调用同一套入口,例如:
```bash
hwpod-ctl spec validate --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod inspect --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod workspace cat projects/01_baseline/User/main.c --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod workspace rg arm_2d_init projects/01_baseline/Middlewares/Arm-2D --context 3 --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
cat patch.txt | hwpod workspace apply-patch --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --reason "edit subject workspace through hwpod-node"
hwpod build --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod download --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod job status <jobId> --hwpod-id d601-f103-v2 --workspace-path <run-worktree>
hwpod uart read --hwpod-id d601-f103-v2 --workspace-path <run-worktree> --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 或 `hwpodId` 引用;每次运行会先在 subject repo 本地 checkout 下创建隔离 Git worktree,再把 `hwpodId` 与该 worktree 路径组合成 `hwpodWorkspaceArgs`。run-local YAML 可作为审计或 runner 后置对照产物保存,但不能作为 Code Agent runner 的注入合同。
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、`hwpodId`/workspace binding 和 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,解析 `hwpodId` 并生成 `hwpodWorkspaceArgs`,然后生成 Code Agent prompt/context,创建或调用 HWLAB Code Agent session,把 isolated worktree、`hwpodId``hwpodWorkspaceArgs`、任务目标和约束交给 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`、worker stdout/stderr、`artifact-manifest.json`,以及 `agent-messages.json``agent-trace.md``agent-transcript.md``final-response.md`run-local YAML 若存在,只是审计/对照产物,不是 runner 注入合同。`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 registry 聚合阅读入口
`hwlab-cli case aggregate <caseId> --run-id <runId> --case-repo /root/hwlab-case-registry` 是已完成 CaseRun 的无服务二次整理入口。它只读取 case registry repo 里已有的 `runs/<caseId>/<runId>/` 产物,不启动新的 CaseRun、不访问硬件、不触发 CI/CD、不追加自动评价或 pass/fail 判定;默认输出 `runs/<caseId>/<runId>/aggregate.md`,并只把这个 markdown 文件 `git add``git commit``git push` 回 case registry repo。若 registry 里存在其他并行 dirty 产物,`case aggregate` 不得顺带提交它们。
`aggregate.md` 是该 run 的主阅读入口,必须按固定顺序聚合运行环境信息、HWPOD 信息、Code Agent 信息、输入 Prompt、低噪声 Trace、final response 和最后 diff。Trace 正文优先使用 `agent-messages.json` 里的共享 Web/CLI renderer rows;普通 message row 直接展示正文,不做折叠,只有工具调用 row 使用 `<details>/<summary>`,且 `<summary>` 本身就是折叠按钮,文案写成 `已运行 <command>`。缺少 rows 时才嵌入已有 `agent-trace.md`。聚合文件可以列原始产物索引和 trace/result/inspect 命令作为审计线索,但不能把 `summary.md``result.json``final-response.md` 或原 trace 文件继续声明为对外主阅读路径。
验收已完成 case04 时,使用现有 registry 产物回放,不重新启动 CaseRun:
```bash
hwlab-cli case aggregate d601-f103-v2-arm2d-integration \
--case-repo /root/hwlab-case-registry \
--run-id <existing-case04-run-id>
```
通过证据至少包括 CLI JSON 输出中的 `action=case.aggregate``autoEvaluation=false``aggregate.rel=runs/<caseId>/<runId>/aggregate.md``registrySync.status`,以及打开 `aggregate.md` 后能在单文件内读到上述七类内容。
当前边界: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. `hwpod-ctl spec validate --hwpod-id <id> --workspace-path <run-worktree>` 能从 runtime service resolve HWPOD document,并验证四要素和 node binding。
2. `hwpod-compiler-cli compile` 能把同一个 `hwpod-id`、workspace override 和高层 intent 编译为稳定 `hwpod-node-ops-v1` plan。
3. `hwpod-cli --dry-run` 输出的 plan 不读取 runner-local `.hwlab/hwpod-spec.yaml`,也不读取其他本地旧 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. 已完成 run 的 registry 聚合验收必须通过 `hwlab-cli case aggregate <caseId> --run-id <runId>` 输出单个 `aggregate.md`,并证明该文件包含运行环境、HWPOD、Code Agent、Prompt、低噪声 Trace、final response 和最后 diffTrace 中 message 直接展示,工具调用用 `已运行 <command>` summary 折叠。该命令不得启动新 CaseRun,也不得提交当前聚合 markdown 以外的并行 registry dirty 文件。
11. Windows subject worktree 文本编辑必须能在 CRLF 文件中通过 `workspace.apply-patch` 完成源码修改,返回 before/after SHA 与 diff 摘要,并保留原文件 CRLF;`workspace.apply-patch` 在 context 不匹配时必须返回可诊断 payload,而不是只给 `context not found`
12. Keil `debug.download` 自动装配必须输出结构化 `cmd.run` argv 步骤;带空格的 `probeName` 在 plan 中必须是单独 argv 元素。`io.uart.read` 必须通过节点本地 `serial-monitor` 读取正在监控的 COM/baud;未监控或工具失败时必须返回包含 `ioProbe`/COM 口/baud/monitor status/启动建议的结构化 blocker details。