# repo_contract Shared gate: every repo tells an agent how to run and test it, so nobody has to explore. Enforced like the other shared gates (real gate in `~/src/utils`, a thin shim per repo, pre-commit + CI). ## The contract `CLAUDE.md` (or `AGENTS.md` that `CLAUDE.md` symlinks to) has a `## Commands` section with one line per key, exactly `- : \`\``: ```markdown ## Commands - run: `` | n/a: library - test: `` - test-changed: `scripts/test_changed.sh` - lint: `` - coverage: `` - coverage-gaps: `coverage-gaps ` ``` Rules (all machine-checked): 1. All six keys present, once each. A value is a backticked command or `n/a: ` / `n/a ()`. A bare `n/a` fails: n/a carries a reason. 2. `test-changed` invokes an existing, executable `scripts/test_changed.sh`-style script that runs only tests related to files changed vs HEAD, falls back to the full suite when it cannot map, and prints failures plus a one-line summary only. 3. `coverage-gaps` runs the shared lister `coverage-gaps ` (`~/src/utils/coverage_gaps`). 4. `test`, `test-changed`, `lint`, `coverage` are quiet: no `-v`/`--verbose`/ expanded reporter, in the command or in the script's runner lines. 5. No placeholders (``, `TODO`, `...`). 6. If `test` is n/a, then `test-changed`, `coverage`, `coverage-gaps` are n/a too, and the repo must contain no tests (bounded scan). ## Use ```bash python3 ~/src/utils/repo_contract/check.py --repo # 0 pass / 1 violations / 2 unreadable python3 ~/src/utils/repo_contract/bootstrap.py --repo # print proposal python3 ~/src/utils/repo_contract/bootstrap.py --repo --write python3 ~/src/utils/repo_contract/sweep.py # ~/data/claude-scratch/repo-contract/SWEEP.md ``` Bootstrap never overwrites: it appends the section (or inserts missing lines at the end of an existing `## Commands`), creates `CLAUDE.md -> AGENTS.md` when only AGENTS.md exists, and writes `scripts/test_changed.sh` only if absent. Sources, in priority order: existing CLAUDE.md, `scripts/.sh`, Makefile, package.json (node only), CI workflows, stack defaults. Anything it cannot infer is written as ``, which the gate rejects until a human fills it. ## Adding the gate to a repo 1. Copy `templates/check_repo_contract.shim.sh` to `scripts/check_repo_contract.sh` (never copy `scripts/check_repo_contract.sh` from this repo). 2. Add `templates/pre-commit-snippet.yaml` to `.pre-commit-config.yaml`. 3. Copy `templates/repo-contract.yml` to `.github/workflows/`. ## Tests ```bash PYTHONPATH=. python -m pytest repo_contract/tests -q --cov=repo_contract --cov-branch --cov-fail-under=100 ```