refactor: agents and skills move to a client-neutral source that renders per client

`.claude/agents/` was the source of truth, which made every role Claude-Code
shaped. Adding a second client meant rewriting each role in that client's syntax
and maintaining both copies — the drift this scaffold exists to prevent, one layer
up.

Roles and skills now live under `.agents/` and render into each registered
client. `.claude/agents/`, `.claude/skills/` and `.codex/agents/` are generated;
`scripts/sync-agent-integrations.py --check` fails on drift and belongs in CI.

The role metadata is portable rather than vendor-named: `reasoning_tier`
(deep/balanced/fast/vision), `capabilities`, `mutation`, `invocation`, and an
optional `preload_skills`. A client manifest maps those to native syntax and must
declare what it cannot express — `codex.yaml` declares `tier_policy: unsupported`
and its adapters say so in the file, rather than the tier silently evaporating and
leaving the repository to believe it was enforced.

The port is behaviour-preserving where it should be and a fix where it should not.
Every instruction body is byte-identical — the whole diff to `.claude/agents/` is
18 added lines and zero deletions. What changed is frontmatter that was missing:

- four agents (`code-reviewer`, `tdd-guardian`, `dependency-audit`, `pr-creator`)
  declared no `tools:` and therefore inherited the ENTIRE tool pool, so three
  review-only agents could edit and write the code they were reviewing. All eight
  now declare capabilities explicitly.
- the six read-only roles gain a non-editing permission mode, so the constraint is
  enforced by the client rather than by the prompt asking nicely.
- `mutation` is now explicit, which records the two roles that genuinely need to
  write: `pr-creator` (external-write — it pushes a branch and opens a PR) and
  `dependency-audit` (workspace-write — package managers rewrite lockfiles).

`pr-creator` keeps `shell` because opening a PR needs it, but it is now the only
agent here with a write mutation and a declared reason for it, instead of one of
four with unlimited access by omission.
This commit is contained in:
2026-09-19 17:27:26 -04:00
parent e111e61832
commit 3f0786f1e7
53 changed files with 13801 additions and 2 deletions
+17 -2
View File
@@ -27,7 +27,7 @@ A comprehensive guidance system for Claude Code with strict TDD enforcement, mul
~/.claude/
├── CLAUDE.md # Core principles (~150 lines)
├── settings.json # Model config (opusplan), Claude hooks
├── agents/
├── agents/ # GENERATED from ../.agents/roles — do not edit
│ ├── tdd-guardian.md # TDD enforcement (sonnet)
│ ├── code-reviewer.md # PR review (opus)
│ ├── security-scanner.md # Security checks (sonnet, read-only)
@@ -36,7 +36,7 @@ A comprehensive guidance system for Claude Code with strict TDD enforcement, mul
│ ├── pr-creator.md # Automated PR creation (haiku)
│ ├── release-notes.md # CHANGELOG generation (haiku, read-only)
│ └── plan-reviewer.md # Plan validation (sonnet, read-only)
├── skills/
├── skills/ # GENERATED from ../.agents/skills — do not edit
│ ├── languages/
│ │ ├── python/SKILL.md # pytest, Ruff, FastAPI
│ │ ├── typescript/SKILL.md # Vitest, ESLint, React
@@ -191,6 +191,21 @@ echo '~/.claude/hooks/pre-commit-tdd.sh' > .husky/pre-commit
@plan-reviewer Review docs/plans/active/3.5_business-capabilities.md
```
## Editing agents and skills
`.claude/agents/` and `.claude/skills/` are **generated**. The source of truth is
[`.agents/`](../.agents/README.md), which is client-neutral so the same roles and
skills also render for Codex (and any client added later) rather than being
rewritten per tool.
```bash
python3 scripts/sync-agent-integrations.py # regenerate
python3 scripts/sync-agent-integrations.py --check # fail on drift (use in CI)
```
Edit `.agents/roles/<name>.md` or `.agents/skills/**`, then run the sync. A direct
edit to a generated file is reverted by the next run.
## Customization
### Project-Specific CLAUDE.md