Skip to content

Why Doc-Bootstrap Works the Way It Does

Doc-bootstrap is the authoring sibling of BoB's non-authoring doc tools./doc-audit measures, /doc-sync mechanically fixes, and /doc-bootstrap authors the net-new content needed to reach a documentation target — and all three read one declarative target so they converge instead of fighting. This doc explains the design; for the steps, see the Doc-Bootstrap how-to, and for the surface, the Doc-Bootstrap reference.

The problem it solves

BoB had mature doc currency tooling — doc-keeper, /doc-audit, /doc-sync, docs-site — but no orchestrated way to apply it to a cold project. Pointing those tools at a brownfield repo with little or no documentation produced an audit full of gaps and a sync that had nothing to fix, because nothing had authored the docs yet. Doc-bootstrap is the missing cold-start capability: take an existing codebase from little-or-no docs to a complete, standard-conforming set, scaled to what the project actually warrants.

It is deliberately distinct from the docs-currency workstream (area:documentation), which keeps already-existing docs fresh. Bootstrap is about docs that do not yet exist; currency is about docs that already do.

One target, three verbs

The load-bearing idea. /doc-bootstrap, /doc-audit, and /doc-sync all operate against a single declarative target: the per-tier coverage rubric (scripts/doc-bootstrap/rubric.json) plus the documentation standard. They differ only in verb:

VerbRoleMutates?
auditmeasure distance to the targetno (read-only report)
syncfix mechanical drift toward the target (counts, links, frontmatter)yes, but never authors prose
bootstrapauthor the net-new content needed to reach the target from zeroyes — the one thing audit/sync deliberately lack

This is the Prime Directive applied to documentation: one source of truth (the rubric), many consumers. Because the target is shared, two invariants fall out for free — and are enforced as acceptance criteria.

Invariant 1 — Convergence

bootstrap then audit ⇒ audit is clean. This is true by construction, not by hope: bootstrap's own exit condition is rubric-coverage-clean. The loop is literally audit (find gaps) → generate (author) → sync (mechanical) → audit (confirm), repeating until the audit reports zero gaps. There is no way for bootstrap to "finish" while leaving a gap the audit would flag, because the same coverage function decides both.

Invariant 2 — Fixpoint (structural idempotency)

Re-running bootstrap at the same tier on docs that already meet that tier is a no-op. So bootstrap is safe as the tail of any audit/fix cycle but is never a required step. Two qualifications make this testable:

  • Tier-raising is the one honest exception. Bootstrap at a higher tier will author new artifacts — that is the target moving, not nondeterminism. Same tier ⇒ fixpoint.
  • Idempotency is structural, not byte-level. "No change" means no new/removed files and no rubric gap opened or closed — not a zero git diff on regenerated prose (LLM wording is not bit-stable). The guard asserts on coverage-state + file set, never textual equality.

The mechanism is gap-targeting: each iteration authors only the rubric artifacts that are currently missing. On a converged tree there are no gaps, so bootstrap writes nothing.

Tiers — scale the docs to the project

Not every project warrants the same documentation. Triage proposes a tier from the project's inventory (a single-purpose script → Tier 0; a multi-audience CMS → Tier 2), with a confidence score and a clean operator override. Tiers are cumulative:

TierForAdds
0 Minimala utility / script / prototypeREADME.md
1 Standardan app or library with a real ops surfaceCLAUDE.md, docs/reference/, docs/how-to/, a runbook
2 Fulla complex, multi-audience systemdocs/tutorials/, docs/explanation/, a docsite (/docs-site)

Trust: every claim is code-grounded

The fastest way to make generated docs worthless is to hallucinate — invent an env var, a CLI flag, a route. So generation carries a hard anti-hallucination guarantee: every factual claim records a source_evidence (file:line) pointer into the real tree, and a verifier rejects any artifact whose evidence does not resolve. The deterministic layer authors the grounded scaffolding (tables and sections derived from declared config); narrative prose is authored on top by the agent and stays subject to the same verifier.

Respect: augment, never clobber

Brownfield projects usually have some docs. Bootstrap reuses doc-keeper's classification (aligned / needs-update / archive) rather than reimplementing it, and the write plan follows from the verdict: an aligned doc is preserved, a needs-update doc is augmented (not rewritten), and a code-vs-doc conflict (a doc asserting a fact the code contradicts) is surfaced for the operator, never silently overwritten. Drafts are staged outside the target tree and written only after review — so reviewing pollutes nothing.

Decoupled from adopting BoB

Documenting a project must not force a project to become a BoB project. So on an external (non-.claude/) project, bootstrap writes no .claude/ config (that is cdi's job), and CLAUDE.md is opt-in — it is a project doc, not BoB config, so it is offered but never force-written.

Composition, not reimplementation

Everything heavy is delegated to tooling that already exists: rubric coverage is the audit, doc-keeper/audit.js is the classifier, /docs-site init is the Tier 2 handoff (and deploy is left an explicit operator step, never automatic), and stack-specific discovery is a pluggable hook (the first being Drupal — content types, views, Drush, hooks — which delegates deeper knowledge to the provisioned drupal-dev skill rather than hardcoding it). Bootstrap is the thin orchestrator that points these at one shared target.

See also