From 4c6111c6557fe723aaeb6182ae7d994dd8dcbf9d Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:12:31 -0700 Subject: [PATCH 1/7] feat: add pixi-workspace-interface skill Operational distillation of the pixi workspace interface protocol (ratified 2026-07-05; rationale in the dev tree's AGENTS.md, public walkthrough in Humanoid-Control-Website docs/how_to/use_pixi_tasks.md): the three command levels (lifecycle tasks / packaged hc toolbox / scenario tasks), reserved vocabulary + single-qualifier rule, task authoring and activation/env rules, and the empirically-verified gotchas (cached vcs-import setup shape, bin/ shim for PATH-visible CLIs, colcon-defaults split). Co-Authored-By: Claude Fable 5 --- .claude-plugin/marketplace.json | 29 +++--- skills/pixi-workspace-interface/SKILL.md | 110 +++++++++++++++++++++++ 2 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 skills/pixi-workspace-interface/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index b663537..7bae33f 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,22 +1,23 @@ { "name": "berkeley-humanoids-skills", "owner": { - "name": "-T.K.-", - "email": "tk233.xyz@gmail.com" + "name": "-T.K.-", + "email": "tk233.xyz@gmail.com" }, "metadata": { - "description": "Berkeley Humanoids organization skills", - "version": "0.1.0" + "description": "Berkeley Humanoids organization skills", + "version": "0.1.0" }, "plugins": [ - { - "name": "berkeley-humanoids-skills", - "description": "Berkeley Humanoids organization skills", - "source": "./", - "strict": false, - "skills": [ - "./skills/robotics-conventions" - ] - } + { + "name": "berkeley-humanoids-skills", + "description": "Berkeley Humanoids organization skills", + "source": "./", + "strict": false, + "skills": [ + "./skills/robotics-conventions", + "./skills/pixi-workspace-interface" + ] + } ] - } \ No newline at end of file +} diff --git a/skills/pixi-workspace-interface/SKILL.md b/skills/pixi-workspace-interface/SKILL.md new file mode 100644 index 0000000..188910b --- /dev/null +++ b/skills/pixi-workspace-interface/SKILL.md @@ -0,0 +1,110 @@ +--- +name: pixi-workspace-interface +description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), the hc CLI, or any Berkeley Humanoids pixi+ROS2 workspace (humanoid_control_ws, *-Deployment repos, the buildfarm manifest). +--- + +# Pixi workspace interface + +Every Berkeley Humanoids pixi workspace exposes the same three-level +command interface. Ratified 2026-07-05; durable rationale lives in the +dev tree's `AGENTS.md` ("Command interface (three levels)") and the +public walkthrough in `Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`. + +## The three levels + +1. **Lifecycle pixi tasks** — reserved names AND semantics, identical in + every workspace: `setup` (fetch sources; idempotent, cached), `build` + (default lane; chains `setup`), `test`, `clean` (wipe + `build/ install/ log/` only), `doctor` (health check). +2. **Product toolbox `hc`** — a packaged CLI on `PATH` + (`humanoid_control_cli`): `hc bus …`, `hc motor slider`, + `hc viz [viser|rerun]`, `hc viz urdf`, `hc calibrate`. +3. **Scenario pixi tasks** — reserved names, workspace-defined scope: + `sim`, `real`, `policy` (+ at most one qualifier). + +Sorting rule for new commands: **invariant meaning in every workspace → +`hc` verb; workspace-dependent meaning → workspace task**. `hc` carries +only the Lite product core + shared diagnostics — never Prime, piano, or +sibling-repo references. Needs root / mutates host state (CAN, kernel) → +a `scripts/*.sh` run with explicit `sudo`, never a task. Rarely used → +no alias; document the canonical `ros2 …` command. + +## Scenario naming + +- Grammar: `[-]`, kebab-case, **at most one + qualifier**, encoding only the primary task variant. All secondary + parameters stay ROS launch arguments: + - Right: `pixi run sim-piano robot:=prime policy:=latest` + - Wrong: `pixi run sim-prime-piano-latest` +- Unqualified = the workspace default (dev ws: Lite base bringup; + a deployment ws: its full task stack — state the scope in the task + `description`). +- Never `launch-*` / `deploy-*` prefixes. Never per-tool task aliases + duplicating `hc` (`robstride-ping`, `rerun-viz`, …). +- No task named `install`/`shell` (shadow pixi verbs) or `run`/`start` + (redundant next to the scenario vocabulary). The buildfarm packaging + verb is `package` — `build*` is reserved for colcon builds. + +## Task authoring + +- Every public task carries `description = "…"` — `pixi task list` is + the menu. `_` prefix hides plumbing tasks. +- Launch-wrapping tasks are arg-less command strings so trailing + `key:=value` forwards verbatim. Don't use typed `args` on them. +- **No scenario task or `hc` verb may auto-build** (a hardware bringup + must never trigger a surprise rebuild). Only `build` chains `setup`. +- The canonical `setup` shape (all three parts required — an uncached + `vcs import` re-fetches every remote and fails offline; without + `--skip-existing` it resets locally-checked-out branches to pins): + +```toml +[tasks.setup] +cmd = "vcs import --skip-existing --input .repos src && mkdir -p build && touch build/.setup-stamp" +inputs = [".repos"] +outputs = ["build/.setup-stamp"] +description = "Import third-party source deps — idempotent, cached on the .repos file" +``` + +## Environment + +- Overlay sourcing via a guarded activation script (POSIX `setup.sh`, + not `setup.bash`), never a bare `install/setup.*` entry: + +```toml +[activation] +scripts = ["scripts/activate.sh"] +``` + +```sh +if [ -f "$PIXI_PROJECT_ROOT/install/setup.sh" ]; then + . "$PIXI_PROJECT_ROOT/install/setup.sh" +fi +``` + +- Colcon *style* flags (`--symlink-install`, compile-commands) go in + `config/colcon-defaults.yaml` via `COLCON_DEFAULTS_FILE` in + `[activation.env]`, so manual `colcon build` == `pixi run build`. + Semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) + stay visible in the task string. +- `[activation.env]` always sets `RCUTILS_COLORIZED_OUTPUT=1` + the + console format; deployment workspaces pin their robot's + `ROS_DOMAIN_ID`, the dev workspace leaves it unpinned. +- Channels: `https://prefix.dev/robostack-jazzy` before + `https://prefix.dev/conda-forge` (binary consumers put + `https://prefix.dev/berkeley-humanoids` first). Single default + environment; add features/environments only when dependencies + genuinely diverge. +- No rosdep, no apt — `pixi.toml` is the dependency source of truth. +- `doctor` checks: workspace root, env active, `/opt/ros` contamination + (hard fail), sources present, overlay built + sourced, `hc` on PATH. + +## Gotchas (verified the hard way) + +- ament_python console scripts install to `lib//` (`ros2 run` + location), never on `PATH`. To put a CLI on `PATH`, also install a + shim via `data_files` `('bin', [...])` — colcon then emits a `path.sh` + hook for the package. +- Day-one ritual is one command: `pixi run build` (pixi self-heals the + env; `setup` is chained and cached). Verify with `pixi run doctor`. +- README quickstarts lead with that ritual, then point at + `pixi task list` and `hc help` instead of duplicating command tables. From b1abffa57bb970fadedc53064c6bf171e0ac46a2 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:18:56 -0700 Subject: [PATCH 2/7] rename skill to pixi-workspace Co-Authored-By: Claude Fable 5 --- .claude-plugin/marketplace.json | 2 +- skills/{pixi-workspace-interface => pixi-workspace}/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename skills/{pixi-workspace-interface => pixi-workspace}/SKILL.md (99%) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 7bae33f..39765a8 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -16,7 +16,7 @@ "strict": false, "skills": [ "./skills/robotics-conventions", - "./skills/pixi-workspace-interface" + "./skills/pixi-workspace" ] } ] diff --git a/skills/pixi-workspace-interface/SKILL.md b/skills/pixi-workspace/SKILL.md similarity index 99% rename from skills/pixi-workspace-interface/SKILL.md rename to skills/pixi-workspace/SKILL.md index 188910b..f7e4ef5 100644 --- a/skills/pixi-workspace-interface/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -1,5 +1,5 @@ --- -name: pixi-workspace-interface +name: pixi-workspace description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), the hc CLI, or any Berkeley Humanoids pixi+ROS2 workspace (humanoid_control_ws, *-Deployment repos, the buildfarm manifest). --- From 408f9fac6e1303494f0199c8d00d0322b2f25149 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:19:54 -0700 Subject: [PATCH 3/7] docs: vendor the full protocol RFC as a skill reference Preserves the ratified RFC (rationale, research base, normative text, migration map) alongside the skill for traceability; Status section updated from review-copy to ratified, with links to the implementing PRs. SKILL.md points at it. Co-Authored-By: Claude Fable 5 --- skills/pixi-workspace/SKILL.md | 9 +- .../references/pixi_interface_protocol.md | 571 ++++++++++++++++++ 2 files changed, 577 insertions(+), 3 deletions(-) create mode 100644 skills/pixi-workspace/references/pixi_interface_protocol.md diff --git a/skills/pixi-workspace/SKILL.md b/skills/pixi-workspace/SKILL.md index f7e4ef5..997e624 100644 --- a/skills/pixi-workspace/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -6,9 +6,12 @@ description: Use when creating, editing, or reviewing pixi.toml manifests, pixi # Pixi workspace interface Every Berkeley Humanoids pixi workspace exposes the same three-level -command interface. Ratified 2026-07-05; durable rationale lives in the -dev tree's `AGENTS.md` ("Command interface (three levels)") and the -public walkthrough in `Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`. +command interface. Ratified 2026-07-05; the full RFC (rationale, +research base, RFC-2119 normative text, migration history) is at +[references/pixi_interface_protocol.md](references/pixi_interface_protocol.md); +durable summaries live in the dev tree's `AGENTS.md` ("Command interface +(three levels)") and the public walkthrough in +`Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`. ## The three levels diff --git a/skills/pixi-workspace/references/pixi_interface_protocol.md b/skills/pixi-workspace/references/pixi_interface_protocol.md new file mode 100644 index 0000000..568964b --- /dev/null +++ b/skills/pixi-workspace/references/pixi_interface_protocol.md @@ -0,0 +1,571 @@ +# Pixi Workspace Interface Protocol + +| | | +|----------------|--------------------------------------------------------------------| +| **Title** | Pixi Workspace Interface Protocol | +| **Type** | Process (convention) | +| **Status** | Ratified 2026-07-05 (see [Status](#status)) | +| **Created** | 2026-07-05 | +| **Applies to** | All Berkeley Humanoids pixi workspaces (see [Scope](#scope)) | + +## Abstract + +This document defines how every Berkeley Humanoids pixi workspace exposes +its environment, tasks, and scripts. It establishes a three-level command +model: + +1. a **universal lifecycle core** of five reserved pixi tasks + (`setup`, `build`, `test`, `clean`, `doctor`), +2. a **packaged product toolbox** (`hc`) for commands whose meaning is + invariant across workspaces, and +3. a **scenario-task vocabulary** (`sim`, `real`, `policy`, …) whose names + are reserved but whose semantics each workspace defines. + +It further specifies a one-command day-one ritual (`pixi run build`), +rules for authoring tasks, and an environment-activation protocol. The +goal is that anyone who has learned one workspace can operate any other, +and that the canonical ROS 2 commands keep working verbatim underneath. + +## Status + +**Ratified and implemented 2026-07-05.** This copy is preserved with the +`pixi-workspace` skill for traceability of the design rationale. The +durable normative text lives in the dev tree's `AGENTS.md` → +"Environment, tooling & version control" → "Command interface (three +levels)"; the public walkthrough in +`Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`; the +operational rules in the sibling `SKILL.md`. Implemented via +[humanoid_control#16](https://github.com/Berkeley-Humanoids/humanoid_control/pull/16), +[Lite-Deployment#1](https://github.com/Berkeley-Humanoids/Lite-Deployment/pull/1), +[Humanoid-Control-Website#13](https://github.com/Berkeley-Humanoids/Humanoid-Control-Website/pull/13), +plus the local `humanoid_control_ws` manifest (30 → 19 tasks). The +migration plan in +[Appendix A](#appendix-a--migration-map-non-normative) is retained as +the historical record of that change. + +## Scope + +This protocol governs: + +- **`humanoid_control_ws`** — the development workspace, +- **the `*-Deployment` repositories** — operator workspaces, +- **the `humanoid_control` repo-root buildfarm manifest** — packaging + (a maintainer-CI surface, partially exempt; see + [Lifecycle tasks](#3-level-1--lifecycle-tasks)). + +There is no official pixi task style guide beyond this document; it sets +convention rather than follows one. Its choices were informed by the +official pixi/RoboStack guidance, a survey of ~15 real pixi + ROS 2 +projects (ros2/ros2, NVIDIA IsaacSim, NASA-JSC, ros-controls, bit-bots, +RobotecAI, rerun, …), and the uv ecosystem's day-one conventions. Key +findings from that survey are cited inline as rationale. + +Throughout, **must**, **must not**, **should**, and **may** are used in +the RFC 2119 sense. + +## Audiences and design goals + +Three audiences must find the interface natural: + +- **uv-native Python developers** expect the ritual `uv sync` → + `uv run `, one runner verb for everything, and a project's + invariant commands shipped *with the package* as `[project.scripts]` + entry points (mjlab's `train` / `play`). Pixi maps 1:1: + `pixi install` → `pixi run`, and `pixi run ` falls back to any + executable on the environment `PATH` exactly like `uv run train`. +- **ROS-native developers** expect `colcon build`, + `ros2 launch pkg file.launch.py`, `key:=value` launch arguments, and a + sourced overlay. All of that must keep working verbatim inside + `pixi shell` / `pixi run --`; tasks and CLI verbs are shortcuts over + canonical commands, never a replacement layer. +- **Robot operators** need a short, memorable, self-documenting menu: + one health check, one command per everyday scenario. + +## When to deviate + +Reserved names carry the weight of this protocol: a reserved name +**must not** be repurposed, and its reserved semantics **must not** be +altered. Beyond that, the protocol is deliberately thin: + +- Workspaces **may** add archetype-local tasks (see + [§3.1](#31-archetype-local-extras)) provided each carries a + `description` and is never required of other workspaces. +- The canonical `ros2` / `colcon` commands are part of the interface + (see [§8.5](#85-escape-hatches)); when no task fits, documenting the + canonical command is preferred over inventing a task. +- If following a rule would clearly make a specific workspace worse, + deviate — and record why in the task description or workspace README + so the deviation reads as a decision, not an accident. + +## 1. The three command levels + +Every command a user types belongs to exactly one level: + +| Level | Commands | Mechanism | Defined by | Scope | +|---|---|---|---|---| +| **1. Pixi-ROS lifecycle** | `setup` `build` `test` `clean` `doctor` | pixi tasks; names **and** semantics reserved by this protocol | each workspace's `pixi.toml` (re-declared — pixi tasks cannot ship with a dependency) | any pixi-ROS repo — ours match the ecosystem's de-facto canon | +| **2. Product toolbox** | `hc []` — `bus`, `motor`, `viz`, `calibrate` | packaged executable on the environment `PATH` | `humanoid_control_cli` | every environment that installs the stack (source or binary) | +| **3. Workspace scenarios & glue** | `sim` `real` `policy` (+ qualifiers), `teleop`, archetype extras | pixi tasks; scenario **names** reserved, **semantics** workspace-defined | that workspace's `pixi.toml` only | that workspace | + +### 1.1 The sorting criterion + +The rule that separates levels 2 and 3: + +> **Invariant meaning → packaged `hc` verb. +> Workspace-dependent meaning → workspace task under the reserved +> vocabulary.** + +`hc bus ping` or `hc viz urdf` mean exactly the same thing in every +workspace and for binary-channel consumers — packaging them once +prevents per-tool alias sprawl and drift (two such aliases were broken +in the dev workspace when this protocol was drafted). `sim` or `policy` +legitimately mean different things per workspace (base bringup in the +dev workspace, the full task stack in a deployment) and typically wrap +workspace-local composition — so each workspace declares them, and the +protocol standardizes only their names and grammar. + +*Rationale.* In practice the scenario tiers of our workspaces barely +overlap (the dev workspace carries the Prime/piano variants; each +deployment carries its own glue), so the re-declaration cost is nominal +— a few TOML lines per workspace, with a reference block in the docs to +copy from. This is also the faithful reading of the mjlab model: mjlab +ships `train`/`play` — invariant utilities — as `[project.scripts]`; it +does not ship "bring up my specific project" commands. That glue is +always your own project file. Pixi offers no mechanism for tasks that +travel with a dependency — `[tasks]` are strictly +workspace-manifest-level — so the only portable mechanism is the one uv +uses: executables shipped by the package (conda `bin/`, Python console +scripts), which `pixi run` resolves after task names. + +## 2. The day-one ritual + +Day one, in every developer-facing workspace, **must** be one command: + +```sh +pixi run build # auto-installs the env, fetches sources, colcon-builds +pixi run doctor # (recommended) verify; prints what to fix if unhealthy +``` + +### 2.1 How it collapses to one command + +- `pixi run` self-heals the environment (installs from the lockfile if + needed). `pixi install` remains an optional explicit step, kept in + the docs for uv users who expect a `sync` verb. +- `setup` **must** be safe to chain from `build`, achieved by two + mechanisms together (both verified empirically): + - **`vcs import --skip-existing`** — exits 0 on re-run, and unlike + plain `vcs import` it never resets a locally-checked-out branch in + a third-party repo back to its pin. + - **pixi `inputs`/`outputs` caching** — because `--skip-existing` + alone still *fetches* every remote (and exits 1 offline; a bare + chain would put the network in front of every build and make an + offline robot unable to rebuild): + + ```toml + [tasks.setup] + cmd = "vcs import src --skip-existing --input humanoid_control.repos && touch build/.setup-stamp" + inputs = ["humanoid_control.repos"] + outputs = ["build/.setup-stamp"] + ``` + + Verified semantics: cache hit (no network) when nothing changed; + re-runs on a `.repos` edit; re-runs after `clean` or on a fresh + clone (the stamp lives under `build/`). + + Caveat (**must** be documented on the task): `--skip-existing` never + moves an existing checkout to a new pin — after a `.repos` pin bump, + delete that repo directory and re-run `setup`. This is no worse than + the pre-protocol behavior. + +### 2.2 Nothing else auto-builds + +The chain stops at `build → setup` by design. **No scenario task or +`hc` verb may ever auto-build** — hardware bringups must not trigger +surprise rebuilds. `doctor` is the staleness/health check instead, and +colcon owns build incrementality. + +### 2.3 The `doctor` check + +`doctor` **must** check: workspace root, environment active, overlay +built and sourced, `/opt/ros` contamination (fail hard), +`ROS_DOMAIN_ID`, source tree present, key packages visible. Fixable +findings are warnings; fatal findings exit non-zero. + +## 3. Level 1 — lifecycle tasks + +These five names are the only **fully** reserved names — reserved in +both name and semantics. Every developer-facing workspace **must** +provide them (with the `test` exception noted): + +| Task | Meaning | +|---|---| +| `setup` | fetch/prepare sources beyond pixi itself; **idempotent**; chained by `build` | +| `build` | build the workspace default lane (depends on `setup`) | +| `test` | run the workspace's tests (omit only if a workspace truly has none) | +| `clean` | wipe `build/ install/ log/`; **never** touches `src/` or `.pixi/` | +| `doctor` | workspace health check (§2.3) | + +*Rationale.* The de-facto standard task core across every credible +surveyed project is `build` / `test` / `clean` — kebab-case, flat; +nobody namespaces. Workspace-type repos keep tasks to lifecycle only; +demo/deployment repos add scenario tasks. prefix.dev's only official +task-set prose adds `lint` and a `check` aggregate, which this protocol +treats as archetype-local (§3.1) rather than universal. + +### 3.1 Archetype-local extras + +Allowed, described, never required of other workspaces: + +- **Dev workspace:** `build-all` (include the EtherCAT/Prime lane), + `test-result` (singular, matching the colcon verb), `lint` (the + `.githooks` ament linter set), `check` (`test` + `lint` pure alias; + the local pre-push gate — its description notes local linter versions + ≠ CI), `gen-dds`, `test-dds`. +- **Buildfarm (maintainer CI, exempt from the developer core):** + `setup` (aggregating hidden `_import` + `_overlay`), `package` + (build `.conda` artifacts — deliberately **not** `build`, ending the + collision with the colcon verb), `publish`. + +Convenience variants that duplicate an existing mechanism **must not** +be added. Deleted at migration: `build-pkg` (equivalent to +`pixi run build --packages-select ` via trailing-argument +forwarding), `test-lint`, `test-results`, `launch-policy-tracking`. + +## 4. Level 2 — the `hc` toolbox + +### 4.1 Verb set + +| Verb | Meaning | +|---|---| +| `hc viz [viser\|rerun]` | live state viewer of a running robot (default: viser) | +| `hc viz urdf` | static URDF/kinematic inspector (sliders + RViz), no robot needed | +| `hc calibrate` | calibration bringup (writes `calibration.yaml`) | +| `hc bus ping\|discover\|probe\|probe-report` | CAN diagnostics | +| `hc motor slider` | MIT-mode slider GUI | + +Behavioral requirements: + +- Bare `hc` prints the menu with one-line descriptions. +- A verb whose target package isn't installed **must** fail with a + clear message naming the package. +- Every verb `execvp`s into the canonical `ros2 run` / `ros2 launch` + command — signals and `key:=value` arguments pass straight through. +- The verb set is fixed, versioned, and CI-tested with the code it + wraps. + +Vocabulary notes: there is no separate `view`/`visualize` verb +(confusable with `viz`), and "model" was rejected as a noun (collides +with the ONNX policy model). The docs site keeps teaching the canonical +`ros2 …` forms alongside `hc`. + +### 4.2 Scope + +Lite product-stack utilities and shared diagnostics only — **zero +references to anything outside that core**: no Prime, no task +scenarios, no sibling repos. + +> **Litmus test:** *identical meaning in every workspace?* +> If not, it is a workspace task. + +### 4.3 Installation requirement + +`hc` **must** be on `PATH` in any activated environment, source-built +or binary, and `ros2 run humanoid_control_cli hc` **must** keep +working. + +*Implementation note.* ament_python puts console scripts in +`lib//` (the `ros2 run` location), never on `PATH` — the root +cause of the previously broken `hc` task. The fix, verified +end-to-end: additionally install a `bin/` shim via `data_files` — +colcon generates a package-level `path.sh` environment hook whenever a +package installs a `bin/` directory, so the shim is on `PATH` after +sourcing — and have the conda recipe place it in `$PREFIX/bin`. The +executable bit was verified under `--symlink-install` (our standard); +confirm it survives a non-symlink colcon install at implementation +time. + +### 4.4 Extension mechanism (deferred) + +If a future invariant genuinely needs to ship from another package, the +mechanism of record is an ament-resource-index manifest (`hc_commands` +resource type) registered by the owning package. This is **deferred** +until a real case exists; nothing uses it at ratification, and the CLI +carries no extension machinery until then. + +## 5. Level 3 — scenario tasks + +### 5.1 Grammar + +Scenario tasks follow **`[-]`**, kebab-case, with +**at most one qualifier**. The reserved scenario words below **must** +be used by every workspace that has the concept; `launch-*` / +`deploy-*` prefixes **must not** be used: + +| Scenario | Meaning (workspace-defined scope) | +|---|---| +| `sim` | bring up this workspace's primary stack in simulation | +| `real` | same, on hardware | +| `policy` | prepare + load the RL policy against a running stack | + +The unqualified name is the workspace's default target; the suffix +selects the **primary task variant only**. Every secondary parameter +(robot, backend, checkpoint, scene, …) **must** remain a ROS launch +argument, forwarded verbatim — task names must never stack qualifiers. +With a robot × task × backend × policy matrix: + +```sh +pixi run sim-piano robot:=prime policy:=latest # right +pixi run sim-prime-piano-latest # wrong — name explosion +``` + +Which axis is "primary" is the workspace's call (in the dev workspace +today it is the robot or scene: `-prime`, `-piano`); everything else +rides the launch-argument surface, which is exactly what `ros2 launch` +users expect and what §7 forwarding preserves. The task `description` +**must** state the scope and the main launch arguments. + +Examples — dev workspace: `sim`, `real`, `sim-prime`, `real-prime`, +`sim-piano`, `policy`, `policy-piano` (unqualified = Lite). +Lite-Deployment: `sim` / `real` are the full reach-task stack +(`launch/task_reach.launch.py backend:=…`) plus `teleop` for its +repo-local gamepad script. + +Names outside the reserved vocabulary **may** be used for concepts the +vocabulary doesn't cover (`teleop`), in free kebab-case. + +### 5.2 Size cap + +The scenario tier **should** stay under roughly a screenful. A launch +file gets a task only if it is an *everyday* entry point; everything +else is documented in canonical `ros2 launch` form, which always works +(§8.5). + +## 6. Choosing where a new entry point goes + +Apply the first rule that matches: + +1. **Invariant meaning in every workspace** (diagnostic, viewer, + calibration) → `hc` verb. Never a workspace task. +2. **Scenario or workspace-local composition/script** → task in that + workspace's `pixi.toml`, using the §5.1 reserved vocabulary where it + applies (`sim`, `real`, `policy`), free kebab-case otherwise + (`teleop`). +3. **Operates on the workspace** (fetch, build, verify) → lifecycle + task, universal names only. +4. **Needs root or mutates host state** (CAN buses, kernel) → + `scripts/*.sh`, run explicitly with `sudo`, never a task. +5. **Rarely used** → nothing; document the canonical `ros2 …` command. + +## 7. Task authoring rules + +### 7.1 Every public task has a description + +`pixi task list` is the workspace menu; `hc` is the toolbox menu. A +task without a `description` is invisible to onboarding. + +```toml +# Correct: +sim = { cmd = "ros2 launch .launch.py", description = "Bring up the Lite stack in MuJoCo" } + +# Wrong: no description — invisible in `pixi task list` +sim = "ros2 launch .launch.py" +``` + +Plumbing tasks are prefixed with `_` (hidden from the menu). + +### 7.2 Launch-wrapping tasks are arg-less strings + +Trailing `key:=value` arguments must forward verbatim: + +```sh +pixi run sim enable_gamepad:=false +pixi run real wandb_run_path:=… # in a deployment +``` + +Typed pixi `args` (defaults/choices) are reserved for non-launch tasks +where they collapse variants; they **must not** appear on tasks whose +users pass launch arguments. + +### 7.3 Chaining and caching + +- `build` chains `setup` (idempotent, §2.1); **nothing else + auto-chains**. +- No pixi `inputs` caching on `build` — colcon owns incrementality. + +### 7.4 Task strings are legible + +The task string shows the canonical command it wraps; non-obvious flags +get a why-first comment above the task. Style flags belong in +`COLCON_DEFAULTS_FILE`, not the task string (§8.3). + +### 7.5 Forbidden names + +- **No `install` or `shell`** — they shadow pixi's own verbs. +- **No `run` or `start`** — `pixi run run` reads badly, and the + scenario vocabulary already names what starts. +- **No colon namespacing** (`build:all`). +- **No same-name tasks in multiple environments** — the interactive + picker breaks CI. + +```text +# Correct: setup build sim sim-prime teleop _import +# Wrong: install shell run start build:all launch-mujoco deploy-real +``` + +## 8. Environment and activation protocol + +### 8.1 Overlay sourcing + +Every colcon workspace **must** source its overlay through a guarded +activation script (NASA-JSC pattern): + +```toml +[activation] +scripts = ["scripts/activate.sh"] +``` + +```sh +# scripts/activate.sh — sourced by pixi on every run/shell +if [ -f "$PIXI_PROJECT_ROOT/install/setup.sh" ]; then + . "$PIXI_PROJECT_ROOT/install/setup.sh" +fi +``` + +POSIX `setup.sh`, not `setup.bash`. The guard makes the first, +pre-build activation a no-op instead of an error. + +### 8.2 `[activation.env]` carries the workspace identity + +- Deployment workspaces pin their robot's `ROS_DOMAIN_ID` (Lite = 5 per + the lab guide; Lite-Specialist = 6). The dev workspace leaves it + unpinned, and `doctor` prints it. +- `RCUTILS_COLORIZED_OUTPUT=1` and the standard + `RCUTILS_CONSOLE_OUTPUT_FORMAT` go in every workspace. + +### 8.3 Colcon flags + +Style flags move to `COLCON_DEFAULTS_FILE` +(`config/colcon-defaults.yaml`: `--symlink-install`, compile-commands +export) so plain `colcon build` inside `pixi shell` behaves exactly +like `pixi run build`. Semantic selection flags +(`--packages-skip-regex`, `--packages-up-to`) stay visible in the task +string — policy, not preference. + +### 8.4 Channels and environments + +- Channel order: `https://prefix.dev/robostack-jazzy` before + `https://prefix.dev/conda-forge`, full URLs. Binary-consumer + manifests put `https://prefix.dev/berkeley-humanoids` first. +- Single default environment. Adopt features/environments only when + dependencies genuinely diverge (the same criterion as the Tier-2 rule + in AGENTS.md). + +### 8.5 Escape hatches + +Escape hatches are part of the interface and **must** be documented in +every README: + +- `pixi shell` — all `ros2`/`colcon` commands and `hc` work verbatim, +- `pixi run -- `, +- the canonical `ros2 launch` forms for anything without a task. + +### 8.6 The `scripts/` directory + +`scripts/` at the workspace root holds host-side helpers that can't run +inside the environment or as tasks: `activate.sh`, `canup.sh` (sudo), +`doctor.sh`. + +--- + +## Appendix A — Migration map (non-normative) + +Transitional; describes how existing repos reach compliance. Delete +once executed. + +### A.1 `humanoid_control_cli` (small; ships first) + +- Add the `bin/` shim install (source overlay) plus `$PREFIX/bin` + placement in the conda recipe so `hc` is on `PATH` in any activated + environment (§4.3). +- Add the `viz urdf` noun (targets + `humanoid_bringup_lite view_lite.launch.py`); keep `bus`, `motor`, + `viz`, `calibrate`. No scenario verbs, no extension mechanism (§4.4). +- Update the not-found error message to suggest `pixi run build`. + +### A.2 `humanoid_control_ws/pixi.toml` (30 tasks → 19) + +| Current | New | Note | +|---|---|---| +| `setup` | `setup` | add `--skip-existing` + `inputs`/`outputs` stamp caching (§2.1); gains description | +| `build`, `build-all`, `clean`, `gen-dds`, `test`, `test-dds` | unchanged names | `build` gains `depends-on = ["setup"]`; all gain descriptions | +| `test-results` | `test-result` | colcon verb parity | +| `build-pkg`, `test-lint` | **deleted** | trailing args / replaced by `lint` + `check` | +| — | `lint`, `check`, `doctor` | new; `lint` requires factoring the `.githooks/pre-commit` linter list into a script with a full-tree mode (the hook itself lints staged files only) — uncrustify/cppcheck stay excluded locally per the hook's version-skew rationale | +| `launch-mujoco` / `launch-real` | `sim` / `real` | scenario vocabulary | +| `launch-mujoco-prime` / `launch-real-prime` | `sim-prime` / `real-prime` | | +| `launch-mujoco-piano` / `launch-policy-piano` | `sim-piano` / `policy-piano` | | +| `launch-policy` | `policy` | | +| `launch-policy-tracking`, `launch-midi-keyboard` | **deleted** | back-compat alias; rarely used (canonical form documented) | +| `launch-viz`, `view`, `calibrate` | **deleted** | → `hc viz` / `hc viz urdf` (fixes the dead `bar_description_lite` target) / `hc calibrate` | +| `robstride-*` (4), `mit-slider-gui`, `rerun-viz`, `viser-viz` | **deleted** | already under `hc bus` / `hc motor` / `hc viz` | +| `hc` | `hc = "ros2 run humanoid_control_cli hc"` | fixed forwarding task (kept for pre-`PATH`-shim compatibility; drop once the bin shim ships) | +| `canup.sh` (root) | `scripts/canup.sh` | + new `scripts/activate.sh`, `scripts/doctor.sh` | + +Final dev-ws task list: `setup build build-all test test-result lint +check clean doctor gen-dds test-dds sim real sim-prime real-prime +sim-piano policy policy-piano hc`. + +### A.3 `Lite-Deployment/pixi.toml` (9 tasks → 7) + +| Current | New | Note | +|---|---|---| +| `setup`, `build`, `doctor` | unchanged | `setup` gains `--skip-existing` + stamp caching; its `fetch_rqt_controller_manager.sh` step needs an idempotency guard (`test -d … \|\|`) since `build` chains it | +| — | `clean` | universal core | +| `deploy-mujoco` / `deploy-real` | `sim` / `real` | full reach-task stack via `task_reach.launch.py` | +| `launch-mujoco`, `launch-policy` | **deleted** | debugging compositions; canonical `ros2 launch` forms documented | +| `launch-teleop` | `teleop` | repo-local script, stays a task | +| `visualize` | **deleted** | → `hc viz urdf` | +| — | add `RCUTILS_*` to `[activation.env]` | | + +`Lite-Specialist-Deployment` gets the same mapping (its scenario tasks +keep their `backends:=` launch-arg pattern; `ROS_DOMAIN_ID` stays 6). + +### A.4 `humanoid_control` repo-root buildfarm manifest + +| Current | New | +|---|---| +| `import` + `overlay` | `_import` + `_overlay`, aggregated by `setup` | +| `build-all` | `package` | +| `publish` | unchanged | + +**CI is a consumer of these names:** `.github/workflows/build_jazzy.yml` +runs `pixi run import` / `overlay` / `build-all ${{ matrix.arch }}` / +`publish` — update the steps to `setup` / `package ` / `publish` +in the same PR (the trailing arch argument forwards unchanged). + +### A.5 Documentation + +- `Humanoid-Control-Website` `how_to/use_pixi_tasks.md`: rewrite around + the three levels (workspace tasks via `pixi task list`; toolbox via + `hc`), including a copy-paste reference block of scenario tasks for + new/consumer workspaces; fixes the stale `bar …` mapping and + `src/humanoid_control/bar.repos` path. Update task names in + `installation.md`, `lite_101.md`, `quick_reference.md`, + `troubleshooting.md`, `packages.md`. +- `AGENTS.md`: fold §1–§8 into "Environment, tooling & version + control"; update decision-log rows (Appendix B). +- READMEs (`humanoid_control_ws` config repo, `humanoid_control`, + `Lite-Deployment`): lead with the §2 one-command ritual. + +## Appendix B — Decision log entries (for AGENTS.md) + +| Choice | Picked | Why (vs the alternative) | +|---|---|---| +| Command levels | L1 lifecycle tasks (reserved names+semantics) / L2 packaged `hc` toolbox / L3 scenario+glue tasks (reserved names, local semantics) | invariant-meaning commands are packaged once and cannot drift (two aliases broken today); workspace-flavored scenarios stay in the workspace that defines their meaning; scenario tiers barely overlap across workspaces so duplication is nominal. vs packaging scenarios into `hc` (needs an extension mechanism + scope policing; `sim`'s meaning varies per workspace) or convention-only with no CLI (regenerates per-tool alias sprawl). | +| `hc` scope | fixed toolbox: `bus`, `motor`, `viz [viser\|rerun\|urdf]`, `calibrate`; litmus = identical meaning everywhere; ament-index `hc_commands` extension mechanism deferred until a real cross-package invariant exists | core stays universally reusable, carries no external payload (no Prime/piano). | +| Universal task core | `setup build test clean doctor` only | matches the ecosystem's de-facto canon; everything else is archetype-local. vs an 11-verb reserved set (over-standardized). | +| Day-one ritual | one command: `pixi run build` (env auto-installs; chained `setup` is `--skip-existing` + stamp-cached on the `.repos` file) | uv-like self-healing; fewer steps to memorize; cache keeps the network out of daily/offline builds (a bare chain would fetch every remote per build and fail offline — verified). vs install→setup→build→doctor sequence. | +| Build freshness | `build`→`setup` chain only; scenario tasks and `hc` verbs never auto-build; `doctor` for health | colcon owns incrementality; no surprise rebuilds before hardware bringup. | +| Overlay activation | guarded `scripts/activate.sh` sourcing `install/setup.sh` | explicit first-build handling, POSIX, matches NASA-JSC/ros-controls. | +| Colcon flags | style flags in `config/colcon-defaults.yaml`, selection flags in task strings | manual `colcon build` == `pixi run build`; policy stays visible. | +| Buildfarm verb | `package` (not `build*`) | packaging ≠ compiling; ends the `build-all` double meaning. | From c8ef958db2033727a8c68be9a18bf01b43e50803 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:24:31 -0700 Subject: [PATCH 4/7] docs: keep the RFC in the PR description, not a committed file The full protocol RFC lives in Skills#1's description for traceability; SKILL.md points there instead of a references/ copy. Co-Authored-By: Claude Fable 5 --- skills/pixi-workspace/SKILL.md | 11 +- .../references/pixi_interface_protocol.md | 571 ------------------ 2 files changed, 5 insertions(+), 577 deletions(-) delete mode 100644 skills/pixi-workspace/references/pixi_interface_protocol.md diff --git a/skills/pixi-workspace/SKILL.md b/skills/pixi-workspace/SKILL.md index 997e624..f07ffc0 100644 --- a/skills/pixi-workspace/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -6,12 +6,11 @@ description: Use when creating, editing, or reviewing pixi.toml manifests, pixi # Pixi workspace interface Every Berkeley Humanoids pixi workspace exposes the same three-level -command interface. Ratified 2026-07-05; the full RFC (rationale, -research base, RFC-2119 normative text, migration history) is at -[references/pixi_interface_protocol.md](references/pixi_interface_protocol.md); -durable summaries live in the dev tree's `AGENTS.md` ("Command interface -(three levels)") and the public walkthrough in -`Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`. +command interface. Ratified 2026-07-05; durable rationale lives in the +dev tree's `AGENTS.md` ("Command interface (three levels)") and the +public walkthrough in `Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`; +the full RFC is preserved in this skill's introducing PR +(Berkeley-Humanoids/Skills#1). ## The three levels diff --git a/skills/pixi-workspace/references/pixi_interface_protocol.md b/skills/pixi-workspace/references/pixi_interface_protocol.md deleted file mode 100644 index 568964b..0000000 --- a/skills/pixi-workspace/references/pixi_interface_protocol.md +++ /dev/null @@ -1,571 +0,0 @@ -# Pixi Workspace Interface Protocol - -| | | -|----------------|--------------------------------------------------------------------| -| **Title** | Pixi Workspace Interface Protocol | -| **Type** | Process (convention) | -| **Status** | Ratified 2026-07-05 (see [Status](#status)) | -| **Created** | 2026-07-05 | -| **Applies to** | All Berkeley Humanoids pixi workspaces (see [Scope](#scope)) | - -## Abstract - -This document defines how every Berkeley Humanoids pixi workspace exposes -its environment, tasks, and scripts. It establishes a three-level command -model: - -1. a **universal lifecycle core** of five reserved pixi tasks - (`setup`, `build`, `test`, `clean`, `doctor`), -2. a **packaged product toolbox** (`hc`) for commands whose meaning is - invariant across workspaces, and -3. a **scenario-task vocabulary** (`sim`, `real`, `policy`, …) whose names - are reserved but whose semantics each workspace defines. - -It further specifies a one-command day-one ritual (`pixi run build`), -rules for authoring tasks, and an environment-activation protocol. The -goal is that anyone who has learned one workspace can operate any other, -and that the canonical ROS 2 commands keep working verbatim underneath. - -## Status - -**Ratified and implemented 2026-07-05.** This copy is preserved with the -`pixi-workspace` skill for traceability of the design rationale. The -durable normative text lives in the dev tree's `AGENTS.md` → -"Environment, tooling & version control" → "Command interface (three -levels)"; the public walkthrough in -`Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`; the -operational rules in the sibling `SKILL.md`. Implemented via -[humanoid_control#16](https://github.com/Berkeley-Humanoids/humanoid_control/pull/16), -[Lite-Deployment#1](https://github.com/Berkeley-Humanoids/Lite-Deployment/pull/1), -[Humanoid-Control-Website#13](https://github.com/Berkeley-Humanoids/Humanoid-Control-Website/pull/13), -plus the local `humanoid_control_ws` manifest (30 → 19 tasks). The -migration plan in -[Appendix A](#appendix-a--migration-map-non-normative) is retained as -the historical record of that change. - -## Scope - -This protocol governs: - -- **`humanoid_control_ws`** — the development workspace, -- **the `*-Deployment` repositories** — operator workspaces, -- **the `humanoid_control` repo-root buildfarm manifest** — packaging - (a maintainer-CI surface, partially exempt; see - [Lifecycle tasks](#3-level-1--lifecycle-tasks)). - -There is no official pixi task style guide beyond this document; it sets -convention rather than follows one. Its choices were informed by the -official pixi/RoboStack guidance, a survey of ~15 real pixi + ROS 2 -projects (ros2/ros2, NVIDIA IsaacSim, NASA-JSC, ros-controls, bit-bots, -RobotecAI, rerun, …), and the uv ecosystem's day-one conventions. Key -findings from that survey are cited inline as rationale. - -Throughout, **must**, **must not**, **should**, and **may** are used in -the RFC 2119 sense. - -## Audiences and design goals - -Three audiences must find the interface natural: - -- **uv-native Python developers** expect the ritual `uv sync` → - `uv run `, one runner verb for everything, and a project's - invariant commands shipped *with the package* as `[project.scripts]` - entry points (mjlab's `train` / `play`). Pixi maps 1:1: - `pixi install` → `pixi run`, and `pixi run ` falls back to any - executable on the environment `PATH` exactly like `uv run train`. -- **ROS-native developers** expect `colcon build`, - `ros2 launch pkg file.launch.py`, `key:=value` launch arguments, and a - sourced overlay. All of that must keep working verbatim inside - `pixi shell` / `pixi run --`; tasks and CLI verbs are shortcuts over - canonical commands, never a replacement layer. -- **Robot operators** need a short, memorable, self-documenting menu: - one health check, one command per everyday scenario. - -## When to deviate - -Reserved names carry the weight of this protocol: a reserved name -**must not** be repurposed, and its reserved semantics **must not** be -altered. Beyond that, the protocol is deliberately thin: - -- Workspaces **may** add archetype-local tasks (see - [§3.1](#31-archetype-local-extras)) provided each carries a - `description` and is never required of other workspaces. -- The canonical `ros2` / `colcon` commands are part of the interface - (see [§8.5](#85-escape-hatches)); when no task fits, documenting the - canonical command is preferred over inventing a task. -- If following a rule would clearly make a specific workspace worse, - deviate — and record why in the task description or workspace README - so the deviation reads as a decision, not an accident. - -## 1. The three command levels - -Every command a user types belongs to exactly one level: - -| Level | Commands | Mechanism | Defined by | Scope | -|---|---|---|---|---| -| **1. Pixi-ROS lifecycle** | `setup` `build` `test` `clean` `doctor` | pixi tasks; names **and** semantics reserved by this protocol | each workspace's `pixi.toml` (re-declared — pixi tasks cannot ship with a dependency) | any pixi-ROS repo — ours match the ecosystem's de-facto canon | -| **2. Product toolbox** | `hc []` — `bus`, `motor`, `viz`, `calibrate` | packaged executable on the environment `PATH` | `humanoid_control_cli` | every environment that installs the stack (source or binary) | -| **3. Workspace scenarios & glue** | `sim` `real` `policy` (+ qualifiers), `teleop`, archetype extras | pixi tasks; scenario **names** reserved, **semantics** workspace-defined | that workspace's `pixi.toml` only | that workspace | - -### 1.1 The sorting criterion - -The rule that separates levels 2 and 3: - -> **Invariant meaning → packaged `hc` verb. -> Workspace-dependent meaning → workspace task under the reserved -> vocabulary.** - -`hc bus ping` or `hc viz urdf` mean exactly the same thing in every -workspace and for binary-channel consumers — packaging them once -prevents per-tool alias sprawl and drift (two such aliases were broken -in the dev workspace when this protocol was drafted). `sim` or `policy` -legitimately mean different things per workspace (base bringup in the -dev workspace, the full task stack in a deployment) and typically wrap -workspace-local composition — so each workspace declares them, and the -protocol standardizes only their names and grammar. - -*Rationale.* In practice the scenario tiers of our workspaces barely -overlap (the dev workspace carries the Prime/piano variants; each -deployment carries its own glue), so the re-declaration cost is nominal -— a few TOML lines per workspace, with a reference block in the docs to -copy from. This is also the faithful reading of the mjlab model: mjlab -ships `train`/`play` — invariant utilities — as `[project.scripts]`; it -does not ship "bring up my specific project" commands. That glue is -always your own project file. Pixi offers no mechanism for tasks that -travel with a dependency — `[tasks]` are strictly -workspace-manifest-level — so the only portable mechanism is the one uv -uses: executables shipped by the package (conda `bin/`, Python console -scripts), which `pixi run` resolves after task names. - -## 2. The day-one ritual - -Day one, in every developer-facing workspace, **must** be one command: - -```sh -pixi run build # auto-installs the env, fetches sources, colcon-builds -pixi run doctor # (recommended) verify; prints what to fix if unhealthy -``` - -### 2.1 How it collapses to one command - -- `pixi run` self-heals the environment (installs from the lockfile if - needed). `pixi install` remains an optional explicit step, kept in - the docs for uv users who expect a `sync` verb. -- `setup` **must** be safe to chain from `build`, achieved by two - mechanisms together (both verified empirically): - - **`vcs import --skip-existing`** — exits 0 on re-run, and unlike - plain `vcs import` it never resets a locally-checked-out branch in - a third-party repo back to its pin. - - **pixi `inputs`/`outputs` caching** — because `--skip-existing` - alone still *fetches* every remote (and exits 1 offline; a bare - chain would put the network in front of every build and make an - offline robot unable to rebuild): - - ```toml - [tasks.setup] - cmd = "vcs import src --skip-existing --input humanoid_control.repos && touch build/.setup-stamp" - inputs = ["humanoid_control.repos"] - outputs = ["build/.setup-stamp"] - ``` - - Verified semantics: cache hit (no network) when nothing changed; - re-runs on a `.repos` edit; re-runs after `clean` or on a fresh - clone (the stamp lives under `build/`). - - Caveat (**must** be documented on the task): `--skip-existing` never - moves an existing checkout to a new pin — after a `.repos` pin bump, - delete that repo directory and re-run `setup`. This is no worse than - the pre-protocol behavior. - -### 2.2 Nothing else auto-builds - -The chain stops at `build → setup` by design. **No scenario task or -`hc` verb may ever auto-build** — hardware bringups must not trigger -surprise rebuilds. `doctor` is the staleness/health check instead, and -colcon owns build incrementality. - -### 2.3 The `doctor` check - -`doctor` **must** check: workspace root, environment active, overlay -built and sourced, `/opt/ros` contamination (fail hard), -`ROS_DOMAIN_ID`, source tree present, key packages visible. Fixable -findings are warnings; fatal findings exit non-zero. - -## 3. Level 1 — lifecycle tasks - -These five names are the only **fully** reserved names — reserved in -both name and semantics. Every developer-facing workspace **must** -provide them (with the `test` exception noted): - -| Task | Meaning | -|---|---| -| `setup` | fetch/prepare sources beyond pixi itself; **idempotent**; chained by `build` | -| `build` | build the workspace default lane (depends on `setup`) | -| `test` | run the workspace's tests (omit only if a workspace truly has none) | -| `clean` | wipe `build/ install/ log/`; **never** touches `src/` or `.pixi/` | -| `doctor` | workspace health check (§2.3) | - -*Rationale.* The de-facto standard task core across every credible -surveyed project is `build` / `test` / `clean` — kebab-case, flat; -nobody namespaces. Workspace-type repos keep tasks to lifecycle only; -demo/deployment repos add scenario tasks. prefix.dev's only official -task-set prose adds `lint` and a `check` aggregate, which this protocol -treats as archetype-local (§3.1) rather than universal. - -### 3.1 Archetype-local extras - -Allowed, described, never required of other workspaces: - -- **Dev workspace:** `build-all` (include the EtherCAT/Prime lane), - `test-result` (singular, matching the colcon verb), `lint` (the - `.githooks` ament linter set), `check` (`test` + `lint` pure alias; - the local pre-push gate — its description notes local linter versions - ≠ CI), `gen-dds`, `test-dds`. -- **Buildfarm (maintainer CI, exempt from the developer core):** - `setup` (aggregating hidden `_import` + `_overlay`), `package` - (build `.conda` artifacts — deliberately **not** `build`, ending the - collision with the colcon verb), `publish`. - -Convenience variants that duplicate an existing mechanism **must not** -be added. Deleted at migration: `build-pkg` (equivalent to -`pixi run build --packages-select ` via trailing-argument -forwarding), `test-lint`, `test-results`, `launch-policy-tracking`. - -## 4. Level 2 — the `hc` toolbox - -### 4.1 Verb set - -| Verb | Meaning | -|---|---| -| `hc viz [viser\|rerun]` | live state viewer of a running robot (default: viser) | -| `hc viz urdf` | static URDF/kinematic inspector (sliders + RViz), no robot needed | -| `hc calibrate` | calibration bringup (writes `calibration.yaml`) | -| `hc bus ping\|discover\|probe\|probe-report` | CAN diagnostics | -| `hc motor slider` | MIT-mode slider GUI | - -Behavioral requirements: - -- Bare `hc` prints the menu with one-line descriptions. -- A verb whose target package isn't installed **must** fail with a - clear message naming the package. -- Every verb `execvp`s into the canonical `ros2 run` / `ros2 launch` - command — signals and `key:=value` arguments pass straight through. -- The verb set is fixed, versioned, and CI-tested with the code it - wraps. - -Vocabulary notes: there is no separate `view`/`visualize` verb -(confusable with `viz`), and "model" was rejected as a noun (collides -with the ONNX policy model). The docs site keeps teaching the canonical -`ros2 …` forms alongside `hc`. - -### 4.2 Scope - -Lite product-stack utilities and shared diagnostics only — **zero -references to anything outside that core**: no Prime, no task -scenarios, no sibling repos. - -> **Litmus test:** *identical meaning in every workspace?* -> If not, it is a workspace task. - -### 4.3 Installation requirement - -`hc` **must** be on `PATH` in any activated environment, source-built -or binary, and `ros2 run humanoid_control_cli hc` **must** keep -working. - -*Implementation note.* ament_python puts console scripts in -`lib//` (the `ros2 run` location), never on `PATH` — the root -cause of the previously broken `hc` task. The fix, verified -end-to-end: additionally install a `bin/` shim via `data_files` — -colcon generates a package-level `path.sh` environment hook whenever a -package installs a `bin/` directory, so the shim is on `PATH` after -sourcing — and have the conda recipe place it in `$PREFIX/bin`. The -executable bit was verified under `--symlink-install` (our standard); -confirm it survives a non-symlink colcon install at implementation -time. - -### 4.4 Extension mechanism (deferred) - -If a future invariant genuinely needs to ship from another package, the -mechanism of record is an ament-resource-index manifest (`hc_commands` -resource type) registered by the owning package. This is **deferred** -until a real case exists; nothing uses it at ratification, and the CLI -carries no extension machinery until then. - -## 5. Level 3 — scenario tasks - -### 5.1 Grammar - -Scenario tasks follow **`[-]`**, kebab-case, with -**at most one qualifier**. The reserved scenario words below **must** -be used by every workspace that has the concept; `launch-*` / -`deploy-*` prefixes **must not** be used: - -| Scenario | Meaning (workspace-defined scope) | -|---|---| -| `sim` | bring up this workspace's primary stack in simulation | -| `real` | same, on hardware | -| `policy` | prepare + load the RL policy against a running stack | - -The unqualified name is the workspace's default target; the suffix -selects the **primary task variant only**. Every secondary parameter -(robot, backend, checkpoint, scene, …) **must** remain a ROS launch -argument, forwarded verbatim — task names must never stack qualifiers. -With a robot × task × backend × policy matrix: - -```sh -pixi run sim-piano robot:=prime policy:=latest # right -pixi run sim-prime-piano-latest # wrong — name explosion -``` - -Which axis is "primary" is the workspace's call (in the dev workspace -today it is the robot or scene: `-prime`, `-piano`); everything else -rides the launch-argument surface, which is exactly what `ros2 launch` -users expect and what §7 forwarding preserves. The task `description` -**must** state the scope and the main launch arguments. - -Examples — dev workspace: `sim`, `real`, `sim-prime`, `real-prime`, -`sim-piano`, `policy`, `policy-piano` (unqualified = Lite). -Lite-Deployment: `sim` / `real` are the full reach-task stack -(`launch/task_reach.launch.py backend:=…`) plus `teleop` for its -repo-local gamepad script. - -Names outside the reserved vocabulary **may** be used for concepts the -vocabulary doesn't cover (`teleop`), in free kebab-case. - -### 5.2 Size cap - -The scenario tier **should** stay under roughly a screenful. A launch -file gets a task only if it is an *everyday* entry point; everything -else is documented in canonical `ros2 launch` form, which always works -(§8.5). - -## 6. Choosing where a new entry point goes - -Apply the first rule that matches: - -1. **Invariant meaning in every workspace** (diagnostic, viewer, - calibration) → `hc` verb. Never a workspace task. -2. **Scenario or workspace-local composition/script** → task in that - workspace's `pixi.toml`, using the §5.1 reserved vocabulary where it - applies (`sim`, `real`, `policy`), free kebab-case otherwise - (`teleop`). -3. **Operates on the workspace** (fetch, build, verify) → lifecycle - task, universal names only. -4. **Needs root or mutates host state** (CAN buses, kernel) → - `scripts/*.sh`, run explicitly with `sudo`, never a task. -5. **Rarely used** → nothing; document the canonical `ros2 …` command. - -## 7. Task authoring rules - -### 7.1 Every public task has a description - -`pixi task list` is the workspace menu; `hc` is the toolbox menu. A -task without a `description` is invisible to onboarding. - -```toml -# Correct: -sim = { cmd = "ros2 launch .launch.py", description = "Bring up the Lite stack in MuJoCo" } - -# Wrong: no description — invisible in `pixi task list` -sim = "ros2 launch .launch.py" -``` - -Plumbing tasks are prefixed with `_` (hidden from the menu). - -### 7.2 Launch-wrapping tasks are arg-less strings - -Trailing `key:=value` arguments must forward verbatim: - -```sh -pixi run sim enable_gamepad:=false -pixi run real wandb_run_path:=… # in a deployment -``` - -Typed pixi `args` (defaults/choices) are reserved for non-launch tasks -where they collapse variants; they **must not** appear on tasks whose -users pass launch arguments. - -### 7.3 Chaining and caching - -- `build` chains `setup` (idempotent, §2.1); **nothing else - auto-chains**. -- No pixi `inputs` caching on `build` — colcon owns incrementality. - -### 7.4 Task strings are legible - -The task string shows the canonical command it wraps; non-obvious flags -get a why-first comment above the task. Style flags belong in -`COLCON_DEFAULTS_FILE`, not the task string (§8.3). - -### 7.5 Forbidden names - -- **No `install` or `shell`** — they shadow pixi's own verbs. -- **No `run` or `start`** — `pixi run run` reads badly, and the - scenario vocabulary already names what starts. -- **No colon namespacing** (`build:all`). -- **No same-name tasks in multiple environments** — the interactive - picker breaks CI. - -```text -# Correct: setup build sim sim-prime teleop _import -# Wrong: install shell run start build:all launch-mujoco deploy-real -``` - -## 8. Environment and activation protocol - -### 8.1 Overlay sourcing - -Every colcon workspace **must** source its overlay through a guarded -activation script (NASA-JSC pattern): - -```toml -[activation] -scripts = ["scripts/activate.sh"] -``` - -```sh -# scripts/activate.sh — sourced by pixi on every run/shell -if [ -f "$PIXI_PROJECT_ROOT/install/setup.sh" ]; then - . "$PIXI_PROJECT_ROOT/install/setup.sh" -fi -``` - -POSIX `setup.sh`, not `setup.bash`. The guard makes the first, -pre-build activation a no-op instead of an error. - -### 8.2 `[activation.env]` carries the workspace identity - -- Deployment workspaces pin their robot's `ROS_DOMAIN_ID` (Lite = 5 per - the lab guide; Lite-Specialist = 6). The dev workspace leaves it - unpinned, and `doctor` prints it. -- `RCUTILS_COLORIZED_OUTPUT=1` and the standard - `RCUTILS_CONSOLE_OUTPUT_FORMAT` go in every workspace. - -### 8.3 Colcon flags - -Style flags move to `COLCON_DEFAULTS_FILE` -(`config/colcon-defaults.yaml`: `--symlink-install`, compile-commands -export) so plain `colcon build` inside `pixi shell` behaves exactly -like `pixi run build`. Semantic selection flags -(`--packages-skip-regex`, `--packages-up-to`) stay visible in the task -string — policy, not preference. - -### 8.4 Channels and environments - -- Channel order: `https://prefix.dev/robostack-jazzy` before - `https://prefix.dev/conda-forge`, full URLs. Binary-consumer - manifests put `https://prefix.dev/berkeley-humanoids` first. -- Single default environment. Adopt features/environments only when - dependencies genuinely diverge (the same criterion as the Tier-2 rule - in AGENTS.md). - -### 8.5 Escape hatches - -Escape hatches are part of the interface and **must** be documented in -every README: - -- `pixi shell` — all `ros2`/`colcon` commands and `hc` work verbatim, -- `pixi run -- `, -- the canonical `ros2 launch` forms for anything without a task. - -### 8.6 The `scripts/` directory - -`scripts/` at the workspace root holds host-side helpers that can't run -inside the environment or as tasks: `activate.sh`, `canup.sh` (sudo), -`doctor.sh`. - ---- - -## Appendix A — Migration map (non-normative) - -Transitional; describes how existing repos reach compliance. Delete -once executed. - -### A.1 `humanoid_control_cli` (small; ships first) - -- Add the `bin/` shim install (source overlay) plus `$PREFIX/bin` - placement in the conda recipe so `hc` is on `PATH` in any activated - environment (§4.3). -- Add the `viz urdf` noun (targets - `humanoid_bringup_lite view_lite.launch.py`); keep `bus`, `motor`, - `viz`, `calibrate`. No scenario verbs, no extension mechanism (§4.4). -- Update the not-found error message to suggest `pixi run build`. - -### A.2 `humanoid_control_ws/pixi.toml` (30 tasks → 19) - -| Current | New | Note | -|---|---|---| -| `setup` | `setup` | add `--skip-existing` + `inputs`/`outputs` stamp caching (§2.1); gains description | -| `build`, `build-all`, `clean`, `gen-dds`, `test`, `test-dds` | unchanged names | `build` gains `depends-on = ["setup"]`; all gain descriptions | -| `test-results` | `test-result` | colcon verb parity | -| `build-pkg`, `test-lint` | **deleted** | trailing args / replaced by `lint` + `check` | -| — | `lint`, `check`, `doctor` | new; `lint` requires factoring the `.githooks/pre-commit` linter list into a script with a full-tree mode (the hook itself lints staged files only) — uncrustify/cppcheck stay excluded locally per the hook's version-skew rationale | -| `launch-mujoco` / `launch-real` | `sim` / `real` | scenario vocabulary | -| `launch-mujoco-prime` / `launch-real-prime` | `sim-prime` / `real-prime` | | -| `launch-mujoco-piano` / `launch-policy-piano` | `sim-piano` / `policy-piano` | | -| `launch-policy` | `policy` | | -| `launch-policy-tracking`, `launch-midi-keyboard` | **deleted** | back-compat alias; rarely used (canonical form documented) | -| `launch-viz`, `view`, `calibrate` | **deleted** | → `hc viz` / `hc viz urdf` (fixes the dead `bar_description_lite` target) / `hc calibrate` | -| `robstride-*` (4), `mit-slider-gui`, `rerun-viz`, `viser-viz` | **deleted** | already under `hc bus` / `hc motor` / `hc viz` | -| `hc` | `hc = "ros2 run humanoid_control_cli hc"` | fixed forwarding task (kept for pre-`PATH`-shim compatibility; drop once the bin shim ships) | -| `canup.sh` (root) | `scripts/canup.sh` | + new `scripts/activate.sh`, `scripts/doctor.sh` | - -Final dev-ws task list: `setup build build-all test test-result lint -check clean doctor gen-dds test-dds sim real sim-prime real-prime -sim-piano policy policy-piano hc`. - -### A.3 `Lite-Deployment/pixi.toml` (9 tasks → 7) - -| Current | New | Note | -|---|---|---| -| `setup`, `build`, `doctor` | unchanged | `setup` gains `--skip-existing` + stamp caching; its `fetch_rqt_controller_manager.sh` step needs an idempotency guard (`test -d … \|\|`) since `build` chains it | -| — | `clean` | universal core | -| `deploy-mujoco` / `deploy-real` | `sim` / `real` | full reach-task stack via `task_reach.launch.py` | -| `launch-mujoco`, `launch-policy` | **deleted** | debugging compositions; canonical `ros2 launch` forms documented | -| `launch-teleop` | `teleop` | repo-local script, stays a task | -| `visualize` | **deleted** | → `hc viz urdf` | -| — | add `RCUTILS_*` to `[activation.env]` | | - -`Lite-Specialist-Deployment` gets the same mapping (its scenario tasks -keep their `backends:=` launch-arg pattern; `ROS_DOMAIN_ID` stays 6). - -### A.4 `humanoid_control` repo-root buildfarm manifest - -| Current | New | -|---|---| -| `import` + `overlay` | `_import` + `_overlay`, aggregated by `setup` | -| `build-all` | `package` | -| `publish` | unchanged | - -**CI is a consumer of these names:** `.github/workflows/build_jazzy.yml` -runs `pixi run import` / `overlay` / `build-all ${{ matrix.arch }}` / -`publish` — update the steps to `setup` / `package ` / `publish` -in the same PR (the trailing arch argument forwards unchanged). - -### A.5 Documentation - -- `Humanoid-Control-Website` `how_to/use_pixi_tasks.md`: rewrite around - the three levels (workspace tasks via `pixi task list`; toolbox via - `hc`), including a copy-paste reference block of scenario tasks for - new/consumer workspaces; fixes the stale `bar …` mapping and - `src/humanoid_control/bar.repos` path. Update task names in - `installation.md`, `lite_101.md`, `quick_reference.md`, - `troubleshooting.md`, `packages.md`. -- `AGENTS.md`: fold §1–§8 into "Environment, tooling & version - control"; update decision-log rows (Appendix B). -- READMEs (`humanoid_control_ws` config repo, `humanoid_control`, - `Lite-Deployment`): lead with the §2 one-command ritual. - -## Appendix B — Decision log entries (for AGENTS.md) - -| Choice | Picked | Why (vs the alternative) | -|---|---|---| -| Command levels | L1 lifecycle tasks (reserved names+semantics) / L2 packaged `hc` toolbox / L3 scenario+glue tasks (reserved names, local semantics) | invariant-meaning commands are packaged once and cannot drift (two aliases broken today); workspace-flavored scenarios stay in the workspace that defines their meaning; scenario tiers barely overlap across workspaces so duplication is nominal. vs packaging scenarios into `hc` (needs an extension mechanism + scope policing; `sim`'s meaning varies per workspace) or convention-only with no CLI (regenerates per-tool alias sprawl). | -| `hc` scope | fixed toolbox: `bus`, `motor`, `viz [viser\|rerun\|urdf]`, `calibrate`; litmus = identical meaning everywhere; ament-index `hc_commands` extension mechanism deferred until a real cross-package invariant exists | core stays universally reusable, carries no external payload (no Prime/piano). | -| Universal task core | `setup build test clean doctor` only | matches the ecosystem's de-facto canon; everything else is archetype-local. vs an 11-verb reserved set (over-standardized). | -| Day-one ritual | one command: `pixi run build` (env auto-installs; chained `setup` is `--skip-existing` + stamp-cached on the `.repos` file) | uv-like self-healing; fewer steps to memorize; cache keeps the network out of daily/offline builds (a bare chain would fetch every remote per build and fail offline — verified). vs install→setup→build→doctor sequence. | -| Build freshness | `build`→`setup` chain only; scenario tasks and `hc` verbs never auto-build; `doctor` for health | colcon owns incrementality; no surprise rebuilds before hardware bringup. | -| Overlay activation | guarded `scripts/activate.sh` sourcing `install/setup.sh` | explicit first-build handling, POSIX, matches NASA-JSC/ros-controls. | -| Colcon flags | style flags in `config/colcon-defaults.yaml`, selection flags in task strings | manual `colcon build` == `pixi run build`; policy stays visible. | -| Buildfarm verb | `package` (not `build*`) | packaging ≠ compiling; ends the `build-all` double meaning. | From 02e4d3467219311e684d25d57ba2a5aacb576749 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:28:10 -0700 Subject: [PATCH 5/7] docs: tabulate the lifecycle must-haves and hc verbs Reference tables replace the prose bullets: Level 1 lists the five required lifecycle tasks with meaning + authoring rules per row; Level 2 lists every standardized hc verb with what it does. Scenario naming, task authoring, environment, and gotchas sections unchanged. Co-Authored-By: Claude Fable 5 --- skills/pixi-workspace/SKILL.md | 72 ++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/skills/pixi-workspace/SKILL.md b/skills/pixi-workspace/SKILL.md index f07ffc0..953e181 100644 --- a/skills/pixi-workspace/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -12,15 +12,10 @@ public walkthrough in `Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`; the full RFC is preserved in this skill's introducing PR (Berkeley-Humanoids/Skills#1). -## The three levels - -1. **Lifecycle pixi tasks** — reserved names AND semantics, identical in - every workspace: `setup` (fetch sources; idempotent, cached), `build` - (default lane; chains `setup`), `test`, `clean` (wipe - `build/ install/ log/` only), `doctor` (health check). +1. **Lifecycle pixi tasks** — reserved names AND semantics, identical + in every workspace (table below). 2. **Product toolbox `hc`** — a packaged CLI on `PATH` - (`humanoid_control_cli`): `hc bus …`, `hc motor slider`, - `hc viz [viser|rerun]`, `hc viz urdf`, `hc calibrate`. + (`humanoid_control_cli`; table below). 3. **Scenario pixi tasks** — reserved names, workspace-defined scope: `sim`, `real`, `policy` (+ at most one qualifier). @@ -31,21 +26,62 @@ sibling-repo references. Needs root / mutates host state (CAN, kernel) → a `scripts/*.sh` run with explicit `sudo`, never a task. Rarely used → no alias; document the canonical `ros2 …` command. -## Scenario naming +## Level 1 — lifecycle tasks (must exist in every workspace) + +| Task | Meaning | Rules | +|---|---|---| +| `setup` | fetch/prepare sources beyond pixi itself (`vcs import`, fetch scripts) | idempotent and cached (canonical shape below); safe to re-run; chained by `build` | +| `build` | build the workspace's default lane with colcon | `depends-on = ["setup"]`; style flags come from `config/colcon-defaults.yaml`, only semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) appear inline | +| `test` | run the workspace's tests, linters excluded | `colcon test … --ctest-args -LE linter`; omit only if the workspace truly has no tests | +| `clean` | wipe the colcon overlay | exactly `rm -rf build install log`; never touches `src/` or `.pixi/` | +| `doctor` | workspace health check (`scripts/doctor.sh`) | checks: workspace root, env active, `/opt/ros` contamination (hard fail), sources imported, overlay built + sourced, `hc` on `PATH`, `ROS_DOMAIN_ID`; warnings for fixable, non-zero for fatal | + +Day-one ritual is one command: `pixi run build` (pixi self-heals the +env; `setup` is chained and cached), verified by `pixi run doctor`. + +Archetype-local extras are allowed (with descriptions), never required +of other workspaces — dev workspace: `build-all`, `test-result` +(singular, matches the colcon verb), `lint` (= `.githooks/pre-commit +--all`), `check` (= `test` + `lint`), `gen-dds`, `test-dds`; buildfarm +manifest: `setup` (hidden `_import` + `_overlay`), `package`, `publish` +— the packaging verb is `package`, never `build*`. + +## Level 2 — `hc` toolbox verbs (standardized, packaged) + +| Verb | What it does | +|---|---| +| `hc bus ping` | single-actuator GetDeviceId ping — no Enable, safe on a powered robot | +| `hc bus discover` | scan a CAN bus for Robstride device ids (read-only) | +| `hc bus probe` | link probe: RTT/jitter (inert) or +lumped delay (PRBS torque) | +| `hc bus probe-report` | RTT distribution + per-DoF lumped delay + plots | +| `hc motor slider` | live MIT-mode slider GUI against one motor | +| `hc viz` | live state viewer of a running robot (`viewer:=viser` default, `viewer:=rerun`) | +| `hc viz viser` / `hc viz rerun` | the standalone live-viewer tools directly | +| `hc viz urdf` | static URDF/kinematic inspector (sliders + RViz), no robot needed | +| `hc calibrate` | calibration bringup; writes `calibration.yaml` | + +Every verb `execvp`s into the canonical `ros2 run` / `ros2 launch` +command, so signals and trailing args pass straight through. Bare `hc` +prints this menu. New invariant tool → new verb in +`humanoid_control_cli`, never a per-workspace task alias +(`robstride-ping`, `rerun-viz`, … are banned). + +## Level 3 — scenario naming - Grammar: `[-]`, kebab-case, **at most one qualifier**, encoding only the primary task variant. All secondary parameters stay ROS launch arguments: - Right: `pixi run sim-piano robot:=prime policy:=latest` - Wrong: `pixi run sim-prime-piano-latest` +- Reserved scenario words: `sim` (primary stack in simulation), `real` + (same, on hardware), `policy` (prepare + load the RL policy against a + running stack). - Unqualified = the workspace default (dev ws: Lite base bringup; a deployment ws: its full task stack — state the scope in the task `description`). -- Never `launch-*` / `deploy-*` prefixes. Never per-tool task aliases - duplicating `hc` (`robstride-ping`, `rerun-viz`, …). -- No task named `install`/`shell` (shadow pixi verbs) or `run`/`start` - (redundant next to the scenario vocabulary). The buildfarm packaging - verb is `package` — `build*` is reserved for colcon builds. +- Never `launch-*` / `deploy-*` prefixes. No task named + `install`/`shell` (shadow pixi verbs) or `run`/`start` (redundant + next to the scenario vocabulary). ## Task authoring @@ -86,8 +122,6 @@ fi - Colcon *style* flags (`--symlink-install`, compile-commands) go in `config/colcon-defaults.yaml` via `COLCON_DEFAULTS_FILE` in `[activation.env]`, so manual `colcon build` == `pixi run build`. - Semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) - stay visible in the task string. - `[activation.env]` always sets `RCUTILS_COLORIZED_OUTPUT=1` + the console format; deployment workspaces pin their robot's `ROS_DOMAIN_ID`, the dev workspace leaves it unpinned. @@ -97,8 +131,6 @@ fi environment; add features/environments only when dependencies genuinely diverge. - No rosdep, no apt — `pixi.toml` is the dependency source of truth. -- `doctor` checks: workspace root, env active, `/opt/ros` contamination - (hard fail), sources present, overlay built + sourced, `hc` on PATH. ## Gotchas (verified the hard way) @@ -106,7 +138,5 @@ fi location), never on `PATH`. To put a CLI on `PATH`, also install a shim via `data_files` `('bin', [...])` — colcon then emits a `path.sh` hook for the package. -- Day-one ritual is one command: `pixi run build` (pixi self-heals the - env; `setup` is chained and cached). Verify with `pixi run doctor`. -- README quickstarts lead with that ritual, then point at +- README quickstarts lead with the one-command ritual, then point at `pixi task list` and `hc help` instead of duplicating command tables. From 10475792ddc090498d4794cac39eb7352c139231 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 22:37:59 -0700 Subject: [PATCH 6/7] docs: wording pass on the skill (guideline framing, simplified intro) --- skills/pixi-workspace/SKILL.md | 47 ++++++++++++++-------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/skills/pixi-workspace/SKILL.md b/skills/pixi-workspace/SKILL.md index 953e181..48074fd 100644 --- a/skills/pixi-workspace/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -1,46 +1,37 @@ --- name: pixi-workspace -description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), the hc CLI, or any Berkeley Humanoids pixi+ROS2 workspace (humanoid_control_ws, *-Deployment repos, the buildfarm manifest). +description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), the hc CLI, or any Berkeley Humanoids pixi+ROS2 workspaces. --- -# Pixi workspace interface +# Pixi workspace guideline Every Berkeley Humanoids pixi workspace exposes the same three-level -command interface. Ratified 2026-07-05; durable rationale lives in the -dev tree's `AGENTS.md` ("Command interface (three levels)") and the -public walkthrough in `Humanoid-Control-Website/docs/how_to/use_pixi_tasks.md`; -the full RFC is preserved in this skill's introducing PR -(Berkeley-Humanoids/Skills#1). - -1. **Lifecycle pixi tasks** — reserved names AND semantics, identical - in every workspace (table below). -2. **Product toolbox `hc`** — a packaged CLI on `PATH` - (`humanoid_control_cli`; table below). -3. **Scenario pixi tasks** — reserved names, workspace-defined scope: - `sim`, `real`, `policy` (+ at most one qualifier). - -Sorting rule for new commands: **invariant meaning in every workspace → -`hc` verb; workspace-dependent meaning → workspace task**. `hc` carries -only the Lite product core + shared diagnostics — never Prime, piano, or -sibling-repo references. Needs root / mutates host state (CAN, kernel) → -a `scripts/*.sh` run with explicit `sudo`, never a task. Rarely used → -no alias; document the canonical `ros2 …` command. - -## Level 1 — lifecycle tasks (must exist in every workspace) +command interface. + +1. **General ros2-pixi tasks** - standardized set of procedures for every ROS2-pixi workspace. +2. **Product toolbox `hc`** - packaged CLI on `PATH` containing common robot utility helpers. +3. **Scenario pixi tasks** - common workspace-defined tasks: `sim`, `real`, `policy`, `viz` etc. + +Sorting rule for new commands: +invariant meaning in every workspace → `hc` verb. +workspace-dependent meaning → workspace task. +`hc` carries only the Lite product core + shared diagnostics. +Needs root / mutates host state (CAN, kernel) → a `scripts/*.sh` run with explicit `sudo`, never a task. +Rarely used → no alias; document the canonical `ros2 …` command. + +## Level 1 — generic tasks (exist in every workspace) | Task | Meaning | Rules | |---|---|---| | `setup` | fetch/prepare sources beyond pixi itself (`vcs import`, fetch scripts) | idempotent and cached (canonical shape below); safe to re-run; chained by `build` | -| `build` | build the workspace's default lane with colcon | `depends-on = ["setup"]`; style flags come from `config/colcon-defaults.yaml`, only semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) appear inline | +| `build` | build the workspace's default libraries with colcon | `depends-on = ["setup"]`; style flags come from `config/colcon-defaults.yaml`, only semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) appear inline | | `test` | run the workspace's tests, linters excluded | `colcon test … --ctest-args -LE linter`; omit only if the workspace truly has no tests | | `clean` | wipe the colcon overlay | exactly `rm -rf build install log`; never touches `src/` or `.pixi/` | | `doctor` | workspace health check (`scripts/doctor.sh`) | checks: workspace root, env active, `/opt/ros` contamination (hard fail), sources imported, overlay built + sourced, `hc` on `PATH`, `ROS_DOMAIN_ID`; warnings for fixable, non-zero for fatal | -Day-one ritual is one command: `pixi run build` (pixi self-heals the -env; `setup` is chained and cached), verified by `pixi run doctor`. +Common setup procedure is one command: `pixi run build` (pixi self-heals the env; `setup` is chained and cached), verified by `pixi run doctor`. -Archetype-local extras are allowed (with descriptions), never required -of other workspaces — dev workspace: `build-all`, `test-result` +Archetype-local extras are allowed (with descriptions), never required of other workspaces — dev workspace: `build-all`, `test-result` (singular, matches the colcon verb), `lint` (= `.githooks/pre-commit --all`), `check` (= `test` + `lint`), `gen-dds`, `test-dds`; buildfarm manifest: `setup` (hidden `_import` + `_overlay`), `package`, `publish` From e7570e4c4756d8538315969329b7d2978624be42 Mon Sep 17 00:00:00 2001 From: "-T.K.-" Date: Sun, 5 Jul 2026 23:56:58 -0700 Subject: [PATCH 7/7] =?UTF-8?q?docs:=20rev=202=20=E2=80=94=20dissolve=20th?= =?UTF-8?q?e=20hc=20CLI=20tier=20into=20workspace=20tasks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The packaged hc toolbox is retired: its verbs become ordinary workspace tasks (ping-bus/scan-bus/profile-bus, viz, calibrate), deploy-sim/ deploy-real are reserved for one-command bringup+policy, sim/real mean plant bringup only, and rarely-used tools (profile report, URDF inspector, motor slider) get no task — canonical commands documented instead. Co-Authored-By: Claude Fable 5 --- skills/pixi-workspace/SKILL.md | 152 ++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/skills/pixi-workspace/SKILL.md b/skills/pixi-workspace/SKILL.md index 48074fd..a277a41 100644 --- a/skills/pixi-workspace/SKILL.md +++ b/skills/pixi-workspace/SKILL.md @@ -1,25 +1,42 @@ --- name: pixi-workspace -description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), the hc CLI, or any Berkeley Humanoids pixi+ROS2 workspaces. +description: Use when creating, editing, or reviewing pixi.toml manifests, pixi tasks, workspace scripts (activate/doctor/canup), or any Berkeley Humanoids pixi+ROS2 workspaces. --- -# Pixi workspace guideline +# Pixi-ROS2 Workspace Guideline -Every Berkeley Humanoids pixi workspace exposes the same three-level -command interface. +Every Berkeley Humanoids pixi workspace exposes the same pixi task +interface: a universal maintenance core plus a reserved vocabulary for +the deployment and utility tasks each workspace defines. Tasks are thin +wrappers over canonical commands (`ros2 launch/run`, `colcon`), never a +replacement layer; everything keeps working verbatim inside `pixi shell`. -1. **General ros2-pixi tasks** - standardized set of procedures for every ROS2-pixi workspace. -2. **Product toolbox `hc`** - packaged CLI on `PATH` containing common robot utility helpers. -3. **Scenario pixi tasks** - common workspace-defined tasks: `sim`, `real`, `policy`, `viz` etc. +## General Guideline -Sorting rule for new commands: -invariant meaning in every workspace → `hc` verb. -workspace-dependent meaning → workspace task. -`hc` carries only the Lite product core + shared diagnostics. -Needs root / mutates host state (CAN, kernel) → a `scripts/*.sh` run with explicit `sudo`, never a task. -Rarely used → no alias; document the canonical `ros2 …` command. - -## Level 1 — generic tasks (exist in every workspace) +- Every task carries `description = "…"`: `pixi task list` is the menu. + `_`-prefixed tasks are hidden plumbing. +- Launch-wrapping tasks are arg-less command strings so trailing + `key:=value` forwards verbatim. Don't use typed `args` on them. +- **No deployment or utility task may auto-build** — a hardware bringup + must never trigger a surprise rebuild. Only `build` chains `setup`. + Display error message and provide guidance if we lack something. +- Where a new entry point goes (first rule that matches): + 1. operates on the workspace (fetch/build/verify) → maintenance task, + universal names only; + 2. everyday robot scenario or utility → workspace task (reserved + vocabulary where it applies, free kebab-case otherwise); + 3. needs root / mutates host state (CAN buses, kernel) → + `scripts/*.sh` run with explicit `sudo`, never a task; + 4. rarely used / one-shot → no task; document the canonical command + (`pixi run ros2 …` or `pixi shell` then `ros2 …`). +- Forbidden names: `install`/`shell` (shadow pixi verbs), `run`/`start` + (redundant next to the vocabulary), `launch-*` prefixes, colon + namespacing (`build:all`), same-name tasks in multiple environments. + +## Maintenance Tasks + +The universal core — every developer-facing workspace provides these +five, names **and** semantics reserved: | Task | Meaning | Rules | |---|---|---| @@ -27,61 +44,62 @@ Rarely used → no alias; document the canonical `ros2 …` command. | `build` | build the workspace's default libraries with colcon | `depends-on = ["setup"]`; style flags come from `config/colcon-defaults.yaml`, only semantic selection flags (`--packages-skip-regex`, `--packages-up-to`) appear inline | | `test` | run the workspace's tests, linters excluded | `colcon test … --ctest-args -LE linter`; omit only if the workspace truly has no tests | | `clean` | wipe the colcon overlay | exactly `rm -rf build install log`; never touches `src/` or `.pixi/` | -| `doctor` | workspace health check (`scripts/doctor.sh`) | checks: workspace root, env active, `/opt/ros` contamination (hard fail), sources imported, overlay built + sourced, `hc` on `PATH`, `ROS_DOMAIN_ID`; warnings for fixable, non-zero for fatal | +| `doctor` | workspace health check (`scripts/doctor.sh`) | checks: workspace root, env active, `/opt/ros` contamination (hard fail), sources imported, overlay built + sourced, `ROS_DOMAIN_ID`; warnings for fixable, non-zero for fatal | + +Day one is one command: `pixi run build` (pixi self-heals the env; +`setup` is chained and cached), verified by `pixi run doctor`. -Common setup procedure is one command: `pixi run build` (pixi self-heals the env; `setup` is chained and cached), verified by `pixi run doctor`. +Archetype-local extras are allowed (with descriptions), never required +of other workspaces — dev workspace: `build-all` (adds the +EtherCAT/Prime lane), `test-result` (singular, matches the colcon verb), +`lint` (the `.githooks` ament linter set), `check` (= `test` + `lint`), +`gen-dds`, `test-dds`; buildfarm manifest: `setup` (hidden `_import` + +`_overlay`), `package`, `publish` — the packaging verb is `package`, +never `build*`. -Archetype-local extras are allowed (with descriptions), never required of other workspaces — dev workspace: `build-all`, `test-result` -(singular, matches the colcon verb), `lint` (= `.githooks/pre-commit ---all`), `check` (= `test` + `lint`), `gen-dds`, `test-dds`; buildfarm -manifest: `setup` (hidden `_import` + `_overlay`), `package`, `publish` -— the packaging verb is `package`, never `build*`. +## Robot Deployment Tasks -## Level 2 — `hc` toolbox verbs (standardized, packaged) +Reserved names: a workspace that has the concept must use the name; the +stack each name brings up is the workspace's own call (state it in the +task `description`). -| Verb | What it does | +| Task | Meaning | |---|---| -| `hc bus ping` | single-actuator GetDeviceId ping — no Enable, safe on a powered robot | -| `hc bus discover` | scan a CAN bus for Robstride device ids (read-only) | -| `hc bus probe` | link probe: RTT/jitter (inert) or +lumped delay (PRBS torque) | -| `hc bus probe-report` | RTT distribution + per-DoF lumped delay + plots | -| `hc motor slider` | live MIT-mode slider GUI against one motor | -| `hc viz` | live state viewer of a running robot (`viewer:=viser` default, `viewer:=rerun`) | -| `hc viz viser` / `hc viz rerun` | the standalone live-viewer tools directly | -| `hc viz urdf` | static URDF/kinematic inspector (sliders + RViz), no robot needed | -| `hc calibrate` | calibration bringup; writes `calibration.yaml` | - -Every verb `execvp`s into the canonical `ros2 run` / `ros2 launch` -command, so signals and trailing args pass straight through. Bare `hc` -prints this menu. New invariant tool → new verb in -`humanoid_control_cli`, never a per-workspace task alias -(`robstride-ping`, `rerun-viz`, … are banned). - -## Level 3 — scenario naming +| `sim` / `sim-` | bring up the robot stack in simulation — environment only, no policy | +| `real` / `real-` | real hardware bringup (pass `hardware_config:=`, `calibration_file:=`) | +| `policy` / `policy-` | prepare + load the control policy against an already-running stack (pass `wandb_run_path:=` or `checkpoint_file:=`) | +| `deploy-sim` | one-command sim2sim deployment = bringup + policy in one (pass `wandb_run_path:=` or `checkpoint_file:=`) | +| `deploy-real` | one-command real deployment = hardware bringup + policy in one (pass `wandb_run_path:=` / `checkpoint_file:=`, `hardware_config:=`, `calibration_file:=`) | +| `viz` | live state viewer of a running robot (`viewer:=viser` default, optionally `viewer:=rerun`, `viewer:=rviz`) | +| `calibrate` | run calibration procedure; writes `calibration.yaml` | - Grammar: `[-]`, kebab-case, **at most one qualifier**, encoding only the primary task variant. All secondary parameters stay ROS launch arguments: - - Right: `pixi run sim-piano robot:=prime policy:=latest` - - Wrong: `pixi run sim-prime-piano-latest` -- Reserved scenario words: `sim` (primary stack in simulation), `real` - (same, on hardware), `policy` (prepare + load the RL policy against a - running stack). -- Unqualified = the workspace default (dev ws: Lite base bringup; - a deployment ws: its full task stack — state the scope in the task - `description`). -- Never `launch-*` / `deploy-*` prefixes. No task named - `install`/`shell` (shadow pixi verbs) or `run`/`start` (redundant - next to the scenario vocabulary). - -## Task authoring - -- Every public task carries `description = "…"` — `pixi task list` is - the menu. `_` prefix hides plumbing tasks. -- Launch-wrapping tasks are arg-less command strings so trailing - `key:=value` forwards verbatim. Don't use typed `args` on them. -- **No scenario task or `hc` verb may auto-build** (a hardware bringup - must never trigger a surprise rebuild). Only `build` chains `setup`. + - Good: `pixi run sim-reach robot:=g1 policy:=latest` + - Bad: `pixi run sim-unitree-g1-reach-latest` +- Unqualified = the workspace's default target. +- `deploy-*` wraps a combined launch file — two blocking bringups can't + be chained with `depends-on`. + +## Debugging and Utility Tasks + +Free kebab-case, verb-first where natural; each is a one-line wrapper +over the canonical `ros2 run` command, so its meaning can't drift from +the tool it wraps. + +| Task | Meaning | +|---|---| +| `ping-bus` | single-actuator GetDeviceId ping — no Enable, safe on a powered robot | +| `scan-bus` | scan a CAN bus for Robstride device ids (read-only) | +| `profile-bus` | link probe: RTT/jitter (inert) or +lumped delay (PRBS torque) | + +Rarely-used companions (the profile report/plot generator, the static +URDF inspector, the MIT slider GUI) deliberately have **no** task — +document their canonical `ros2 run/launch` forms instead. + +## Environment + - The canonical `setup` shape (all three parts required — an uncached `vcs import` re-fetches every remote and fails offline; without `--skip-existing` it resets locally-checked-out branches to pins): @@ -94,8 +112,6 @@ outputs = ["build/.setup-stamp"] description = "Import third-party source deps — idempotent, cached on the .repos file" ``` -## Environment - - Overlay sourcing via a guarded activation script (POSIX `setup.sh`, not `setup.bash`), never a bare `install/setup.*` entry: @@ -126,8 +142,8 @@ fi ## Gotchas (verified the hard way) - ament_python console scripts install to `lib//` (`ros2 run` - location), never on `PATH`. To put a CLI on `PATH`, also install a - shim via `data_files` `('bin', [...])` — colcon then emits a `path.sh` - hook for the package. -- README quickstarts lead with the one-command ritual, then point at - `pixi task list` and `hc help` instead of duplicating command tables. + location), never on `PATH`. If a CLI ever needs to be on `PATH`, + also install a shim via `data_files` `('bin', [...])` — colcon then + emits a `path.sh` hook for the package. +- README quickstarts lead with the one-command tasks, then point at + `pixi task list` instead of duplicating command tables.