git:20260915.ccc644b to git:20260915.96b4731

3 added, 0 removed. Audit A to A.

# Working on tagout
This repo ships as a Claude Code plugin (bash + python + markdown skills, no build step). The
per-repo profile at [`.claude/skills/repo-profile.md`](skills/repo-profile.md) is the single
source of commit identity, build/test commands, CI gates, labels and conflict hot-spots — read it
first.
## Routing
The kit is what is being dogfooded here, so its own skills come first. Which one, for what: the
routing table in `AGENTS.md` — its one home since #525, where every host reads it — imported here so
a session in this repository sees it whether or not the plugin is installed:
@../AGENTS.md
## Where each concern lives
- Prerequisites (runtime) → [`requirements.json`](../requirements.json), never a hard-coded list;
`scripts/preflight.sh` reads it.
- Control-flow decisions → [`decisions/registry.json`](../decisions/registry.json) +
[`docs/decisions.md`](../docs/decisions.md) — one id, one program, one home.
- Architectural decisions → the profile's `## ADRs` section (`.claude/skills/repo-profile.md`) — `docs/adr/`.
- Domain language → [`CONTEXT.md`](../CONTEXT.md).
- Trigger contracts → `evals/<skill>-trigger-eval.json`, the one home (#331); structure checked by `tests/skills/check-frontmatter.py`.
- Shared test preamble → `tests/_lib.sh` (`local rc=$?` must be the first statement in its trap).
- Shared skill procedures → `skills/_shared/`.
- Kit backlog (YAGNI debts) → [`docs/backlog.md`](../docs/backlog.md), hand-edited, read by
`scripts/followups.py`.
+ - The two plugin directories → generated copies, never hand-edited ([ADR 0017](../docs/adr/0017-the-two-plugin-trees-ship-as-generated-copies.md)):
+ edit the source under `skills/`, `scripts/`, `hooks/`…, then `python3 scripts/host-adapters.py build`
+ and commit both halves; `check` refuses a drifted copy, an orphan, a symlink (#619) or a mode mismatch.
## Adding a skill
- The folder name obeys one of the two naming rules — `verb-object`, or `<family>-<role>` for a
family member. The name is the identifier six times over, and renaming one is a breaking change,
so it only happens in a major: [ADR 0012](../docs/adr/0012-two-skill-naming-rules-verb-object-and-family-role.md).
- Frontmatter carries no `version` key — `tests/skills/check-frontmatter.py`.
- A trigger contract exists for it — `evals/<skill>-trigger-eval.json`, listed in `evals/run_all.py` and `evals/trigger_eval.py`.
- A golden suite is wired into CI — `scripts/ci-wiring-check.py`.
- A script that makes a decision is registered in `decisions/registry.json`, or named in that
file's `not_decisions` map with a one-line reason.
- The skill is linked from `README.md` — `tests/skills/test.sh`.
- The PR title is releasable — `scripts/release-title-gate.sh`.
## The guard convention
A destructive operation gets a guard script under `skills/<skill>/scripts/`, a golden test that
exercises its **refusal** path (not just its happy one), and a CI step that runs it — never the raw
command. See the README's "Hardening a destructive operation".
## Releases
Squash-merge only; the PR title *is* the release commit release-please parses
(`scripts/release-title-gate.sh` gates it). Never bump `plugins/tagout/.claude-plugin/plugin.json` (and its `tagout-migrate` twin) by hand.
## Commit identity
The profile's author line (`.claude/skills/repo-profile.md`) is canonical; this file sets none.