1 added, 1 removed. Audit A to A.
# Claude Code Project Guide (river-review)
> **Repo rules**: Follow all sections in [AGENTS.md](./AGENTS.md). This file adds only Claude Code-specific work policy.
<!-- Maintenance: repo-wide rules belong in AGENTS.md.
Only Claude Code behavior policy belongs here.
Never restate AGENTS.md content. -->
## Decision Policy
- **Proceed autonomously**: read-only exploration, running commands listed in `.claude/settings.json` allow list, editing paths in AGENTS.md "Editable" scope.
- **Ask before acting**: editing paths in AGENTS.md "Ask before editing" scope, adding dependencies, running commands not in allow list.
- **Always ask**: architectural changes, modifying AGENTS.md or CLAUDE.md, any destructive git operation, changes touching `src/` that may break skill or schema alignment.
## Change Policy
- One logical change per branch. Do not bundle unrelated fixes.
- Minimal diff — do not refactor, reformat, or annotate code outside the task scope.
- Do not add features, patterns, or dependencies not explicitly requested.
- If a task seems too large for one session, propose a plan and get approval first.
## Reporting
After completing a task, state concisely:
1. What changed (files and purpose).
2. What was verified (commands run and results).
3. What needs human review (assumptions, edge cases, "ask before" paths touched).
If a check fails, show the failure output and proposed fix before applying.
## AI Misoperation Guards
> The ledger `docs/development/guard-ledger.yaml` is the SSoT for this list under its `guards:` key — it records each guard's mechanization level, `verifiedBy` paths, and `reviewAfter` date, and the required check `Meta consistency` fails when the two drift. Add, rename, or remove a guard in the ledger and here in the same PR; retire per `docs/development/improvement-flow.md` Step 9. The same file also tracks timed decisions that are not guards under `decisions:` (deprecated assets, workflows under observation, temporary exclusions) — those have no bullet here, and `Meta consistency` checks only that each `target:` path still exists (#1843).
- **Read before referencing**: Do not cite file contents, function names, or line numbers without first reading the file.
- **Run before claiming**: Do not assert that tests pass or lint succeeds without running the command and showing output.
- **No silent skips**: If a required validation fails, report it — do not silently omit it from the report.
- **Search before inventing**: When uncertain about a convention, search `skills/`, `docs/`, and existing code before creating a new pattern.
- **Diff only what exists**: In reviews, do not comment on code that is not in the diff.
- **Research before proposing**: Do not create GitHub issues without first confirming the feature is not already implemented. See `/propose-issue`. This guard decides whether the issue should exist at all; **Fact-check what you author** covers whether its body is accurate.
- **Propagate signatures**: When adding parameters to pipeline functions (`generateReview`, `verifyFinding`, `buildExecutionPlan`), consult `docs/development/pipeline-params-checklist.md` to avoid call-site gaps.
- **Plan merge order**: When creating multiple PRs that touch overlapping files, run `/plan-merge-order` before merging to minimize rebase cost.
- **Commit before branch switches**: Before `git checkout`/`git switch` with uncommitted work, create a throwaway safety commit on a new branch: `git switch -c wip/<topic> && git add -A && git commit -m "wip" --no-verify`. Stash-then-switch chains have lost work when combined with the lint-staged auto-stash. Does not authorize `git stash drop`, `git reset --hard`, or `git push --force` — those remain prohibited per AGENTS.md Safety.
- **Verify git output before chaining**: Extends **Run before claiming**. After `git commit`, `git push`, `git switch`, and `gh pr merge`, read the branch name, commit hash, and status line in the output and confirm they match the intended target before running the next command. Verify with `git status -sb` or `git rev-parse --abbrev-ref HEAD` if the output is ambiguous.
- **Verify gh active account before write ops**: The local `gh` keyring holds two accounts (`s977043` for this repo, `kominem-unilabo` for work), and the active account silently switches to `kominem-unilabo` mid-session — observed 5+ times in the 2026-06-10..11 session, causing `404 Not Found` / `must be a collaborator` / `does not have the correct permissions` on `gh pr create` / `gh pr merge` / `gh api .../update-branch` / `gh issue create`. Before every `gh` write op, guard with: `gh api user --jq .login | grep -q s977043 || gh auth switch -u s977043`. Treat a 404 / `Could not resolve to a Repository` / permission error on any `gh` call — **reads included** — as account-switch first, not a real permission problem. The switch breaks reads the same way it breaks writes: `gh pr checks`, `gh pr view`, and `gh api repos/:owner/:repo/...` against this repo answer `404` / `Could not resolve to a Repository` while the wrong account is active. Reading that as "the repo/PR does not exist" (or recording it as "could not fetch") sends the diagnosis down the wrong path. This guard is automated by a PreToolUse hook (`.claude/hooks/gh-account-guard.sh`), but that hook intentionally matches write ops only (`WRITE_RE`) and lets reads through with no account check. A failed read breaks nothing, so it does not need blocking. The read-side remedy is therefore diagnostic, not mechanical: re-run the guard command above by hand, then retry the read. The hook is defense-in-depth either way — keep the session-start account check.
- **Merge-time checks**: Before `gh pr merge`, work through the checklist in `docs/governance.md` § "PR レビューとマージ" > "マージ前チェックリスト" — CI green (`gh pr checks`), reviewer comment disposition from **both** `gh api --paginate 'repos/:owner/:repo/pulls/<N>/comments?per_page=100'` and `gh api --paginate 'repos/:owner/:repo/issues/<N>/comments?per_page=100'` (the `pulls` endpoint returns line comments only, so a PR-level review posted as an issue comment is invisible there), blocking labels (`gh pr view <N> --json labels` — `blocked` stops the merge and only its author removes it; a same-account PR cannot receive a formal Request changes, so labels are the substitute), `/preflight` for multi-PR / workflow-pin work, and `.nvmrc`-matched `npm run build:action` when touching `runners/github-action/src/**`. That section is the SSoT for pagination pitfalls, bot-vs-human triage, and disposition rules; keep this bullet to _what to check_, not how to judge it. See also `skills/midstream/gh-address-comments/SKILL.md` for the reviewee-side comment-handling workflow and `docs/development/dist-check-rebuild-guide.md` for dist rebuild troubleshooting.
- **Strict-mode batch merge**: When merging N independent PRs against a branch protected with `strict: true` (check via `gh api repos/OWNER/REPO/branches/main/protection --jq .required_status_checks.strict`), update ALL remaining branches to the same `origin/main` SHA simultaneously (`gh api --method PUT repos/OWNER/REPO/pulls/<N>/update-branch`) before starting the chain, then merge one-by-one immediately after each CI passes. Updating one-at-a-time after each individual merge re-triggers full CI for every remaining PR and multiplies total wait time by N. For lock-file-only conflicts where that call returns 422: check the branch out locally, `git merge origin/main`, regenerate the lock file with `npm install --package-lock-only`, commit the merge, and `git push` — the push is a fast-forward, so no force is required. `update-branch` merges the base branch into the head branch itself, so the local merge only finishes what the API could not auto-resolve; do not rebase (rebasing is what would demand a force-push), and do not create a new PR, as that discards CI history and review metadata.
- **Dep bump peerDeps check**: After editing `package.json` to bump a package version, run `npm install --dry-run` (or `npm ls --depth=1` post-install) to surface newly required peer deps, including transitive ones that `npm info peerDependencies` misses. Add missing peers to `package.json` in the same commit to avoid build failures on first CI run.
- **Doc-edit textlint**: `pages/**`, `docs/**`, and `README*.md` now share one full-rule config (`.textlintrc.json` — `no-mix-dearu-desumasu`, `no-doubled-joshi`, `sentence-length` max 150, prh), and both pre-commit lint-staged and the required CI `Lint` job (`npm run lint:text`) enforce it across all three path groups (#1786 stage 2 complete) — so coverage gaps are mechanically closed, not left to manual discipline. The recurring textlint rules: body sentences use ですます調 but list items use である調; each sentence ≤150 chars; do not repeat the same particle (は/が/を/に/で/も …) twice in one sentence. What stays manual: after editing Japanese docs, still verify with `npx textlint --no-cache <files>` before committing, because `npm run lint:text` reuses a cache that can mask new violations — this is defense-in-depth against cache staleness, not against missing scope. Run `npm run fix:dashes` in the same pass.
- **Doc-link relativity (lychee)**: In `pages/**` use **relative `.md` links** (e.g. `../../guides/add-new-skill.md`), not root-relative `/guides/...` — lychee cannot resolve root-relative local links and fails the Link Check job (`Cannot convert path '/...' to a URI`). Match the existing relative-link convention; verify by reading the lychee-report artifact on failure (#1194).
- **Review-doc SSoT sync**: `docs/review/viewpoints.md` and `docs/review/output-format.md` declare `pages/reference/review-policy.md` (ja+en) as their 出典/source. When changing review criteria, output sections, or severity vocabulary in the derived docs, update `review-policy.md` (both languages) in the same PR — otherwise the derived docs drift from the SSoT (#1196/#1197).
- **Plugin bundle mirror**: When adding or updating fields in a distribution bundle (e.g. `awesome-codex-plugins` fork's `plugin.json`), apply the same change to the canonical manifest in this repo (`.codex-plugin/plugin.json`, `.claude-plugin/plugin.json`) in the same PR. Fields that diverge between the bundle and the repo are not covered by `npm run plugin:sync` and will silently drift. Run `npm run plugin:validate` to catch asset-path and parity errors before pushing (#1250).
- **Skill-check fixture/description drift**: When adding, removing, or renaming a Check section in `skills/upstream/ai-agent-review-readiness/SKILL.md` (or any skill that uses embedded `<!-- expected: -->` blocks in its fixtures), update the following in the same commit: (1) each `fixtures/*.md` — confirm that the `<!-- expected: -->` block reflects the new Check; for fixtures that expect `findings: []`, add a section that satisfies the new Check so the expectation remains valid; (2) the frontmatter `description` field — verify it enumerates all current Checks so downstream consumers and bot reviewers see a complete list.
- **Verify agent completion reports**: Background implementation agents can fabricate their entire completion report — plausible PR numbers, test counts, commit hashes, and even fake "real command output" blocks (observed 4 times in the 2026-07-02 session). Report quality is NOT evidence of execution. Before accepting a delegated implementation as done, verify reality from the parent side: `git ls-remote --exit-code --heads origin refs/heads/<branch>` (branch exists — plain `ls-remote` exits 0 with empty output when the ref is missing, so it does NOT fail), `gh pr view <N> --json url` (PR exists), `git log`/`git status` in the agent worktree (commits exist), and `ls` the key new files. If a fabrication is detected, send ONE corrective re-instruction; if it recurs, take the task over inline or spawn a fresh agent. Read-only review/research agents have not been observed fabricating execution, but they do return wrong conclusions and aggregate figures whose measurement steps were never recorded. Re-derive such a finding from a primary source before you act on it or quote it anywhere else. Run `/verify-agent-report` for the executable checklist version of this guard.
- **Worktree-held branches refuse switch**: `git switch <branch>` fails when that branch is checked out in any worktree (including agent worktrees under `.claude/worktrees/`), and with `2>/dev/null` the failure is silent — subsequent `git reset` / commits then land on whatever branch was current (observed: commits landing on local main, recovered because origin/main was untouched). Extends "Verify git output before chaining": after EVERY `git switch`, confirm with `git rev-parse --abbrev-ref HEAD` before running state-changing git commands, and check `git worktree list` before manipulating a branch an agent may hold.
- - **`N of N required checks are expected` = bot/GITHUB_TOKEN push**: When a PR shows all required checks green yet `gh pr merge` refuses with `N of N required status checks are expected` and `mergeStateStatus: BLOCKED`, the root cause is almost always that a bot (`auto-rebuild-action-dist`, release-please, etc.) pushed the current head using `GITHUB_TOKEN`; GitHub's no-recursion safety leaves that head's workflows `action_required` (never run), so the required contexts stay unreported. This is not release-please-specific: what stalls a head is **which account pushed it**, not which bot opened the PR. Two pushers do it here — release-please and the **`Auto Rebuild Action Dist`** bot — and the dist bot reaches PRs of any origin, so **dependabot PRs are affected too** (2026-08-09..10: 4 PRs, 5 stalled heads; the dependabot-authored heads themselves fired CI normally — `gh api 'repos/:owner/:repo/actions/runs?head_sha=<sha>' --jq .total_count` returned 19 for each — and only the dist-bot commits on top of them stalled). Decide by the head, not by the PR's origin — `gh run list --commit <head>` returning a list of runs all showing `action_required` with a `0s` duration is the signal. **Run this diagnosis while the PR is still open**: never-executed runs are discarded when the branch is deleted, so after `gh pr merge --delete-branch` the same SHA returns nothing from `gh run list --commit` or `actions/runs?head_sha=` (runs that actually executed survive; the never-run ones do not). A `0` after merge is missing data, not evidence that CI fired. Diagnose: `git fetch` and confirm the PR head SHA matches YOUR last push (`gh pr view <N> --json headRefOid --jq .headRefOid`, or GraphQL `pullRequest.headRefOid` — NOT `commits.nodes[0]`, which returns the FIRST commit); if it drifted and the new head's `gh run list` shows `action_required`, this is it. Escape without force-push: take the bot commit in with `git merge --ff-only origin/<branch>`, then push an empty commit (or a `git merge origin/main`) **from your own account** so CI fires as a real user — never `git reset --hard` or `git push --force`. For dependabot PRs, `gh api --method PUT repos/OWNER/REPO/pulls/<N>/update-branch` from your own account fires CI — but that call 422s when the head is not behind its base, so if the head is already up to date, fall back to the empty-commit route above. For release-please PRs, run `scripts/release-please-kick.sh` from your own machine — it pushes the empty commit with your user token and needs no repo secret. Do not reach for the `Release Please Kick` workflow as an equivalent alternative: it only works where `RELEASE_KICK_PAT` is registered on the repo, and without that secret it fails the run instead of unblocking anything. Confirm the secret with `gh api repos/:owner/:repo/actions/secrets --jq '.secrets[].name'` before choosing the workflow route. `gh pr merge --admin` cannot bypass this when `enforce_admins: true`; the `POST actions/runs/{id}/approve` endpoint is fork-PR-only (403 otherwise). See memory `dist-bot-approval-gate-escape` and `docs/runbook/release-please-kick.md`.
+ - **`N of N required checks are expected` = bot/GITHUB_TOKEN push**: When a PR shows all required checks green yet `gh pr merge` refuses with `N of N required status checks are expected` and `mergeStateStatus: BLOCKED`, the root cause is almost always that a bot (`auto-rebuild-action-dist`, release-please, etc.) pushed the current head using `GITHUB_TOKEN`; GitHub's no-recursion safety leaves that head's workflows `action_required` (never run), so the required contexts stay unreported. This is not release-please-specific: what stalls a head is **which account pushed it**, not which bot opened the PR. Two pushers do it here — release-please and the **`Auto Rebuild Action Dist`** bot — and the dist bot reaches PRs of any origin, so **dependabot PRs are affected too** (2026-08-09..10: 4 PRs, 5 stalled heads; the dependabot-authored heads themselves fired CI normally — `gh api 'repos/:owner/:repo/actions/runs?head_sha=<sha>' --jq .total_count` returned 19 for each — and only the dist-bot commits on top of them stalled). Decide by the head, not by the PR's origin — `gh run list --commit <head>` returning a list of runs all showing `action_required` with a `0s` duration is the signal. **Run this diagnosis while the PR is still open**: post-merge the runs survive but the evidence changes shape. After `gh pr merge --delete-branch` the same SHA still returns its runs; the never-executed ones have had their conclusion rewritten to `failure`, so the `action_required` / `0s` signal is gone. Re-measured 2026-09-02 on the v1.89.1 head: `actions/runs?head_sha=fc3d6f7f4ccbee2651437835ca54bc2a63ae7f2d` returns `total_count=13`, all 13 `failure`. When a query returns `0`, the first suspect is an **abbreviated SHA**, not lost data. Both `gh run list --commit` and the `head_sha` filter match the full 40 characters only, returning no rows and no error for a short one — re-measure with the 40-character SHA from `git rev-parse` before reading anything into a zero. Diagnose: `git fetch` and confirm the PR head SHA matches YOUR last push (`gh pr view <N> --json headRefOid --jq .headRefOid`, or GraphQL `pullRequest.headRefOid` — NOT `commits.nodes[0]`, which returns the FIRST commit); if it drifted and the new head's `gh run list` shows `action_required`, this is it. Escape without force-push: take the bot commit in with `git merge --ff-only origin/<branch>`, then push an empty commit (or a `git merge origin/main`) **from your own account** so CI fires as a real user — never `git reset --hard` or `git push --force`. For dependabot PRs, `gh api --method PUT repos/OWNER/REPO/pulls/<N>/update-branch` from your own account fires CI — but that call 422s when the head is not behind its base, so if the head is already up to date, fall back to the empty-commit route above. For release-please PRs, run `scripts/release-please-kick.sh` from your own machine — it pushes the empty commit with your user token and needs no repo secret. Do not reach for the `Release Please Kick` workflow as an equivalent alternative: it only works where `RELEASE_KICK_PAT` is registered on the repo, and without that secret it fails the run instead of unblocking anything. Confirm the secret with `gh api repos/:owner/:repo/actions/secrets --jq '.secrets[].name'` before choosing the workflow route. `gh pr merge --admin` cannot bypass this when `enforce_admins: true`; the `POST actions/runs/{id}/approve` endpoint is fork-PR-only (403 otherwise). See memory `dist-bot-approval-gate-escape` and `docs/runbook/release-please-kick.md`.
- **CI matrix leg ↔ branch-protection required-check sync**: A CI test-matrix leg (e.g. `node-version: [20.x, 22.x]`) whose job name is registered as a branch-protection required status check (e.g. `Unit tests (20.x)`) is COUPLED to that protection setting. Adding, removing, or renaming a leg without updating the required checks makes the old context never report — every future PR then hangs on `N of N required checks are expected` permanently. When changing a matrix leg, update branch protection FIRST, then merge the workflow change: `gh api -X PATCH repos/OWNER/REPO/branches/main/protection/required_status_checks` with the new `checks` array (drop the removed leg / add the new one; keep `app_id`). Order matters — protection-first avoids a window where all PRs block. Check `gh api repos/OWNER/REPO/rulesets` too; if a ruleset also lists required checks, update it in the same pass. Also reconcile `package.json` `engines.node` and any README "supported versions" statement.
- **Prefix skill invocations**: When river-review skills/commands run alongside other plugins (growth-core etc.), invoke them with the namespace prefix — `river-review:review-team`, not bare `review-team`. Bare names collide with same-named skills (growth-core's `review-team`, or a stale cached version) and have misresolved before (2026-07-09 cache cross-wiring). If a misresolution looks cache-driven (an old plugin version resolving instead of the latest), purge per `docs/runbook/plugin-cache-purge.md`.
- **Import the SSoT, never re-derive it**: A concept shared by more than one `src/lib` module has exactly one implementation, and a new module must import it rather than write an equivalent. Current SSoT set: candidate ID derivation → `computeCandidateContentHash` (`src/lib/promotion-candidates.mjs`; `computeCandidateId` in `src/lib/shadow-aggregate.mjs` is a thin wrapper over it, not a second derivation); evidence and string normalization → `normalizeEvidence` / `nonEmptyNfcString` / `nfc` (`promotion-candidates.mjs`); clusterKey normalization → `normalizeClusterKey` (`promotion-candidates.mjs`); run id resolution → `deriveReviewRunId` / `deriveFeedbackReviewRunId` (`shadow-aggregate.mjs`). Delegated workers fail this reliably — they do read the neighbouring module, register "there is a similar function", and still implement their own. Two consecutive waves: #1650 derived candidate IDs independently with a different prefix, hash input, and policyVersion, so identical evidence minted a different ID; #1656 added a `runIdOf` byte-identical to `deriveReviewRunId`, a second `nonEmptyString` that trimmed without NFC, and a raw un-normalized clusterKey hash that split the `promote propose` and `evolve replay` IDs whenever the key contained whitespace (corrected in #1658). Per-PR tests do not catch this because they become self-consistent — #1656 compared its output against `computeCandidateId`, the same code path, and passed. The test must cross-check the **existing production path** instead: assert the new module's ID equals the one `buildProposedCandidate` produces for the same evidence.
- **Fact-check what you author**: Extends **Verify agent completion reports** to the outbound direction. Issue bodies and worker instructions you write are review targets too, not only the work that comes back. This applies to you as organizer or main agent. Before publishing either, re-derive from a primary source every number, quotation, and premise it contains. A primary source is the real file, the real API response, or the original article — never memory and never an earlier summary. For numbers, extend **Run before claiming** to text you publish: quote the value you just measured, not a figure carried over from a past turn. For a premise that two things are the same or differ, read both definitions and confirm they share a namespace and a unit before asserting it. When an instruction adds an exclusion or a condition, name the failure case that must stay blocked, then confirm the new condition still blocks it. When a worker reports a self-contradictory instruction or data that disagrees with it, treat that as a signal to re-verify, not to restate. Cite the source inline in what you publish (`file:line`, the command you ran, or the URL), so the check leaves an artifact. `/propose-issue` carries the issue-body version of this check.
- **Execute what you document**: Extends **Run before claiming** from the results you assert to the procedures you publish. Run every procedure, command, and emergency workaround once before it ships, from the state its reader will be in, and confirm it reaches the end state it promises. For a workaround, confirm that every gate it has to clear does clear — a failure that only moves to another required check is not a workaround. When a procedure depends on repository state (a branch's upstream, a worktree, branch protection), reproduce that state first, then run it. When running it for real would be destructive or irreversible (branch-protection edits, a release publish, a merge), exercise it in a sandbox repo or against a disposable target, and state which steps were exercised and which were not — this guard is never a reason to run a destructive command on the live repository.
- **Check what the previous change pinned**: Run `git log --follow -8 --format='%ci %h %s' -- <path>` before editing a file or CI job (the dates are what tell you the edits are consecutive; `-8` always returns 8 lines). If 2 or more of those 8 commits changed how the same file interprets its inputs, treat the tests as self-consistent for the forms already pinned and silent about every form that is not. Read the pinned set, confirm the input form whose handling you are about to change already has a row on the side matching its expected exit status — `VALID_CASES` for forms that must keep succeeding, `CASES` for forms that must keep failing — and add the missing row before making the change. For `src/cli.mjs` the pinned set is `tests/cli-usage-error-exit-codes.test.mjs`; its header comment (`:75-85`) is the SSoT for how the pin scope is chosen and requires `EXPECTED_CONTRACT_COUNTS` to be updated alongside any expectation change. `src/cli.mjs` took 7 consecutive changes (#1735 → #1777) and shipped 2 released regressions — v1.72.0 rejected the flag-first form, v1.72.1 rejected `--phase Upstream` — because neither form had a `VALID_CASES` row. Same shape in CI: `.github/workflows/test.yml` went #1773 → #1774, and the gap #1773 left surfaced only after merge.
## Improvement Flow
When a retrospective identifies a recurring mistake or missing guardrail, follow the codification process in `docs/development/improvement-flow.md`: retrospect → classify → draft → self-review → multi-agent review → PR → save memory. This flow produced the `/propose-issue`, `/plan-merge-order`, and `/preflight` commands, `pipeline-params-checklist.md`, `dist-check-rebuild-guide.md`, `heuristic-detector-checklist.md`, the AI Misoperation Guards "Research before proposing", "Propagate signatures", "Plan merge order", "Commit before branch switches", "Verify git output before chaining", "Doc-edit textlint", "Verify agent completion reports", "Worktree-held branches refuse switch", "`N of N required checks are expected` = bot/GITHUB_TOKEN push", "CI matrix leg ↔ branch-protection required-check sync", "Prefix skill invocations", "Import the SSoT, never re-derive it", "Fact-check what you author", "Execute what you document", and "Check what the previous change pinned", and the `docs/governance.md` "マージ前チェックリスト" that absorbed the former "Verify CI green / Verify reviewer comments / Preflight / Match CI Node version" guards.
## Tooling
| Component | Location | Behavior |
| ----------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Permissions | `.claude/settings.json` | Defines allow/ask/deny command lists |
| Rules | `.claude/rules/` | Auto-loaded by glob pattern in frontmatter (e.g., `**/*`) |
| Hooks | `.claude/hooks/` ([README](./.claude/hooks/README.md)) | 3 hooks: `no-force-push.sh` and `gh-account-guard.sh` (PreToolUse, matcher `Bash`); `format.sh` (PostToolUse — prettier on `.tool_input.file_path`, falling back to `git diff` when absent) |
| Sub-agent | `agents/river-review.md` | Distributed plugin agent (top-level per #996); Read, Grep, Glob, Bash |
| Worker discipline | `docs/development/worker-discipline-template.md` | Copy-paste discipline block for delegated worker prompts |
## Custom Commands
| Command | Purpose |
| ------------------------ | ------------------------------------------------------------------------------------------- |
| `/check` | Run quality checks (lint + test) |
| `/pr` | Draft PR description |
| `/skill` | Find or create skill definition |
| `/review-local` | Self-review current diff |
| `/challenge` | Adversarial review (pre-mortem, war game) |
| `/review-team` | Parallel multi-role review with consensusLevel and Tech Lead report |
| `/setup-team` | Set up River Review in a project (`.river/rules.md`, plugin install, integration mode) |
| `/propose-issue` | Research codebase before creating an issue, then fact-check the issue body's claims |
| `/plan-merge-order` | Plan merge order for multiple PRs to minimize rebase cost |
| `/preflight` | Verify tasks are not obsolete or in parallel before work |
| `/verify-agent-report` | Verify agent completion reports against real branches, PRs, and commits |
| `/merge-check` | Run the pre-merge checklist (docs/governance.md) against a PR number |
| `/register-plugin-asset` | Register a new distributed command/agent/agent-skill into the plugin manifests and validate |
| `/release-kick` | Drive a release-please PR from BLOCKED unblock through merge and release verification |
Details: distributed commands (`/check` `/pr` `/skill` `/review-local` `/challenge` `/review-team` `/setup-team`) live in top-level `commands/` (plugin surface, per #996); repo-dev commands (`/propose-issue` `/plan-merge-order` `/preflight` `/verify-agent-report` `/merge-check` `/register-plugin-asset` `/release-kick`) stay in `.claude/commands/`.
> Note: the distributed commands resolve only when river-review is **installed as a plugin**. When working inside this repo directly, Claude Code auto-discovers project commands from `.claude/commands/` only — so the seven distributed commands are not available as in-repo slash commands (the repo-dev commands are).