AGENTS.md · git:20260921.e55f564 · 2026-09-21 · sha256 a385f9e34b4e32bf

AGENTS.md git:20260921.e55f564B

Immutable. This exact content never changes and is served at /api/v1/blob/a385f9e34b4e32bf.

# AGENTS.md

> **This is the repository's single agent guide.** It used to be named
> `CLAUDE.md`; that file is gone so there is exactly one copy of these rules.
> Older Claude Code releases only read `CLAUDE.md` — if yours is one of them,
> point it at this file rather than re-creating that one (see the
> `init-workspace` skill for the same rule applied to target projects).

Guidance for AI coding agents working in **this** repository (`agentic-workflow`).

This repo is **not** an application. It ships two things:

1. **`skills/`** — a stack-agnostic set of agent skills that run a disciplined,
   doc-driven feature/issue workflow. Each is one `skills/<name>/SKILL.md`.
2. **`template/`** — an exportable documentation scaffold: the *way of working*
   (documentation map, SPEC/feature/fix templates, GitHub templates, conventions)
   that a target project copies so the skills have a substrate to operate on.

The skills are **project-adaptive**: at runtime they discover and obey the target
project's own guide, documentation map, architecture, roadmap and style docs.
Nothing here is tied to a specific stack, framework, or architecture pattern.

---

## Repository layout

```
skills/                  the workflow skills (one SKILL.md each) — the installable source
template/                the exportable documentation scaffold (generic, copyable)
packages/                two companion npm packages (bun-managed islands — see Packages below)
docs/workflow/           the tutorial: feature flow, issue flow, skill reference, replication
docs/features/_TEMPLATE  feature SPEC template + ROADMAP
docs/fix/                fix SPEC template + index
.github/                 issue + PR templates the workflow expects
README.md                project overview
```

**Dogfooding model (authoring):** repo sessions consume the workflow from the
installed release (Pi package / installed plugin), not from the working copy.
The committed layout carries no working-copy activation surface. Authoring
sessions opt in by creating a local, gitignored mount
(`ln -sfn ../skills .claude/skills`) or by exercising a single working-copy
skill via per-session flags (e.g. `pi --no-skills --skill skills/<name>/SKILL.md`).

---

## Working rules

- **Docs language is English-only (interim).** Every committed artifact (skills,
  docs, templates, `README`, `CHANGELOG`, commits, PR descriptions) is in English,
  regardless of the language used to request the work; reply to the user in the
  user's language. The bilingual EN/ES `.es.md` siblings and their reciprocal
  language-switcher links were removed repo-wide (2026-09-15) to stop paying a
  per-commit translation cost. Feature 57 (`per-release-bilingual`, issue #232)
  restores bilingualism as a per-release batch pass. Until then: do **not** create
  or update any `.es.md` sibling and do **not** add a language-switcher link.
- **Vendored third-party code carries its provenance.** Any code copied from a
  third party into this repository — into a package's `src/`, a script, or a
  skill reference — keeps a header comment naming the **source URL, the author,
  the version copied, and the license name**. A copy without those four is a
  provenance defect, not a formatting slip: nothing else in the tree says where
  the bytes came from, so an upstream relicensing or an attribution obligation
  cannot be audited later. Vendoring is a real alternative to adding a
  dependency and it is weighed as one (unit 28's D36 rejected a 1,419-line
  copied `sha256` closure on measured cost and kept the package's own core, and
  AC21 keeps the schema package dependency-free); whichever route a change
  takes, the provenance header is mandatory for the first.
- **Stack/architecture agnostic.** Do not introduce references to any specific
  product, stack, framework, ORM, runtime, or architecture pattern into the
  skills or the shared docs. Generic phrasing ("the project's architecture",
  "the project's verification gate") is the rule.
- **One PR per unit of work, always against `main`.** Never work on `main`
  directly; never stack PRs (a PR's base is always `main`).
- **Commit format:** conventional commits, e.g. `feat(skills): add execute-phase`,
  `docs(workflow): clarify replicate steps`, `chore(template): add brand stub`.

---

## Authoring a skill

A skill is a folder `skills/<name>/SKILL.md` with YAML frontmatter + a body.

```yaml
---
name: <kebab-case-name>          # must match the directory name
user-invocable: true             # REQUIRED for it to appear in the agent's /command menu
version: 1.0.0                   # per-skill semver; bump on every change (see below)
description: >
  One paragraph with concrete trigger phrases so the agent knows when to load it.
---
```

Body sections every skill follows: `When to use`, `Step 0 — Discover the project
(always first)`, `Process`, `Guardrails`, `Relationship to other skills`,
`Done when`.

> **`user-invocable: true` is mandatory.** Without it, the skill is not offered
> in the slash-command menu in this environment. Always set it explicitly.

> **Always close with a `→ Next:` block.** Every skill ends its turn with a
> **visible recommendation block** — not a buried "Done when" bullet. The shape is
> the "review checkpoint" style: one **recommended** command on the `→ Next:` line,
> then the open alternatives as `·` sub-bullets, leaving the choice to the user
> (recommend, never dictate). Use this exact shape:
>
> ```
> → Next: /<recommended-command> — <one-line why>
>   · <alternative> → <when to pick it>
>   · <alternative> → <when to pick it>
> ```
>
> Two cases the block must cover when they apply: (a) **finishing a unit/feature** →
> point to the next concrete unit (`/plan-feature --next`, or a named issue/roadmap
> entry); (b) **recurring inconsistency** — when `review-change`/`triage-issue` see
> the *same* problem twice (e.g. SPEC drift on consecutive units) → recommend
> `/product-audit`. A terminal verdict still names what to do with it (merge,
> re-audit, triage). This is part of "Done when" for every skill.

> **Phases are `P1, P2, …` ("phases"), never "Steps"/`S1`.** Any skill that
> produces or references a plan labels implementation steps `P1, P2, …` and calls
> them *phases* (a Spanish or other-language UI may say "fases"/"pasos", but the
> committed artifacts and the labels stay `P1, P2, …`). The label is the executor's
> argument (`execute-phase NN P2`), so it must be stable and uniform — never emit
> `S1`/`S2`/"Step N" into a `PLAN.md`, `TASKS.md`, `progress.md`, SPEC, or roadmap.

> **Checklists over heuristics; fixed output formats.** Skills are executed by
> models of any strength, not only frontier ones — write instructions a weaker
> model cannot misread: (a) heuristics become **checklists** ("pass only if: ✓ …"),
> every item independently checkable, n/a stated explicitly; (b) reports and
> verdicts carry a **fixed output contract** ("Return exactly: …" with the block
> quoted) ending in an unambiguous decision (`PASS | FAIL`,
> `MERGE-READY | BLOCKED`, a named verdict); (c) bound freedom with
> **Allowed / Forbidden lists** wherever a skill could "improve" beyond scope;
> (d) "if needed" is banned — name the minimum set to verify (docs, files,
> checks). Claude tiers stay the declared defaults (they set the reference bar),
> but every skill must run correctly on any agent and any model — see the README
> model-equivalence table.

> **Complete dynamic hand-offs.** When the invocation or artifact contains more
> than one issue, dependency, finding, or other target, the closing recommendation
> must name every actual ID once, in order, joined with ` + ` (for example,
> `#71 + #72 + #73`). A command may use the designated primary when its syntax
> requires one, but the full set must remain visible beside it. Never emit only
> the primary, a generic "act on the verdicts", or literal placeholders/ellipsis
> in a live hand-off.

> **Turn contract at the top.** Every user-facing skill opens with a
> `## Turn contract` section: the 2–6 boxes every invocation must tick before
> the turn may end (the deliverable in its fixed format; the closing `→ Next:`
> block printed **last**; for executors: git/forge commands actually **RUN**
> with sha/PR-URL pasted — describing an action is not performing it). Weaker
> models drop end-of-document duties, so the contract goes first, and every
> skill states that an about-to-end turn with an unchecked box is not done.

> **Self-contained reviews — never depend on external skills.** The review axes
> are covered by the repo's **own internal review pack**
> (`skills/review-*`: code, security, verify, debt, design, a11y, brand, perf,
> seo — each a fixed checklist returning a findings table + `PASS | FAIL`).
> `review-change` / `product-audit` compose the pack; platform skills a project
> installs are **optional extras run in addition, never dependencies** — a skill
> body must never require a Claude Code-bundled or third-party skill to function.

> **Every user-facing skill carries a `## Portability` section.** The skills
> install into 70+ agents via the `skills` CLI; Claude Code features (slash-command
> menu, per-skill `model:`/`effort:`, `/loop`, subagents, hooks, `ultracode`) are
> conveniences, **not the contract**. Every `user-invocable: true` skill includes a
> short `## Portability (agents other than Claude Code)` section stating the
> fallbacks that apply to it, drawn from these standards:
> *no slash menu* → open the target skill's `SKILL.md` and follow it literally in a
> fresh conversation; *no model tiers* → strongest model for planning/review/audit,
> cheaper for mechanical execution, and never review a change with a model weaker
> than the one that wrote it; *no `/loop`/subagents* → re-invoke manually and follow
> the closing `→ Next:` block. Tailor per skill (e.g. hooks for `log-session`,
> subagents for `ship-roadmap`). Additionally, whenever a skill body references a
> Claude Code-specific feature, pair it **inline** with the generic fallback — the
> instruction must be executable by an agent that has never heard of Claude Code.

> **Version every change.** Each skill carries its own `version:` and evolves
> independently. When you change a skill, bump its `version:` (major = rename or
> contract/flag change; minor = backward-compatible capability; patch = wording/
> examples) and add a line to [`CHANGELOG.md`](CHANGELOG.md). Renames are major and
> need a note in `docs/workflow/MIGRATION.md`. Until [#176](https://github.com/gtrabanco/agentic-workflow/issues/176)
> is merged, freeze majors: bump `minor` (or `patch`) only, shipping breaking changes
> as a `minor` bump with a conventional `BREAKING CHANGE:` footer ([#209](https://github.com/gtrabanco/agentic-workflow/issues/209)).

> **Smoke-test wording changes to executor-path skills.** After editing
> `execute-phase`, `plan-feature`, `plan-feature-scaffold`,
> `plan-feature-from-issue`, `design-feature`, or a `review-*` skill, run the
> manual procedure in
> [`docs/workflow/GOLDEN_FIXTURE.md`](docs/workflow/GOLDEN_FIXTURE.md) — it
> drives a fixed toy fixture through the changed skill with the weakest model
> in your fleet to catch wording a frontier model absorbs silently but a weak
> model misreads.

### Hand off, don't compose across a model/effort boundary

A skill's `model` and `effort` are **fixed at the start of its turn** and do **not**
change when it loads another skill mid-turn (verified against the Claude Code
skills / model-config docs). So invoking skill B from skill A runs B at **A's**
model and effort, not B's — silently under- or over-powering B.

**Rule (the test is ≥, not "same"):** before composing skill B in-turn, compare
tiers. Compose **only when A's model/effort is ≥ B's** (so B isn't under-powered).
If B needs a **higher** model or effort than A, **hand off** instead — print
`run /<skill>` / the next command and let the user invoke B in a fresh turn at its
own tier. Most of the flow already hands off (`plan-feature` prints
`execute-phase NN P1`; `plan-fix` stops and suggests `execute-phase --fix`;
`triage-issue`/`review-change`/`audit-pr` route with suggestions; `execute-phase`
hands off to `/review-change` at its review checkpoint).

**Why ≥ and not "same":** composing at a *higher* tier (e.g. `product-audit` at
`opus`/`max` running `audit-docs`'s `sonnet`/`medium` checks) over-powers B —
harmless, just costlier. Composing at a *lower* tier (the bug we hit: `execute-phase`
at `sonnet`/`medium` running `review-change` at `opus`/`high`) **under-powers** B — a
real regression. So the orchestrators and routers, which are the high-tier (`opus`,
`high`/`max`) skills, may safely compose what they synthesize: `review-change` →
`review-implementation` + companions; `product-audit` → its sub-checks; the
`plan-feature` router → its `opus` internals (it carries the highest effort of its
paths). Everything else hands off.

> Note: `ultracode` is a Claude Code **session setting** (xhigh effort + automatic
> multi-agent workflow orchestration), **not** a frontmatter `effort:` value — a
> skill cannot declare it. The accepted `effort:` values are `low`/`medium`/`high`/
> `xhigh`/`max`.

---

## Distribution

The skills install with the [`skills`](https://github.com/vercel-labs/skills) CLI,
which reads the `SKILL.md` files straight from this repo into any supported agent
(Claude Code, Cursor, Codex, …):

```sh
npx skills add gtrabanco/agentic-workflow
```

There is no build step and no generated installer — adding a skill is just adding
a `skills/<name>/SKILL.md`. Full replication guidance is in
`docs/workflow/REPLICATE.md`.

---

## Verification

This repo has no application build. "Green" means:

- The `skills` CLI discovers every skill: `npx skills add . --list` lists them all.
- Markdown is well-formed; cross-references between docs resolve.
- Context budgets pass: `bun scripts/check-skill-context.mjs` (every skill's
  `SKILL.md` is within its enforced line/token budget and reference reachability).
- No stack/real-project references leaked into the skills or shared docs.
- Root suites pass: `node --test scripts/*.test.mjs` — including
  `scripts/golden-fixture.test.mjs`, which asserts the golden fixture's deterministic half.
- If `packages/agentic-workflow-schema/` was touched: `bun run test` passes
  there, and any change to the envelope schema in
  `skills/orchestration-envelope/SKILL.md` is mirrored in the package (types +
  `envelope.schema.json` + version bump) — same PR, always.
- If `packages/pi-agentic-workflow/` was touched: `bun run test` passes there.
  Nothing to re-bundle by hand: `skills/` at the repo root is the only skills
  tree in git, and the package stages its filtered copy at test and pack time
  (that copy is gitignored and deleted again by `postpack`).
  `test/alias-coverage.test.mjs` and `test/skill-parity.test.mjs` read both
  trees; the staged one is always rebuilt first, so it is never stale.

**Runtime convention (one rule, everywhere):** scripts run with **bun first**
(`bun scripts/x.mjs`, `bun run <pkg-script>`); when bun is absent, the same
command with `node` (`node scripts/x.mjs`, `npm run <pkg-script>`) is the
guaranteed fallback, enforced by a node-compat CI job. Skill prose and usage
strings show the bun form; skills running in user projects resolve
bun-else-node at invocation (`AGENTIC_WORKFLOW_RUNTIME=bun|node` overrides;
`npm_config_user_agent` starting with `bun/` pins bun). The shebangs stay
`#!/usr/bin/env node` — the portable fallback, since a shebang cannot express
"bun else node".

### Normalizer inventory (this repository)

The rule that orders these steps — and the fact that a post-freeze byte change voids
the receipts that bound those bytes — is owned by
`skills/execute-phase/references/PRE_EXECUTION_GATE.md` §"Normalizer order"; this list
only says which of **our** steps rewrite bytes and where they sit relative to a
snapshot or acceptance freeze. `scripts/pre-execution-quality.test.mjs` parses this
block and refuses the schedule if a mutating step is ever re-marked as a tail step.

```text
normalizer-inventory@1
step | kind | side
bump-skill | version bumper and doc writer (rewrites SKILL.md `version:`, the CHANGELOG table, README/SKILLS cells) | before
bun run bundle:skills | generator (stages the pack-time skill bundle at `packages/pi-agentic-workflow/skills/`; gitignored and removed by `postpack`, so it is build output, never a committed mirror) | before
bun run build (packages/agentic-workflow-schema) | generator (`tsc`, emits `dist/`) | before
generate-pre-execution-schemas.mjs | generator (writes the two `pre-execution-*.schema.json` projections) | before
generate-verification-schemas.mjs | generator (writes the verification schema projections) | before
generate-docs | docs generator (writes `docs/site/guides/`) | before
generate-pre-execution-schemas.mjs --check | check-only (drift report, `bun run check:pre-execution-schemas`) | after
generate-verification-schemas.mjs --check | check-only (drift report, `bun run check:verification-schemas`) | after
pre-execution-snapshot.mjs verify | check-only (re-derives a bound digest, writes nothing) | after
bun scripts/check-skill-context.mjs (--routes) | check-only (budget report, writes nothing) | after
probe-sha256-paths.mjs (packages/agentic-workflow-schema) | check-only (SHA-256 path and cost probe, `bun run probe:sha256-paths`, prints digests/timings, writes nothing) | after
formatter | none declared — this repository has no Prettier, Biome or EditorConfig configuration, so the formatter category is empty here | n/a
```

### Normative surfaces (the drift gate's scope)

A *normative surface* is a place that orders what an agent may do next: a flag it
may pass, a gate trace it may print, a verdict it may emit, a field it may write,
a route it may hand off to. Feature 28's AC15 binds each of those to the machine
surface that accepts it — the schema package's published vocabularies
(`packages/agentic-workflow-schema/src/`), the `argument-hint:` frontmatter of each
skill, and the skill directory itself. The gate reads **versioned grammar only**:
a `block:` id, a `fenced:` fixed-output contract, a `table:` section, a
`schema-export:` published const read from committed source, or frontmatter.
It never parses a sentence, so a surface with no fixed grammar in the `grammar` cell
is the defect this table exists to prevent, and `scripts/normative-drift.test.mjs`
fails closed on it. `machine` names the vocabulary the surface's tokens resolve
against (`+` joins several); `must-name` is `yes` only where the machine's every
value must be ordered by some surface, which is the direction that catches a value
published and never declared anywhere else. The `#` lines are directives: host
commands a hand-off may print that are not skills.

```text
normative-surfaces@1
# hand-off-host-commands: clear
surface | file | grammar | machine | must-name
skill-declared-arguments | skills/*/SKILL.md | frontmatter:argument-hint | n/a | no
closing-hand-offs | skills/*/SKILL.md | fenced:→ Next: | skill | no
gate-rejection-vocabulary | skills/pre-execution-review/references/POLICY.md | block:gate-rejection-vocabulary@1 | gate-rejection-type | yes
preflight-gate-traces | skills/execute-phase/references/PREFLIGHT.md | fenced:GATE REJECTION — | gate-rejection-type | no
pre-execution-gate-trace | skills/execute-phase/references/PRE_EXECUTION_GATE.md | fenced:GATE REJECTION — | gate-rejection-type | no
plan-mode-routing | skills/plan-feature/references/ROUTING.md | block:plan-mode-routes@1 | skill+flag | no
fix-mode-routing | skills/plan-fix/references/PLANNING_PROCESS.md | block:fix-mode-routes@1 | skill+flag | no
review-spec-verdicts | skills/review-spec/references/OUTPUT.md | fenced:SPEC-REVIEW-PASS+Verdict: | pre-execution-verdict | yes
review-plan-verdicts | skills/review-plan/references/OUTPUT.md | fenced:PLAN-REVIEW-PASS+Verdict: | pre-execution-verdict | yes
review-spec-handoff | skills/review-spec/references/OUTPUT.md | fenced:→ Next: | skill | no
review-plan-handoff | skills/review-plan/references/OUTPUT.md | fenced:→ Next: | skill | no
sensor-labels | skills/workflow-status/references/PRE_EXECUTION.md | table:One label per stage | n/a | no
snapshot-commands | skills/pre-execution-review/references/SNAPSHOT.md | fenced:--stage | pre-execution-stage+pre-execution-unit-kind | no
ledger-ownership-map | skills/pre-execution-review/references/LEDGERS.md | block:ledger-ownership@1 | n/a | no
ledger-review-mark-shape | skills/pre-execution-review/references/LEDGERS.md | block:review-mark@1 | n/a | no
ledger-finding-mark-shape | skills/pre-execution-review/references/LEDGERS.md | block:finding-mark@1 | n/a | no
ledger-gate-ran-mark | skills/pre-execution-review/references/LEDGERS.md | block:gate-ran@1 | n/a | no
sensor-envelope-fields | skills/workflow-status/references/SENSOR_CORE.md | block:sensor-fields@1 | envelope-field | no
continuation-refusal-vocabulary | packages/agentic-workflow-schema/src/continuation.ts | schema-export:CONTINUATION_REFUSALS | continuation-refusal-type | yes
turn-contract-fields | skills/orchestration-envelope/references/TURN_CONTRACT.md | block:hand-off-fields@1 | envelope-field:next | yes
turn-contract-transitions | skills/orchestration-envelope/references/TURN_CONTRACT.md | block:hand-off-transitions@1 | workflow-intent | no
turn-contract-receipt | skills/orchestration-envelope/references/TURN_CONTRACT.md | block:turn-contract-receipt@1 | n/a | no
path-protection-contract | skills/orchestration-envelope/references/TURN_CONTRACT.md | block:path-protection@1 | path-protection-reason | no
path-protection-reasons | packages/agentic-workflow/src/path-policy.mjs | schema-export:PATH_GUARD_REASONS | path-protection-reason | no
```

### Rendered facts (prose that restates a machine value)

Where prose repeats a version, a count, or a contract id, the machine is
authoritative and the prose is the defect (AC15). A regex over sentences cannot
find those, so each restatement is declared once here and the test **recomputes**
the value: `claim` is a fixed form (`literal:<exact text>`, `version-tables`,
`package-versions`), `machine` names the publisher, `+` joins surfaces that each
carry the same fact. `literal:` compares the number or id inside the quoted text;
the table kinds compare every row the same way. A restatement found in review but
not pinned here is a known-issue with its re-trigger condition, never a silent gap.

```text
rendered-facts@1
surface | claim | machine | rule
docs/workflow/SKILLS.md | pattern:\*\*(\d+) user-facing skills\*\* | count:user-facing | equals
CHANGELOG.md | version-tables | frontmatter:version | equals-each
CHANGELOG.md | package-versions | package:version | equals-each
skills/review-spec/references/OUTPUT.md + skills/review-plan/references/OUTPUT.md | literal:agentic-workflow/pre-execution-review-receipt@1 | const:PRE_EXECUTION_RECEIPT_CONTRACT_ID | equals
```

The two schema generators are the clean example of the split the rule turns on: the
same script rewrites a projection or reports on it, and only the reporting mode may
run after a freeze. `bundle:skills` stages a gitignored build artifact that the
package's own lifecycle stages and removes again, so no one has to sequence it by
hand. No script or skill may keep a second copy of this list.

---

## Packages

The two npm packages under `packages/` are independent bun-managed islands,
not a workspaces monorepo — there is no root `package.json` and nothing
hoists.

- **bun is the package manager, everywhere.** `bun.lock` (committed) is the
  sole lockfile: install with `bun install --frozen-lockfile`, run scripts
  with `bun run <script>`. A `package-lock.json` inside any package is drift
  — each package's `.gitignore` rejects it and
  `test/lockfile-policy.test.mjs` fails the suite if one appears (both npm
  lockfiles resurrected once, on main, and had to be removed again). The npm
  CLI is still used for the publish step only (Trusted Publishing +
  `--provenance` are npm-CLI-specific tooling Bun doesn't replicate).
- **Dependency versions are pinned.** Every `dependencies`/`devDependencies` entry in both packages uses an **exact version** (no `^`, `~`, or major-only ranges) — a fresh install must reproduce the committed lockfile byte-for-byte. `peerDependencies` stay ranges by nature (they resolve against the host's own version — e.g. the pi peer). Dependency **upgrades are deliberate `fix(deps)` PRs on a cadence** (not side effects of other work): bump the pinned versions, re-run the gate, ship as a patch.
- **Version bumps are manual and same-PR.** Bump `version:` in the touched
  package's `package.json` and add a row to the "Companion npm packages"
  table in `CHANGELOG.md` in the same PR. CI publishes on merge to `main`
  when the version differs
  from the registry (`publish-schema.yml`, `publish-pi-package.yml` — one
  file per package, because npm Trusted Publisher records pin the workflow
  filename; a rename would break the npm-side record until re-registered by
  hand).
- **Changesets: deliberately not adopted** (decided 2026-08-30). The curated
  changelog tables above are the release-notes surface; changesets
  would fork them into per-package English-only `CHANGELOG.md` files,
  require re-binding both packages' npm Trusted Publisher records to a new
  release workflow, and add a version-PR loop for exactly two independent
  packages with no cross-dependencies. Revisit when a third package lands or
  per-package beta/snapshot channels are needed.

---

## Conventions

| Type | Convention |
|---|---|
| Skill directories | kebab-case (`execute-phase`) |
| Markdown docs | kebab-case or SCREAMING_CASE per existing siblings |
| Skill `name:` | matches the directory name exactly |
| Machine/config surfaces (`.claude-plugin/plugin.json` `skills` array) | alphabetical |
| Narrative surfaces (README "The skills" `###` sections, `docs/workflow/SKILLS.md`) | flow order (the stage a skill runs at: Setup, Design, Plan, Execute, Review & audit, Decide, Document, Session, Repo maintenance, Autopilot) — never alphabetized |

---

## Skills available in this repo

When repeated searches or repeated documentation lookups happen while working
here, prefer creating or refining a skill over re-deriving the knowledge. Store
reusable operational knowledge as a skill under `skills/`.

**Repo maintenance skill (specific to this repo):**

- **`bump-skill`** — after editing any SKILL.md, run this before committing.
  It bumps `version:`, adds changelog rows to `CHANGELOG.md`, and updates the
  skills and model tables in `README.md`.
  This is the mechanical enforcement of the "Version every change" rule above.
  `bump-skill` itself is `user-invocable: false` — invoke it via the Skill
  tool / by following its `SKILL.md` directly, not the slash-command menu.
  It also carries `metadata.internal: true`, the `skills` CLI's own gate
  that keeps `npx skills add` from discovering/offering repo-internal
  skills to target projects (see `docs/fix/74-bump-skill-discovery-exclusion/`).