Imported from 0xjgv/harness (
rust/AGENTS.md). Install upstream withnpx skills add 0xjgv/harness --skill rust. Copyright stays with the author.
CLAUDE
Commands
- After edits:
cargo harness check— fix, format, lint, test, suppression ratchet - Pre-commit:
cargo harness pre-commit— runs when Rust files are staged (auto via git hook): clippy fix + format. A stagedCLAUDE.mdis copied toAGENTS.mdand staged with it; a hand edit toAGENTS.mdalone fails. Stagedarch.tomlchanges warn, they do not fail. Tests run at pre-push. - Pre-push:
cargo harness pre-push— branch guard runs first and short-circuits (refuses pushes to main/master unlessHARNESS_ALLOW_PROTECTED_PUSH=1, printing only the refusal and exiting before anything else runs); then the arch config guard, then agents-md-drift as a separate hard check, then the test suite (alone, without git'sGIT_*hook variables, because it writestarget/), then a read-only push gate over the whole tree: clippy, format check, acceptance, arch, run in parallel (the offline checks pre-commit and stop-hook skip). Auto via git pre-push hook. - CI:
cargo harness ci— read-only gates (clippy, format check, complexity, acceptance, arch) run in parallel — captured, printed in submission order, run to completion — then agents-md-drift as a separate hard check, then audit, tests + coverage (stream), crap. CRAP is advisory (warns only — pass--enforceto hard-fail). Requiresuvxon PATH. - Complexity:
cargo harness complexity— lizard@1.22.2 CC gate (CCN≤15, args≤8, length≤100) over src + tests - Deadcode: no separate target — rust's
dead_codelint is on by default andci's strict clippy (-D warnings) denies unused functions, fields, and variants; unused dependencies surface viacargo's own warnings (orcargo-machete). At stop,dead_codeon changed lines arrives through the stop hook's lint. - CRAP (advisory):
cargo harness crap --max=30— complexity × coverage gate (joins lizard --csv withtarget/llvm-cov/lcov.info). Add--enforceto exit 1 on offenders (default exits 0 with warning). - Audit:
cargo harness audit— audit dependencies for known vulnerabilities (via cargo-audit) - Acceptance:
cargo harness acceptance— run cucumber againsttests/features/ - Coverage:
cargo harness coverage --min=0— cargo-llvm-cov line coverage with threshold; default comes from.harness-baselinecoverage.min - Mutation (advisory):
cargo harness mutation— cargo-mutants kill-rate on the crate - Suppressions:
cargo harness suppressions— full suppression breakdown;--update-baselinerequires human sign-off and updates.harness-baseline - Arch:
cargo harness arch— cargo-modules checks againstarch.toml - Branch guard:
cargo harness branch-guard— refuses pushes to (or deletions of)main/master; readsHARNESS_PRE_PUSH_REFS, else git pre-push stdin (1s deadline; partial input fails), else the current branch;HARNESS_ALLOW_PROTECTED_PUSH=1overrides - Arch config guard:
cargo harness arch-config-guard— warns in check/pre-commit, blocks pre-push/CI;--pre-pushalso inspects the push refs; useHARNESS_ALLOW_ARCH_CONFIG=1after review - Agents drift:
cargo harness agents-md-drift— fail if AGENTS.md differs from CLAUDE.md - Sync:
cargo harness sync-agents-md— overwrite AGENTS.md from CLAUDE.md - Setup:
cargo harness setup-hooksinstalls git pre-commit + pre-push hooks (path resolved viagit rev-parse, worktree-safe) and verifies the Claude/Codex Stop wiring and the Claude PostToolUse wiring (the runner is std-only — it checks rather than rewrites JSON that carries other hooks; copy the template's.claude/.codexif it warns) - Stop hook:
cargo harness stop-hook— post-edit, then changed-lines lint and touched-function complexity; silent on success, exit 2 with findings. Changed lines =git diffagainst the merge-base with the base branch (HARNESS_ARCH_BASE,GITHUB_BASE_REF, then origin/HEAD, origin/main, origin/master, main, master; never fetched) plus untracked files. Lint = clippy warnings and errors (rustc's included) on a changed.rsline. Complexity = a function insrc/ortests/that is over a lizard limit and overlaps a changed line: touch an over-limit function and leave it under the limit; an untouched one never blocks. Findings go to stderr (at most 20 lines;--verboselifts the cap); exit 1 means a tool could not run (a build that fails away from the changed lines included), or findings on a stop the agent is already continuing from (stop_hook_active: the hook blocks once per stop, never in a loop). An uncommittedCLAUDE.mdedit is copied toAGENTS.md. Whole-tree gates stay in check/pre-push/ci. - Runner:
cargo harnessis a.cargo/config.tomlalias that runs theharnessbin withbuild.warnings='allow'. The bin depends on the crate's lib, so cargo would otherwise replay every cached lib warning ahead of each hook's output; ci's strict clippy stays the gate. Older cargo ignores the key and prints those warnings (1.96 does; 1.98 honors it). - Post-edit:
cargo harness post-edit— rustfmt on.rsfiles with uncommitted changes, never on untouched child modules;cargo clippy --fixrewrites the whole crate, so it stays incheck/fix/pre-commit.--hook(Claude PostToolUse) formats the one edited file and, when it changed, prints anadditionalContextline asking the agent to re-read it; it never blocks.
Definition of done
cargo harness checkpasses clean — never stop with check failing.- Behavior worth specifying → a
.featurescenario exists and acceptance passes; other behavior changes have unit tests. - No new suppressions: additions above
.harness-baselinefail check; suppress only with the human's sign-off, stating why. - Arch config changes are integration-blocked:
check/pre-commitwarn, andpre-push/cifail unlessHARNESS_ALLOW_ARCH_CONFIG=1is set after review. pre-push/cimust pass on your branch before you open or update a PR. Merge is the human's.- Never spend a turn on what a tool checks: formatting, lint, types, dead code, drift, and complexity come back as
check/stop-hookoutput. Read the output, fix the code, never the gate.
Behavior contract
- The human is the engineer. They own design, API shape, and merge authority. You propose on a branch, they merge.
- Commit and push on a feature branch as you go. Never commit to
main/master, never force-push, never merge.pre-pushrefuses direct pushes tomain/masterunless a human setsHARNESS_ALLOW_PROTECTED_PUSH=1; that guard stops accidents, not--no-verify, so merge ownership is a rule you follow, not one the tool can enforce.