From c837082579a7f947a30b2be246bd01ae1853a673 Mon Sep 17 00:00:00 2001 From: wyattb Date: Sun, 11 Oct 2026 21:58:09 -0400 Subject: [PATCH 1/4] New workspace software/firmware/calypso/calypso-dev --- .../calypso-dev/.claude/settings.json | 5 +++ .../.claude/skills/ci-local/SKILL.md | 16 ++++++++ .../.claude/skills/journal/SKILL.md | 22 ++++++++++ .../.claude/skills/journal/scripts/capture.sh | 13 ++++++ .../.claude/skills/new-worktree/SKILL.md | 16 ++++++++ .../.claude/skills/setup-workspace/SKILL.md | 18 ++++++++ .../.claude/skills/sim-drive/SKILL.md | 11 +++++ .../.claude/skills/switch-workspace/SKILL.md | 20 +++++++++ .../.claude/skills/trace-signal/SKILL.md | 14 +++++++ .../workspaces/calypso-dev/.gitattributes | 2 + .../calypso-dev/.github/workflows/delphi.yml | 41 +++++++++++++++++++ .../calypso/workspaces/calypso-dev/CLAUDE.md | 12 ++++++ .../workspaces/calypso-dev/workspace.yml | 8 ++++ 13 files changed, 198 insertions(+) create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md create mode 100755 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.gitattributes create mode 100644 software/firmware/calypso/workspaces/calypso-dev/.github/workflows/delphi.yml create mode 100644 software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md create mode 100644 software/firmware/calypso/workspaces/calypso-dev/workspace.yml diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json b/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json new file mode 100644 index 0000000..772217f --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "attribution": { + "sessionUrl": false + } +} diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md new file mode 100644 index 0000000..66430ae --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md @@ -0,0 +1,16 @@ +--- +name: ci-local +description: Run Calypso's CI checks (build, test, fmt, clippy) locally, in a Linux container on macOS. Use before pushing or when CI fails. +--- + +In `W=worktrees/calypso/`: + +- Linux: `(cd $W && cargo build --all && cargo test --all && cargo fmt --all --check && cargo clippy --all -- -D warnings)`. +- macOS (the main crate needs socketcan), in the background, ~2 minutes: + ``` + (cd $W && docker run --rm -v "$PWD":/w -w /w -e CARGO_TARGET_DIR=/w/target-linux rust:latest bash -c \ + 'rustup component add clippy rustfmt >/dev/null 2>&1; set -e; cargo build --all; cargo test --all; cargo fmt --all --check; cargo clippy --all -- -D warnings') + ``` + Natively, `cargo test -p calypso-sim` works. + +Report where each step ran and any failing output. Fix clippy findings in code, not with `#[allow]`. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md new file mode 100644 index 0000000..a7d029b --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md @@ -0,0 +1,22 @@ +--- +name: journal +description: Capture rough notes locally with zero ceremony, then export them to their right permanent home. Use when the user wants to jot/park/stash a thought mid-task without derailing ("note to self", "remember to", "journal this"), or when they later want to export/file/route parked notes into an issue, spec, ADR, CONTEXT term, or docs. Capture is local and gitignored; export delegates to whichever existing skill owns the note's permanent home. +--- + +Notes live in `.journal/` at the workspace root (git-excluded, outside worktrees so they survive removal): an **entry** is one file, a **category** a subfolder. The journal only captures and routes; it never pushes, files, or contacts GitHub itself. + +**Capture** (from anywhere; no git, no other skills): + +``` +bash /.claude/skills/journal/scripts/capture.sh [-c ] ["note text"] +``` + +Omit `-c` for a loose entry, omit the text for an empty one to edit. Report the path it prints. + +**Export** (only when asked): + +1. Read the entries and propose a grouping: one entry → one output, a category → one merged output, or one entry split across several. Let the user adjust. +2. For each output, pick the workspace skill whose description fits its permanent home (see CLAUDE.md and each skill's description), preferring an existing docs area; a new section always needs approval. +3. Show the destination and reshaped text and wait for approval. Nothing lands silently. +4. Delegate to that skill; it owns formatting, conventions, and any GitHub contact. +5. Ask whether to delete the exported entry (default: keep). diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh new file mode 100755 index 0000000..1a93667 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# capture.sh [-c ] [note text]: write a timestamped journal entry to .journal/[/] +# at the workspace root (adding /.journal/ to .git/info/exclude once) and print its path. An empty +# entry is created when no text is given. Never touches git history, GitHub, or other skills. +set -euo pipefail +root=$(cd "$(dirname "$0")/../../../.." && pwd) && dir=$root/.journal +[ "${1:-}" = -c ] && dir=$dir/${2:?usage: capture.sh [-c ] [note text]} && shift 2 +exclude=$(git -C "$root" rev-parse --path-format=absolute --git-path info/exclude 2>/dev/null || true) +[ -z "$exclude" ] || grep -qxF /.journal/ "$exclude" 2>/dev/null || { mkdir -p "${exclude%/*}" && echo /.journal/ >>"$exclude"; } +mkdir -p "$dir" +file=$dir/$(date +%Y-%m-%d-%H%M%S).md +{ echo ""; [ $# -eq 0 ] || echo "$*"; } >"$file" +echo "$file" diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md new file mode 100644 index 0000000..bdf76e8 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md @@ -0,0 +1,16 @@ +--- +name: new-worktree +description: Create or reuse a worktree for a branch of a code repo (worktrees//). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees. +--- + +`repos/` is a bare store (no files); every checkout of a code repo is a worktree under `worktrees//`. `.delphi/setup.sh` makes the default branch's (`worktrees///`); keep it a clean reference: fetch and fast-forward only. Make every other branch with this script, never by switching branches in an existing worktree, unless the user explicitly says not to use worktrees. + +Run from the workspace root: + +``` +bash .delphi/new-worktree.sh [] +``` + +An existing branch (local or on origin, e.g. a PR's head) is checked out; anything else is created from `` (default: the repo's default branch). It's safe to re-run. It prints the worktree path: `cd` there and do all work in it. + +After the branch merges, remove it with `git -C repos/ worktree remove ../../worktrees//`. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md new file mode 100644 index 0000000..881db38 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md @@ -0,0 +1,18 @@ +--- +name: setup-workspace +description: Change what this workspace checks out and re-run its setup. workspace.yml lists code repos (repos:), read-only dependency sources (references-git:), and read-only copies of other Delphi workspaces or main (workspaces:). Use when the user wants to read or compare another workspace's or main's instructions, skills, or docs (link it), add or remove a repo or dependency reference, or run setup after cloning or pulling. +--- + +`workspace.yml` at the workspace root lists what `.delphi/setup.sh` checks out, all git-ignored: code repos (`repos:`), dependency sources (`references-git:`), and other Delphi workspaces or main (`workspaces:`, entries `- ws/` or `- main`; a workspace's name is its place in the tree, like `software/application-software/argos/argos-dev`). The comment on each section gives its entry format and where it lands; read it, then edit the file. + +Run from the workspace root after any change, and to refresh references and workspace copies to their latest: + +``` +bash .delphi/setup.sh +``` + +- The copies under `linked/` are for reading: never edit, branch, or push them. To change one of those workspaces or main, switch to it (`switch-workspace` skill). +- This workspace's project folder (shared context, `AUTHORING.md`, `defaults/`) is `linked/main/` plus this workspace's name without its last part: for `software/application-software/argos/argos-dev`, `linked/main/software/application-software/argos/`. List workspaces: `git branch -r --list 'origin/ws/*'`. +- `workspace.yml` is shared: change it on a branch and open a PR into `ws/` (the `name:` in `workspace.yml`). For a one-off look, add the entry, run setup, then `git restore workspace.yml`. +- Setup never deletes what you'd lose. A removed entry's `linked//`, `references//`, or repo store and worktrees stay until you delete them (ask first). +- When Delphi releases a version that needs cleanup in clones, setup runs its migration first (`.delphi/migrations/`), once per workspace. A migration removes only what nothing is lost from, and otherwise stops setup with what to do: tell the user, do it with their go-ahead, and re-run. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md new file mode 100644 index 0000000..9818ae0 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md @@ -0,0 +1,11 @@ +--- +name: sim-drive +description: Run calypso-sim against a Siren (Zenoh or MQTT), drive it, and verify what arrives on the wire. Use to reproduce a UI state, feed a consumer, or test a sim change. +--- + +Read the worktree's `calypso-sim/README.md` first; run with `(cd worktrees/calypso/ && cargo run -q -p calypso-sim -- )`. + +1. **Siren:** a running Argos stack (`:7447` Zenoh, `:1883` MQTT) is someone's; ask before publishing into it. Otherwise start your own: `mosquitto -p 18833 &` (`-u localhost:18833`), or `docker run -d --rm --name sim-zenohd -p 17447:7447 eclipse/zenoh` with `--zenoh --zenoh-conf` pointing at `{mode:"client", connect:{endpoints:["tcp/127.0.0.1:17447"]}, scouting:{multicast:{enabled:false}}}`. +2. **Drive:** `--mock` (heartbeat, filter with `--enable-topic REGEX`), `--key-map FILE --play ACTION` (replay), or `--stream --mock` (JSON-RPC on stdin: `publish`, `set_filter`, `add_topic`, ...). +3. **Verify on the wire:** `mosquitto_sub -p 18833 -t '' -F '%U %t'`, or a Python `eclipse-zenoh` subscriber. Rate ≈ `1000 / sim_freq` Hz. +4. Stop what you started. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md new file mode 100644 index 0000000..412016f --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md @@ -0,0 +1,20 @@ +--- +name: switch-workspace +description: Switch this clone to another Delphi workspace, or to Delphi's main, to work in it. Use when the user wants to check out, switch to, open, or work in another workspace or project, or to change another workspace's or main's files. +--- + +Run from the workspace root: + +``` +bash .delphi/switch.sh # ws/: its place in the tree, e.g. software/application-software/argos/argos-dev +bash .delphi/switch.sh argos-dev # its last part alone, if only one workspace ends in it +bash .delphi/switch.sh main # Delphi's main: project folders, templates, CI +``` + +- List workspaces: `git branch -r --list 'origin/ws/*'`. A workspace's name is its folder path on main without `workspaces/`. +- It refuses while tracked files have changes: commit them on a branch (and PR them) first. Then it fetches, switches, fast-forwards, and runs the new workspace's `.delphi/setup.sh`. +- The post-checkout hook parks this workspace's `repos/`, `worktrees/`, `references/` and `linked/` in `.delphi/parked//` (git-ignored; `` as in its `workspace.yml`) and brings the other's back at the same paths, so worktrees and the work in them return as they were. Switch back the same way. Never run `git clean -X` or `git stash --all` at the workspace root: they take ignored files, parked work included. +- Before switching, stop anything running from `worktrees/` (dev servers, Docker builds): its folder moves. +- This session keeps the old workspace's `CLAUDE.md` and skills. After switching, tell the user to restart Claude Code in the same folder, and don't start work in the new workspace until they have. +- To change the workspace you switched to: `git switch -c `, commit, push, and open a PR into `ws/` (or `main`). +- To only read another workspace or main without leaving this one, list it under `workspaces:` instead (`setup-workspace` skill). diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md new file mode 100644 index 0000000..3c10d33 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md @@ -0,0 +1,14 @@ +--- +name: trace-signal +description: Trace a CAN message or telemetry topic through Calypso (spec → codegen → decode/encode → Siren) and explain why it is or isn't published or simulated. Use for "where does topic X come from", "why don't I see X", or "can this reach the car". +--- + +Answer from the worktree's code and spec, citing `file:line`: + +1. **Spec:** `grep -rn '' Odyssey-Definitions/can-messages/`: the message `id`, `fields` (topics), point `sim` blocks, message `sim_freq`. +2. **Codegen:** `build.rs` → `libs/calypso-cangen/src/` (`validate.rs`, `can_gen_{decode,encode,simulate}.rs`). +3. **Decode:** `src/main.rs` (`DECODE_FUNCTION_MAP`) → `mqtt_handler.rs` or `zenoh_handler.rs`. +4. **Encode:** only `Calypso/Bidir/Command/…` with a `CommandData` payload, and only with `-e`. Nothing else reaches CAN. +5. **Sim:** only messages with `sim_freq` (a period in ms) are simulated; `calypso-sim --list-topics` shows which. + +Report the chain and any break in it. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.gitattributes b/software/firmware/calypso/workspaces/calypso-dev/.gitattributes new file mode 100644 index 0000000..4965641 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.gitattributes @@ -0,0 +1,2 @@ +# LF everywhere, so .delphi/setup.sh runs in Git Bash even with core.autocrlf=true +* text=auto eol=lf diff --git a/software/firmware/calypso/workspaces/calypso-dev/.github/workflows/delphi.yml b/software/firmware/calypso/workspaces/calypso-dev/.github/workflows/delphi.yml new file mode 100644 index 0000000..b8ffdd9 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.github/workflows/delphi.yml @@ -0,0 +1,41 @@ +# Delphi CI (docs/design.md). This file is at main's root and, identically, at the root of every +# ws/ (GitHub runs a push's workflow from the pushed commit, so ws pushes need their own copy). +# PRs to main: ci/check.sh, against main (so released versions stay as they are). Pushes to main or +# ws/**: ci/sync.sh (refresh + propose), always run from main. Pushes and PRs made with GITHUB_TOKEN +# trigger no workflows: no loops, and CI-opened PRs don't run `check` (sync.sh runs it itself). +name: delphi +on: + pull_request: + branches: [main] + push: + branches: [main, 'ws/**'] +permissions: + contents: read +jobs: + check: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + - run: ci/check.sh . origin/main + sync: + if: github.event_name == 'push' + runs-on: ubuntu-latest + concurrency: delphi-sync + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + - env: + GH_TOKEN: ${{ github.token }} + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' + ci/sync.sh diff --git a/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md b/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md new file mode 100644 index 0000000..84bc2e3 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md @@ -0,0 +1,12 @@ +# Delphi workspace + +You're in Delphi workspace `software/firmware/calypso/calypso-dev` (branch `ws/software/firmware/calypso/calypso-dev`); code repos are checked out as worktrees under `worktrees//` (`.delphi/setup.sh` makes the default branch's). Make new branches as worktrees (`new-worktree` skill) unless the user says not to. Read-only dependency sources from `references-git:` are checked out under `references//` at the version the workspace pins: read them to learn how a dependency behaves (prefer them over web docs), and never edit, branch, or push them. Delphi workspaces (or `main`) under `workspaces:` in `workspace.yml` (`- ws/`, a workspace's place in the tree, or `- main`) are read-only copies at `linked//` for reading their context; change what's checked out with the `setup-workspace` skill. To work in another workspace, switch this clone to it (`switch-workspace` skill). Park rough notes with the `journal` skill. Work here unless the task clearly belongs to another project. + +# Calypso + +CAN ↔ telemetry bridge for NER's Odyssey car (Rust). Decodes CAN into protobuf `ServerData` published per topic to Siren (MQTT, or Zenoh with `-z`); encodes `CommandData` on `Calypso/Bidir/Command/#` back to CAN. The CAN spec is JSON in the `Odyssey-Definitions` submodule. `calypso-sim` publishes simulated `ServerData`; its `README.md` is the source of truth for its flags. + +- `worktrees/calypso/Develop/` mirrors `Develop` (capital D): run things there, never edit or commit. Make branches with `new-worktree` from `origin/Develop`, then `git -C worktrees/calypso/ submodule update --init --recursive`. +- Branches `{issue}-{kebab-title}`; commits `#{issue} - {description}`; draft PRs into `Develop`. +- Check with `ci-local` (bare `cargo test` skips workspace members; on macOS the main crate doesn't compile). +- On macOS, `develop` (a stale branch) can collide with `Develop` in `repos/calypso`. If `worktrees/calypso/Develop` isn't at GitHub's `Develop`: `git -C repos/calypso config --add remote.origin.fetch '^refs/heads/develop'`, `git -C repos/calypso update-ref -d refs/remotes/origin/Develop`, `git -C repos/calypso fetch origin`, `git -C worktrees/calypso/Develop reset --hard origin/Develop`. diff --git a/software/firmware/calypso/workspaces/calypso-dev/workspace.yml b/software/firmware/calypso/workspaces/calypso-dev/workspace.yml new file mode 100644 index 0000000..e7b7778 --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/workspace.yml @@ -0,0 +1,8 @@ +name: software/firmware/calypso/calypso-dev # its place in the tree, the folder path without workspaces/ (branch ws/); checkouts park and restore repos/ by it +harness: claude-code +plugins: # `- [.]`: plugin sets to enable; CI lists the `default` set of every folder above first and generates .claude/settings.json +# .delphi/setup.sh checks out everything below (git-ignored); re-run it after any change. +repos: # `: `: code you change; bare store at repos/, default branch at worktrees// + calypso: https://github.com/Northeastern-Electric-Racing/Calypso.git +workspaces: # `- ws/` or `- main`: Delphi workspaces to read, never edit; shallow copy at linked/ + - main From c8ccf38f1d7801bc077b3b083ded230630706bf9 Mon Sep 17 00:00:00 2001 From: wyattb Date: Sun, 11 Oct 2026 22:29:59 -0400 Subject: [PATCH 2/4] Calypso skills: ci-local runs scripts/ci.sh (builds into the ignored target/linux); trace-signal and sim-drive trimmed --- .../.claude/skills/ci-local/SKILL.md | 14 +++----------- .../.claude/skills/ci-local/scripts/ci.sh | 19 +++++++++++++++++++ .../.claude/skills/sim-drive/SKILL.md | 12 +++++++----- .../.claude/skills/trace-signal/SKILL.md | 12 ++++++------ 4 files changed, 35 insertions(+), 22 deletions(-) create mode 100755 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/scripts/ci.sh diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md index 66430ae..58ea84c 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/SKILL.md @@ -1,16 +1,8 @@ --- name: ci-local -description: Run Calypso's CI checks (build, test, fmt, clippy) locally, in a Linux container on macOS. Use before pushing or when CI fails. +description: Run Calypso's CI checks (build, test, fmt, clippy) locally. Use before pushing or when CI fails. --- -In `W=worktrees/calypso/`: +`bash scripts/ci.sh ` runs `rust-ci.yml`'s checks in `worktrees/calypso/`: natively on Linux, in Docker on macOS (~2 min; run it in the background). On macOS, `cargo test -p calypso-sim` also works natively for a fast loop. -- Linux: `(cd $W && cargo build --all && cargo test --all && cargo fmt --all --check && cargo clippy --all -- -D warnings)`. -- macOS (the main crate needs socketcan), in the background, ~2 minutes: - ``` - (cd $W && docker run --rm -v "$PWD":/w -w /w -e CARGO_TARGET_DIR=/w/target-linux rust:latest bash -c \ - 'rustup component add clippy rustfmt >/dev/null 2>&1; set -e; cargo build --all; cargo test --all; cargo fmt --all --check; cargo clippy --all -- -D warnings') - ``` - Natively, `cargo test -p calypso-sim` works. - -Report where each step ran and any failing output. Fix clippy findings in code, not with `#[allow]`. +Report the failing step's output. Fix clippy findings in code, not with `#[allow]`. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/scripts/ci.sh b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/scripts/ci.sh new file mode 100755 index 0000000..d29d18a --- /dev/null +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/ci-local/scripts/ci.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# ci.sh : run rust-ci.yml's checks (build, test, fmt, clippy; all --all) in +# worktrees/calypso/, stopping at the first failure. Natively on Linux; on macOS in a +# rust:latest container (the main crate needs socketcan), building into the git-ignored target/linux. +set -euo pipefail +branch=${1:?usage: ci.sh } +# shellcheck source=/dev/null +. "${DELPHI_ROOT:?unset: start the session at the workspace root, on Delphi 0.2.0+ (pull its ws/ branch), or source /.delphi/paths.sh}/.delphi/paths.sh" +w=$DELPHI_WORKTREES/calypso/$branch +[ -d "$w" ] || { echo "no worktree at $w; make it with new-worktree" >&2; exit 2; } +[ -n "$(ls -A "$w/Odyssey-Definitions" 2>/dev/null)" ] || { echo "run: git -C $w submodule update --init --recursive" >&2; exit 2; } +# shellcheck disable=SC2016 +steps='set -e; for s in "build --all" "test --all" "fmt --all --check" "clippy --all -- -D warnings"; do echo "== cargo $s"; cargo $s; done' +if [ "$(uname -s)" = Linux ]; then + (cd "$w" && bash -c "$steps") +else + docker run --rm -v "$w":/w -w /w -e CARGO_TARGET_DIR=/w/target/linux rust:latest \ + bash -c "rustup component add clippy rustfmt >/dev/null 2>&1; $steps" +fi diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md index 9818ae0..0c8e622 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/sim-drive/SKILL.md @@ -1,11 +1,13 @@ --- name: sim-drive -description: Run calypso-sim against a Siren (Zenoh or MQTT), drive it, and verify what arrives on the wire. Use to reproduce a UI state, feed a consumer, or test a sim change. +description: Run calypso-sim against a private Siren and check what arrives on the wire. Use to test a sim change or feed a consumer. --- -Read the worktree's `calypso-sim/README.md` first; run with `(cd worktrees/calypso/ && cargo run -q -p calypso-sim -- )`. +Modes and flags are in `worktrees/calypso//calypso-sim/README.md`. The sim defaults to MQTT on `localhost:1883`, which may be someone's running Argos stack (`:1883` MQTT, `:7447` Zenoh): ask before publishing there. -1. **Siren:** a running Argos stack (`:7447` Zenoh, `:1883` MQTT) is someone's; ask before publishing into it. Otherwise start your own: `mosquitto -p 18833 &` (`-u localhost:18833`), or `docker run -d --rm --name sim-zenohd -p 17447:7447 eclipse/zenoh` with `--zenoh --zenoh-conf` pointing at `{mode:"client", connect:{endpoints:["tcp/127.0.0.1:17447"]}, scouting:{multicast:{enabled:false}}}`. -2. **Drive:** `--mock` (heartbeat, filter with `--enable-topic REGEX`), `--key-map FILE --play ACTION` (replay), or `--stream --mock` (JSON-RPC on stdin: `publish`, `set_filter`, `add_topic`, ...). -3. **Verify on the wire:** `mosquitto_sub -p 18833 -t '' -F '%U %t'`, or a Python `eclipse-zenoh` subscriber. Rate ≈ `1000 / sim_freq` Hz. +1. Start your own broker in the background: `mosquitto -p 18833`. +2. Run: `(cd worktrees/calypso/ && cargo run -q -p calypso-sim -- -u localhost:18833 )`. +3. Check: `mosquitto_sub -p 18833 -t '' -F '%U %t'`; expect about `1000 / sim_freq` messages a second. 4. Stop what you started. + +For Zenoh, pass `--zenoh --zenoh-conf FILE` with multicast scouting off and a private router endpoint, or it joins whatever router is running. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md index 3c10d33..2e1e2d8 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/trace-signal/SKILL.md @@ -1,14 +1,14 @@ --- name: trace-signal -description: Trace a CAN message or telemetry topic through Calypso (spec → codegen → decode/encode → Siren) and explain why it is or isn't published or simulated. Use for "where does topic X come from", "why don't I see X", or "can this reach the car". +description: Trace a CAN message or topic through Calypso and explain why it is or isn't published, simulated, or sent to the car. Use for "where does topic X come from", "why don't I see X", or "can this reach the car". --- -Answer from the worktree's code and spec, citing `file:line`: +In `worktrees/calypso//`, cite `file:line` for each link: -1. **Spec:** `grep -rn '' Odyssey-Definitions/can-messages/`: the message `id`, `fields` (topics), point `sim` blocks, message `sim_freq`. -2. **Codegen:** `build.rs` → `libs/calypso-cangen/src/` (`validate.rs`, `can_gen_{decode,encode,simulate}.rs`). +1. **Spec:** `grep -rn '' Odyssey-Definitions/can-messages/`. Topic names can be templates (`BMS/PerCell/Alpha/{4}/Volts/{5}`), so grep an id or a prefix. +2. **Codegen:** `build.rs` → `libs/calypso-cangen/`. 3. **Decode:** `src/main.rs` (`DECODE_FUNCTION_MAP`) → `mqtt_handler.rs` or `zenoh_handler.rs`. -4. **Encode:** only `Calypso/Bidir/Command/…` with a `CommandData` payload, and only with `-e`. Nothing else reaches CAN. -5. **Sim:** only messages with `sim_freq` (a period in ms) are simulated; `calypso-sim --list-topics` shows which. +4. **Encode:** only `Calypso/Bidir/Command/…` with a `CommandData` payload, and only with `-e`. +5. **Sim:** only messages with `sim_freq` (a period in ms); `calypso-sim --list-topics` shows which. Report the chain and any break in it. From ab09275adf718b2e675d84e51062909c54f7b457 Mon Sep 17 00:00:00 2001 From: wyattb Date: Sun, 11 Oct 2026 22:50:58 -0400 Subject: [PATCH 3/4] Calypso workspace: develop is the default branch now --- software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md b/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md index 84bc2e3..bbfe2c8 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md +++ b/software/firmware/calypso/workspaces/calypso-dev/CLAUDE.md @@ -6,7 +6,7 @@ You're in Delphi workspace `software/firmware/calypso/calypso-dev` (branch `ws/s CAN ↔ telemetry bridge for NER's Odyssey car (Rust). Decodes CAN into protobuf `ServerData` published per topic to Siren (MQTT, or Zenoh with `-z`); encodes `CommandData` on `Calypso/Bidir/Command/#` back to CAN. The CAN spec is JSON in the `Odyssey-Definitions` submodule. `calypso-sim` publishes simulated `ServerData`; its `README.md` is the source of truth for its flags. -- `worktrees/calypso/Develop/` mirrors `Develop` (capital D): run things there, never edit or commit. Make branches with `new-worktree` from `origin/Develop`, then `git -C worktrees/calypso/ submodule update --init --recursive`. -- Branches `{issue}-{kebab-title}`; commits `#{issue} - {description}`; draft PRs into `Develop`. +- `worktrees/calypso/develop/` mirrors `develop`: run things there, never edit or commit. Make branches with `new-worktree` from `origin/develop`, then `git -C worktrees/calypso/ submodule update --init --recursive`. +- Branches `{issue}-{kebab-title}`; commits `#{issue} - {description}`; draft PRs into `develop`. - Check with `ci-local` (bare `cargo test` skips workspace members; on macOS the main crate doesn't compile). -- On macOS, `develop` (a stale branch) can collide with `Develop` in `repos/calypso`. If `worktrees/calypso/Develop` isn't at GitHub's `Develop`: `git -C repos/calypso config --add remote.origin.fetch '^refs/heads/develop'`, `git -C repos/calypso update-ref -d refs/remotes/origin/Develop`, `git -C repos/calypso fetch origin`, `git -C worktrees/calypso/Develop reset --hard origin/Develop`. +- On macOS, the old `Develop` branch (until it's deleted) can collide with `develop` in `repos/calypso`. If `worktrees/calypso/develop` isn't at GitHub's `develop`: `git -C repos/calypso config --add remote.origin.fetch '^refs/heads/Develop'`, `git -C repos/calypso update-ref -d refs/remotes/origin/develop`, `git -C repos/calypso fetch origin`, `git -C worktrees/calypso/develop reset --hard origin/develop`. From b12fe0391fe4cd214bd53b07192420373ef184e8 Mon Sep 17 00:00:00 2001 From: wyattb Date: Mon, 12 Oct 2026 23:41:34 -0400 Subject: [PATCH 4/4] Calypso workspace: the shared skills come from software/workspace-inherit/; the delphi plugin by default --- .../calypso-dev/.claude/settings.json | 24 +++++++++++++++++++ .../.claude/skills/journal/SKILL.md | 22 ----------------- .../.claude/skills/journal/scripts/capture.sh | 13 ---------- .../.claude/skills/new-worktree/SKILL.md | 16 ------------- .../.claude/skills/setup-workspace/SKILL.md | 18 -------------- .../.claude/skills/switch-workspace/SKILL.md | 20 ---------------- .../workspaces/calypso-dev/workspace.yml | 3 +++ 7 files changed, 27 insertions(+), 89 deletions(-) delete mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md delete mode 100755 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh delete mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md delete mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md delete mode 100644 software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json b/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json index 772217f..61c35f2 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json +++ b/software/firmware/calypso/workspaces/calypso-dev/.claude/settings.json @@ -1,5 +1,29 @@ { "attribution": { "sessionUrl": false + }, + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "bash \"$CLAUDE_PROJECT_DIR/.delphi/paths.sh\" >> \"$CLAUDE_ENV_FILE\"" + } + ] + } + ] + }, + "extraKnownMarketplaces": { + "delphi": { + "source": { + "source": "github", + "repo": "Northeastern-Electric-Racing/Delphi" + }, + "autoUpdate": true + } + }, + "enabledPlugins": { + "delphi@delphi": true } } diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md deleted file mode 100644 index a7d029b..0000000 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/SKILL.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: journal -description: Capture rough notes locally with zero ceremony, then export them to their right permanent home. Use when the user wants to jot/park/stash a thought mid-task without derailing ("note to self", "remember to", "journal this"), or when they later want to export/file/route parked notes into an issue, spec, ADR, CONTEXT term, or docs. Capture is local and gitignored; export delegates to whichever existing skill owns the note's permanent home. ---- - -Notes live in `.journal/` at the workspace root (git-excluded, outside worktrees so they survive removal): an **entry** is one file, a **category** a subfolder. The journal only captures and routes; it never pushes, files, or contacts GitHub itself. - -**Capture** (from anywhere; no git, no other skills): - -``` -bash /.claude/skills/journal/scripts/capture.sh [-c ] ["note text"] -``` - -Omit `-c` for a loose entry, omit the text for an empty one to edit. Report the path it prints. - -**Export** (only when asked): - -1. Read the entries and propose a grouping: one entry → one output, a category → one merged output, or one entry split across several. Let the user adjust. -2. For each output, pick the workspace skill whose description fits its permanent home (see CLAUDE.md and each skill's description), preferring an existing docs area; a new section always needs approval. -3. Show the destination and reshaped text and wait for approval. Nothing lands silently. -4. Delegate to that skill; it owns formatting, conventions, and any GitHub contact. -5. Ask whether to delete the exported entry (default: keep). diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh deleted file mode 100755 index 1a93667..0000000 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/journal/scripts/capture.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# capture.sh [-c ] [note text]: write a timestamped journal entry to .journal/[/] -# at the workspace root (adding /.journal/ to .git/info/exclude once) and print its path. An empty -# entry is created when no text is given. Never touches git history, GitHub, or other skills. -set -euo pipefail -root=$(cd "$(dirname "$0")/../../../.." && pwd) && dir=$root/.journal -[ "${1:-}" = -c ] && dir=$dir/${2:?usage: capture.sh [-c ] [note text]} && shift 2 -exclude=$(git -C "$root" rev-parse --path-format=absolute --git-path info/exclude 2>/dev/null || true) -[ -z "$exclude" ] || grep -qxF /.journal/ "$exclude" 2>/dev/null || { mkdir -p "${exclude%/*}" && echo /.journal/ >>"$exclude"; } -mkdir -p "$dir" -file=$dir/$(date +%Y-%m-%d-%H%M%S).md -{ echo ""; [ $# -eq 0 ] || echo "$*"; } >"$file" -echo "$file" diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md deleted file mode 100644 index bdf76e8..0000000 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/new-worktree/SKILL.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: new-worktree -description: Create or reuse a worktree for a branch of a code repo (worktrees//). Worktrees are the default way to make or check out any new branch; use this before starting a ticket, reviewing or fixing a PR branch, or any other branch work, unless the user says not to use worktrees. ---- - -`repos/` is a bare store (no files); every checkout of a code repo is a worktree under `worktrees//`. `.delphi/setup.sh` makes the default branch's (`worktrees///`); keep it a clean reference: fetch and fast-forward only. Make every other branch with this script, never by switching branches in an existing worktree, unless the user explicitly says not to use worktrees. - -Run from the workspace root: - -``` -bash .delphi/new-worktree.sh [] -``` - -An existing branch (local or on origin, e.g. a PR's head) is checked out; anything else is created from `` (default: the repo's default branch). It's safe to re-run. It prints the worktree path: `cd` there and do all work in it. - -After the branch merges, remove it with `git -C repos/ worktree remove ../../worktrees//`. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md deleted file mode 100644 index 881db38..0000000 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/setup-workspace/SKILL.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -name: setup-workspace -description: Change what this workspace checks out and re-run its setup. workspace.yml lists code repos (repos:), read-only dependency sources (references-git:), and read-only copies of other Delphi workspaces or main (workspaces:). Use when the user wants to read or compare another workspace's or main's instructions, skills, or docs (link it), add or remove a repo or dependency reference, or run setup after cloning or pulling. ---- - -`workspace.yml` at the workspace root lists what `.delphi/setup.sh` checks out, all git-ignored: code repos (`repos:`), dependency sources (`references-git:`), and other Delphi workspaces or main (`workspaces:`, entries `- ws/` or `- main`; a workspace's name is its place in the tree, like `software/application-software/argos/argos-dev`). The comment on each section gives its entry format and where it lands; read it, then edit the file. - -Run from the workspace root after any change, and to refresh references and workspace copies to their latest: - -``` -bash .delphi/setup.sh -``` - -- The copies under `linked/` are for reading: never edit, branch, or push them. To change one of those workspaces or main, switch to it (`switch-workspace` skill). -- This workspace's project folder (shared context, `AUTHORING.md`, `defaults/`) is `linked/main/` plus this workspace's name without its last part: for `software/application-software/argos/argos-dev`, `linked/main/software/application-software/argos/`. List workspaces: `git branch -r --list 'origin/ws/*'`. -- `workspace.yml` is shared: change it on a branch and open a PR into `ws/` (the `name:` in `workspace.yml`). For a one-off look, add the entry, run setup, then `git restore workspace.yml`. -- Setup never deletes what you'd lose. A removed entry's `linked//`, `references//`, or repo store and worktrees stay until you delete them (ask first). -- When Delphi releases a version that needs cleanup in clones, setup runs its migration first (`.delphi/migrations/`), once per workspace. A migration removes only what nothing is lost from, and otherwise stops setup with what to do: tell the user, do it with their go-ahead, and re-run. diff --git a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md b/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md deleted file mode 100644 index 412016f..0000000 --- a/software/firmware/calypso/workspaces/calypso-dev/.claude/skills/switch-workspace/SKILL.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: switch-workspace -description: Switch this clone to another Delphi workspace, or to Delphi's main, to work in it. Use when the user wants to check out, switch to, open, or work in another workspace or project, or to change another workspace's or main's files. ---- - -Run from the workspace root: - -``` -bash .delphi/switch.sh # ws/: its place in the tree, e.g. software/application-software/argos/argos-dev -bash .delphi/switch.sh argos-dev # its last part alone, if only one workspace ends in it -bash .delphi/switch.sh main # Delphi's main: project folders, templates, CI -``` - -- List workspaces: `git branch -r --list 'origin/ws/*'`. A workspace's name is its folder path on main without `workspaces/`. -- It refuses while tracked files have changes: commit them on a branch (and PR them) first. Then it fetches, switches, fast-forwards, and runs the new workspace's `.delphi/setup.sh`. -- The post-checkout hook parks this workspace's `repos/`, `worktrees/`, `references/` and `linked/` in `.delphi/parked//` (git-ignored; `` as in its `workspace.yml`) and brings the other's back at the same paths, so worktrees and the work in them return as they were. Switch back the same way. Never run `git clean -X` or `git stash --all` at the workspace root: they take ignored files, parked work included. -- Before switching, stop anything running from `worktrees/` (dev servers, Docker builds): its folder moves. -- This session keeps the old workspace's `CLAUDE.md` and skills. After switching, tell the user to restart Claude Code in the same folder, and don't start work in the new workspace until they have. -- To change the workspace you switched to: `git switch -c `, commit, push, and open a PR into `ws/` (or `main`). -- To only read another workspace or main without leaving this one, list it under `workspaces:` instead (`setup-workspace` skill). diff --git a/software/firmware/calypso/workspaces/calypso-dev/workspace.yml b/software/firmware/calypso/workspaces/calypso-dev/workspace.yml index e7b7778..ac4b871 100644 --- a/software/firmware/calypso/workspaces/calypso-dev/workspace.yml +++ b/software/firmware/calypso/workspaces/calypso-dev/workspace.yml @@ -1,6 +1,9 @@ name: software/firmware/calypso/calypso-dev # its place in the tree, the folder path without workspaces/ (branch ws/); checkouts park and restore repos/ by it harness: claude-code plugins: # `- [.]`: plugin sets to enable; CI lists the `default` set of every folder above first and generates .claude/settings.json + - delphi # default, from software/ +opt-out: # `- `: files from the workspace-inherit/ folders above that CI leaves alone here, so the workspace keeps its own copy (or none) + # - .claude/skills/journal # .delphi/setup.sh checks out everything below (git-ignored); re-run it after any change. repos: # `: `: code you change; bare store at repos/, default branch at worktrees// calypso: https://github.com/Northeastern-Electric-Racing/Calypso.git