229 lines
14 KiB
Markdown
229 lines
14 KiB
Markdown
# HWPOD Harness 规格
|
||
|
||
本文是 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 probe:UART、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 工程链路下载。下载前若存在 `probeUid`,compiler 会先生成 Keil probe-binding 写回命令,再生成 `program --program-backend keil` 命令,以保持旧 host profile 中 probe 绑定与 Keil 下载语义在新 hwpod 概念系统内收敛。
|
||
|
||
`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 可执行的基础动作。第一版最小集合:
|
||
|
||
| op | 用途 |
|
||
| --- | --- |
|
||
| `node.health` | 查询 node 存活和基础状态 |
|
||
| `node.version` | 查询 node runtime 版本 |
|
||
| `node.inventory` | 查询 workspace/probe/io 能力 |
|
||
| `workspace.ls` | 列目录 |
|
||
| `workspace.cat` | 读文件 |
|
||
| `workspace.rg` | 搜索文件内容 |
|
||
| `workspace.apply-patch` | 应用源码补丁 |
|
||
| `debug.build` | 编译工程 |
|
||
| `debug.download` | 下载或烧录目标设备 |
|
||
| `debug.reset` | 复位目标设备 |
|
||
| `io.uart.read` | 读取 UART |
|
||
| `io.uart.write` | 写入 UART |
|
||
| `io.uart.jsonrpc` | 通过 UART 做 JSON-RPC |
|
||
| `cmd.run` | 临时维护命令透传,仅用于 `hwpod-ctl` 或早期薄 node 调试 |
|
||
|
||
标准 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-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 链路。
|
||
|
||
## 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。`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"
|
||
}
|
||
}
|
||
```
|
||
|
||
CaseRun 是强化学习 Harness 的最小执行单元,但它本身不是完整 epoch。完整 epoch 还需要样本选择、策略生成、奖励/评价、批量调度、跨 run 归因和自动训练闭环;第一阶段只要求一个 `caseId` 能从 case registry repo 进入真实 HWPOD 编译闭环,并把可审计产物稳定落盘。
|
||
|
||
最小入口:
|
||
|
||
```bash
|
||
bun tools/hwlab-cli/bin/hwlab-cli.ts case prepare d601-f103-v2-compile --case-repo /root/hwlab-case-registry
|
||
bun tools/hwlab-cli/bin/hwlab-cli.ts case build d601-f103-v2-compile --case-repo /root/hwlab-case-registry --run-dir .state/hwlab-cli/caserun/<runId>
|
||
bun tools/hwlab-cli/bin/hwlab-cli.ts case collect d601-f103-v2-compile --case-repo /root/hwlab-case-registry --run-dir .state/hwlab-cli/caserun/<runId>
|
||
bun tools/hwlab-cli/bin/hwlab-cli.ts case run d601-f103-v2-compile --case-repo /root/hwlab-case-registry
|
||
```
|
||
|
||
`case run` 默认按 compile-only 验收:prepare 先在 subject repo 本地 checkout 下创建 `.worktree/caserun-<runId>` 隔离 worktree 并写入 run-local spec,然后调用 `hwpod-cli build`,再通过 `cmd.run` 查询 Keil 异步 job-status,收集 `evidence.json` 到 run state,并把审计副本写入 case registry repo 的 `runs/<caseId>/<runId>/`。下载不作为 compile-only CaseRun 的隐式步骤;后续需要下载验收时,应作为独立 action 显式加入 case 定义和验收口径。
|
||
|
||
当前标准 smoke case 是 `d601-f103-v2-compile`。它绑定已发现并预装的 `D601-F103-V2` HWPOD spec,目标是让 Code Agent 通过 Web 等价入口或 AgentRun runner 调用 `hwlab-cli case run d601-f103-v2-compile`,而不是由操作员手工编译后代替通过。通过结果必须至少包含:`status=succeeded`、Keil build job terminal success、`returnCode=0`、`compileOnly=true`、`downloadSkipped=true`,并记录 `.hex` 和 `.axf` artifact 路径。
|
||
|
||
产物归属按两条线分开:
|
||
|
||
- case registry repo 的 `runs/<caseId>/<runId>/` 是审计产物,PR 默认保持打开,不作为必须合并的训练改进。
|
||
- HWLAB repo 的 harness、`hwpod-cli`、`hwpod-ctl`、`hwpod-compiler-cli` 或文档改进可以按风险进入 `v0.2` 分支;单纯文档和轻量 CLI/helper 变更可直接提交,业务代码、运行面或发布链路变更走 PR 工作流。
|
||
|
||
当前边界:CaseRun 仍是无服务化短连接 CLI 编排,不负责排队、并发、评分、自动合并、长期 run retention 或 epoch 汇总;这些能力属于后续强化学习 Harness 层。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,产出 isolated run state 和 case registry repo evidence;compile-only case 的通过条件是 Keil build job terminal success,并明确记录 downloadSkipped。
|
||
7. CaseRun 的真实验收必须由 Code Agent 或 AgentRun runner 从用户入口发起;操作员直接运行 `hwpod-cli build`、直接调用 Keil 或只检查 node 侧 job,不等同于 CaseRun 通过。
|