CLAUDE.md · diff
git:20260904.d3726b0 to git:20260906.bca11b3
1 added, 292 removed. Audit A to B.
- # CLAUDE.md
-
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
- ## Repository Overview
-
- This is a repository providing a complete development environment for agentic tools like Claude Code and Codex, with tool configs, pre-configured MCP servers, and plugins. It provides opinionated configurations and installable plugins for claude-code and codex.
-
- ## Architecture
-
- Three integrated components:
-
- 1. **Claude Code** (`.claude/`): Project settings (`settings.json`), statusline scripts, and sync infrastructure
- 2. **Codex** (`.codex/`, `kodex-plugin/`): Codex-equivalent config, hooks, rules, agents, and generated plugin. See §Codex Support below
- 3. **kk plugin** (`klaude-plugin/`): Skills, commands, hooks, and utility scripts — the canonical source of truth, distributed via the Claude Code plugin system
-
- For API keys and MCP server setup, see the "MCP Server Configuration" section in `README.md`.
-
- ### Codex Support
-
- `klaude-plugin/` is the canonical source. A Go generation tool (`cmd/generate-kodex/`) produces:
-
- - `kodex-plugin/` — transformed skills for Codex (resolves `${CLAUDE_PLUGIN_ROOT}`, injects headers)
- - `.codex/agents/*.toml` — sub-agent definitions (converted from `klaude-plugin/agents/*.md`)
-
- Hand-authored codex files (not generated): `.codex/config.toml`, `.codex/hooks.json`, `.codex/rules/default.rules`, `.codex/scripts/`, `AGENTS.md`.
-
- **Developer workflow:** After editing skills in `klaude-plugin/`, run `make generate-kodex` to regenerate. CI checks freshness via `make generate-kodex && git diff --exit-code kodex-plugin/ .codex/agents/`.
-
- ## Testing
-
- Tests are in `test/`. Run with:
-
- ```bash
- for test in test/test-*.sh; do $test; done
- ```
-
- Key test suites: `test-plugin-structure.sh` (klaude-plugin + kodex-plugin generated output), `test-codex-structure.sh` (codex config, hooks, agents, rules), `test-template-sync.sh` (sync infrastructure). Tests use shared utilities from `test/helpers.sh`.
-
- The Go tools under `cmd/` have their own tests: `make generate-kodex` (Codex generation + freshness) and `make plugin-graph` (the `cmd/plugin-graph/` dependency-graph analyzer's tests, plus `plugin-graph validate` against `klaude-plugin/` as a broken-link/orphan gate). See [docs/contributing/architecture.md](docs/contributing/architecture.md) for what `plugin-graph` analyzes.
-
- **Eval-fixture links are intentionally partial.** `plugin-graph validate` (and any "fix the broken link" instinct) must not touch deliberately-broken markdown links under `evals/` or in `example-*.md` templates — several eval fixtures omit their link targets precisely to exercise missing-target detection. `validate` exempts these `nonOperativeSource`s by design; "fixing" them breaks the evals.
-
- ## Troubleshooting
-
- See `README.md` for detailed troubleshooting of MCP connection issues and template sync problems.
-
- ## Skill & Command Naming Conventions
-
- Applies when creating or renaming kk-plugin skills and commands.
-
- ### Skills
-
- - **Imperative verbs over noun phrases.** `/kk:design` not `/kk:analysis-process`, `/kk:implement` not `/kk:implementation-process`. Drop filler suffixes like `-process`. Skills are invoked as `/skill-name` — shorter names are faster to type.
- - **Self-documenting over acronyms.** `/kk:chain-of-verification` beats `cove`. If the name requires expansion to understand it, it's the wrong name.
- - **Family prefixes for grouped skills.** When multiple skills do the same action on different targets, share a prefix: `/kk:review-design`, `/kk:review-spec`, `/kk:review-code`. Tab-completion, discoverability, and mental grouping all benefit.
- - **Always use `/kk:` prefix.** Reference skills with the `/kk:` prefix everywhere — prose, invocation examples, docs (e.g., `` `/kk:review-code` `` not `` `review-code` ``). This ensures consistent, greppable, unambiguous skill references. The codex generation tool rewrites `/kk:` → `$kk:` for Codex output. Exception: `kk:review-findings`, `kk:lang-idioms`, etc. are capy knowledge-store labels, not skill references.
-
- ### Commands
-
- Commands live under `klaude-plugin/commands/<name>/`. For skills with standard + isolated modes:
-
- - `default.md` — standard variant, invoked as `/kk:<name>:default`
- - `isolated.md` — isolated sub-agent variant, invoked as `/kk:<name>:isolated`
-
- Symmetric naming avoids stuttering (`/kk:cove:cove` → `/kk:chain-of-verification:default`).
-
- ### Agents
-
- Agent names describe the **role**, not the skill that invokes them. `code-reviewer`, `design-reviewer`, `spec-reviewer` persist across skill renames. Don't rename agent files when renaming the skills that delegate to them.
-
- ### Plugin content is self-contained
-
- `klaude-plugin/` ships standalone via the plugin marketplace — consumers get the plugin tree only, never this repo's `docs/`. Therefore skill, agent, and profile prose must NEVER reference toolbox-repo documents: no "(ADR NNNN)" citations, no `docs/adr/`-as-this-repo links, no `docs/wip|done` pointers. For a consumer these are unresolvable at best; at worst they collide with the consumer repo's own ADR numbering and point to unrelated decisions. State the rule and its rationale in full in the plugin file itself; keep the ADR back-reference in repo-side docs only (the ADR cites the operative plugin files, not the other way around). Distinguish: consumer-repo paths as *behavioral targets* (e.g. review-architecture accepting artifacts from the consumer's `docs/adr/`, the document skill writing ADRs to the consumer's `/docs/adr`) are correct and expected.
-
- ### Shared instructions
-
- Instructions referenced by more than one skill live in `klaude-plugin/skills/_shared/<name>.md` with a bare basename (e.g., `review-scope-protocol.md`, `pal-codereview-invocation.md`).
-
- Each consuming skill gets a **per-skill symlink** at `klaude-plugin/skills/<skill>/shared-<name>.md` pointing to `../_shared/<name>.md`. Reasons:
-
- - Markdown links inside a skill stay local — `[shared-foo.md](shared-foo.md)` resolves without `../` path traversal, which keeps links working when the skill is bundled/copied.
- - The `shared-` prefix in the skill directory makes it obvious at a glance which files are shared vs skill-specific.
- - Only symlink into skills that actually reference the file — don't blanket-symlink.
-
- When adding a new shared instruction:
-
- 1. Create `klaude-plugin/skills/_shared/<name>.md` (bare basename, no `shared-` prefix on the source file).
- 2. In each consuming skill directory, run `ln -s ../_shared/<name>.md shared-<name>.md`.
- 3. Reference it in skill docs as `[shared-<name>.md](shared-<name>.md)`.
- 4. Agents (in `klaude-plugin/agents/`) can't use the per-skill symlink pattern — reference shared files by their repo-relative path: `klaude-plugin/skills/_shared/<name>.md`.
-
- ### When renaming
-
- - Update `test/test-plugin-structure.sh` `EXPECTED_SKILLS` and `EXPECTED_COMMANDS`.
- - **Don't touch `run_plugin_migration`'s `dirs_to_remove` in `.claude/toolbox/scripts/template-sync.sh`** — those are historical paths for cleaning up pre-v0.5.0 downstream projects. They must stay as the names that existed at migration time.
- - Leave `docs/done/**` untouched — it's frozen history.
- - Watch for substring collisions (e.g., a `design-review` → `/kk:review-design` rename will also hit the `design-reviewer` agent name via simple sed; hand-fix those).
-
- ### Skill description budget
-
- Claude Code loads skill descriptions into context so the model can pick the right skill. Two caps apply (see [Claude Code docs — Skill descriptions are cut short](https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short)):
-
- - **Per-entry cap: 1,536 characters.** Each skill's `description` + `when_to_use` combined text is truncated at 1,536 characters regardless of the global budget.
- - **Global context budget.** Scales dynamically at 1% of the context window, with a fallback of 8,000 characters. Override via the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable. When many skills are loaded, each description's share of the budget shrinks — trailing content gets stripped first.
-
- OpenCode's documented limit for the same field is 1024 characters. For portability across both harnesses, treat 1,024 as a soft budget for skills that must work on both; stay under 1,536 at a minimum.
-
- Authoring rules:
-
- - **Lead with trigger keywords.** Truncation happens at the tail, so the decisive "when to invoke this" words must come first.
- - **Front-load the key use case.** The Claude Code docs' own guidance — one concrete TRIGGER phrase beats a paragraph of hedging.
- - **Keep descriptions tight.** Detailed rules, cascades, and examples belong in the SKILL.md body, not the description.
-
- When touching a skill description in the future, re-check the docs page linked above in case the caps have shifted.
-
- ### Skill workflow ordering — instructions before action
-
- Applies to every plugin skill. The canonical failure example surfaced in `/kk:review-code`, but the rule is universal. See [ADR 0004](docs/adr/0004-skill-workflow-ordering.md) for the full rationale and the failure transcripts.
-
- Core rule: a skill MUST fully load its instructions before taking any action on its subject matter.
-
- - **Instructions** = `SKILL.md` + every process/rubric/protocol file it links + every per-skill symlinked shared instruction + (for profile-driven skills) every profile file the detection procedure resolves.
- - **Action on subject matter** = reading diff/file content, editing code, engaging with idea prose beyond detection keywords, running tests, emitting documentation, producing findings.
- - **Minimal early scope is permitted** — enough to drive profile detection. Examples: `git diff --stat` for filenames, a feature-directory listing, a keyword scan of idea prose. Content-level reading is blocked until instructions are fully loaded.
- - **Content-level read instructions appear exactly once** in the workflow, after the instruction-load steps. Restating them earlier — even as a "Preflight" step — re-creates the failure mode.
-
- Profile-driven skills have an additional specialization: profile content (resolved checklists, gotchas, rubrics, validator lists) is part of "instructions". Every `(profile, <phase>/<content>)` pair the detection procedure resolves is read via the `Read` tool before content-level subject-matter reading — index entries alone are not enough.
-
- Authoring requirements for every skill:
-
- 1. **Mandatory-order directive** at the top of SKILL.md's Workflow section, explicitly stating that the flow is strictly sequential and subject-matter action is blocked until instructions are loaded. Name the rule by intent, not by step numbers — step numbers drift; intent does not.
- 2. **Workflow phase summary in SKILL.md matches the detailed process file.** A reader who skims SKILL.md must not see a different ordering than the process file prescribes.
- 3. **Dedup pass.** After drafting, grep the skill directory for repeated content-read instructions — if the same `git diff` / `Read` step appears twice, collapse to one instance at the post-instruction position.
-
- Sub-agents delegated by skills (in `klaude-plugin/agents/`) inherit the same rule. Payload delivery order (the spawning skill passing instructions and subject matter in the same prompt) is not sufficient — the sub-agent's own workflow must read instructions before acting, or the LLM will re-create the shortcut on its side.
-
- ### Skill evaluations
-
- Skills with non-trivial decision logic (routing, detection, conditional loading) should ship **evaluation scenarios** under `klaude-plugin/skills/<skill>/evals/`. Evals are spec files — no built-in harness exists ([Anthropic docs — Evaluation and iteration](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#evaluation-and-iteration)) — but they give a reviewer or future harness an objective rubric to grade against.
-
- Directory layout:
-
- ```
- klaude-plugin/skills/<skill>/evals/
- <eval-name>/
- eval.json # scenario definition
- test-files/ # real fixtures (YAML, code, configs, …) — everything here may be staged for the model under test
- …
- oracle/ # grader-only expected outputs (gold-claims.json, expected-verdicts.json, …) — optional
- ```
-
- **Oracles are grader-only and live outside `test-files/`.** Expected-output files (`gold-claims.json`, `expected-verdicts.json`, …) go in a sibling `oracle/` directory, never inside `test-files/`. A harness may stage the whole `test-files/` directory, so an oracle placed there would leak the graded answers to the model under test even when omitted from `files[]`. `oracle/` contents are consumed only by the grader.
-
- **One directory per eval, not a single `evals.json`.** Skills that detect on paths or directory adjacency (e.g., `/kk:review-code` → `values*` adjacent to `Chart.yaml`, `templates/` ancestor chains, `kustomization.yaml` filename signal) can only be exercised against real filesystem structure. Inline-in-prompt fixtures force the evaluator to describe directory layout in prose, which tests pattern-matching on prose rather than the detection logic. Real fixtures are also syntax-highlightable, validatable (`kubeconform`, `helm lint`, `go build`), and trivial to edit — YAML embedded in JSON strings as `\n`-escaped text is not.
-
- `eval.json` schema:
-
- ```json
- {
- "id": 1,
- "name": "eval-name-kebab-case",
- "description": "One-sentence summary of what this eval tests.",
- "skills": ["skill-name"],
- "prompt": "The natural user prompt that triggers the skill.",
- "trap": "The failure hypothesis — what a model is likely to get wrong.",
- "files": ["test-files/foo.yaml", "test-files/bar.yaml"],
- "assertions": [
- { "id": "1.1", "text": "Specific, graded behavior bullet." },
- { "id": "1.2", "text": "…" }
- ]
- }
- ```
-
- - `skills`, `prompt`, `files` follow the [Anthropic best-practices format](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#evaluation-and-iteration) so a future harness aligned with that spec can ingest these evals.
- - `trap` and numbered `{id, text}` assertions are borrowed from [samber/cc-skills-golang](https://github.com/samber/cc-skills-golang/blob/main/skills/golang-cli/evals/evals.json) — the trap sharpens intent (*which* failure mode is this eval testing?); numbered assertions make manual grading and failure reports traceable.
- - `assertions[].id` follows `<eval-id>.<n>` — eval 1's assertions are `1.1, 1.2, …`; eval 2's are `2.1, 2.2, …`.
-
- **When to author evals.** Proactively, for skills with detection/routing logic where false positives and false negatives both matter; for skills with conditional content loading; and include at least one **regression eval** proving the skill does NOT activate (or falls back to default behavior) when it shouldn't. Skip for trivial skills whose behavior is captured by the skill's markdown alone.
-
- **Running.** No built-in harness. A reviewer (or a future harness) stages the eval's `test-files/` where the skill expects input — never the `oracle/` directory — sends `prompt` with the target skill available, and grades the response against each assertion (consulting `oracle/` for expected outputs). Keep per-eval directories self-contained so the harness has zero external dependencies.
-
- ## Profile Conventions
-
- Applies when authoring profiles under `klaude-plugin/profiles/`. Profiles make per-domain concerns (programming languages, IaC DSLs, config schemas) available to every phase of the `/kk:design` → `/kk:implement` → `/kk:review-code` → `/kk:test` → `/kk:document` flow.
-
- ### Directory layout
-
- Every profile lives at `klaude-plugin/profiles/<name>/` and follows the same shape:
-
- ```
- klaude-plugin/profiles/<name>/
- DETECTION.md # authoritative trigger rule (required)
- overview.md # human-readable summary + dependency-lookup targets (required)
- review-code/ # per-phase subdirectory (populated as needed)
- index.md # router; see §`index.md` contract
- <content files>
- design/
- implement/
- test/
- document/
- review-spec/
- ```
-
- Not every profile populates every phase — a programming-language profile may only need `review-code/`; an IaC profile like `k8s` populates all six; a tooling profile like `skill-md` populates only the phases where domain-specific guidance adds value. A phase subdirectory contains only its `index.md` and the files the index references; human-facing authoring notes belong in `overview.md` or a sibling file at the profile root.
-
- ### `DETECTION.md` — schema
-
- `DETECTION.md` is the single authoritative source for "when does this profile activate". It has three mandatory sections (every heading must be present even when its body is empty) and one optional section:
-
- - **`## Path signals`** — path globs that promote a file to a candidate. Fast pre-filter only; not authoritative on their own.
- - **`## Filename signals`** — literal filenames or filename globs. Authoritative: any match activates the profile.
- - **`## Content signals`** — content-inspection rules (anchors, regexes, key presence). Authoritative for files not already caught by filename signals. Bounded inspection (~16 KB per file; multi-document YAML inspected per `---`-separated block).
- - **`## Design signals`** *(optional)* — enables design-phase detection for profiles that participate before code exists. Contains `display_name` (human-readable label for confirmation prompts) and `tokens` (keyword list matched against idea prose). Not required; not asserted by the structure test. Only relevant to profiles that need design-phase activation.
-
- **Two dimensions, different orders.** Signals are *evaluated* in cost order (path → filename → content) but *authority* runs filename ≈ content > path — filename and content are equally authoritative; filename resolves first only because it is cheaper to evaluate (a filename match short-circuits content inspection for that file). A file caught only by a path signal does not activate the profile.
-
- Consumers invoke `klaude-plugin/skills/_shared/profile-detection.md` (via the per-skill symlinks `shared-profile-detection.md`) — they do not replicate per-profile logic.
-
- ### `index.md` contract — bidirectional invariant
-
- Each phase subdirectory's `index.md` is the contract between the profile and the consuming skill. It has two sections:
-
- - **Always load.** Files loaded whenever the profile is active. Each entry: markdown link + one-line description.
- - **Conditional.** Files loaded only when a stated trigger matches. Each entry: link + description + an explicit **Load if:** clause naming concrete diff properties (field values, filenames, directory names) — not vague category labels. Two agents evaluating the same diff against the same trigger must reach the same conclusion.
-
- **Bidirectional invariant** (enforced by `test/test-plugin-structure.sh`):
-
- - **Forward.** Every markdown link in `index.md` resolves to a file on disk.
- - **Reverse.** Every `.md` file in the phase subdirectory (except `index.md` itself) is referenced by at least one link in `index.md`.
-
- An unreferenced `.md` inside a phase subdirectory is always a bug — an orphan checklist or a stray README. Authoring notes and READMEs belong at the profile root (in `overview.md` or a sibling file), not inside a phase subdirectory.
-
- ### Naming
-
- - Lowercase profile names. Underscores allowed where filename-safe (e.g., `js_ts`).
- - Phase subdirectory names match the consuming skill's directory name exactly: `review-code/`, `review-spec/`, `design/`, `implement/`, `test/`, `document/`.
-
- ### Referencing profile content from skills and agents
-
- Skills and agents reference profile content via `${CLAUDE_PLUGIN_ROOT}/profiles/<name>/...` — no symlinks from skills into `profiles/` ([ADR 0003](docs/adr/0003-plugin-root-referenced-content.md)).
-
- **Brace form required for substitution.** The Claude Code harness substitutes `${CLAUDE_PLUGIN_ROOT}` (with braces) before any agent reads the content. Bare `$CLAUDE_PLUGIN_ROOT` is NOT substituted.
-
- **Substitution is markdown-container-unaware.** The harness applies a literal text replacement. Substitution happens inside inline backticks, fenced code blocks (plain / bash / markdown / tilde), indented code blocks, blockquotes, and HTML comments. **No markdown container escapes substitution.**
-
- **Literal-reference authoring rule.** When prose *inside* `klaude-plugin/` (SKILL.md, agent files, profile content) needs to reference the variable *by name* — documenting or explaining it, not using it as a runtime path — use one of two surviving forms:
-
- - Bare `$CLAUDE_PLUGIN_ROOT` (simplest; verified not substituted on 2026-04-18).
- - HTML entity `${CLAUDE_PLUGIN_ROOT}` (useful when the brace shape must appear in rendered output).
-
- **Substitution boundary: plugin-load vs `Read` tool.** The harness substitutes `${CLAUDE_PLUGIN_ROOT}` at **plugin-load time** for files the harness loads directly — SKILL.md, `agents/*.md`, hook configs, MCP configs. The brace form in those files reaches the agent as a resolved absolute path and can be used directly in tool arguments. **The `Read` tool does NOT substitute** — it returns file content byte-for-byte. Any `${CLAUDE_PLUGIN_ROOT}` inside a file an agent reads at runtime via `Read` (everything under `klaude-plugin/skills/_shared/`, per-skill referenced content, every `profiles/**/*.md`) reaches the agent as a literal token. Forwarding that literal into another tool call fails: `Bash` shell-expands against the usually-unset env var to empty; `Read` fails `ENOENT`.
-
- Authoring consequence:
-
- - Use `${CLAUDE_PLUGIN_ROOT}/…` freely in plugin-load files (SKILL.md, agent files, hook/MCP configs).
- - In files consumed via `Read` at runtime, **prefer explicit content over tokens**: hard-code the names/paths the procedure needs (e.g., the Known Profiles list in `shared-profile-detection.md`). If the file must describe a plugin-root path, instruct the agent to construct it using the resolved prefix it already knows from the SKILL.md that invoked it — not to forward the literal `${CLAUDE_PLUGIN_ROOT}` token.
- - Never use `Glob` against `${CLAUDE_PLUGIN_ROOT}/…` patterns regardless of substitution: `Glob` is cwd-scoped and returns 0 matches for outside-cwd absolute paths.
-
- **`TOOLBOX_PLUGIN_ROOT` — session-wide runtime alternative.** A `SessionStart` hook in `klaude-plugin/hooks/hooks.json` exports `TOOLBOX_PLUGIN_ROOT` into every Bash call via `$CLAUDE_ENV_FILE`. Unlike `${CLAUDE_PLUGIN_ROOT}` (plugin-load-time only), `${TOOLBOX_PLUGIN_ROOT}` is available in the shell environment throughout the session. Use it in Bash commands when the plugin root is needed at runtime — e.g., `ls ${TOOLBOX_PLUGIN_ROOT}/profiles/`. The hook resolves the path primarily via `klaude-plugin/scripts/cpr.py` (which reads `installed_plugins.json` and returns the versioned `cache/` path); the harness-substituted `${CLAUDE_PLUGIN_ROOT}` passed as the hook's argument is the fallback. Read-only sub-agents (e.g. `code-reviewer`, `profile-resolver`) have no shell to resolve the variable — the spawning skill resolves it and injects the absolute path into their prompt under a `## Plugin Root` heading.
-
- Files outside `klaude-plugin/` (this CLAUDE.md, README.md, ADRs under `docs/adr/`) are NOT subject to substitution and may use the brace form freely.
-
- ### Adding a new profile
-
- 1. Copy an existing profile as a template (e.g., `cp -r klaude-plugin/profiles/go klaude-plugin/profiles/<name>`).
- 2. Rewrite `DETECTION.md` with the new profile's signals. Keep all three mandatory headings (`## Path signals`, `## Filename signals`, `## Content signals`) even when empty. Add `## Design signals` if the profile needs design-phase activation.
- 3. Rewrite `overview.md`: what the profile covers, when it activates, and "Looking up dependencies" cascade targets for each dependency category the profile cares about.
- 4. Populate the phase subdirectories the profile needs. Each populated phase must have an `index.md` listing its content files (always-load + conditional with explicit **Load if:** clauses). Leave phases the profile does not serve absent — the structure test's presence-conditional assertion only fires on directories that exist.
- 5. Append the profile name to `EXPECTED_PROFILES` in `test/test-plugin-structure.sh` — *after* the profile's files exist, not before. Per-profile assertions will fail if the profile is listed first.
- 6. Append the profile name to the **Known profiles** list in `klaude-plugin/skills/_shared/profile-detection.md`. This list is the authoritative runtime enumeration — consumers iterate it rather than enumerating the filesystem (see §Referencing profile content for why).
- 7. Run `bash test/test-plugin-structure.sh` and confirm green.
-
- ### Vendored profile content
-
- Some profiles populate phase content by vendoring files from external upstream repositories (e.g., the Go profile vendors from [samber/cc-skills-golang](https://github.com/samber/cc-skills-golang)). A Go CLI tool at `cmd/vendor-profiles/` drives this:
-
- 1. A YAML manifest (`scripts/<profile>-vendor-manifest.yml`) maps upstream files to profile phase directories, specifying keep transforms, target filenames, and load conditions.
- 2. The tool fetches each file, applies transforms (strip frontmatter via `from_first_h1`, extract specific headings, or passthrough), rewrites internal markdown links, and writes to the target phase directory.
- 3. Each phase's `index.md` is updated between `<!-- BEGIN VENDORED -->` / `<!-- END VENDORED -->` injection markers. Content outside the markers (hand-written entries) is preserved.
-
- **Developer workflow:**
-
- - **Update upstream version:** Edit the manifest's `ref` field, run `make vendor-go`, review the diff, commit.
- - **Add a file to an existing profile:** Add a `files` entry to the manifest, run `make vendor-go`.
- - **Add vendoring for a new profile:** Create `scripts/<profile>-vendor-manifest.yml`, add a `make vendor-<profile>` target. The tool is profile-agnostic.
-
- The `make vendor-go` target runs the vendor tool and then `test/test-plugin-structure.sh` to validate the bidirectional index invariant. See `docs/wip/go-vendor-integration/design.md` for the full manifest schema and transform details.
-
- ## ADR location
-
- Architecture decisions that span more than one feature live at `docs/adr/NNNN-slug.md` using [Michael Nygard's template](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions) (Context, Decision, Consequences). Per-feature design docs live at `docs/wip/<feature>/` while work is active and move to `docs/done/<feature>/` on completion — they are not ADRs.
+ @AGENTS.md
# Extra Instructions
@.claude/CLAUDE.extra.md
# capy — context-window routing
@.capy/AGENTS.md