Plan: Docs Prose Readability
On this page
Status
24 batches, each its own GitLab issue + branch + MR. Weight is the word-count band (1 = under 5k, 2 = 5-10k, 3 = 10-20k) from the combined word count of the batch’s pages, computed against the repo state at plan-authoring time (2026-08-14); re-verify per batch before filing its issue, since pages may grow.
| # | Pages | Words | Wt | Status |
|---|---|---|---|---|
1 |
|
6,804 |
2 |
Done (2026-08-21) — MR !1433 merged (f556688c, closed #1436). All 4 non-skipped pages rewritten ( |
2 |
|
14,433 |
3 |
Done (2026-08-25) — MR !1483 merged (0c83b841, closed #1437). Five source-verified fact corrections rode the rewrite (1.97.0 pin, 66 members, live-count e2e phrasing, the personal glab path, the #1579 tombstone-404 convention); zero new Antora warnings (differential 8 = 8). |
3 |
|
14,551 |
3 |
Done (2026-08-25) — MR !1484 merged (27f702f8, closed #1438). Reference-shaped pages kept scannable by design; fact corrections: the ADR-014 mislabel, the onboarding toolchain/count staleness, the ATO DB list, three count pins to live phrasing. |
4 |
|
15,222 |
3 |
Done (2026-08-25) — MR !1485 merged (9aa7bafc, closed #1439). known-issues + stale-work-policy already genuine prose, untouched by design; fact corrections on the other two (realm roles 6→9, Plan E client note, build-list gaps, count pins); the docker-promote registry gap filed as #1584. |
5 |
|
15,427 |
3 |
Done (2026-08-25) — MR !1486 merged (c423cf48, closed #1440). Scorecard untouched by design; the retired 5-stage CI description, the May-era Playwright enumerations, and the composition-less module list corrected; residual "CI security-only" drift filed as #1585. |
6 |
|
14,512 |
3 |
Done (2026-08-25) — MR !1487 merged (ed921a79, closed #1441). quality-gates/why-craig/screenshots untouched by design; rulesets' dead CI claim + roadmap’s perf-section drift corrected; the "~29 requests" sweep extends #1585. |
7 |
|
15,454 |
3 |
Done (2026-08-25) — MR !1488 merged (1cedd016, closed #1442). Terse-reference form kept; the contradictory count pins retired (70 constants / 54 variants today), security’s catalog reconciled to 19 tables, financial gains the platform-tables note + placement_terminations. |
8 |
|
3,807 |
1 |
Done (2026-08-25) — MR !1489 merged (a3603380, closed #1443). All five gain the platform-tables note; cases' catalog reconciled 18 → 26 domain tables (eight verified rows added); exchange gains ssa_cohort_watermarks. |
9 |
|
17,649 |
3 |
Done (2026-08-25) — MR !1490 merged (b3defcf3, closed #1444). Historical phase-spec form kept; the retired five-stage CI table, the pre-#1579 soft-delete bullet, the six-role table, the Planned perf status, Phase 4’s stale deferrals, and the placeholder-dashboard claim all corrected. |
10 |
|
5,783 |
2 |
Done (2026-08-25) — MR !1491 merged (6df31e80, closed #1445). Four pages untouched by design; multi-jurisdiction-extensibility synced with the post-guide trait/struct growth (4-required/3-defaulted split, the tx-stub search_schemes override, 7 → 8 contribution fields, snippets byte-faithful again). |
11 |
|
5,747 |
2 |
Done (2026-08-25) — MR !1492 merged (f017872b, closed #1446). Landing-page count pins retired; the 9-role reality landed on security + NIST (with the #489 exception recorded); the VPAT’s CI overclaim fixed; VPAT dated-count refresh filed as #1586. |
12 |
|
15,324 |
3 |
Blocked (maintainer decision on #1447: the interfaces/* pages are imported legacy vendor documents banner-marked "as written" — humanising would corrupt the faithful record; batches 12-18 all hold on this call) |
13 |
|
13,325 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
14 |
|
14,911 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
15 |
|
12,967 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
16 |
|
15,101 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
17 |
|
13,318 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
18 |
|
15,416 |
3 |
Blocked (the #1447 as-written vendor-document decision — see batch 12’s row) |
19 |
|
16,529 |
3 |
Done (2026-08-25) — MR !1497 merged (08b7e6c3, closed #1454). Generator-owned prose humanised per the re-scope (response-line colons fleet-wide, the :description: attribute, the index page + linked #1022) + all ten pages regenerated under the drift gate; follow-up #1588 (path-brace escaping). |
20 |
|
15,399 |
3 |
Done (2026-08-25) — MR !1498 merged (da66191a, closed #1455). The eight service-level OpenAPI |
21 |
|
12,258 |
3 |
Done (2026-08-25) — MR !1493 merged (1a75fe43, closed #1456). ui-philosophy gained the composition build-state passage; current-state’s |
22 |
|
4,870 |
1 |
Done (2026-08-25) — MR !1494 merged (e5e991aa, closed #1457). ~40 verified build-state corrections (the four-state shell-owns-loading split + shipped blocking lint, the 9-role table, Phase-11 portal framing, unshipped-asset/lint honesty); R4 follow-up #1587 (theme.rs 28-token comment). |
23 |
|
2,687 |
1 |
Done (2026-08-25) — MR !1495 merged (7259fb05, closed #1458). Target-state IMPORTANT banners per page (the payments house pattern) with verified built/design-target splits; the #1054 fence, the five-variant ICPC vocabulary, the broken caseworker-guide anchor, and the jurisdiction-owned safety vocabulary corrected inline. |
24 |
|
1,040 |
1 |
Done (2026-08-25) — MR !1496 merged (48e46d20, closed #1459). Target-state banners; the NCANDS-built vs AFCARS-#949-stub split stated honestly (J-review catch); phantom roles dropped. Closes the design arc (batches 21-24). |
Epic: &82
Issues: #1436-#1459
Label: Plan::DOCS-PROSE (scoped label, applied to the epic and all 24 child issues, per this
project’s recorded label taxonomy for scoped Plan labels)
Branch: feature/docs-prose-readability (this plan). Per-batch work happens on
feature/docs-batch-{N}-{slug} (one branch per batch, one MR per batch) — see Design for how Batch 1
reconciles with the pilot page’s existing branch.
Commit/issue/MR type: docs throughout (issue titles, commit subjects, MR titles) — this is a
prose-only documentation initiative, no other type applies.
Context
Most of the ~304 pages under docs/modules/ROOT/pages were authored (or heavily edited) by AI agents
working the codebase, and it shows: long comma/em-dash-chained sentences, parenthetical issue/PR/ADR
citations embedded mid-clause, and jargon used without definition. intake-standalone-architecture.adoc
was rewritten as a pilot (2026-08-14, this session, commit 75dff456 on branch
feature/humanize-intake-standalone-architecture, not yet merged) to establish the pattern; the result
reads as prose a human would write, not a compressed changelog, while keeping every technical claim,
cross-reference, and the embedded mermaid diagram unchanged.
This plan formalizes that pattern into a repeatable, reviewed process for the rest of the human-facing
docs tree, per .claude/rules/plan-lifecycle.md and .claude/rules/gitlab-issue-mr-standards.md (a plan
that yields multiple issues gets an epic first, then child issues, each independently shippable and
mergeable).
Scope
In scope (90 pages total — verified by direct ls/wc -w against the repo at plan-authoring time,
2026-08-14):
-
Top-level pages directly under
docs/modules/ROOT/pages/.adoc: 45 files. This total already includes the 7data-model-.adocpages (data-model-cases.adoc,data-model-exchange.adoc,data-model-financial.adoc,data-model-placement.adoc,data-model-reporting.adoc,data-model-rules.adoc,data-model-security.adoc) — they live directly underpages/, not a subdirectory, so they are not a separate bucket on top of the 45. -
docs/modules/ROOT/pages/interfaces/*.adoc: 18 files. -
docs/modules/ROOT/pages/api/*.adoc: 10 files. -
docs/modules/ROOT/pages/design/*.adoc: 17 files.
45 + 18 + 10 + 17 = 90. Every one of the 90 files is enumerated by name in exactly one batch in the Status table above — there is no glob, wildcard, or "everything else" bucket left for an implementer to re-derive.
Out of scope, and why:
-
docs/modules/ROOT/pages/adrs/.adoc(64 files) — ADRs are frozen, point-in-time decision records. Per `writing-adrs.adoc’s Errata step, even a genuine implementation deviation from an ADR is documented in the ADR’s *linked plan, never by editing the ADR text itself — "the plan tracks how the implementation actually shipped; the ADR records what was decided." A prose-readability pass is not a deviation errata, so there is no mechanism in this project for revising ADR prose after acceptance; ADRs stay untouched. -
docs/modules/ROOT/pages/plans/.adoc, both active (48) andplans/archive/.adoc(95) — active plans are living specs maintained by whoever implements them as part of that work (plan-lifecycle.md: "when implementation deviates, update the plan’s Design/Scope so the plan-code diff is zero"), not a standalone documentation-quality target; archived plans are frozen records of what shipped and are explicitly reserved for "genuine post-hoc corrections only." -
Synced surfaces (
.claude/rules/,docs/modules/standards/pages/) — per.claude/rules/macro-feedback.md, these are template-owned; a readability issue there is aclaude-quickstarttemplate issue, escalated separately, never edited locally.
Design
Per-page process (established by the pilot, intake-standalone-architecture.adoc):
-
Work section by section (or paragraph by paragraph for Batch 1, the pilot batch): the rewriter proposes current-vs-proposed prose for one section, the batch’s assigned reviewer (the MR reviewer for unattended batches; the user, synchronously, for a batch worked in an interactive session) responds with approve/adjust, the rewriter applies via a single edit, then moves to the next section. From Batch 2 onward the rewriter instead proposes a full rewritten page in one pass, falling back to paragraph-by-paragraph only for a specific page that draws pushback.
-
Preserve every technical fact, code identifier, and existing
xref:/link exactly. Rewriting changes sentence structure and word choice, never content — with two source-verified exceptions established in Batch 1’s J5 remediation (2026-08-18): (a) defining jargon inline may add a fact the removed text didn’t state (an acronym expansion, a standard’s name), provided it’s verified against the actual source/spec before writing, not asserted from training-data recall; (b) a claim in the pre-rewrite prose that is factually stale (verified against current source, e.g. a hardcoded port number superseded by ephemeral allocation) is corrected, not preserved — pergit-and-mr-workflow.md, a found bug still gets filed as its own issue rather than silently fixed, but a doc-only staleness the rewrite is already touching that sentence for is corrected in place, not left wrong on the theory that word-choice-only edits can’t touch facts. Either exception requires the same source verificationjudgment-protocols.mdalready mandates for library/API claims — an unverified addition is still out of scope. -
Convert em dashes used as a colon-substitute (X — meaning Y) to actual colons.
-
Define jargon inline on first use (e.g. "seam", the JOSE
kidclaim) rather than removing the term or renaming the section heading. -
Where a bare
#NNNissue reference exists, prefer linking it:#NNN(noxref:shortcut exists for GitLab issues in this project). -
Where a cross-page anchor is needed that doesn’t already have an explicit
, verify the real Asciidoctor-generated anchor ID against the built site (npx antora antora-playbook.yml --to-dir <scratch>, thengrep -o 'id="…"'in the built HTML) before using it. Asciidoctor’s default ID separator is_, not-— confirmed the hard way on the pilot page, where a guessed hyphenated anchor would have silently 404’d. An explicitanchor added as part of this plan’s own edits (e.g. a glossary term newly linked from a rewritten page) does not need this verification — explicit anchors are spec-deterministic (always yieldsid="x"), unlike guessed auto-generated section IDs. -
Agent-index exception: a page whose own text states it is a terse index for agents rather than human-facing documentation (
services.adoc’s NOTE: "a thin per-service INDEX… NOT a catalog"), and whose content is predominantly a reference table plus one-line lookup bullets rather than narrative paragraphs, is skipped — decompressing single-line reference bullets into fuller sentences would hurt the scanability that is the page’s actual purpose. Confirmed with the user per-page, not assumed; record the skip in the batch’s Status cell rather than silently dropping the page. `index.adoc(Batch 11) andapi/index.adoc(Batch 19) are the other candidates for this exception when their batches are reached. -
Generated-page exception (Batches 19-20, decided 2026-08-21): every page under
api/is auto-generated bycargo xtask api-docsand drift-gated in CI (ci-testsfails when the committed pages differ from a from-source regeneration), so hand-editing the committed pages cannot work. These two batches instead humanise the generator (the api-docs emitter templates) so regenerated pages come out readable; the drift gate keeps holding. Decision recorded on #1454 / #1455 (maintainer steer). The split between the two batches follows the two prose surfaces, not the issue page lists (the emitter is ONE shared code path, so a per-page split cannot map onto it): Batch 19 = the generator-owned strings (the response-list separator, the page:description:attribute, the index page) + a full regeneration; Batch 20 = the pass-through service-level intros (each service’s OpenAPIinfo.description, which renders as its page’s lead paragraph) + a full regeneration. Endpoint-level pass-through prose (utoipa summaries/descriptions) stays out of scope for this program — humanising it fleet-wide would be a services-wide annotation sweep, not a docs batch.
Batching rule: cap each batch at 5 pages OR ~15k combined words, whichever is hit first, so no single MR
is unreviewable. A single page whose own word count already exceeds ~15k (only implementation-guide.adoc,
at 17,649 words) is its own one-page batch — the cap bounds how much gets bundled together, not the size
of an individual page, which cannot be split across two MRs without corrupting its structure.
Batch 1 / branch reconciliation: the pilot page (intake-standalone-architecture.adoc) was rewritten
before this plan or its epic existed, on a page-scoped branch (feature/humanize-intake-standalone-architecture).
That branch becomes Batch 1’s working branch (rename convention aside — it is not renamed, to preserve the
existing commit’s branch reference); the remaining 4 Batch 1 pages are added to it as further commits, and
it is opened as Batch 1’s single MR once all 5 pages are done. Batches 2-24 start clean on
feature/docs-batch-{N}-{slug} with no equivalent pre-existing work.
Steps
Step 0: Plan + governance setup
-
Author this plan (this file), take it through contextless review rounds until clean.
-
Create the epic (title, summary, plan link) and 24 child issues (one per batch), weight-tagged per the Status table, linked via the
epic_idAPI field per.claude/rules/gitlab-issue-mr-standards.md. -
Add the
docs/modules/ROOT/nav.adocentry under Active. -
Commit this plan on its own branch (
feature/docs-prose-readability), separate from any batch’s implementation branch — mirroring thegateway-199-reportingplan’s precedent of a dedicated plan-revision branch distinct from MR branches.
Steps 1-24: Batches 1-24
-
One step per batch row in the Status table above. Each batch’s Status cell is updated as its issue progresses (
Not started→In progress→Done (YYYY-MM-DD) — MR !N), per the canonical Status vocabulary. -
On Batch 24’s completion: Status → Done for the whole plan, move the nav entry from Active to Archive, close the epic.
Files Touched
| File | Change |
|---|---|
90 pages enumerated in the Status table ( |
Prose rewritten for readability; no technical content, xref target, or diagram changes. |
|
Plan entry added under Active on creation, moved to Archive on completion. |
Verification
-
Per page:
npx antora antora-playbook.yml --to-dir <scratch>and grep the build log for warnings scoped to the changed file — no new broken xref targets or unresolved attributes introduced by the edit (pre-existing warnings, e.g. from{id}-shaped code spans predating the rewrite, are not regressions). -
Per page: a fresh read confirms every technical claim, identifier, and link in the rewritten prose matches the pre-rewrite version. The pre-commit token-gate subagent review already runs this check on every commit (not once per MR — a multi-page batch means multiple firings on one branch); for a pure-prose diff, J5 (do the docs still match reality) is the item doing the real work here, with J3 (wrong logic / incompatible change) as a secondary check against any accidental fact-drift and J4 (authn/authz/PII wording) relevant only on pages describing security-sensitive behavior.
-
cargo xtask plan-lintclean on this plan file throughout its lifecycle. -
cargo xtask check-docsclean (no drift introduced in synced surfaces — none should be touched by this plan’s scope).
Documentation Updates
-
docs/modules/ROOT/nav.adoc— Active entry on creation, Archive entry on completion. -
CHANGELOG.adoc— one== Unreleasedentry per batch MR.