repo-doctor · git:20261007.4dd3818 · 2026-10-07 · sha256 5775b31a909aafe4
repo-doctor git:20261007.4dd3818A
Immutable. This exact content never changes and is served at /api/v1/blob/5775b31a909aafe4.
--- name: repo-doctor description: "Audit any repo against the agentic-quality doctrine; create, audit, upgrade or org-survey its AGENTS.md. Triggers on: repo doctor, repo audit, agentic quality, agent-friendly, write AGENTS.md, audit AGENTS.md, upgrade AGENTS.md, AGENTS.md not loading, CLAUDE.md shadows AGENTS.md, AGENTS.md org survey, stale AGENTS.md, monorepo structure, nested AGENTS.md, ARCHITECTURE.md, which instructions load." license: MIT allowed-tools: "Read Bash Glob Grep Agent" metadata: author: claude-mods related-skills: "doc-scanner, adr-ops, refactor-ops, techdebt, scaffold, project-planner, github-ops" --- # Repo Doctor Scores a repository against the **agentic-quality doctrine** (the cross-repo standard in [rules/agentic-quality.md](../../rules/agentic-quality.md) for code, comments, docs and structure a cold agent session can navigate), and owns the **AGENTS.md protocol**: creating, auditing, upgrading and org-surveying a repo's entry doc. Read-only by default. The scorer, the scan, the audit, `explain` and the survey never write. The only writing step is `agents-md.py scaffold --write` (root, `--dir` or `--architecture`), which **creates** the file and refuses to overwrite one (there is deliberately no `--force`). ## AGENTS.md: create, audit, upgrade, survey The protocol (what goes in, what stays out, the 150/200-line and 12,000/16,000-character budget and how to split, CLAUDE.md shadowing, staleness in commits) is [references/agents-md-protocol.md](references/agents-md-protocol.md). Read it before writing or judging an entry doc. The load-bearing fact: **Claude Code reads AGENTS.md only when no `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md` sits in the working directory or above it**, unless that CLAUDE.md imports `@AGENTS.md`. ```bash # 1. Deep scan: deterministic facts JSON; every fact cites file:line or a command, # plus landmine CANDIDATES from git history (always questions, never facts) python scripts/repo-scan.py --repo path/to/repo --json > facts.json # 2. Create: draft from the facts (commands only from declared scripts, tagged [untested]) python scripts/agents-md.py scaffold --repo path/to/repo --facts facts.json > AGENTS.draft.md python scripts/agents-md.py scaffold --repo path/to/repo --write # creates; never overwrites # 3. Audit, then upgrade with a reviewable patch python scripts/agents-md.py audit --repo path/to/repo # exit 10 on warn/crit python scripts/agents-md.py audit --repo path/to/repo --diff > agents-md.patch git -C path/to/repo apply "$PWD/agents-md.patch" # 4. Nest and map where the scan says so (protocol sections 6 and 10) python scripts/agents-md.py scaffold --repo path/to/repo --dir packages/engine --write python scripts/agents-md.py scaffold --repo path/to/repo --architecture > ARCHITECTURE.md # 5. What each tool loads for work in a folder (protocol section 11) python scripts/agents-md.py explain --repo path/to/repo packages/engine --tool all # 6. Survey a GitHub org: read-only gh api, no clones, writes nothing python scripts/agents-md.py survey --org my-org --json | jq '.meta' ``` Workflow rules: 1. **Scan before drafting.** The scaffold's archetype templates ([assets/agents-md/](assets/agents-md/): PHP CMS + DDEV + bundler, Node/TS app, Python service, static site, generic) hold slots, not claims. Everything the scan can't verify becomes a `TODO(owner):` question. 2. **The owner finishes the draft, through an interview.** `scaffold --json` splits the questions: confirm the guided ones (each has a recommended answer and its source) and ask only the assisted ones, one at a time ([references/owner-interview.md](references/owner-interview.md)). Run each command once and drop its `[untested]` tag, delete the DRAFT comment; the audit flags all three until done. Optional synthesis (one read-only Explore subagent per custom code area, at most four, fed the facts JSON) is in the protocol's section 8. 3. **The patch never removes landmines.** `--diff` adds missing-section stubs, an `@AGENTS.md` import for a shadowing CLAUDE.md, annotations on dead commands, and moves for oversized sections (setup prose to README, subsystem detail to a nested AGENTS.md, the rest to `docs/agents/`). It leaves the overview, Commands, Landmines and Deploy where they are. The audit also lists scan candidates whose files the owning doc never names: each is a landmine to write, or a line in `docs/agents/ruled-out.md` pinned to its evidence count (protocol section 1). 4. **Pair with Claude Code's own checks.** `/doctor prompt-audit` does the semantic pass (outdated or contradictory instructions); this tooling is the deterministic, CI-able one (protocol section 7). Never run repo tooling to "verify" a command: Composer plugins, justfile backticks and `make $(shell ...)` execute repo code even when listing. The scan reads tracked files and git metadata only, never opens secret files, and keeps variable names (not values) from `.env.example`. ## Repo scorer ```bash python scripts/repo-doctor.py # audit cwd, human panel python scripts/repo-doctor.py --repo path/to/repo # audit another repo python scripts/repo-doctor.py --json | jq .data.grade # machine-readable python scripts/repo-doctor.py --strict # CI gate: exit 10 below B ``` Six dimensions, 0-5 each, weighted into a letter grade: | Dimension | Measures | Weight | |---|---|---| | `entry_docs` | AGENTS.md/CLAUDE.md present · Landmines section · 200-line / 16,000-character budget · freshness in **commits-since-touched** · a CLAUDE.md that shadows AGENTS.md | 2.0 | | `docs_health` | README · docs/ index when >6 files · ghost links in the index | 1.5 | | `comments` | contract blocks on the largest source files · section markers in files >400 lines | 2.0 | | `structure` | monster files (>800 warn, >1500 crit; generated exempt) · repo-root junk | 2.0 | | `enforcement` | tests · CI · single `check` entry point · invariant gate scripts | 1.5 | | `doc_pairing` | fraction of recent feat/fix commits touching a `*.md` in the same commit | 1.0 | Full rubric (each check, threshold and fix): [references/scoring-rubric.md](references/scoring-rubric.md). ### Audit workflow 1. **Run the scorer.** On cp1252/plain terminals it degrades to ASCII; nothing is written. 2. **Read findings top-down** (crit, then warn, then info). Facts (monster-file list, pairing ratio, entry-doc age) ride in `--json` under `.data.facts`. 3. **Verify before acting.** The scorer is heuristic: a flagged 900-line file may be a justified single-writer module (then it needs the guard comment, section map and gate, not a split); a "stale" AGENTS.md may describe code that genuinely didn't change. 4. **Remediate via the owning skill** (below). Batch fixes into small commits: entry doc first (highest leverage), then indexes, guard comments, splits. 5. **Re-run to confirm** the grade moved. For fleets, loop `--json` over repo roots, or use `agents-md.py survey --org` for the entry-doc column without cloning. ## Remediation map: who owns each fix | Finding | Owner | |---|---| | Missing/weak/oversized AGENTS.md, shadowing CLAUDE.md | `agents-md.py scaffold` / `audit --diff` (above); hand skeleton: [assets/AGENTS-template.md](assets/AGENTS-template.md) | | Multi-platform doc mess (CLAUDE.md + COPILOT.md + CURSOR.md ...) | `doc-scanner` (consolidate), then audit the result here | | Missing docs index | Write from [assets/docs-index-template.md](assets/docs-index-template.md) | | Monster file needs splitting | `refactor-ops` (extract-module patterns, circular-dep cautions) | | Monster file is *justified* | Guard comment + section map + a `scripts/check-*` invariant gate ([references/comment-doctrine.md](references/comment-doctrine.md)) | | Missing/weak comments | [references/comment-doctrine.md](references/comment-doctrine.md): contract blocks, WHY-only, guard comments, citations | | Decisions undocumented | `adr-ops` | | Stale PLAN/roadmap | `project-planner` | | Code-level debt (duplication, dead code, security) | `techdebt`: deliberately NOT scored here | | New repo from scratch | `scaffold` + the templates in assets/ | Boundary: repo-doctor audits **repo-level conventions**; `techdebt` scans **code-level debt**; `review`/code-review judge **diffs**. Don't blur the three. ## Nested entry docs and monorepos Nest an AGENTS.md only where a subsystem has its own contract (invariant law, audience or gate). The scan's advisor says where, `scaffold --dir` drafts the doc (40 lines, 60 at most), and the audit checks every nested doc against its own folder; a CLAUDE.md beside a nested AGENTS.md shadows it (protocol section 6). Past a few contracted areas, an ARCHITECTURE.md holds the codemap and the invariants (section 10). The root entry doc is then judged as a *router* (invariants + ownership table), each contracted package needs its own entry doc and `check`, and cross-package invariants need mechanical gates: [references/monorepo-structure.md](references/monorepo-structure.md). Run the scorer per package as well as at root. ## Resources | Resource | What it owns | |---|---| | [scripts/repo-doctor.py](scripts/repo-doctor.py) | The scorer: six dimensions, findings, grade; `--json` envelope `claude-mods.repo-doctor/v1`; `--strict` CI gate | | [scripts/repo-scan.py](scripts/repo-scan.py) | Deep scan: manifests (per folder too), DDEV, deploy hooks and the scripts they call, CI, tests, generated output, code areas, size outliers, docs, env names, git-history landmine candidates, nesting advice, invariant gates, the architecture map; `--json` (`repo-scan/v1`), `--only`, `--dir` | | [scripts/agents-md.py](scripts/agents-md.py) | `scaffold` (root, `--dir`, `--architecture`; `--write` creates only), `audit` (every entry doc; `--diff` patch, `--explain <finding-id>`), `explain` (per-tool load view), `survey --org` / `--remote` (GET-only); exit 10 on findings | | [scripts/check-memory-docs.py](scripts/check-memory-docs.py) | Tripwire for the Claude Code facts the protocol encodes: `--offline` in PR CI, `--live` in the scheduled freshness workflow | | [scripts/check-tool-profiles.py](scripts/check-tool-profiles.py) | The same tripwire for other tools' loading rules in `assets/agents-md/tool-profiles.json` | | [references/owner-interview.md](references/owner-interview.md) | Resolving a draft's questions with the owner: guided versus assisted, one at a time, the test > comment > doc ladder, ruled-out lines | | [references/agents-md-protocol.md](references/agents-md-protocol.md) | The AGENTS.md protocol: contents, exclusions, size and split, CLAUDE.md shadowing, staleness, how the tools fit beside `/doctor` | | [references/scoring-rubric.md](references/scoring-rubric.md) | Every scorer check: what it measures, threshold, why, and the fix | | [references/comment-doctrine.md](references/comment-doctrine.md) | Contract blocks, WHY-only inline, guard comments, section markers, format-at-site, citations | | [references/monorepo-structure.md](references/monorepo-structure.md) | Structuring very large monorepos for agentic development | | [assets/agents-md/](assets/agents-md/) | Archetype, nested and ARCHITECTURE.md templates the scaffold fills (usable by hand: the slots are documented in each file's header), and `tool-profiles.json` | | [assets/AGENTS-template.md](assets/AGENTS-template.md) | Hand-fill entry-doc skeleton with the mandatory Landmines section | | [assets/docs-index-template.md](assets/docs-index-template.md) | `docs/00_INDEX.md` skeleton with the two anti-rot rules baked in |