Writing commission's documentation
You will be able to add or change a documentation page and have it be consistent with every other page: in the right section, opening the right way, with examples that are tested and terminology that is defined exactly once.
These are the authoring conventions for everything under docs/. They are short
because there are only a few of them and all of them are enforceable.
Generated versus written
This is the rule that matters most. Some pages are produced by a script from the
source of truth in src/. They are overwritten on the next run, so hand-editing one
looks like it worked, is silently reverted, and in the meantime makes the
documentation disagree with the binary.
Every generated page opens with a comment naming its generator:
<!-- generated by scripts/generate-docs.ts — do not edit -->If you see that line, close the file and edit the source instead.
The generated pages
| page | generated by | source of truth | regenerate with |
|---|---|---|---|
docs/reference/cli.md | scripts/generate-docs.ts | the commander program exported from src/cli/index.ts | bun run generate:docs |
docs/reference/apply.md | scripts/generate-docs.ts | applySchemaJson() in src/core/apply.ts | bun run generate:docs |
docs/reference/mcp.md | scripts/generate-docs.ts | the tools registered in src/mcp/server.ts, read over the MCP protocol | bun run generate:docs |
docs/reference/config.md | scripts/generate-config-reference.ts | the config schema in src/config | bun run generate:config |
schema/commission-config.schema.json | scripts/generate-config-reference.ts | the config schema in src/config | bun run generate:config |
Everything else under docs/ is prose, written by hand, owned by a person or an agent
holding a Commission task.
How the rule is enforced
tests/docs.test.ts and tests/config.test.ts regenerate every artifact in memory and
compare it to what is on disk. Any difference fails the suite and names the command
that fixes it. Both generators also take --check, which does the same thing at the
terminal and exits 2 — a refusal, in commission’s own vocabulary — so CI can run it
directly:
bun run scripts/generate-docs.ts --check
bun run scripts/generate-config-reference.ts --checkThe consequence worth internalising: you cannot change the CLI, the apply schema, or the MCP tool list without the documentation change landing in the same commit. That is the entire point. Reference pages that drift are the most expensive kind of documentation, because they are trusted and wrong.
Adding a new generated page
Extend scripts/generate-docs.ts rather than writing a new script. It already owns the
--check flag, the artifacts() export the drift test imports, and the shared
table-and-escaping helpers. A new page is a text() function plus one entry in
build(); the drift test picks it up with no change.
If a page’s source cannot be read right now — for example, an export that another
in-flight task is still adding — push a { path, reason } onto blocked instead of
throwing. A missing page with a stated reason is recoverable; a crashed generator
takes the whole suite down with it.
Every page opens with what the reader will be able to do
The first paragraph, before any subheading, is one sentence in the second person naming the capability the reader walks away with.
You will be able to bring an existing backlog into commission, or run commission alongside a tracker that is still the system of record — binding only the work that genuinely has to reflect outward, and keeping every outbound write supervised.
Not “this page covers interop.” Not a summary of the contents. What the reader will be able to do. If you cannot write that sentence, the page does not have a purpose yet, and no amount of good prose underneath will give it one.
This applies to index pages too, including the section indexes.
Every command example is copy-pasteable and tested
- Copy-pasteable. No
$prompts, no...elisions, no placeholder that is not obviously a placeholder. A reader should be able to select the block and paste it. - In order. A page’s blocks run top to bottom from a clean checkout. If a block depends on a previous one, they are part of the same sequence, not scattered.
- Real output. Where output is shown, it is output that was actually produced, copied verbatim. Invented output is a lie with a short half-life.
- Tested. Every command sequence in a guide or a getting-started page is executed by a test. Documentation that lies is worse than none, and the only way to know it has stopped lying is to run it.
How “tested” is enforced. tests/docs.test.ts extracts every ```sh block
from every registered page, runs the commands in page order against a scratch database
with commission on PATH, and asserts the exit code — 0 unless the page is deliberately
showing a refusal, in which case the expected 2 is declared in the page’s entry. A
silent success fails as loudly as a silent failure.
Three consequences for how you write a page:
- Use
```shonly for commands that run. Captured transcripts and illustrative output go in a bare```block, which nothing executes. - A command that cannot run hermetically is skipped with a stated reason — a live
Jira token, a long-running server, a network clone — and is then validated against
the live commander tree instead, so an invented flag still fails. Same shape as the
generator’s
blockedlist: recoverable, visible, never silent. - A closing “whole sequence” block must be a subset of the page. It is checked against what the page actually ran, so the recap cannot drift from the body.
A new page carrying a ```sh block must be registered in PAGES, or the suite
fails — which is the point.
Annotate with # comments inside the block rather than prose between blocks, so the
block survives being copied:
commission next --claim # picks + claims a task, prints the context bundle
commission note myapp-3 -m "..." # breadcrumbs for the next session
commission done myapp-3 # refused until criteria + gate evidence existOne definition, in one place
docs/positioning.md is canonical. Its §6 vocabulary table is the
only definition of commission’s terms, and its §1 sentences marked canonical are copied
verbatim rather than paraphrased.
Documentation links to it and never redefines a term. If a page needs a word to
mean something §6 does not say, the page is wrong, or the word is — and the fix is to
change positioning.md first, which is owned by relay-54.
The same applies to claims about what commission does. Anything described in the present
tense must be in the shipped list of
positioning.md §8. Planned capability
is written as planned, with its task id, or is not written at all. Check with
commission show <id> before you put a claim on a page.
Where a page goes
| if the page… | it belongs in |
|---|---|
| gets a new reader to their first working loop | start/ |
| walks a specific job end to end | guides/ |
| exhaustively lists what something accepts or returns | reference/ |
| explains why the design is what it is | concepts/ |
| tells a contributor how to work on commission | contributing/ |
Pages that want to be in two sections are usually two pages. The commonest mistake is a guide that slowly turns into a reference table; the fix is to link to the generated table instead.
Structure and formatting
- One
#heading per page, matching the page’s subject. Titles come from the H1 — there is no frontmatter, because these files are read both on GitHub and rendered by the site, and frontmatter renders badly in one of them. - Sentence case in headings.
## Importing an existing backlog, not## Importing An Existing Backlog. - Relative links with the
.mdextension —../reference/cli.md, not/reference/cli. That is what works when the file is read on GitHub; the site rewrites them at build time. Link to a section with a GitHub-style anchor:../positioning.md#6-vocabulary. - Every section index links its children, and every page links back to its section. Nothing is reachable only by search.
- Wrap prose at about 90 columns. Diffs are read in terminals.
- American or British spelling — pick the one already used on the page and stop thinking about it.
Tone
Declarative, specific, willing to state limits. Commission’s refusals are written that way and the documentation should match its error messages.
State the trade-off rather than hiding it. “Commission is not a semantic memory system” belongs in the docs for the same reason it belongs in the positioning: a reader who finds the limit themselves, after adopting, stops trusting the parts that were true.
Avoid entirely: AI-powered project management, autonomous software engineer,
10x productivity, AI teammate, and the rest of
positioning.md §9.
Before you open a pull request
bun run generate:docs # if you touched the CLI, apply schema, or MCP tools
bun run generate:config # if you touched the config schema
bun test # the drift tests live hereThen attach the evidence the task’s gate asks for. Documentation tasks in this
repository carry the documented gate: test, commit, and docs.
This page is docs/contributing/documentation.md in the Commission
repository, rendered in place — the site keeps no copy of it. The repository is private, so there is no edit link to follow.