feat(docs): size bands with a docs-count cap, and no per-file escape #1090

Closed
coilyco-ops wants to merge 7 commits from aos/claude/ym96-docs-bands into main
Member

Kai's numbers, my implementation and measurement.

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 is 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. The existing cap did not fail, it succeeded into a different problem.

The pairs came from measurement

Markdown across the fleet runs about 49 chars per line (sampled sirens-echo directly: 42-57). So lines bind first in both bands and the char cap sits above as the backstop for tables and code. That is the same relationship the old 80/4,000 already had, preserved rather than invented.

The two caps multiply into a budget, which is the number worth arguing about rather than either cap alone: 800 lines small, 4,800 large.

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 accumulated exactly where the pressure was highest. agentic-os-kai excluded nine individual SKILL.md files; agentic-os-kai and infrastructure both excluded docs/FEATURES.md from the cap that exists to keep it an inventory.

One test changed meaning as a result: a wildcard exclude used to clear generated guardfile docs from the size cap, and now clears only their placement. An oversized generated doc is a generator emitting too much, and the generator is the fix - which is the rule you already applied to infra.

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

The count check lands unwired, deliberately

A strict fleet cap cannot land from inside a repo that violates it. agentic-os carries 100 docs against its own new cap of 40, documentation-layout runs on every commit here, and --no-verify is banned - so wiring it now bricks commits to the repo that owns the hook, including the commits that would fix it.

So check_docs_count is implemented and tested but not in main()'s violation list. Wiring it is one line, in the commit that lands this repo's own migration. Every other repo goes red on its own schedule after that.

Measured migration cost, with the real validator

repo band docs over count oversized
infrastructure large 127 87 1
agentic-os large 99 59 0
lore small 69 49 44
agent-proxy small 67 47 42
agent-compose small 63 43 59
deploy small 20 0 11
agentic-os-kai small 18 0 14

285 docs to merge away, 199 needing a trim, across the checkouts I can reach. sirens-echo and ward are not local; sirens-echo adds 116 over its count.

Worth seeing before this lands: the two large repos are almost entirely a count problem (agentic-os has zero oversized docs), while agent-compose, agent-proxy and lore are both - 59 of agent-compose's 63 docs exceed 40 lines. Those three carry 3,000-4,000 lines of docs against an 800-line budget, so small band asks them to shed roughly 78%. That is the number I would want you to confirm rather than discover.

32 tests, pre-commit green.

🤖 Generated with Claude Code

Kai's numbers, my implementation and measurement. ``` 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` is 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. The existing cap did not fail, it succeeded into a different problem. ## The pairs came from measurement Markdown across the fleet runs about **49 chars per line** (sampled sirens-echo directly: 42-57). So lines bind first in both bands and the char cap sits above as the backstop for tables and code. That is the same relationship the old 80/4,000 already had, preserved rather than invented. The two caps multiply into a budget, which is the number worth arguing about rather than either cap alone: **800 lines small, 4,800 large.** ## 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 accumulated exactly where the pressure was highest. `agentic-os-kai` excluded **nine individual `SKILL.md` files**; `agentic-os-kai` and `infrastructure` both excluded `docs/FEATURES.md` from the cap that exists to keep it an inventory. One test changed meaning as a result: a wildcard exclude used to clear generated guardfile docs from the size cap, and now clears only their placement. An oversized generated doc is a generator emitting too much, and the generator is the fix - which is the rule you already applied to infra. `docs/FEATURES.md` loses its own constants and takes the band. They equalled the ordinary cap, so it was a special case in name only. ## The count check lands unwired, deliberately **A strict fleet cap cannot land from inside a repo that violates it.** agentic-os carries 100 docs against its own new cap of 40, `documentation-layout` runs on every commit here, and `--no-verify` is banned - so wiring it now bricks commits to the repo that owns the hook, including the commits that would fix it. So `check_docs_count` is implemented and tested but not in `main()`'s violation list. Wiring it is one line, in the commit that lands this repo's own migration. Every other repo goes red on its own schedule after that. ## Measured migration cost, with the real validator | repo | band | docs | over count | oversized | | --- | --- | --- | --- | --- | | infrastructure | large | 127 | 87 | 1 | | agentic-os | large | 99 | 59 | 0 | | lore | small | 69 | 49 | 44 | | agent-proxy | small | 67 | 47 | 42 | | agent-compose | small | 63 | 43 | 59 | | deploy | small | 20 | 0 | 11 | | agentic-os-kai | small | 18 | 0 | 14 | **285 docs to merge away, 199 needing a trim**, across the checkouts I can reach. sirens-echo and ward are not local; sirens-echo adds 116 over its count. Worth seeing before this lands: the two large repos are almost entirely a **count** problem (agentic-os has zero oversized docs), while `agent-compose`, `agent-proxy` and `lore` are both - 59 of agent-compose's 63 docs exceed 40 lines. Those three carry 3,000-4,000 lines of docs against an 800-line budget, so small band asks them to shed roughly 78%. That is the number I would want you to confirm rather than discover. 32 tests, `pre-commit` green. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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>
Author
Member

Band assignment revised: agent-compose is large. Kai, 2026-08-16.

Re-measured with the real validator. The change does more than move one repo across a line.

repo band docs cap over oversized lines budget keeps
infrastructure large 127 40 87 1 6,473 4,800 74%
agentic-os large 99 40 59 0 4,934 4,800 97%
agent-compose large 63 40 23 0 3,879 4,800 123%
lore small 69 20 49 44 2,869 800 27%
agent-proxy small 67 20 47 42 3,165 800 25%
deploy small 20 20 0 11 989 800 80%
agentic-os-kai small 18 20 0 14 982 800 81%
voice-corpus small 15 20 0 14 856 800 93%
agentic-os-xxx small 10 20 0 8 589 800 135%
agentic-os-hardware small 6 20 0 5 388 800 206%

Fleet: 265 docs to merge away, 140 needing a trim, down from 285 and 199.

What the move actually did

agent-compose's oversized count went 59 to 0. Every one of its docs already fits 120 lines and 8,000 chars. It was never a length problem, and small band was the wrong instrument: 40 lines would have forced a rewrite of nearly every page to solve a count problem.

That makes the three large repos one consistent job - consolidation, with essentially no per-doc trimming. agentic-os has zero oversized, infrastructure has one, agent-compose has zero.

The remaining question is agent-proxy

With agent-compose reclassified, agent-proxy is the odd one out and the data does not distinguish them:

  • agent-compose - 63 docs, 3,879 lines
  • agent-proxy - 67 docs, 3,165 lines

agent-proxy carries fewer lines of documentation than agent-compose and slightly more files. On every measure here they are the same repo. Under the current split, one gets a 4,800-line budget and the other 800, and agent-proxy sheds 75% of its content while agent-compose gains headroom.

If there is a product reason - agent-compose being more central to how agents are built - that is a fine reason and it should be the recorded one, because the numbers will not support the distinction later when someone asks.

lore is the other 27%-keep row, and it is already handled: Kai has it being refactored in a way that dissolves the problem.

Small band is validated by the tail

The genuinely small repos sit at 135%, 206% and 1403% of budget, and the mid-sized ones at 80-93%. So 40/3,000/20 is comfortable where it should be and tight where it should be, which is the shape a default wants.

**Band assignment revised: agent-compose is large. Kai, 2026-08-16.** Re-measured with the real validator. The change does more than move one repo across a line. | repo | band | docs | cap | over | oversized | lines | budget | keeps | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | infrastructure | large | 127 | 40 | 87 | 1 | 6,473 | 4,800 | 74% | | agentic-os | large | 99 | 40 | 59 | 0 | 4,934 | 4,800 | 97% | | agent-compose | large | 63 | 40 | 23 | **0** | 3,879 | 4,800 | 123% | | lore | small | 69 | 20 | 49 | 44 | 2,869 | 800 | 27% | | agent-proxy | small | 67 | 20 | 47 | 42 | 3,165 | 800 | 25% | | deploy | small | 20 | 20 | 0 | 11 | 989 | 800 | 80% | | agentic-os-kai | small | 18 | 20 | 0 | 14 | 982 | 800 | 81% | | voice-corpus | small | 15 | 20 | 0 | 14 | 856 | 800 | 93% | | agentic-os-xxx | small | 10 | 20 | 0 | 8 | 589 | 800 | 135% | | agentic-os-hardware | small | 6 | 20 | 0 | 5 | 388 | 800 | 206% | Fleet: **265 docs to merge away, 140 needing a trim**, down from 285 and 199. ## What the move actually did **agent-compose's oversized count went 59 to 0.** Every one of its docs already fits 120 lines and 8,000 chars. It was never a length problem, and small band was the wrong instrument: 40 lines would have forced a rewrite of nearly every page to solve a count problem. That makes the three large repos one consistent job - consolidation, with essentially no per-doc trimming. agentic-os has zero oversized, infrastructure has one, agent-compose has zero. ## The remaining question is agent-proxy With agent-compose reclassified, **agent-proxy is the odd one out and the data does not distinguish them**: * agent-compose - 63 docs, 3,879 lines * agent-proxy - 67 docs, 3,165 lines agent-proxy carries **fewer** lines of documentation than agent-compose and slightly more files. On every measure here they are the same repo. Under the current split, one gets a 4,800-line budget and the other 800, and agent-proxy sheds 75% of its content while agent-compose gains headroom. If there is a product reason - agent-compose being more central to how agents are built - that is a fine reason and it should be the recorded one, because the numbers will not support the distinction later when someone asks. `lore` is the other 27%-keep row, and it is already handled: Kai has it being refactored in a way that dissolves the problem. ## Small band is validated by the tail The genuinely small repos sit at 135%, 206% and 1403% of budget, and the mid-sized ones at 80-93%. So 40/3,000/20 is comfortable where it should be and tight where it should be, which is the shape a default wants.
Author
Member

Migration is #1095, based on this branch. 101 docs to 68, every hook green.

Your skill-discipline example was better than the PR body says. Its index file states the thesis outright:

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

Ten files, now five.

I could not reach 40, and the arithmetic says nobody can by merging

Merging costs lines rather than saving them. I assumed the opposite going in. 101 docs held 5,089 lines and 68 hold 5,210: each fold adds a heading and its spacing, 3.7 lines per merge measured over 33 merges.

cap capacity   40 x 120 = 4,800 lines
current                   5,210 lines
minimum docs   ceil(5210/120) = 44, at perfect packing, zero overhead

44 > 40 before any packing loss. And in practice only twelve docs are under 60 lines. The rest have a median of 77, so two of them breach the 120-line cap on contact. Merging floors out near 62.

Reaching 40 means deleting about 500 lines, 10% of the corpus.

Which changes what the number should be

Your measured migration table reads as a count problem for the two large repos, and for agentic-os it is really a volume problem wearing a count cap. The table says agentic-os | large | 99 | 59 over count | 0 oversized - zero oversized is the tell. There is no fat to squeeze, so the count cap can only be met by deletion.

I would raise the large band to around 55 rather than delete. The cap exists to stop a folder nobody can read, and sirens-echo at 156 docs with a 2,935-char median is that. 68 coherent pages is not.

Whichever way you go, check_docs_count should stay unwired until the repo passes, which is what your PR already says and what 1095 preserves.

**Migration is https://forgejo.coilysiren.me/coilyco-flight-deck/agentic-os/pulls/1095, based on this branch. 101 docs to 68, every hook green.** Your `skill-discipline` example was better than the PR body says. Its index file states the thesis outright: > The handbook is split across topic files to stay under the documentation size cap. Ten files, now five. ## I could not reach 40, and the arithmetic says nobody can by merging **Merging costs lines rather than saving them.** I assumed the opposite going in. 101 docs held 5,089 lines and 68 hold 5,210: each fold adds a heading and its spacing, **3.7 lines per merge** measured over 33 merges. ``` cap capacity 40 x 120 = 4,800 lines current 5,210 lines minimum docs ceil(5210/120) = 44, at perfect packing, zero overhead ``` **44 > 40 before any packing loss.** And in practice only twelve docs are under 60 lines. The rest have a median of 77, so two of them breach the 120-line cap on contact. Merging floors out near 62. Reaching 40 means deleting about **500 lines, 10% of the corpus**. ## Which changes what the number should be Your measured migration table reads as a count problem for the two large repos, and for agentic-os it is really a **volume** problem wearing a count cap. The table says `agentic-os | large | 99 | 59 over count | 0 oversized` - zero oversized is the tell. There is no fat to squeeze, so the count cap can only be met by deletion. I would raise the large band to around 55 rather than delete. The cap exists to stop a folder nobody can read, and sirens-echo at 156 docs with a 2,935-char median is that. 68 coherent pages is not. Whichever way you go, `check_docs_count` should stay unwired until the repo passes, which is what your PR already says and what 1095 preserves.
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>
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>
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 (#1098)
Some checks failed
ci / ward-doctor (pull_request) Successful in 14s
ci / aos-cli-tests (pull_request) Successful in 20s
ci / gate (pull_request) Successful in 53s
dev-base-pr / build (pull_request) Failing after 15m25s
1e16fa2b49
Refs #1097. Based on `aos/claude/ym96-docs-bands`, same as #1095 was.

Two docs whose content had stopped being true.

**`issue-corpus.md`** said, in full, that the corpus it documents is retired and must not be revived. `FEATURES.md` meanwhile listed it as a shipped capability: *Issue-corpus discovery index - offline corpus and live Forgejo lookup*. One of those had been wrong long enough that nobody caught the pair. Both are gone.

**`security-boundaries.md`** is two dated audits that closed their issues. Zero inbound references anywhere in the repo.

## What the walk did not find

Staleness. No doc references a renamed thing (`ward-mcp`, `cli-guard`) or a deleted repo. The quiet docs are quiet because their subject is stable: `signoz.md`, `aos-catalogue-cache.md` and `composed-house-taste.md` each have one commit and one inbound reference, and each documents a live capability. Deleting those to reach a number would destroy the reference material the cap exists to make readable.

## Where that leaves the count

66 docs against a cap of 40, all hooks green.

The remaining gap is a **trimming pass, not a deletion pass**: roughly 600 lines of prose cut out of docs that all stay, plus 17 merges. #1097 carries the per-doc list and the arithmetic showing it closes at 40 docs / 4,525 lines.

The blocker on merging alone is density. Median doc is 77 lines, so two of them breach the 120-line cap on contact. I hit it three times today, including `features-agents` + `claude-settings-guardrails` at 116 lines but 9,146 chars, over the char cap, despite the second file opening with *Back to features-agents.md*. Reverted rather than forced.

`pre-commit run --all-files` clean.

Reviewed-on: #1098
coilysiren closed this pull request 2026-08-17 00:39:38 +00:00
Some checks failed
ci / ward-doctor (pull_request) Successful in 14s
ci / aos-cli-tests (pull_request) Successful in 20s
ci / gate (pull_request) Successful in 53s
dev-base-pr / build (pull_request) Failing after 15m25s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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!1090
No description provided.