fix(device-pod-cli): add selector cheat sheet and fail-fast hints
Address the friction in #760 where Code Agent picked <pod>:workspace:/ keil download/flash and <pod>:debug-probe flash for firmware flashing, all of which are not SOP. Add to SKILL.md: - Selector Cheat Sheet: explicit per-surface allowed operations table - Common selector mistakes table: wrong selector -> error you would hit -> correct selector - Pitfalls Observed in Real Runs: --reason required for build/download even on read-only sub-actions, cloud-api job output is empty for build/download, workspace rg --pattern shell-pipe collision In tools/src/device-pod-cli-lib.ts: - workspace.keil now fail-fasts on any action that is not add-source or remove-source, with code unsupported_workspace_keil_action and a selector hint pointing to debug-probe download start - debug-probe flash now has a dedicated error code path with the same selector hint instead of the generic unsupported_debug_operation - catch-all debug-probe error message now includes the allowed list - help() payload exposes a selectorCheatSheet array so hwpod --help callers see the SOP table without reading the SKILL.md file Tests in tools/device-pod-cli.test.ts: 6 new cases lock in the new error codes, the selector cheat sheet, and that add-source still dispatches correctly. 26/26 pass.
This commit is contained in:
committed by
Codex
parent
0d06a4c5fe
commit
5c35f8349e
@@ -37,6 +37,100 @@ HWLAB_DEVICE_POD_SESSION_TOKEN=<assembled-device-pod-session-token>
|
||||
`hwpod` automatically locates cloud-api from the assembled runtime env and automatically uses `HWLAB_DEVICE_POD_SESSION_TOKEN`. When `HWLAB_RUNTIME_ENDPOINT_LOCKED=1`, passing `--api-base-url`, `--api-url`, `--cloud-api-url`, or `--base-url` is a hard error. This prevents stale trace examples or model guesses from overriding the current cluster/lane.
|
||||
|
||||
`--api-base-url` and `--session-token` are local-debug-only options outside locked HWLAB runners. Do not use them in normal DS / AgentRun / Cloud Workbench flows.
|
||||
## Selector Cheat Sheet
|
||||
|
||||
The selector is `<devicePodId>:<surface>:<path> <operation> [args...]`. The CLI
|
||||
dispatches to a fixed set of operations per surface. Anything outside this
|
||||
table is rejected either fail-fast in the TS CLI (`unsupported_*` code) or by
|
||||
the host tool after dispatch. Always pick from this table; if a need is not
|
||||
listed, that is a missing intent - file an issue instead of guessing.
|
||||
|
||||
| Surface | Selector path | Allowed operations (intent) | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| `workspace` | `/` or `<relpath>` | `ls`, `cat`, `rg`, `bootsharp`, `apply-patch`, `put`, `rm`, `rmdir`, `keil add-source`, `keil remove-source`, `build start\|status\|output\|cancel\|wait` | `keil` is for **project-file maintenance only**. Compile/link goes through `build start`, not through `keil`. |
|
||||
| `debug-probe` | `:<probe>` (default `/`) | `status`, `chip-id`, `download start\|status\|output\|cancel\|wait`, `reset` | Firmware flash is `download`, not `flash`. There is no `debug-probe flash` op. |
|
||||
| `io-probe` | `:/uart/<n>` | `read`, `write`, `jsonrpc`, `read-after-launch-flash`, `ports` | UART id is a strict path token (`/uart/1`); do not split it across argv. |
|
||||
|
||||
### Common selector mistakes (do not retry - pick the right one)
|
||||
|
||||
| Wrong selector | Error you would hit | Correct selector |
|
||||
| --- | --- | --- |
|
||||
| `<pod>:workspace:/ keil download` | `unsupported workspace keil command: download` (host-side, after dispatch) | `<pod>:debug-probe download start --reason "..."` |
|
||||
| `<pod>:workspace:/ keil flash` | `unsupported workspace keil command: flash` | `<pod>:debug-probe download start --reason "..."` |
|
||||
| `<pod>:debug-probe flash` | `unsupported_debug_operation: flash` (TS-side, fail-fast) | `<pod>:debug-probe download start --reason "..."` |
|
||||
| `<pod>:workspace:/ build` | `workspace.build` job runs but with empty `action`; always pass `start` | `<pod>:workspace:/ build start --reason "..."` |
|
||||
|
||||
If a CLI call returns an `unsupported_*` error, do not retry the same
|
||||
selector - re-check the table and switch to the right one. When the right
|
||||
selector still does not exist, file an issue against `pikasTech/HWLAB` with
|
||||
the selector name and the underlying intent you wanted.
|
||||
## Pitfalls Observed in Real Runs
|
||||
|
||||
These are concrete friction points seen in production runs against
|
||||
`D601-71-FREQ` and `D601-F103-V2`. They are not bugs in the SOP but are
|
||||
worth knowing before you start a long build+download job.
|
||||
|
||||
### 1. `--reason` is required for mutating `workspace.build` / `debug-probe.download`
|
||||
|
||||
`cloud-api` enforces `device_job_reason_required` on any job whose intent
|
||||
is `workspace.build` or `debug-probe.download`, even when the sub-action
|
||||
is `status` / `wait` / `output` / `cancel` and even when the job id points
|
||||
to an already-completed host sub-job. Always pass `--reason "<short text>"`
|
||||
for these selectors, including read-only `build status` and
|
||||
`download output`:
|
||||
|
||||
```sh
|
||||
# ok
|
||||
hwpod <pod>:workspace:/ build status <jobId> --reason "poll previous build"
|
||||
hwpod <pod>:debug-probe download output <jobId> --reason "poll previous download"
|
||||
|
||||
# fails with device_job_reason_required
|
||||
hwpod <pod>:workspace:/ build status <jobId>
|
||||
```
|
||||
|
||||
If you do not have a meaningful business reason yet, use a placeholder
|
||||
like `--reason "v0.2 smoke"` and surface that in the trace.
|
||||
|
||||
### 2. `job output` for build/download is empty; host evidence is on the Windows host
|
||||
|
||||
For `intent=workspace.build` and `intent=debug.download` jobs, cloud-api's
|
||||
`body.output.text` is currently `""` and `body.bytes == 0`. The
|
||||
`Programming Done` / `Verify OK` / `Application running` / `0 Error(s)` /
|
||||
`0 Warning(s)` evidence is on the D601 host in
|
||||
`F:\\Work\\ConStart\\.device-pod\\.state\\device-host-cli\\keil\\`.
|
||||
Do not loop on `workspace rg` looking for those strings - that selector
|
||||
sees the project source tree, not the host job log directory.
|
||||
|
||||
Until cloud-api propagates host `logTail` / `buildSummary` to
|
||||
`body.output.text` (tracked separately), the only SOP-compatible
|
||||
verification path is:
|
||||
|
||||
1. `hwpod job status --pod-id <pod> <jobId>` returns `status=completed`
|
||||
2. `hwpod <pod>:workspace:/ bootsharp` re-runs and shows the workspace is
|
||||
unchanged (host job store keeps the latest log file)
|
||||
3. SSH into D601 directly (out of band) and read the matching
|
||||
`build_FREQ_Controller_FW_<ts>.log` / `download_FREQ_Controller_FW_<ts>.log`
|
||||
under `.device-pod\\.state\\device-host-cli\\keil\\`
|
||||
|
||||
If you need the evidence in-band, file a follow-up issue against
|
||||
`pikasTech/HWLAB` requesting a `download evidence` selector that returns
|
||||
host `logTail` + `buildSummary` directly through the formal REST job path.
|
||||
|
||||
### 3. `workspace rg --pattern "regex|pipes"` collides with local shell
|
||||
|
||||
When the regex contains `|` or other shell metacharacters, the local shell
|
||||
interprets them before `hwpod` sees the pattern. Two safe forms:
|
||||
|
||||
```sh
|
||||
# shell-safe: pattern as one arg, but | still needs quoting
|
||||
hwpod <pod>:workspace:/ rg --pattern "Programming Done|Verify OK" --path <relpath>
|
||||
|
||||
# bullet-proof: pattern as base64
|
||||
P=$(printf "%s" "Error\(s\)|Warning\(s\)|Erase Done|Programming Done|Verify OK|Application running" | base64 -w0)
|
||||
hwpod <pod>:workspace:/ rg --pattern-b64 "$P" --path <relpath> --reason "log scan"
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Primary Commands
|
||||
|
||||
|
||||
Reference in New Issue
Block a user