summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-09-05 00:17:48 +0700
committerGitHub <[email protected]>2026-09-05 00:17:48 +0700
commit91127e108c7a948be5bbf93be9655454fcc0bcb9 (patch)
tree76e4af4f6b1958f4799c5a3373125eddd23dbded
parent29851564af08cb4909175315d20c71f5eca13040 (diff)
parent9a22ec66115d43d94e22e08909b04952958076f4 (diff)
Merge pull request #3884 from hathach/claude/codex-collaborationHEADmaster
Share Claude harness with Codex
l---------.agents1
-rw-r--r--.claude/skills/pre-pr/SKILL.md4
-rw-r--r--.claude/skills/read-doc/SKILL.md14
-rw-r--r--.codex/agents/builder.toml7
-rw-r--r--.codex/agents/code-verifier.toml7
-rw-r--r--.codex/agents/code-writer.toml7
-rw-r--r--.codex/agents/hil-operator.toml7
-rw-r--r--.codex/agents/pr-ci-watcher.toml7
-rw-r--r--.codex/agents/pr-review-validator.toml7
-rw-r--r--.codex/agents/static-analyzer.toml7
-rw-r--r--.codex/agents/target-debugger.toml7
-rw-r--r--CLAUDE.md10
-rw-r--r--docs/superpowers/plans/2026-09-04-claude-codex-collaboration.md178
-rw-r--r--docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md2
-rw-r--r--docs/superpowers/specs/2026-09-04-claude-codex-collaboration-design.md95
-rw-r--r--docs/superpowers/specs/2026-09-04-neutral-skill-wording-design.md32
-rw-r--r--test/hil/test/test_ci_select.py7
-rwxr-xr-xtools/ci_select.py4
18 files changed, 390 insertions, 13 deletions
diff --git a/.agents b/.agents
new file mode 120000
index 000000000..c8161850a
--- /dev/null
+++ b/.agents
@@ -0,0 +1 @@
+.claude \ No newline at end of file
diff --git a/.claude/skills/pre-pr/SKILL.md b/.claude/skills/pre-pr/SKILL.md
index 8e5c408a6..56db5a5dd 100644
--- a/.claude/skills/pre-pr/SKILL.md
+++ b/.claude/skills/pre-pr/SKILL.md
@@ -3,7 +3,7 @@ name: pre-pr
description: Use before opening or updating a TinyUSB PR — derives affected boards from the branch diff, runs the full-check workflow (software validation + optional HIL on the rig), and summarizes a ship/no-ship verdict.
---
-# /pre-pr — pre-PR validation
+# Pre-PR validation
Run the software + hardware gate for the current branch. The user invoking this skill is the opt-in for launching the workflows below.
@@ -52,6 +52,6 @@ Invoke the Workflow tool:
## 5. Summarize
- Per-stage table: unit / build:<board> / size / pvs, then HIL per board — pass/fail with the first error for each failure.
-- If the hardware result has non-empty `locked` (a CI job held those boards): ask the user with AskUserQuestion — **Force now** (re-invoke `hil-validate` with `force: true` for those boards; user accepts the risk of colliding with a mid-test CI job), **Keep waiting** (re-invoke `hil-validate` for them after a few minutes; ask again if still locked), or **Accept** the partial verdict. Never force without the user's answer.
+- If the hardware result has non-empty `locked` (a CI job held those boards): ask the user to choose **Force now** (re-invoke `hil-validate` with `force: true` for those boards; user accepts the risk of colliding with a mid-test CI job), **Keep waiting** (re-invoke `hil-validate` for them after a few minutes; ask again if still locked), or **Accept** the partial verdict. Never force without the user's answer.
- Wedged boards: point at `.claude/skills/usb-kernel-recover/SKILL.md`.
- End with a clear ship / no-ship verdict and what to fix first.
diff --git a/.claude/skills/read-doc/SKILL.md b/.claude/skills/read-doc/SKILL.md
index feaa914af..aca30fb8c 100644
--- a/.claude/skills/read-doc/SKILL.md
+++ b/.claude/skills/read-doc/SKILL.md
@@ -40,7 +40,7 @@ Not for general concepts, repo/code questions, or when no such doc is likely.
## Find
-Keywords from `/read-doc <keywords>`, else derived from the question (part
+Keywords supplied as skill arguments, else derived from the question (part
number, peripheral, spec name). `search.py` ANDs them across every metadata
field and prints the best matches first — at most 40, and the header says when
more matched:
@@ -53,7 +53,7 @@ python3 .claude/skills/read-doc/search.py RT1060 RT1064 --any
Exit 0 matched, 1 nothing matched, 2 bad usage or no library — 2 means the
search never ran, so fix the invocation instead of broadening.
-One match → read it. Several → list and ask via AskUserQuestion. Nothing
+One match → read it. Several → list them and ask the user which to read. Nothing
(exit 1) → retry with fewer keywords; the part number alone often works where
`<part> datasheet` does not, because words like "datasheet" and "manual" are
rarely in the metadata. `--any` only changes anything with two or more
@@ -66,11 +66,11 @@ Set `CALIBRE_LIBRARY` to search a library elsewhere.
`search.py` prints one `FORMAT path` line per stored file:
-- **PDF** — Read with `pages`; for >10 pages start `pages: "1-20"` (TOC/overview),
- report the page count, then read sections on demand.
-- **Any other format** (EPUB, MOBI, CHM, ZIP…) — Read has no decoder for these
- and returns mojibake rather than an error. Say the document is not in a
- readable format; do not paste what Read returned.
+- **PDF** — use the runtime's PDF-reading capability with page ranges; for >10
+ pages start with pages 1-20 (TOC/overview), report the page count, then read
+ sections on demand.
+- **Any other format** (EPUB, MOBI, CHM, ZIP…) — if the runtime has no decoder,
+ say the document is not in a readable format; do not paste mojibake.
- **`MISSING`** — the metadata is real but the file is not on disk (library
mid-sync, or the file was deleted). Report the file as unavailable, not the
document as nonexistent.
diff --git a/.codex/agents/builder.toml b/.codex/agents/builder.toml
new file mode 100644
index 000000000..ed856c2d5
--- /dev/null
+++ b/.codex/agents/builder.toml
@@ -0,0 +1,7 @@
+name = "builder"
+description = "Load the canonical builder agent from .claude/agents/builder.md."
+model = "gpt-5.6-luna"
+model_reasoning_effort = "low"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/builder.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/code-verifier.toml b/.codex/agents/code-verifier.toml
new file mode 100644
index 000000000..1a3965594
--- /dev/null
+++ b/.codex/agents/code-verifier.toml
@@ -0,0 +1,7 @@
+name = "code-verifier"
+description = "Load the canonical code-verifier agent from .claude/agents/code-verifier.md."
+model = "gpt-5.6-sol"
+model_reasoning_effort = "xhigh"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/code-verifier.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/code-writer.toml b/.codex/agents/code-writer.toml
new file mode 100644
index 000000000..d63a7e863
--- /dev/null
+++ b/.codex/agents/code-writer.toml
@@ -0,0 +1,7 @@
+name = "code-writer"
+description = "Load the canonical code-writer agent from .claude/agents/code-writer.md."
+model = "gpt-5.6-sol"
+model_reasoning_effort = "xhigh"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/code-writer.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/hil-operator.toml b/.codex/agents/hil-operator.toml
new file mode 100644
index 000000000..efdf5cc49
--- /dev/null
+++ b/.codex/agents/hil-operator.toml
@@ -0,0 +1,7 @@
+name = "hil-operator"
+description = "Load the canonical hil-operator agent from .claude/agents/hil-operator.md."
+model = "gpt-5.6-terra"
+model_reasoning_effort = "high"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/hil-operator.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/pr-ci-watcher.toml b/.codex/agents/pr-ci-watcher.toml
new file mode 100644
index 000000000..212dd7ad1
--- /dev/null
+++ b/.codex/agents/pr-ci-watcher.toml
@@ -0,0 +1,7 @@
+name = "pr-ci-watcher"
+description = "Load the canonical pr-ci-watcher agent from .claude/agents/pr-ci-watcher.md."
+model = "gpt-5.6-terra"
+model_reasoning_effort = "high"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/pr-ci-watcher.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/pr-review-validator.toml b/.codex/agents/pr-review-validator.toml
new file mode 100644
index 000000000..eb0a3be6a
--- /dev/null
+++ b/.codex/agents/pr-review-validator.toml
@@ -0,0 +1,7 @@
+name = "pr-review-validator"
+description = "Load the canonical pr-review-validator agent from .claude/agents/pr-review-validator.md."
+model = "gpt-5.6-sol"
+model_reasoning_effort = "xhigh"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/pr-review-validator.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/static-analyzer.toml b/.codex/agents/static-analyzer.toml
new file mode 100644
index 000000000..ad98a9772
--- /dev/null
+++ b/.codex/agents/static-analyzer.toml
@@ -0,0 +1,7 @@
+name = "static-analyzer"
+description = "Load the canonical static-analyzer agent from .claude/agents/static-analyzer.md."
+model = "gpt-5.6-terra"
+model_reasoning_effort = "medium"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/static-analyzer.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/.codex/agents/target-debugger.toml b/.codex/agents/target-debugger.toml
new file mode 100644
index 000000000..78cd06a3e
--- /dev/null
+++ b/.codex/agents/target-debugger.toml
@@ -0,0 +1,7 @@
+name = "target-debugger"
+description = "Load the canonical target-debugger agent from .claude/agents/target-debugger.md."
+model = "gpt-5.6-sol"
+model_reasoning_effort = "xhigh"
+developer_instructions = """
+Before acting, locate the repository root with `git rev-parse --show-toplevel`, then read `.claude/agents/target-debugger.md` from that root completely and follow its body as your role instructions. Ignore its Claude-specific YAML frontmatter.
+"""
diff --git a/CLAUDE.md b/CLAUDE.md
index f7ffb305b..7a55aabb0 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -14,6 +14,16 @@ Bias toward caution over speed. For trivial tasks, use judgment.
- **Goal-driven** — turn tasks into verifiable goals ("write failing test, make it pass"). For multi-step work, state a brief `step → verify` plan.
- **Worktrees** — default to a git worktree for any branch or multi-step work; never switch the shared primary checkout's branch. Sessions run concurrently: switching the primary checkout mid-flight disrupts other sessions and can silently point a review, build, or commit at the wrong diff. Only trivial one-shot fixes may skip this. Standard location: `.worktrees/<branch-name>` at the repo root (gitignored), e.g. `git worktree add .worktrees/my-branch -b my-branch`. In a new worktree, symlink the dependency dirs (`lib/*`, `hw/mcu/*`, `tools/linkermap` — the keys of `deps_all` in `tools/get_deps.py`) to the primary checkout instead of re-cloning them; only if the branch needs a different dep revision, replace that one symlink with a real dir and run `get_deps.py` for it.
+## Claude and Codex Collaboration
+
+Claude Code is the primary harness. `CLAUDE.md` and `.claude/{agents,skills,workflows}` are canonical; `AGENTS.md -> CLAUDE.md` and `.agents -> .claude` expose the same instructions and skills to standalone Codex. `.codex/agents/*.toml` are thin adapters that pin Codex models and load the canonical Markdown roles; do not copy role bodies or maintain other Codex-specific mirrors.
+
+- Use `/codex:review` for an independent read-only review and `/codex:adversarial-review` to challenge the implementation or design.
+- Use `/codex:rescue` for substantial bounded implementation, diagnosis, or a second pass when Claude is stuck; use its `--background`, `--resume`, and `--fresh` controls when needed.
+- When Codex should use a named TinyUSB role, select its `.codex/agents/<role>.toml` adapter; the adapter loads `.claude/agents/<role>.md` as the canonical role.
+- Reviews and research may run beside Claude. For write-capable delegation, use a separate worktree if Claude continues editing; otherwise yield the current worktree to Codex until it finishes. Never let both edit overlapping files in one worktree.
+- `.claude/workflows/*.js` remain Claude Code-native orchestration. Codex may review or rescue work around a workflow, but no Codex-specific workflow mirror is maintained.
+
## Ground Rules
- **Language/style:** C99, 2-space indent (no tabs), snake_case helpers, `UPPER_CASE` macros. Public APIs use `tud_`/`tuh_`; macros use `TU_`. Headers self-contained with `#if CFG_TUSB_MCU` guards.
diff --git a/docs/superpowers/plans/2026-09-04-claude-codex-collaboration.md b/docs/superpowers/plans/2026-09-04-claude-codex-collaboration.md
new file mode 100644
index 000000000..98a4b0791
--- /dev/null
+++ b/docs/superpowers/plans/2026-09-04-claude-codex-collaboration.md
@@ -0,0 +1,178 @@
+# Claude and Codex Collaboration Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Make Claude Code the primary TinyUSB harness while sharing its repository instructions and skills with Codex and using the Codex Claude Code plugin for offload and review.
+
+**Architecture:** Keep `CLAUDE.md` and `.claude/` as the canonical instruction, role, skill, and workflow sources. Expose them to standalone Codex through relative symlinks and thin TOML role adapters, and use Claude Code's existing `codex@openai-codex` bridge for offload and review.
+
+**Tech Stack:** Markdown, Git symlinks, Claude Code plugins, Codex CLI, existing Claude Code workflow syntax checker
+
+**Spec:** `docs/superpowers/specs/2026-09-04-claude-codex-collaboration-design.md`
+
+## Global Constraints
+
+- `CLAUDE.md` and `.claude/{agents,skills,workflows}` remain the canonical authored content.
+- Keep `AGENTS.md -> CLAUDE.md` unchanged.
+- Add `.agents -> .claude`; `.codex/agents/*.toml` may contain only adapter metadata and canonical-role loading instructions.
+- Do not change Claude Code or Codex permission defaults or enable the stop-time review gate.
+- Never allow Claude and Codex to edit overlapping files concurrently in one worktree.
+
+---
+
+### Task 1: Canonical Repository Wiring
+
+**Files:**
+- Create: `.agents` (relative symlink to `.claude`)
+- Modify: `CLAUDE.md`
+
+**Interfaces:**
+- Produces: `AGENTS.md -> CLAUDE.md` for Codex instruction discovery.
+- Produces: `.agents/skills -> .claude/skills` for Codex skill discovery.
+- Produces: a durable collaboration policy used by Claude Code and standalone Codex.
+
+- [x] **Step 1: Verify the compatibility link is absent**
+
+Run:
+
+```bash
+test -L .agents && test "$(readlink .agents)" = .claude
+```
+
+Expected: FAIL because the imported directory is absent in the isolated worktree and no compatibility symlink exists yet.
+
+- [x] **Step 2: Add the relative compatibility symlink**
+
+Run:
+
+```bash
+ln -s .claude .agents
+```
+
+Expected: `readlink .agents` prints `.claude`, and `git status --short` reports `?? .agents` without copied skill files.
+
+- [x] **Step 3: Document the collaboration contract**
+
+Add a concise `Claude and Codex Collaboration` section to `CLAUDE.md` after `Behavioral Guidelines`. It must state:
+
+```markdown
+## Claude and Codex Collaboration
+
+Claude Code is the primary harness. `CLAUDE.md` and `.claude/{agents,skills,workflows}` are canonical; `AGENTS.md -> CLAUDE.md` and `.agents -> .claude` expose the same instructions and skills to standalone Codex. `.codex/agents/*.toml` are thin adapters that pin Codex models and load the canonical Markdown roles; do not copy role bodies or maintain other Codex-specific mirrors.
+
+- Use `/codex:review` for an independent read-only review and `/codex:adversarial-review` to challenge the implementation or design.
+- Use `/codex:rescue` for substantial bounded implementation, diagnosis, or a second pass when Claude is stuck; use its `--background`, `--resume`, and `--fresh` controls when needed.
+- When Codex should use a named TinyUSB role, select its `.codex/agents/<role>.toml` adapter; the adapter loads `.claude/agents/<role>.md` as the canonical role.
+- Reviews and research may run beside Claude. For write-capable delegation, use a separate worktree if Claude continues editing; otherwise yield the current worktree to Codex until it finishes. Never let both edit overlapping files in one worktree.
+- `.claude/workflows/*.js` remain Claude Code-native orchestration. Codex may review or rescue work around a workflow, but no Codex-specific workflow mirror is maintained.
+```
+
+- [x] **Step 4: Verify links and canonical skill resolution**
+
+Run:
+
+```bash
+test -L AGENTS.md
+test "$(readlink AGENTS.md)" = CLAUDE.md
+test -L .agents
+test "$(readlink .agents)" = .claude
+test "$(realpath .agents/skills)" = "$(realpath .claude/skills)"
+test "$(find .codex/agents -maxdepth 1 -name '*.toml' | wc -l)" -eq 8
+git ls-files --error-unmatch AGENTS.md CLAUDE.md
+```
+
+Expected: all commands succeed; all eight Codex role adapters are present.
+
+- [x] **Step 5: Verify all canonical dynamic workflows**
+
+Run:
+
+```bash
+for workflow_file in .claude/workflows/*.js; do
+ .claude/workflows/check.sh "$workflow_file"
+done
+```
+
+Expected: six `OK:` lines, one for each workflow.
+
+- [x] **Step 6: Check and commit the repository change**
+
+Run:
+
+```bash
+git diff --check
+git diff -- CLAUDE.md
+git status --short
+git add .agents CLAUDE.md
+git commit -m "docs: share Claude harness with Codex"
+```
+
+Expected: the commit contains one symlink and the collaboration section; role adapters are added separately.
+
+---
+
+### Task 2: Live Claude-to-Codex Verification
+
+**Files:**
+- Verify only: `AGENTS.md`, `.agents/skills`, `.claude/agents`, `.codex/agents`, `.claude/workflows`
+
+**Interfaces:**
+- Consumes: the symlinks and collaboration policy from Task 1.
+- Consumes: the enabled `codex@openai-codex` Claude Code plugin.
+- Produces: evidence that standalone Codex and the Claude Code companion both use the shared repository setup.
+
+- [x] **Step 1: Check the Claude Code Codex companion setup**
+
+Run from the worktree, resolving the installed plugin root first:
+
+```bash
+plugin_root=$(claude plugin list --json | jq -r '.[] | select(.id == "codex@openai-codex" and .enabled == true) | .installPath' | head -1)
+node "$plugin_root/scripts/codex-companion.mjs" setup --json
+```
+
+Expected: Codex CLI is installed and authenticated; the review gate remains disabled unless it was already enabled before this task.
+
+- [x] **Step 2: Verify standalone Codex instruction and skill discovery**
+
+Run:
+
+```bash
+codex --ask-for-approval never exec --sandbox read-only \
+ "Read-only setup check. State the repository instruction file you loaded and the project skill root you discovered. Do not modify files."
+```
+
+Expected: Codex identifies `AGENTS.md` and project skills under `.agents/skills`; the command leaves `git status --short` unchanged.
+
+- [x] **Step 3: Verify Claude-to-Codex role reuse**
+
+Run:
+
+```bash
+codex --ask-for-approval never exec --sandbox read-only \
+ "Use spawn_agent to run the builder project agent for a read-only integration check. Return only its name and whether its output contract is JSON. Do not build or modify files."
+```
+
+Expected: Codex selects `.codex/agents/builder.toml`, loads the canonical role,
+and reports its JSON output contract without changing files.
+
+- [x] **Step 4: Run an independent Codex review of the integration diff**
+
+Run:
+
+```bash
+node "$plugin_root/scripts/codex-companion.mjs" review --wait --base HEAD~1 --scope branch
+```
+
+Expected: the review completes and reports either no major issue or actionable findings; it makes no edits.
+
+- [x] **Step 5: Verify a clean bounded result**
+
+Run:
+
+```bash
+git status --short
+git diff --check HEAD~1..HEAD
+git show --stat --oneline HEAD
+```
+
+Expected: only the implementation-plan tracking update, if any, is uncommitted; the collaboration commit is whitespace-clean and contains only `CLAUDE.md` plus `.agents`.
diff --git a/docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md b/docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md
index 799c83c23..888dfb8dc 100644
--- a/docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md
+++ b/docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md
@@ -49,7 +49,7 @@ never inflates one axis with another's breadth.
| # | Changed path | Build families | Build examples | HIL boards → tests |
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| 1 | `docs/`, `.claude/`, `*.md`, `*.rst`, `LICENSE` | — | — | — |
-| 1b | `.gitignore`, `.clang-format`, `.idea/**`, `test/{fuzz,unit-test}/**`, `test/hil/test/**`, non-build `.github/**`, packaging manifests | — | — | — |
+| 1b | `.gitignore`, `.clang-format`, `.agents`, `.codex/**`, `.idea/**`, `test/{fuzz,unit-test}/**`, `test/hil/test/**`, non-build `.github/**`, packaging manifests | — | — | — |
| 2 | `test/hil/**` (not `test/hil/test/**`) | — | — | all boards → all tests |
| 2b | `tools/metrics.py`, `.github/scripts/metrics_*.py` | `ALL` (unchanged — `tinyusb_metrics` runs `metrics.py` as a build target) | `ALL` | — (nothing on the rig runs it) |
| 3 | `src/portable/<port>/dcd_*`, `*_device.[ch]` | `FAM` | `DEV`+`DUAL` | `FAM`'s device-role boards → device+dual tests |
diff --git a/docs/superpowers/specs/2026-09-04-claude-codex-collaboration-design.md b/docs/superpowers/specs/2026-09-04-claude-codex-collaboration-design.md
new file mode 100644
index 000000000..fa8d3b6d1
--- /dev/null
+++ b/docs/superpowers/specs/2026-09-04-claude-codex-collaboration-design.md
@@ -0,0 +1,95 @@
+# Claude and Codex Collaboration — Design
+
+Date: 2026-09-04
+Branch: `claude/codex-collaboration`
+
+## Goal
+
+Keep Claude Code as the primary TinyUSB harness while making Codex available
+for independent review, diagnosis, and bounded implementation work. Preserve
+one repository-owned source for instructions, agents, skills, and dynamic
+workflows, while keeping standalone Codex useful.
+
+## Source of Truth
+
+- `CLAUDE.md` is the only authored repository instruction file.
+- `.claude/agents/`, `.claude/skills/`, and `.claude/workflows/` are the only
+ authored agent, skill, and workflow trees.
+- `AGENTS.md` remains a relative symlink to `CLAUDE.md` so standalone Codex
+ loads the same repository instructions.
+- `.agents` becomes a relative symlink to `.claude` so Codex discovers the
+ canonical skills at `.agents/skills` without a copied mirror.
+- The imported `.codex/` agent tree is replaced with thin TOML adapters that
+ contain only each role's name, model/effort pin, and instruction to load the
+ canonical `.claude/agents/<role>.md` body.
+
+Standalone Codex therefore uses the shared project instructions, skills, and
+named TinyUSB roles. JavaScript workflows remain Claude Code orchestration
+surfaces.
+
+## Claude-to-Codex Flow
+
+The enabled `codex@openai-codex` Claude Code plugin is the bridge:
+
+- `/codex:review` performs an independent, read-only review of local git state.
+- `/codex:adversarial-review` challenges the implementation and design.
+- `/codex:rescue` delegates diagnosis or an explicitly requested fix.
+- `/codex:status`, `/codex:result`, and `/codex:cancel` manage background work.
+
+Claude should offload work when a second implementation or diagnosis pass is
+valuable, when it is stuck, or when a substantial bounded task can be isolated.
+Simple tasks stay in the main Claude session.
+
+When a Codex task should follow a named TinyUSB role, select its
+`.codex/agents/<role>.toml` adapter. The role body remains authored once in
+`.claude/agents/<role>.md`.
+
+## Concurrency and Safety
+
+- Reviews and research may run in parallel with Claude because they are
+ read-only.
+- Claude and Codex must not edit overlapping files concurrently in the same
+ worktree.
+- Write-capable background delegation uses a separate worktree when Claude will
+ continue editing; otherwise Claude yields ownership of the current worktree
+ until Codex finishes.
+- Codex follows the same destructive-action, HIL, push, and hardware-lock rules
+ through `AGENTS.md -> CLAUDE.md`.
+
+## Dynamic Workflows
+
+`.claude/workflows/*.js` stay Claude Code-native. Claude remains responsible
+for workflow control flow and structured joins. Codex can be called before or
+after a workflow for a second opinion or rescue task, but the workflow files
+are not translated into a Codex-specific format.
+
+This avoids an unsupported generated workflow mirror and keeps deterministic
+orchestration in one place.
+
+## Repository Changes
+
+1. Replace the untracked imported `.agents/` directory with the tracked
+ `.agents -> .claude` symlink.
+2. Replace the untracked imported `.codex/` directory with thin agent adapters.
+3. Add a concise collaboration section to `CLAUDE.md` covering delegation,
+ review, role reuse, and the single-writer rule.
+4. Keep the existing tracked `AGENTS.md -> CLAUDE.md` symlink unchanged.
+
+## Verification
+
+- Confirm both compatibility paths are relative symlinks with the intended
+ targets.
+- Confirm `.agents/skills/*/SKILL.md` resolves to the canonical files and every
+ `.codex/agents/*.toml` adapter loads its matching canonical role.
+- Run every `.claude/workflows/*.js` through `.claude/workflows/check.sh`.
+- Run Codex non-interactively from the worktree and verify it identifies the
+ shared instruction source and project skills.
+- Run the Claude Code Codex companion setup check, a small rescue/read task,
+ and a small review task without changing repository source.
+
+## Out of Scope
+
+- Translating Claude Code dynamic workflows to a second runtime.
+- Maintaining Codex-native copies of the named Claude agent bodies.
+- Changing Claude Code or Codex permission defaults.
+- Enabling automatic stop-time reviews without explicit user direction.
diff --git a/docs/superpowers/specs/2026-09-04-neutral-skill-wording-design.md b/docs/superpowers/specs/2026-09-04-neutral-skill-wording-design.md
new file mode 100644
index 000000000..ee632b1da
--- /dev/null
+++ b/docs/superpowers/specs/2026-09-04-neutral-skill-wording-design.md
@@ -0,0 +1,32 @@
+# Neutral Skill Wording Design
+
+## Goal
+
+Make the `read-doc` and `pre-pr` skill instructions understandable in both
+Claude Code and Codex without changing their behavior.
+
+## Changes
+
+- Replace slash-command wording with references to arguments or context supplied
+ in the skill request.
+- Replace the Claude-specific `AskUserQuestion` name with the neutral instruction
+ to ask the user.
+- Replace Claude-specific `Read` tool wording with capability-based document
+ reading instructions.
+- Remove slash-command syntax from skill headings.
+
+## Deferred Scope
+
+Leave the `pre-pr` invocation of the Claude Code `full-check` workflow unchanged.
+Standalone Codex execution of that workflow will be designed separately.
+
+No other skill files need changes: their instructions already use portable
+Markdown, repository paths, and shell commands.
+
+## Verification
+
+- Search every `.claude/skills/*/SKILL.md` for slash-command headings,
+ `AskUserQuestion`, and Claude-specific `Read` tool wording.
+- Confirm `pre-pr` still invokes `full-check` exactly as before.
+- Confirm `.agents` still resolves to `.claude`, so Codex discovers the canonical
+ skill files without a generated copy.
diff --git a/test/hil/test/test_ci_select.py b/test/hil/test/test_ci_select.py
index 22fbde17b..61d3f23a4 100644
--- a/test/hil/test/test_ci_select.py
+++ b/test/hil/test/test_ci_select.py
@@ -203,6 +203,11 @@ class TestFallbackRules(unittest.TestCase):
self.assertFalse(s['full'])
self.assertEqual(s['boards'], {})
+ def test_agent_metadata_is_empty_not_full(self):
+ s = sel(['.agents', '.codex/agents/builder.toml'])
+ self.assertFalse(s['full'])
+ self.assertEqual(s['boards'], {})
+
def test_bsp_family_selects_family_boards(self):
s = sel(['hw/bsp/rp2040/family.cmake'])
self.assertFalse(s['full'])
@@ -1624,7 +1629,7 @@ class TestBuildClassifier(unittest.TestCase):
'.clang-format', '.idea/misc.xml', 'version.yml', 'library.json',
'examples/CMakePresets.json', 'test/fuzz/fuzz.cc',
'test/unit-test/project.yml', '.github/workflows/pr_comment.yml',
- 'tools/gen_doc.py'):
+ 'tools/gen_doc.py', '.agents', '.codex/agents/builder.toml'):
s = self.b([p])
self.assertFalse(s['full'], p)
self.assertEqual(s['families'], [], p)
diff --git a/tools/ci_select.py b/tools/ci_select.py
index 1526f2064..9723ed6fb 100755
--- a/tools/ci_select.py
+++ b/tools/ci_select.py
@@ -23,7 +23,7 @@ _prune_buildable then intersects each family with what it can actually build.
| # | Changed path | Build families | Build examples | HIL boards → tests |
| 1 | `docs/`, `.claude/`, `*.md`, `*.rst`, `LICENSE` | — | — | — |
-| 1b | `.gitignore`, `.clang-format`, `.idea/**`, `test/{fuzz,unit-test}/**`, `test/hil/test/**`, non-build `.github/**`, packaging manifests | — | — | — |
+| 1b | `.gitignore`, `.clang-format`, `.agents`, `.codex/**`, `.idea/**`, `test/{fuzz,unit-test}/**`, `test/hil/test/**`, non-build `.github/**`, packaging manifests | — | — | — |
| 2 | `test/hil/**` (not `test/hil/test/**`) | — | — | all boards → all tests |
| 2b | `tools/metrics.py`, `.github/scripts/metrics_*.py` | `ALL` (unchanged — `tinyusb_metrics` runs `metrics.py` as a build target) | `ALL` | — (nothing on the rig runs it) |
| 3 | `src/portable/<port>/dcd_*`, `*_device.[ch]` | `FAM` | `DEV`+`DUAL` | `FAM`'s device-role boards → device+dual tests |
@@ -103,7 +103,7 @@ _NONCODE_RE = re.compile(
_META_RE = re.compile(
r'^('
r'\.(gitignore|gitattributes|clang-format|codespellrc|readthedocs\.yaml)$|'
- r'\.pre-commit-config\.yaml$|\.PVS-Studio/|\.idea/|\.vscode/|'
+ r'\.pre-commit-config\.yaml$|\.PVS-Studio/|\.agents$|\.codex/|\.idea/|\.vscode/|'
r'sonar-project\.properties$|library\.json$|pkg\.yml$|repository\.yml$|'
r'version\.yml$|SConscript$|'
r'.*CMakePresets\.json$|hw/bsp/BoardPresets\.json$|examples/west\.yml$|'