From feb3bbab02eb8fcdf1efdf184d2f384ba345c392 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 27 May 2026 17:44:27 +0800 Subject: [PATCH] docs: plan device pod cli and server mvp --- docs/plan/device-pod-cli-mvp.md | 85 ++++++++++++++++++++++++ docs/plan/device-pod-server-mvp.md | 102 +++++++++++++++++++++++++++++ docs/reference/device-pod.md | 15 +++++ 3 files changed, 202 insertions(+) create mode 100644 docs/plan/device-pod-cli-mvp.md create mode 100644 docs/plan/device-pod-server-mvp.md diff --git a/docs/plan/device-pod-cli-mvp.md b/docs/plan/device-pod-cli-mvp.md new file mode 100644 index 00000000..1fafe2ec --- /dev/null +++ b/docs/plan/device-pod-cli-mvp.md @@ -0,0 +1,85 @@ +# Device Pod CLI MVP 计划 + +本文描述 `device-pod-cli` 第一阶段实现计划。长期设备模型以 [../reference/device-pod.md](../reference/device-pod.md) 为准;本文只约束如何开发、调试和验收 CLI MVP。 + +## 目标 + +`device-pod-cli` 是给 HWLAB code agent 使用的独立硬件能力 CLI,不并入 `hwlab-cli`,也不继承 `hwlab-cli` 的广泛管理权限。第一版目标是先不实现真正的 `device-pod-server`,而是把 `device-pod` 当作 profile 驱动的抽象能力单元,通过以下路径跑通最小真实闭环: + +```text +code agent -> device-pod-cli -> hwlab cloud-api/gateway -> device-host-cli -> debug probe / serial / WiFi / vendor protocol -> target +``` + +gateway 保持单纯 cmd 转发;硬件协议、串口、下载器和厂商工具复杂度隔离在用户 PC 上的 `device-host-cli` 后面。`device-pod-cli` 只暴露 workspace、debug-probe、io-probe 的受控语义能力,不提供泛化远程 shell。 + +## Profile 来源 + +CLI 每次执行都从 HWLAB code agent workspace 的 `.device-pod/` 目录读取 profile。推荐文件名为 `.device-pod/.json`;后续可以兼容 YAML,但 MVP 优先使用 JSON,方便 schema 校验和 trace 记录。 + +profile 是灵活 source-of-truth,不做中心注册。CLI 输出必须包含 `profilePath`、`profileHash`、`devicePodId` 和 `targetId`,便于确认每次操作实际使用的是哪个 profile。profile 中只允许描述 route、受控 workspace root、debug-probe 能力、io-probe 能力和 host CLI 能力;不得写入 Git key、云端 token、kubeconfig、数据库 URL 或长期 secret。 + +## 命令口径 + +统一 locator 语法为: + +```text +device-pod-cli :[:] [args...] +``` + +MVP surface 固定为: + +- `workspace`:源码、工程、构建产物和受控文件操作。 +- `debug-probe`:下载、复位、探针状态和芯片 ID。 +- `io-probe`:UART、GPIO、AI/AO/DI/DO、状态采样和日志读取。 + +workspace 操作采用 busybox 风格白名单,不提供 `cmd` 子命令。第一版建议只开放 `ls`、`cat`、`stat`、`rg`、`find`、`head`、`tail`、`wc`、`apply-patch`、`upload`、`download`、`build`、`clean` 和 `artifact list`。所有文件路径必须限制在 profile 声明的 workspace root 内。 + +示例: + +```text +device-pod-cli device-pod-71-freq:workspace:/firmware ls +device-pod-cli device-pod-71-freq:workspace:/firmware/main.c cat --max-bytes 12000 +device-pod-cli device-pod-71-freq:workspace:/firmware/main.c apply-patch < fix.patch +device-pod-cli device-pod-71-freq:workspace:/firmware build --profile debug +device-pod-cli device-pod-71-freq:debug-probe download --artifact build/app.hex --approved --reason "DEV smoke" +device-pod-cli device-pod-71-freq:debug-probe reset --approved --reason "DEV smoke" +device-pod-cli device-pod-71-freq:debug-probe chip-id +device-pod-cli device-pod-71-freq:io-probe:/uart/1 read --max-bytes 12000 +device-pod-cli device-pod-71-freq:io-probe:/inner/gpio/pa1 read +``` + +`io-probe:/inner/...` 必须显式表示从 target 内部状态读取,例如寄存器、全局变量、debug memory 或固件导出的状态。默认 `io-probe:/gpio/pa1`、`io-probe:/uart/1` 等路径表示外部真实 I/O probe、仪器或另一个设备观测到的物理信号。验收证据中不得混淆 inner 和外部 I/O。 + +## 输出与权限 + +CLI 默认输出 JSON。成功和失败都必须包含 `devicePodId`、`targetId`、`surface`、`operation`、`traceId`、`operationId`、`profileHash`、`route`、`status`、`blocker`、`evidence` 和截断元数据。输出文本、串口日志和命令日志必须有 `maxBytes` 或分页边界。 + +下载、复位、写 I/O、修改 workspace 等动作属于 mutating operation,必须要求显式 approval 参数,并写入 reason。长耗时操作返回 `jobId`,CLI 轮询或拉取 job output,不让一次 HTTP/gateway 调用长期阻塞。 + +## 开发方式 + +1. 先实现 profile schema、loader、locator parser 和 JSON 输出合同,用 fake profile 在本地单元测试覆盖成功、缺 profile、坏 profile、路径越界和未知 surface。 +2. 实现 workspace busybox 操作和 fake gateway adapter,先在不接硬件时证明路径裁剪、输出截断和错误结构稳定。 +3. 实现 debug-probe 与 io-probe 的 adapter 接口,先用 fake `device-host-cli` 返回 chip ID、UART 样例和下载 job 状态。 +4. 在 D518 Windows 上开发 `device-host-cli`,通过 `D518:win` 做真实 DAPLink、串口或下载器 smoke;D518 侧只承载硬件上位机逻辑,不改变 G14 source truth。 +5. 在 G14 code agent pod 中开发和验证 `device-pod-cli`,code agent pod 不放完整 HWLAB 源码和 Git key;CLI 通过 skill 分发到预装位置,并在 skill 说明中写清仅适用于 HWLAB 内部 code agent。 +6. fake 闭环通过后再做 G14 -> gateway -> D518 -> 硬件的最小 live smoke,然后把修复固化到源码、测试和长期参考。 + +## 调试方式 + +- `--dry-run` 只解析 profile、locator 和路由计划,不触发 gateway 或硬件动作。 +- `--trace-id` 可传入外部 trace;未传入时 CLI 生成 trace,并在所有 adapter 输出中透传。 +- `--verbose` 只展开结构化 adapter 阶段和截断摘要,不直接打印 secret 或无限日志。 +- fake adapter 用于本地和 CI;live adapter 只在明确选择 profile route 时启用。 +- 真实硬件问题先在 D518 `device-host-cli` 单独复现,再通过 `device-pod-cli` 验证端到端链路。 + +## 验收标准 + +MVP 通过至少需要满足: + +- `.device-pod/.json` 能被读取、校验、hash 并体现在每次 CLI JSON 输出中。 +- workspace `ls/cat/rg/apply-patch/build/artifact list` 在受控 root 内可用,路径越界、过大输出和未知命令有结构化失败。 +- `debug-probe chip-id/download/reset` 能通过 fake adapter 稳定返回 job/evidence;live smoke 至少证明一次真实 debug probe 路径可达。 +- `io-probe:/uart/1 read` 与 `io-probe:/inner/... read` 在输出中明确标注外部/内部来源,不互相冒充。 +- gateway 仍只是 cmd transport;CLI 不暴露任意 shell、不接收泛化 `cmd` 子命令、不绕过 profile 访问硬件。 +- 文档、CLI 帮助和 skill 说明明确写明该 CLI 只用于 HWLAB 内部 code agent,不适用于 UniDesk 外部开发者工作区。 diff --git a/docs/plan/device-pod-server-mvp.md b/docs/plan/device-pod-server-mvp.md new file mode 100644 index 00000000..46f644c9 --- /dev/null +++ b/docs/plan/device-pod-server-mvp.md @@ -0,0 +1,102 @@ +# Device Pod Server MVP 计划 + +本文描述 `device-pod-cli` 跑通后的第二阶段:实现真正的 `device-pod-server`。长期设备模型以 [../reference/device-pod.md](../reference/device-pod.md) 为准;本文只约束 server MVP 的开发、调试、目标和验收。 + +## 目标 + +`device-pod-server` 是一个与 `device-pod` 一一对应的服务实例,用来提供短同步 RESTful API、短异步 RESTful job API 和后台监控缓存。它解决 CLI 直连 profile/gateway 之后仍无法持续监控设备的问题。 + +MVP 对外目标是: + +- `device-pod-cli` 的稳定语义能力都能映射到 REST API。 +- server 后台维护 debug-probe 和 io-probe 的最新状态、freshness 和错误 blocker。 +- HWLAB cloud-api 代理 server API,前端只通过 cloud-api 查看设备状态,不直连 gateway 或用户 PC。 +- 前端最小版本只显示 `io-probe:/uart/1` 的最新状态/日志尾部,以及 `debug-probe` 的 chip ID 和 probe 状态。 + +## Profile 同步 + +server 阶段仍不引入中心 profile 注册表。HWLAB code agent workspace 的 `.device-pod/` 目录继续作为 profile source-of-truth;`device-pod-cli` 或 code agent 每次连接 server 前读取 `.device-pod/.json`,自动上传或刷新 profile。 + +server 只保存 active profile、`profileHash`、加载时间和校验结果,作为运行时缓存。profile 修改后不需要改 server 配置或重启服务;下一次 CLI/agent 同步即可更新 active profile。server 收到缺失、坏格式或能力不匹配的 profile 时返回 `profile-missing`、`profile-invalid` 或 `capability-mismatch` blocker,不回退到历史 profile 执行 mutating operation。 + +建议最小 profile API: + +```text +PUT /v1/profile +GET /v1/profile +``` + +CLI 可以提供调试入口: + +```text +device-pod-cli device-pod-71-freq:profile sync +``` + +`profile` 是 CLI/server 控制面同步动作,不属于 deviceTarget 四要素之一。 + +## 最小 REST API + +同步 API 只返回短状态和缓存快照: + +```text +GET /health +GET /v1/status +GET /v1/capabilities +GET /v1/debug-probe/status +GET /v1/debug-probe/chip-id +GET /v1/io-probe/status +GET /v1/io-probe/uart/1 +GET /v1/io-probe/uart/1/tail?maxBytes=12000 +``` + +异步 API 用于下载、复位、workspace build、串口写入和采样窗口等动作: + +```text +POST /v1/workspace/jobs +POST /v1/debug-probe/jobs +POST /v1/io-probe/jobs +GET /v1/jobs/{jobId} +GET /v1/jobs/{jobId}/output +POST /v1/jobs/{jobId}/cancel +``` + +cloud-api 代理最小口径: + +```text +GET /v1/device-pods +GET /v1/device-pods/{devicePodId}/status +GET /v1/device-pods/{devicePodId}/debug-probe/chip-id +GET /v1/device-pods/{devicePodId}/io-probe/uart/1 +GET /v1/device-pods/{devicePodId}/io-probe/uart/1/tail?maxBytes=12000 +``` + +所有响应必须包含 `devicePodId`、`targetId`、`profileHash`、`traceId`、`operationId`、`status`、`freshness`、`blocker` 和 `evidence`。server、cloud-api 和 frontend 不得把 fake、dry-run、SOURCE、LOCAL 或缓存过期状态标成 `DEV-LIVE`。 + +## 开发方式 + +1. 从已跑通的 `device-pod-cli` profile schema、locator parser、operation adapter 和 JSON 输出合同中抽取共享模块,避免 CLI 与 server 两套语义分叉。 +2. 实现 server skeleton:health、profile sync、status、capabilities、job store、bounded output、lock 和 freshness 模型。 +3. 先接 fake `device-host-cli` adapter,稳定 chip ID、UART tail、job 状态和 blocker 行为。 +4. 再接 gateway/cmd/device-host-cli live adapter,保持 gateway 仍是 transport,不把 server 做成任意 shell 代理。 +5. 在 G14 DEV k3s 中部署单个 device-pod server 实例做 smoke,不改 PROD、不重启无关服务。 +6. 增加 cloud-api proxy 和前端最小展示,只显示 chip ID、probe 状态、UART1 最新片段和 freshness。 + +## 调试方式 + +- `GET /health` 只验证进程、profile loader 和基础依赖,不触发硬件动作。 +- `GET /v1/profile` 展示脱敏后的 active profile 摘要、`profileHash` 和校验状态。 +- fake profile + fake host CLI 用于 server 单测和 G14 DEV 无硬件 smoke。 +- live 调试先看 server 结构化日志中的 `profileHash`、`route`、`jobId`、`freshness` 和 blocker,再到 D518 `device-host-cli` 单独复现硬件问题。 +- UART tail、job output 和日志都必须截断或分页;默认调试输出不能 dump 全量串口日志、源码或 secret。 + +## 验收标准 + +MVP 通过至少需要满足: + +- 修改 `.device-pod/.json` 后,无需重启 server,下一次 CLI/agent 同步即可看到新的 `profileHash`。 +- 无 profile、坏 profile、过期 profile 和 capability mismatch 都有明确 blocker,不执行下载、复位或 I/O 写入。 +- `GET /v1/debug-probe/chip-id` 能通过 fake adapter 和至少一次 live smoke 返回 chip ID 或结构化硬件 blocker。 +- `GET /v1/io-probe/uart/1` 和 tail API 能显示 UART1 最新状态、freshness、截断信息和 evidence。 +- cloud-api 代理能返回同一组字段,前端最小页面能显示 chip ID、UART1 和 freshness,不直连 server/gateway。 +- mutating job 都是短 HTTP 创建、异步轮询、可取消、有 lock、有 approval reason。 +- server 与 CLI 的 operation 名称、错误码、profileHash 和 evidence 字段保持一致。 diff --git a/docs/reference/device-pod.md b/docs/reference/device-pod.md index 7968c4f1..c78fabe5 100644 --- a/docs/reference/device-pod.md +++ b/docs/reference/device-pod.md @@ -12,6 +12,21 @@ device-pod + ioInterface ``` +## 实施计划 + +长期模型以本文为准;分阶段实现计划单独维护,避免把一次性开发步骤写进长期参考: + +- [Device Pod CLI MVP 计划](../plan/device-pod-cli-mvp.md):先做 code agent 可调用的独立 CLI,通过 profile、gateway 和用户 PC 侧 `device-host-cli` 跑通 workspace、debug-probe 和 io-probe 的最小闭环。 +- [Device Pod Server MVP 计划](../plan/device-pod-server-mvp.md):在 CLI 跑通后再实现真正的 `device-pod-server`,提供与 CLI 对应的 RESTful API、后台监控缓存和前端最小可视化。 + +## Profile 注册与同步 + +MVP 不使用刚性的中心 profile 注册表。`device-pod` profile 的灵活源头是 HWLAB code agent workspace 下的 `.device-pod/` 目录,推荐按 `devicePodId` 存放 profile 文件,例如 `.device-pod/device-pod-71-freq.json`。 + +`device-pod-cli` 每次执行都从当前 code agent workspace 的 `.device-pod/` 读取 profile,并在输出中保留 `profilePath` 和 `profileHash`。进入 `device-pod-server` 阶段后,CLI 或 code agent 仍以 `.device-pod/` 为 profile source-of-truth;每次连接 server 前自动上传或刷新 profile,server 只把 active profile 当作运行时缓存,不把它变成长期配置真相。 + +profile 必须只描述 target、debugInterface、projectWorkspace、ioInterface、gateway route、host CLI 能力和受控路径边界;不得放入 Git key、云端 token、kubeconfig、数据库 URL 或其他长期 secret。profile 校验失败时应返回 `profile-invalid` 或 `profile-missing` blocker,而不是回退到默认设备或任意 shell。 + ## 四要素 ### `deviceTarget`