Skip to content

owieschon/clean-docs

Repository files navigation

clean-docs

clean-docs is a source-bound documentation engine and CLI for maintainers whose code changes faster than its documentation. It identifies stale claims and provides a local, deterministic path from source change to repaired, verified docs; models may phrase facts, but they never choose the facts or gate results.

CI Release License: MIT

Start here for the product map, runnable drift tutorial, real-repository postmortem, and deterministic-boundary explanation.

Why clean-docs exists

A stale sentence does not fail loudly. It keeps a straight face after the code has moved on, leaving reviewers no mechanical way to know which claim became false. Human review and general-purpose agents can improve wording, but neither makes the relationship between a claim and its source reproducible in CI.

clean-docs exists to make that relationship explicit. Source owns the facts; the packaged standard owns their form. clean-docs audits tracked Markdown, binds claims to source evidence, repairs declared regions, and fails CI when either the facts or the documentation contract drift.

Static adapters cover Python, TypeScript, OpenAPI, JSON Schema, package metadata, and MCP tools without importing repository code. Declared commands and versioned plugins run in disposable copies with bounded I/O and minimal environments.

The same verified graph produces llms.txt, named context bundles, grounded release facts, and task evaluations for people and agents. Local receipts make those checks inspectable without telemetry.

derive previews changes unless you pass --write. audit, check, verify, and release never change documentation.

How the pieces fit

clean-docs architecture: repository sources become typed evidence, source bindings, and verified documentation outcomes

Repository sources such as code, schemas, commands, package metadata, and API metadata become typed evidence through static extraction or declared, bounded execution. Source bindings connect that evidence to documentation regions, claims, and symbols. The clean-docs engine combines those bindings with the packaged writing standard, then produces three outcomes: repaired documentation, a read-only CI gate that rejects stale changes, and verified context projections such as llms.txt, context bundles, and release facts. Models may phrase supplied evidence outside this deterministic path; they do not choose facts or decide whether the gate passes.

Install and audit

Create an isolated environment, install the project, and audit the current repository:

git clone https://github.com/owieschon/clean-docs.git && cd clean-docs
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
clean-docs audit

audit inventories tracked Markdown without .clean-docs.yml, enforces corpus rules, and scans tracked product files for repository residue.

A successful audit prints the number of checked documents and exits 0. Release wheels use a separate local-artifact procedure because they do not install from a development checkout.

Protect a repository

Bootstrap the source bindings once, inspect the patch, and verify the protected baseline:

clean-docs init --no-model
git diff
clean-docs check
clean-docs verify

The final command prints a clean-docs.outcome.v1 receipt with "ok": true. Commit the manifest, generated documentation, and source change together only after that result appears.

init adds a compact source-surface summary, .clean-docs.yml, and a checked llms.txt projection. It discovers nested package manifests, proposes at most eight canonical documents, and caps machine-readable plan details while retaining the full-plan digest and counts. Run clean-docs inventory for the complete detected catalog. The summary carries a hidden catalog digest, so check catches a source replacement even when its surface count stays the same.

Catalog coverage detects additions, removals, and replacements. It does not validate individual prose claims or track every member of a discovered collection. Bind a claim to its specific source when a source edit must make that prose fail. After bound source drift, use this repair sequence:

clean-docs check       # exits 1 and names the stale binding
clean-docs drive       # repairs recognized bound regions
clean-docs project     # refreshes projections that include the repaired document
clean-docs verify      # exits 0 only when the repository is current

Commit the generated files with the source they describe. drive does not refresh projections, so a document included in llms.txt or another projection requires the separate project step.

If clean-docs cannot identify substantive authored purpose prose, init reports the affected page instead of marking metadata, a status line, or a feature fragment as a valid contract. If existing hygiene findings block adoption, follow the mature-repository baseline procedure. The explicit baseline protects existing debt by exact fingerprint and still fails on new or resolved findings.

CLI reference

Use the CLI reference to look up each command and whether it writes. The support guide defines supported runtimes, upgrades, diagnostics, and local outcome receipts.

Manifest reference

This table is derived from the binding types accepted by the manifest validator:

binding required verifies
region id, type, doc, region, extractor, source, renderer Generated content matches source evidence
claim id, type, doc, anchor, command, assertion Observed command value matches the assertion
symbol id, type, doc, anchor, source A source path or Python symbol still exists

Create .clean-docs.yml at the repository root and declare the source for each protected fact:

version: 1
bindings:
  - id: actions
    type: region
    doc: README.md
    region: actions
    extractor: python-literal
    source: {path: src/actions.py, symbol: ACTIONS}
    renderer: markdown-table
    columns: [name, tier]

Mark the generated destination in the document:

<!-- clean-docs:begin actions -->
<!-- clean-docs:end actions -->

The source assignment may be a list of dictionaries or a dictionary whose values are records. Constructor calls are read as keyword records. clean-docs parses the syntax tree and does not execute the module.

Repositories do not configure a standard path. clean-docs bundles a versioned policy pack compiled from STANDARD.md. CI fails if the authored standard changes without rebuilding that pack.

Verify public and self-hosted behavior

Reproduce the pinned public-repository proof with:

PYTHONPATH=src python3 scripts/dogfood_public_repos.py
PYTHONPATH=src python3 scripts/dogfood_bootstrap_repos.py

The binding proof checks source drift and recovery at two fixed commits; the bootstrap proof initializes pinned Python and TypeScript repositories, verifies each baseline, and requires empty reruns without executing target code.

Self-hosting uses python3 scripts/trusted_self_check.py; the verifier pinned in .clean-docs-trust.json independently checks candidate code, and updating that pin is a release operation.

Supported binding surface

This table is derived from src/clean_docs/capabilities.py by clean-docs itself:

binding source output check
claim Allowlisted JSON command Assertion at a document anchor Compare typed expected and observed values
region Static Python, structured data, text, or paths Table, list, scalar, or fenced text Re-render and compare
symbol Static path or Python symbol Reference at a document anchor Resolve the cited locator

Current limits

  • Claims consume JSON from an allowlisted command; symbols resolve static paths or Python names.
  • Declared commands and plugins run in disposable repository copies with minimal environments, active I/O limits, and timeouts. In an allowlisted argv, {python} selects the interpreter running clean-docs. Network isolation belongs to the execution environment; the security model defines the remaining OS boundary.
  • Coverage ignores must name a detected inventory ID and carry a specific reason; explain reports the evidence and repair for gaps.
  • Changed checks have published P95 time and peak-memory budgets for small, medium, and monorepo fixtures.
  • Destination markers must already exist and cannot nest.
  • Evaluation claim boundaries are defined in the evaluation guide.
  • clean-docs reports malformed configuration as exit 2, drift as exit 1, and extraction failures as exit 3. See the recorded drift demonstration and use the evaluation guide for task fixtures. The full product contract and version plan live in CLEAN_DOCS_SPEC.md.

About

A source-bound documentation engine that keeps repository prose tied to code and fails CI when declared facts drift.

Topics

Resources

License

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors