Plan: an llm-doc-structure consistency audit for AGENTS.md and ARCHITECTURE.md¶
Context¶
AGENTS.md and ARCHITECTURE.md have accreted exactly the way the
READMEs did before the readme-structure audit. Measured across the
fleet today:
| repo | AGENTS.md | ARCHITECTURE.md |
|---|---|---|
| ryll | 1015 lines / 7,020 words | 2262 lines / 13,772 words |
| shakenfist | 878 / 6,889 | 1294 / 8,998 |
| instar | 684 / 4,008 | 1387 / 9,872 |
| kerbside | 538 / 3,598 | 500 / 3,050 |
| divergulent | 486 / 4,163 | 478 / 3,842 |
| occystrap | 243 / 1,412 | 950 / 5,084 |
| everything else | ≤ 181 | ≤ 284 |
ryll alone is ~21,000 words (~28k tokens) across the two files.
AGENTS.md is auto-loaded into every session, so its whole length is
a fixed per-task tax; ARCHITECTURE.md is a large on-demand read that
an agent is instructed to consult and update on every change.
The failure modes are concrete, not theoretical:
- Restating
docs/. ryll'sARCHITECTURE.md## Configurationre-documents the.vvfile format and connection methods thatdocs/configuration.mdalready covers, and then adds amake test-qemurunbook that belongs indocs/development.md. ryll'sAGENTS.md## Control socketis a 70-line mini-manual for the wire protocol whose canonical home it names in its own text (docs/control-socket-protocol.md, 1046 lines). - Restating each other. ryll has
## Code Organisationin both files; kerbside has## Configurationin both; clingwrap has## Dependenciesin both. - Plan history. ryll's
ARCHITECTURE.mdhas four top-level## Phase 5/6/7/8sections. Counts ofphase <n>across the two files: ryll 19+44, instar 3+46, divergulent 6+7, shakenfist 5+5. The existingplan-phase-referencesaudit cannot see any of it —iter_doc_content_filesscans onlyREADME.mdanddocs/. - Detail that drifts. ryll's
AGENTS.mdcarries aServer::runsignature sketch in Rust — a copy of code, in a file nothing compiles.
Root cause is partly the standing instruction in ~/.claude/CLAUDE.md
to "always update AGENTS.md and ARCHITECTURE.md ... for any
user-visible change", which literally directs growth on every change.
That wording gets fixed too.
Intended outcome: AGENTS.md becomes a working guide plus an
index; ARCHITECTURE.md becomes a map plus an index; the detail lives
in docs/ where humans benefit from it as well — and an audit keeps it
that way, structured exactly like readme-structure (measurable
proxies in CI, judgment enforced at push time by a shared block).
What "good" looks like¶
AGENTS.md— how to work in this repo. Conventions, invariants and gotchas an agent cannot infer by reading the code, plus curated links intodocs/. Not tutorials, not protocol specs, not architecture, not CLI reference.ARCHITECTURE.md— how the system is shaped. Component inventory, how data moves between components, key design decisions and why, plus links to the deep dives. Not configuration reference, not runbooks, not phase history.- One canonical home per fact. If
docs/covers it, link to it. Same rule between the two files.
Implementation¶
Work happens in a worktree off shakenfist/development; the plan file
moves into that worktree so it lands with the change (per CLAUDE.md).
1. Audit spec — audits/llm-doc-structure.md¶
New file following the audits/README.md structure, modelled closely
on audits/readme-structure.md: "What we check", no template, and an
empty <!-- consistency-audit:begin/end --> marker block. Pairs with
the existing llm-tooling audit, which checks existence of these
files; this one checks shape. Register it in the audit index table
in audits/README.md.
2. Automated check — scripts/audit-check.py¶
New check_llm_doc_structure(repo_path, props) next to
check_readme_structure (~line 2199), reusing check_file_exists,
strip_markdown_code, MD_LINK_RE and MD_REFDEF_RE. Accumulates a
problems list and returns pass/fail/not_applicable in the same
shape. N/A when neither file exists.
Four measurable proxies:
- Length caps.
AGENTS.md≤ 300 lines / 2,500 words;ARCHITECTURE.md≤ 500 lines / 4,000 words. Constants besideREADME_MAX_LINES/README_MAX_WORDS. - Index behaviour. If
docs/exists, each present file must contain at least one link intodocs/. (occystrap'sAGENTS.mdmentionsdocs/zero times today.) - Cross-file duplication. Flag H2 headings appearing in both files, normalised to lowercase. Fleet-wide this fires on exactly three repos — precise, not noisy.
- Duplication with
docs/. Flag an H2/H3 heading whose normalised text matches adocs/<slug>.mdfilename stem (configuration↔docs/configuration.md). Fires on kerbside (×3), ryll (×1), instar (×1) today.
Checks 3 and 4 are suppressible with an
<!-- audit-ok: llm-doc-structure --> marker on the heading line,
following the PHASE_REFERENCE_OK precedent.
Register in the dispatch table (~line 2924) and in
scripts/audit_common.py: AUDIT_METADATA['llm-doc-structure'] with
'spec': 'audits/llm-doc-structure.md', 'template': None, plus
ISSUE_TITLES['llm-doc-structure'] = 'AGENTS.md / ARCHITECTURE.md
structure' and the display-name map at audit-check.py:83.
Unit tests in scripts/test_audit_check.py alongside the
check_readme_structure test at line 164: one pass case, one per
proxy, one N/A, one suppression-marker case.
3. Extend plan-phase-references (your choice: extend, don't fork)¶
One seam: iter_doc_content_files (audit-check.py:2264) also yields
top-level AGENTS.md and ARCHITECTURE.md when present. The existing
fenced-code, inline-code and audit-ok suppression logic then applies
unchanged. Update the "What we check" text in
audits/plan-phase-references.md to say so, and its N/A condition
(currently "neither a top-level README.md nor a docs/ directory").
This marks ryll, instar, divergulent and shakenfist non-compliant on that audit as soon as it runs — expected and intended.
4. Shared block — templates/shared-blocks/llm-doc-discipline.md¶
New versioned block (v1) mirroring readme-discipline.md, carrying
the judgment half of the policy: what each file is for, one canonical
home per fact, no reference manuals / runbooks / plan history, and
"growth in either file is itself a finding — move it to docs/".
Add 'llm-doc-discipline' to the required=[...] list in
check_push_audit (audit-check.py:2515), update that function's
docstring, audits/push-audit.md, and the required-blocks list in
templates/shared-blocks/README.md. Every repo with a PUSH-AUDIT.md
(all in-scope except client-python) then needs the block embedded —
the push-audit audit files those issues automatically.
5. Root-cause fix — ~/.claude/CLAUDE.md¶
Rewrite the "Updating documentation" bullet so it stops instructing
growth. Replacement intent: document user-visible changes in docs/;
touch AGENTS.md only when a convention changes and
ARCHITECTURE.md only when the shape of the system changes; both
files summarise and link rather than restate. Keeps the existing
"propose moving misplaced content into docs/" clause, which already
points the right way.
6. Regenerate and document¶
PROJECT-CONSISTENCY-AUDITS.md gets the new criterion. The compliance
tables in the affected audit specs are regenerated by the workflow —
never by hand.
Migration (separate commits, after the audit lands)¶
The audit will file issues on ~7 repos. Trimming a 2262-line
ARCHITECTURE.md is judgment-heavy, so:
- ryll and kerbside by hand, one commit per file, as the reference
examples — they are the two you named and the two worst cases. Each
trim is a move: the detail lands in a
docs/page (new pages such asdocs/spice-protocol.md,docs/display-pipeline.mdfor ryll's 600+ lines of protocol and image-format detail) before it leavesARCHITECTURE.md, and the section is replaced by a one-paragraph summary plus a link. - shakenfist, instar, occystrap, divergulent follow via the normal consistency-issue flow, using the ryll/kerbside commits as the worked example.
I will not start the migration without a separate go-ahead.
Verification¶
python3 -m pytest scripts/test_audit_check.py— new and existing cases pass.python3 scripts/audit-check.pyagainst local checkouts (dry run, no issue filing) and confirm the reported non-compliance matches the table in Context: AGENTS — divergulent, instar, kerbside, ryll, shakenfist; ARCHITECTURE — instar, occystrap, ryll, shakenfist; plus the duplication hits on kerbside, ryll, instar, clingwrap.- Confirm the small repos (agent-python, client-python, clingwrap, cloudgood, sfui, kerbside-patches, client-python-k3s) stay compliant — no busywork for repos that are already fine.
- Confirm
plan-phase-referencesnow reports the ryll/instar/ divergulent/shakenfist hits, and that nothing insidedocs/plans/or fenced code blocks is flagged. pre-commit run --all-filesbefore proposing any commit.