Skip to content

docs(link): generate the CLI, configuration, and API references from … - #1416

Closed
evanorti wants to merge 8 commits into
mainfrom
docs-reference-generation
Closed

docs(link): generate the CLI, configuration, and API references from …#1416
evanorti wants to merge 8 commits into
mainfrom
docs-reference-generation

Conversation

@evanorti

Copy link
Copy Markdown
Collaborator

The three reference pages under link/docs are derived from the code rather than typed by hand, so they cannot drift from it. Tables live between markers and are written by link/docs/tools/refgen.py; the prose around them is hand-written and never touched by the tool.

python3 link/docs/tools/refgen.py all --check   # fails if a table moved
python3 link/docs/tools/refgen.py all           # heals it

Sources: the config structs for configuration, the built binary's --help tree for the CLI, and proto/link/*.proto for the API. Facts that live in neither a struct nor a schema are read out of the code that enforces them: config required-ness from the Validate methods, required flags from the MarkFlagRequired calls in the command wiring.

The generator refuses to write rather than guess. A new command in no task group, a new config key with no description, a region with no marker on its page, a renamed default constant, or a flag documented nowhere all fail loudly, because a table that silently omits something looks complete.

Two test suites: test-refgen.py covers the marker engine and the extraction, and test-refgen-e2e.py mutates a copy of the source fifteen ways and asserts what happens, including removals. Every "it fails loudly" claim above is one of those cases.

The workflow runs check mode on any change under link/, proto/, or gen/. It only reports; regenerating stays a human's command for now.

…source

The three reference pages under link/docs are derived from the code rather
than typed by hand, so they cannot drift from it. Tables live between
<!-- GEN:... --> markers and are written by link/docs/tools/refgen.py; the
prose around them is hand-written and never touched by the tool.

    python3 link/docs/tools/refgen.py all --check   # fails if a table moved
    python3 link/docs/tools/refgen.py all           # heals it

Sources: the config structs for configuration, the built binary's --help tree
for the CLI, and proto/link/*.proto for the API. Facts that live in neither a
struct nor a schema are read out of the code that enforces them: config
required-ness from the Validate methods, required flags from the
MarkFlagRequired calls in the command wiring.

The generator refuses to write rather than guess. A new command in no task
group, a new config key with no description, a region with no marker on its
page, a renamed default constant, or a flag documented nowhere all fail
loudly, because a table that silently omits something looks complete.

Two test suites: test-refgen.py covers the marker engine and the extraction,
and test-refgen-e2e.py mutates a copy of the source fifteen ways and asserts
what happens, including removals. Every "it fails loudly" claim above is one
of those cases.

The workflow runs check mode on any change under link/, proto/, or gen/. It
only reports; regenerating stays a human's command for now.
Comment on lines +39 to +71
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

# The CLI generator builds the binary, because Cobra computes a flag's
# default when the flag is registered, so --help is the honest source.
- uses: actions/setup-go@v5
with:
# read from the module rather than pinned here, so a Go bump in
# link/go.mod does not silently break this job
go-version-file: link/go.mod

- name: Generator tests
run: python3 link/docs/tools/test-refgen.py

# Mutates a temp copy of the source and asserts that a stale page goes
# red and that each loud failure fires. Slower, because four cases
# rebuild the binary.
- name: The loop still fails when the source moves
run: python3 link/docs/tools/test-refgen-e2e.py

- name: Reference pages are current
run: python3 link/docs/tools/refgen.py all --check

# When the step above fails, the prose around those tables is suspect
# too. `--list-regions` names what moved, for the reference-drift pass.
- name: Name the stale regions
if: failure()
run: python3 link/docs/tools/refgen.py all --list-regions || true
Region discovery no longer uses hardcoded lists. Config blocks are every
struct reachable from Config, protos come from a walk of proto/, and a
command group's flags are found rather than named, so a new block, file,
or group cannot be silently absent from a page.

Each hand-written key description now carries a fingerprint of the source
it describes, so a key whose meaning changes under a stable name stops the
generator instead of keeping a stale sentence.

refgen.py all --plan reports every gap as JSON: stale regions, regions the
page has nowhere to put with their tables already rendered, orphaned
markers, and the choices only a person can make.

link/docs/README.md says where to edit and what never to touch.
@evanorti evanorti closed this Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants