Audience: Contributors, interns included, and AI coding agents. Status: Live. Every tool on this page runs today.
This page lists each tool that checks this repository: what it catches, which command runs it, where CI runs it,
and where its version is pinned. The rules for the gates are in AGENTS.md. Setup is in
CONTRIBUTING.md.
| Tool | What it catches | Command | In CI | Version pinned in |
|---|---|---|---|---|
| ruff | Python formatting and lint errors (rules in ruff.toml) |
make format, make format:check, make lint |
static |
dev/tools/pyproject.toml |
| mypy | Python type errors, strict mode (mypy.ini) |
make typecheck |
static |
dev/tools/pyproject.toml |
| unittest | Failing tests: the engine, the audit tools, the implement tools, the dev checks | make test (on Linux, its four suites at once; CI splits the engine's and the audit tools' suites into shards with dev/test_shard.py, and the dev checks too on Python 3.14) |
test-coverage, test-dev, test-py314; unsharded in nightly.yml |
Python standard library |
| coverage.py | Test coverage below the floor in .coveragerc |
make coverage (in CI: coverage-part, then coverage-combine SHARDED=1) |
test-coverage, coverage; unsharded in nightly.yml |
dev/tools/pyproject.toml |
| jsonschema | The tools' schema validator disagrees with the reference package | make crosscheck |
crosscheck |
dev/tools/pyproject.toml |
dev/recipe_lint.py |
Broken links, bad SKILL.md frontmatter, a recipe SKILL.md that does not link the shared user prompt, oversize files, unknown tools, check IDs and requirement IDs |
make recipe-lint |
static |
This repository |
dev/adr_lint.py |
An ADR with a lifecycle field, a lifecycle footer or a retired-ADR marker, a missing template section, or no row in the ADR index (and, for an engine ADR, the engine's index); an index row to a missing ADR; a page that names an ADR number or path no folder holds | make adr-lint |
static |
This repository |
dev/build_masters.py |
An audit master list or implement master list that no longer matches the catalogue, the check files or the playbooks | make masters-check; make update-masters rewrites both pages |
static |
This repository |
dev/eval/generate_fixture_expected.py |
An eval-expected file (dev/eval/expected/fixtures/) that no longer matches a fresh engine run on its fixture |
make eval-expected-check; the script without --check rewrites the files |
static |
This repository |
| actionlint | Workflow mistakes: syntax, expressions, action inputs, shellcheck on run: blocks |
make workflow-lint |
static |
dev/tools/actionlint/go.mod |
| zizmor | Workflow and Dependabot security: injection, broad permissions, unpinned actions, cooldown. Runs at the pedantic persona, so a permission without a comment or a missing concurrency limit fails too | make workflow-lint |
static |
dev/tools/pyproject.toml |
| typos | Misspelled words in the tracked text, code identifiers included (word list: _typos.toml) (Spell check) |
make spell; make spell-fix writes the fixes |
static |
dev/tools/pyproject.toml |
| check-jsonschema | .github/workflows/*.yml and .github/dependabot.yml that do not match their SchemaStore schemas |
make workflow-lint |
static |
dev/tools/pyproject.toml |
| detect-secrets | Key-shaped strings not in .secrets.baseline |
make security (part: security-secrets) |
security-secrets |
dev/tools/pyproject.toml |
| osv-scanner | A known vulnerability in a dev tool or its dependencies (Python, Node, Go lockfiles), unless osv-scanner.toml accepts it (Dependency audit) |
make security (part: security-deps) |
security-deps |
dev/tools/osv/go.mod |
| markdownlint-cli2 | Markdown rule violations (.markdownlint-cli2.jsonc) |
make docs-lint; make changelog-fix rewrites CHANGELOG.md with the fixes |
docs; format-changelog in release-please.yml |
dev/tools/package.json |
dev/prose_check.py |
Long sentences, vague words, explanation pages without a diagram (COMMUNICATION_RULES.md). Advisory: warnings and notices, never a failure. Its copy for target repositories, implement/playbooks/templates/docs_prose_check.py, adds --max-issues; dev/tests/test_prose_template_parity.py holds the two equal |
make docs-prose [FILES=...] |
docs (annotations on changed Markdown) |
This repository |
| mermaid-cli | A Mermaid block that does not render | make docs-mermaid FILES=<file.md> |
docs |
dev/tools/package.json |
| skills-ref | A skill bundle that breaks the Agent Skills specification | make validate-skills |
Release only | dev/tools/pyproject.toml |
dev/commit_lint.py |
A commit subject that is not Conventional Commits | make commit-lint |
commits |
This repository |
| The audit engine | A readiness finding that .audit-baseline.json does not have |
make self-audit |
self-audit |
This repository |
| actions/attest | Signs build provenance for the release files; users check it with gh attestation verify (Install the skills) |
— | release.yml, release only |
.github/workflows/release.yml (action pinned by SHA) |
| CodeQL | Security flaws in the Python code and the workflows. Advisory: alerts go to the Security tab (Code scanning) | — | codeql.yml, outside CI Gate |
.github/workflows/codeql.yml (action pinned by SHA) |
| OpenSSF Scorecard | Weak security practices of the repository (Branch-Protection, Pinned-Dependencies, Token-Permissions, Signed-Releases, ...). Advisory: alerts go to the Security tab; the score is published on scorecard.dev and in the README badge (Scorecard alerts) | — | scorecard.yml, on push to dev and weekly |
.github/workflows/scorecard.yml (action pinned by SHA) |
| release-please | Computes the next version from the commit subjects, writes CHANGELOG.md, tags and creates the GitHub release (release-please-config.json) |
— | release-please.yml, on each push to main |
.github/workflows/release-please.yml (action pinned by SHA) |
| uv | Runs the Python tools through uvx and uv run |
— | All jobs | dev/tools/pyproject.toml |
| Node | Runs the Node tools through npx |
— | docs |
.nvmrc |
| Go | Builds and runs actionlint and osv-scanner through go tool |
— | check, security |
the go line of each Go tool module |
make check runs format:check, typecheck, test, the engine's rule check, crosscheck, recipe-lint,
adr-lint, masters-check, eval-expected-check, workflow-lint and spell, in sequence. CI's CI Gate
passes only when the check, security, coverage, self-audit, docs and commits jobs pass (Branch protection).
make spell runs typos on every tracked file that .gitignore does not hide. It skips the data paths that
_typos.toml excludes: the fixtures, the worked examples, CHANGELOG.md and the lockfiles.
typos splits code identifiers into words, so a typo inside a variable name fails too. Each finding shows the file,
the line and the suggested word.
To fix a finding, do one of these:
- Correct the word.
make spell-fixwrites every suggested fix; review the diff before you commit. - If the word is correct here (a project term, a regex stem or a code token), add it to
[default.extend-words]in_typos.toml. Add a comment that says why.
make security runs osv-scanner after the secrets scan
(ADR 0007). It reads the
dev-tool lockfiles (Python, Node and each Go tool module) and asks osv.dev for known vulnerabilities. It needs Go
1.27 or newer and the network. The first run builds osv-scanner, which takes about 30 seconds.
The scan fails when it finds a vulnerability that no osv-scanner.toml accepts. Each ignore file covers the
lockfiles in its own folder: dev/tools/osv-scanner.toml for uv.lock and
package-lock.json, and dev/tools/<tool>/osv-scanner.toml for a Go tool module. OpenSSF Scorecard reads the same
files, so an accepted vulnerability raises no Scorecard alert either.
The output has one table row per vulnerability: the OSV link, the package, its version, the fixed version and the lockfile. To fix a finding, do one of these:
- Raise the tool or the dependency to the fixed version. Follow Change a tool version.
- If no fix reaches this repository, add an entry to the
osv-scanner.tomlnext to the lockfile. Give theidand areason. SetignoreUntilto a date at most six months ahead.dev/tests/test_tool_pins.pychecks the entry.
When an ignoreUntil date passes, the scan fails again. Look at the advisory again, then fix or renew it.
A ratchet holds a count that may only go down, or a floor that may only go up. A change that makes a count go up fails its gate. When a count goes down, lower the baseline in the same change.
| Ratchet | File | Checked by |
|---|---|---|
| ruff, mypy and Markdown lint counts | .quality-baseline.json |
make format:check, make typecheck, make docs-lint |
| Known key-shaped strings | .secrets.baseline |
make security |
| Coverage floor | .coveragerc (fail_under) |
make coverage (runs as CI does: an empty HOME and CI=true) |
| Readiness findings | .audit-baseline.json |
make self-audit |
lefthook.yml runs these before a commit lands, after you run lefthook install once:
| Hook | Runs | On |
|---|---|---|
protected-branch |
Stops a commit on dev or main |
Every commit |
format-check |
make format-check |
Staged Python files |
docs-lint |
make docs-lint |
Staged Markdown in the ratchet paths |
workflow-lint |
make workflow-lint |
Staged files under .github/ |
spell |
typos, at the pinned version | Staged files, except the paths _typos.toml excludes |
secrets |
detect-secrets on the staged files | Every commit |
conventional-commits |
dev/commit_lint.py --message-file |
The commit message |
The hooks are a convenience. CI runs the same checks, and a skipped hook does not skip CI.
Each tool version is written once:
- Python tools:
dev/tools/pyproject.toml, grouptools, locked indev/tools/uv.lock. - Node tools:
dev/tools/package.json, locked indev/tools/package-lock.json. - Go tools: one module each, with a Go
toolrequirement and checksums in itsgo.sum: osv-scanner indev/tools/osv/, actionlint indev/tools/actionlint/. The Go module proxy serves them.
The Makefile, lefthook.yml, dev/mermaid_check.py and the workflows read each version from those files.
Nothing is installed into the project: the tools run through uvx, npx and go tool. Dependabot watches these
files and opens a pull request only for a security fix that is not a major version
(ADR 0003).
dev/tests/test_tool_pins.py fails when a version is not exact, when a lockfile disagrees with its manifest, or when
another file repeats a version.
To change a version, follow Change a tool version.
MCP servers make an agent faster. No gate, CI job or release step needs one. Anything that must be right runs
through make.
.mcp.json at the repository root registers one server, codebase-memory-mcp (the code index). It names the bare
command, so each person installs the server and keeps its version. No version is written in the repository.
dev/tests/test_mcp_config.py checks the file, and checks that .claude/settings.json approves no project server
for you.
How each harness treats a project MCP file (checked 2026-11-09 in each harness's own docs):
| Harness | Reads | First start in this repository |
|---|---|---|
| Claude Code | .mcp.json |
Asks you to approve the server, once per person |
| VS Code with Copilot | .mcp.json or .vscode/mcp.json |
Starts it when the folder is trusted |
| Cursor | .cursor/mcp.json |
You turn each server on or off |
| Gemini CLI | .gemini/settings.json (mcpServers) |
Starts it after you trust the folder |
| opencode | opencode.json (mcp) |
Connects it with no prompt |
| Codex CLI | .codex/config.toml ([mcp_servers]) |
Loads it only for a trusted project |
| Antigravity | Its own user-level list (agy mcp add) |
Starts it in every repository |
For a harness that does not read .mcp.json, dev/mcp_config.py translates the entry into that harness's format:
| Command | What it does |
|---|---|
python3 dev/mcp_config.py show --harness <name> [--scope project|user] |
Prints the target file and the entry. Writes nothing |
python3 dev/mcp_config.py write --harness <name> [--scope project|user] |
Adds the entry to the file. Stops if a different entry has the same name |
python3 dev/mcp_config.py detect |
Names the harness from the variable it sets (CLAUDECODE, ANTIGRAVITY_AGENT, OPENCODE), or says to ask |
python3 dev/mcp_config.py check |
Is each server's command on PATH? Prints its version, or the install routes |
python3 dev/mcp_config.py status --harness <name> |
Has the person answered the setup offer for this harness? |
python3 dev/mcp_config.py record --harness <name> --answer accepted|declined |
Records the answer in .agentic-readiness/setup.json |
A language server is an optional aid beside the index. pyrightconfig.json gives pyright and basedpyright the same
import paths as mypy.ini, and dev/tests/test_pyright_config.py keeps the two in step. make typecheck stays the
gate. Routes per harness: Set up the agent tools.
The names are claude-code, vscode, cursor, gemini, opencode, codex, antigravity and other. The tool
installs nothing. If
the server is not installed, it fails to start and the agent reads files instead.
These checks run on GitHub, outside the repository files:
| Setting | What it does | Documented in |
|---|---|---|
Rulesets on dev and main |
Pull request required, CI Gate, Check source branch on main |
Branch protection |
| Dependabot alerts and security updates | Alerts on vulnerable dependencies; security pull requests into dev |
ADR 0003 |
| Secret scanning and push protection | Refuses a push that holds a known secret format | SECURITY.md |
| CODEOWNERS | Requests a review from the maintainer | .github/CODEOWNERS |