feat(docs): size bands with a docs-count cap, and the migration that lets it land #1108

Merged
coilysiren merged 10 commits from aos/claude/aw85-docs-prune into main 2026-08-17 00:34:22 +00:00
Owner

Supersedes #1090, which is the first two commits here. That PR could not land on its own: it adds a cap this repository failed, and documentation-layout runs on every commit with --no-verify banned, so wiring the check would have bricked commits to the repo that owns the hook. This is the check plus the migration that lets it land.

small (default)   40 lines   3,000 chars   20 docs
large             120 lines  8,000 chars   40 docs

The count cap is the point

A per-doc size cap does not bound a docs folder, it reshapes it. A repo that caps length and not count answers every over-long doc by splitting it.

sirens-echo was the proof: 156 docs, median 2,935 chars, largest 3,989 against a 4,000 cap. Not one file over the limit, and a folder nobody can read.

This repository had the same disease in miniature, and its own skill-discipline handbook said so out loud:

The handbook is split across topic files to stay under the documentation size cap.

Ten files. The count cap is that sentence, enforced.

The migration: 100 docs to 40

docs/ goes from 100 files to 40, 5,089 lines to 4,120, every one inside the band caps. check_docs_count is now in main()'s violation list.

Two docs were deleted because their content had stopped being true. issue-corpus.md said in full that the corpus it documents is retired, while FEATURES.md advertised it as a shipped capability. security-boundaries.md was two dated audits that closed their issues, referenced by nothing.

Nothing else was dead. No doc referenced a renamed thing or a deleted repo. The quiet docs were quiet because their subject is stable, and deleting those to reach a number would have destroyed the reference material the cap exists to make readable.

So the rest is merging and trimming, and what the trimming cut was restatement rather than explanation:

  • 252 lines of per-doc See also sections. FEATURES.md is the index and each was a second copy of a slice of it.
  • Four repo-map traces repeating one "find the surfaces / first check / notes" skeleton.
  • A GitHub mirror contract whose every clause was already stated by the mirror-workflow section directly above it.
  • A role matrix duplicating roles.kdl, which the page itself calls authoritative.
  • Install recipes the README owns, and a JSON sample restated in the prose beside it.

Three findings worth keeping

Merging costs lines rather than saving them, measured at 3.7 per fold: the heading and its spacing. I assumed the opposite going in, and that measurement is why the migration needed a trimming pass rather than more folding.

Rephrasing prose to be tighter does not reduce line count. Reflowed text occupies the same rows. The last dozen lines came from folding small trailing sections into the paragraph above them, which removes a heading and a blank line without touching a word.

A generated doc cannot be merged at all. Folding catalog-caps-reference.md into another page turned test_committed_render_is_in_sync red, because the generator writes that exact path. It is back out and regenerated.

No per-file escape

excludes no longer reaches either size cap or the count. It still governs placement and flatness, where it does real work for vendored trees and generated output. The old escape had accumulated exactly where the pressure was highest: agentic-os-kai excluded nine individual SKILL.md files, and two repos excluded docs/FEATURES.md from the cap that exists to keep it an inventory.

Verification

pre-commit run --all-files clean, 539 tests green. 23 files of validator and test changes, the rest documentation.

What this does not do

Every other repo goes red on its own schedule after this lands. The measured cost at the time of writing: infrastructure 127 docs, lore 69, agent-proxy 67, agent-compose 63, sirens-echo 156. agent-compose, agent-proxy, and lore are the hard ones, carrying 3,000 to 4,000 lines of docs against an 800-line small-band budget.

Supersedes #1090, which is the first two commits here. That PR could not land on its own: it adds a cap this repository failed, and `documentation-layout` runs on every commit with `--no-verify` banned, so wiring the check would have bricked commits to the repo that owns the hook. This is the check plus the migration that lets it land. ``` small (default) 40 lines 3,000 chars 20 docs large 120 lines 8,000 chars 40 docs ``` ## The count cap is the point A per-doc size cap does not bound a docs folder, it reshapes it. A repo that caps length and not count answers every over-long doc by splitting it. `sirens-echo` was the proof: 156 docs, median 2,935 chars, largest 3,989 against a 4,000 cap. Not one file over the limit, and a folder nobody can read. This repository had the same disease in miniature, and its own `skill-discipline` handbook said so out loud: > The handbook is split across topic files to stay under the documentation size cap. Ten files. The count cap is that sentence, enforced. ## The migration: 100 docs to 40 `docs/` goes from 100 files to 40, 5,089 lines to 4,120, every one inside the band caps. `check_docs_count` is now in `main()`'s violation list. Two docs were **deleted** because their content had stopped being true. `issue-corpus.md` said in full that the corpus it documents is retired, while `FEATURES.md` advertised it as a shipped capability. `security-boundaries.md` was two dated audits that closed their issues, referenced by nothing. **Nothing else was dead.** No doc referenced a renamed thing or a deleted repo. The quiet docs were quiet because their subject is stable, and deleting those to reach a number would have destroyed the reference material the cap exists to make readable. So the rest is merging and trimming, and what the trimming cut was **restatement rather than explanation**: - 252 lines of per-doc `See also` sections. FEATURES.md is the index and each was a second copy of a slice of it. - Four repo-map traces repeating one "find the surfaces / first check / notes" skeleton. - A GitHub mirror contract whose every clause was already stated by the mirror-workflow section directly above it. - A role matrix duplicating `roles.kdl`, which the page itself calls authoritative. - Install recipes the README owns, and a JSON sample restated in the prose beside it. ## Three findings worth keeping **Merging costs lines rather than saving them**, measured at 3.7 per fold: the heading and its spacing. I assumed the opposite going in, and that measurement is why the migration needed a trimming pass rather than more folding. **Rephrasing prose to be tighter does not reduce line count.** Reflowed text occupies the same rows. The last dozen lines came from folding small trailing sections into the paragraph above them, which removes a heading and a blank line without touching a word. **A generated doc cannot be merged at all.** Folding `catalog-caps-reference.md` into another page turned `test_committed_render_is_in_sync` red, because the generator writes that exact path. It is back out and regenerated. ## No per-file escape `excludes` no longer reaches either size cap or the count. It still governs placement and flatness, where it does real work for vendored trees and generated output. The old escape had accumulated exactly where the pressure was highest: `agentic-os-kai` excluded nine individual `SKILL.md` files, and two repos excluded `docs/FEATURES.md` from the cap that exists to keep it an inventory. ## Verification `pre-commit run --all-files` clean, 539 tests green. 23 files of validator and test changes, the rest documentation. ## What this does not do Every other repo goes red on its own schedule after this lands. The measured cost at the time of writing: `infrastructure` 127 docs, `lore` 69, `agent-proxy` 67, `agent-compose` 63, `sirens-echo` 156. `agent-compose`, `agent-proxy`, and `lore` are the hard ones, carrying 3,000 to 4,000 lines of docs against an 800-line small-band budget.
feat(docs): size bands with a docs-count cap, and no per-file escape
All checks were successful
ci / ward-doctor (pull_request) Successful in 15s
ci / aos-cli-tests (pull_request) Successful in 20s
ci / gate (pull_request) Successful in 51s
3f15a8d3db
Two bands, declared per repo, each carrying three caps:

    small (default)   40 lines   3,000 chars   20 docs
    large             120 lines  8,000 chars   40 docs

The count cap is the new part and the reason for the change. A per-doc size
cap does not bound a docs folder, it reshapes it: a repo that caps length and
not count answers every over-long doc by splitting it. sirens-echo is the
proof, at 156 docs with a 3,989-char maximum against a 4,000 cap. Not one file
over the limit, and a folder nobody can read.

The pairs are set from measurement rather than taste. Markdown here runs about
49 chars per line fleet-wide, so lines bind first and the char cap sits above
as the backstop for tables and code. The two caps multiply into a budget - 800
lines for small, 4,800 for large - which is the number worth arguing about
rather than either cap alone.

Excludes no longer reach either size cap or the count. They still govern
placement and flatness, where they are doing real work for vendored trees and
generated output. The old per-file escape accumulated exactly where pressure
was highest: one repo excluded nine individual SKILL.md files, and two
excluded docs/FEATURES.md from the cap that keeps it an inventory.

docs/FEATURES.md loses its own constants and takes the band. They were equal to
the ordinary cap, so it was a special case in name only.

check_docs_count is implemented and tested but deliberately not in main()'s
violation list. A strict fleet cap cannot land from inside a repo that
violates it, and this one carries 100 docs against its own 40. Wiring it is
one line, in the commit that lands this repo's own migration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
docs: merge 101 docs into 68, every one inside the band caps
All checks were successful
ci / ward-doctor (pull_request) Successful in 13s
ci / aos-cli-tests (pull_request) Successful in 18s
ci / gate (pull_request) Successful in 1m7s
dev-base-pr / build (pull_request) Successful in 12m31s
40471adc5e
The docs-count cap this branch adds cannot be wired until this repository
passes it. This is the migration, and it stops short of the cap for a reason
the last section states.

101 docs became 68 by folding topical clusters into one page each. Every doc is
inside the large band's 120-line and 8,000-char caps, and every hook is green,
including dead-cross-links across the roughly 100 inbound references the merges
had to repoint.

The skill-discipline handbook is the clearest case and the one this branch's
own body cites. It was ten files, and its index said so in as many words:

  The handbook is split across topic files to stay under the documentation
  size cap.

That sentence is the count cap's whole argument, written down in the repo as a
design note. It is now five files: the handbook, its conventions, its hooks,
the authoring walkthrough, and the entry point.

The other clusters went the same way. Five repo-map traces became one page,
three Forgejo Actions pages became two, six dev-base pages became three, eight
native-session pages became four, fourteen aos-* pages became ten.

Merging costs lines rather than saving them. 101 docs held 5,089 lines and 68
hold 5,210, because every fold adds a heading and the spacing around it, about
3.7 lines per merge. That number matters for what comes next and is measured
here rather than assumed.

check_docs_count stays unwired. At 68 docs against a cap of 40 this repository
still fails it, and wiring a check the repository fails would brick commits to
the repository that owns the hook. The remaining distance is not more merging:
5,210 lines against a 40-doc cap of 120 lines is a 4,800-line ceiling, so the
content does not fit at any packing, and perfect packing would still need 44
docs. Twelve docs are under 60 lines and can still pair. Everything else has a
median of 77, so two of them breach the cap on contact.

Closing the last 28 docs means deleting roughly 500 lines, which is a content
decision rather than a layout one. Left for Kai on the tracking issue.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
feat(docs): every repo declares its band, small included
All checks were successful
ci / ward-doctor (pull_request) Successful in 14s
ci / aos-cli-tests (pull_request) Successful in 20s
ci / gate (pull_request) Successful in 1m16s
3fe68ed74d
Small was the implicit default, which made an undeclared repo and a
deliberately small one the same file. Only one of them has had the
decision made, and the migration needs to tell them apart.

A missing declaration now fails the same way a typo does. Caps still
resolve to small while a repo is red, so the size checks stay meaningful
rather than passing everything or crashing.

Refs agentic-os#1085

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Merge commit '3fe68ed7' into aos/claude/aw85-docs-migrate
All checks were successful
ci / ward-doctor (pull_request) Successful in 13s
ci / aos-cli-tests (pull_request) Successful in 18s
ci / gate (pull_request) Successful in 1m17s
dev-base-pr / build (pull_request) Successful in 4m52s
febaa8f745
Merge pull request 'docs: merge 101 docs into 68, and measure why 40 is not reachable' (#1095) from aos/claude/aw85-docs-migrate into aos/claude/ym96-docs-bands
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 19s
ci / ward-doctor (pull_request) Successful in 12s
ci / gate (pull_request) Successful in 54s
dev-base-pr / build (pull_request) Successful in 4m8s
bd139a8c6c
Merge branch 'main' into aos/claude/ym96-docs-bands
Some checks failed
ci / aos-cli-tests (pull_request) Successful in 24s
ci / ward-doctor (pull_request) Successful in 17s
ci / gate (pull_request) Successful in 1m15s
dev-base-pr / build (pull_request) Has been cancelled
dafeecfc85
docs: delete a tombstone and a closed audit log
All checks were successful
ci / ward-doctor (pull_request) Successful in 13s
ci / aos-cli-tests (pull_request) Successful in 18s
ci / gate (pull_request) Successful in 1m5s
613af4fa29
Two docs whose content had already stopped being true.

issue-corpus.md said, in full, that the corpus it documents is retired and
should not be revived. FEATURES.md meanwhile advertised it as a shipped
capability: "Issue-corpus discovery index - offline corpus and live Forgejo
lookup". One of those was wrong for long enough that nobody caught the pair.
The warning it carried is the doc's only load, and a retired thing not coming
back does not need a page to say so.

security-boundaries.md is two dated audits that closed their issues. Nothing
references it, the findings are recorded where the work happened, and an audit
is a record of a question already answered rather than a description of the
boundary today. The boundary itself is documented where it is enforced.

Both were found by reading rather than by pattern: zero inbound references and
a FEATURES entry contradicting its own target.

This is 66 docs against a cap of 40. The rest of the walk, with the arithmetic
for what closes the gap, is on the tracking issue.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
66 docs to 54. Three systematic passes rather than case-by-case editing.

Per-doc 'See also' sections went, 252 lines across 43 docs. FEATURES.md is the
index and every one of those lists was a second copy of a slice of it, which is
the same duplication the count cap exists to stop.

Merge scaffolding went next. Folding a page in added an H2 repeating the page
title, so a merged doc opened with its own name twice.

Then twelve clusters merged, and seven of those landed over a cap and were
trimmed back under rather than reverted. The trims cut restatement: a section
pointing at a page that is now a section of itself, an abstract repeating its
own heading, a migration checklist that belongs to the rollout repo, a
closed-issue note about code already removed.

features-agents did not survive the trim. 111 lines but 10,278 chars, and
nothing short of deleting capability rows got it under 8,000, so it split back
out. Density rather than length is what stops these merges.

54 docs against a cap of 40, all within caps, 539 tests green.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
54 docs to 50, all within caps, 539 tests green.

Six clusters merged: the caps reference into pre-commit hygiene, shell and
secrets into install, the composed-role probes into test harnesses, the hooks
reference into authoring, the status-line composer into the branded terminal,
and the catalogue cache into convergence. Four landed over a cap and were
trimmed rather than reverted, cutting an index of pages that had become
sections of their own file, a dated first-run note, a per-OS install recipe the
README already owns, and a JSON sample restated in the prose beside it.

Two did not survive, and both are findings rather than setbacks.

catalog-caps-reference.md is generated with a drift test. Folding it into
another page broke test_committed_render_is_in_sync, because the generator
writes a file and the test compares that file. It is back out, regenerated, and
it cannot be merged at all: a generated doc is pinned to its own path by the
thing that generates it.

The skill-discipline hooks reference moved to the handbook and pushed that page
to 159 lines, so it is its own page again. Moving 61 lines of reference between
two pages that are both near cap relocates the overflow rather than removing it.

Ten docs from the cap. The remaining pairs are 70 to 90 lines each, so every one
needs real cutting rather than folding.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
docs: reach the 40-doc cap, and wire the check
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 16s
ci / ward-doctor (pull_request) Successful in 13s
ci / gate (pull_request) Successful in 53s
dev-base-pr / build (pull_request) Successful in 13m54s
642e597fe1
40 docs, 4,120 lines, every doc inside 120 lines and 8,000 chars.
check_docs_count is now in main()'s violation list, which is the line #1090
deferred until this repository could pass it.

Ten more clusters merged, then the overflow trimmed back under rather than
reverted. What the trimming cut was restatement, not explanation: four repo-map
traces that repeated one 'find the surfaces / first check / notes' skeleton, a
mirror contract whose every clause was already stated by the mirror workflow
section above it, a role matrix duplicating roles.kdl, install recipes the
README owns, and a JSON sample restated in the prose beside it.

Two merge bugs surfaced and are fixed corpus-wide. Folding a page in carried its
YAML frontmatter into the middle of the host document, 64 lines across the
corpus. And a part whose title differed slightly from its new page kept an H2
repeating that page's own name, so a merged doc opened with its title twice.

One pairing was wrong rather than oversized. 61 lines of hook reference had been
folded into features-agents, a capability inventory, where it did not belong. It
went to the authoring walkthrough instead, which is the page that tells someone
to run those hooks.

Rephrasing to be tighter does not reduce line count, since reflowed prose
occupies the same rows. The last dozen lines came from folding small trailing
sections into the paragraph above them, which removes a heading and its blank
line without touching a word of content.

539 tests green.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilyco-ops changed title from aos/claude/aw85-docs-prune to feat(docs): size bands with a docs-count cap, and the migration that lets it land 2026-08-17 00:23:32 +00:00
coilysiren deleted branch aos/claude/aw85-docs-prune 2026-08-17 00:34:22 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!1108
No description provided.