Proposal (rationale)
Forty-three parameters across fifteen modules have no user-facing documentation. Counted
2026-08-15 with grep -h '^\[params\.' modules/*/module.toml | wc -l — which proves how many are
declared, and says nothing about whether any is reachable by a user who has not read the
manifests. They are absent from README.md, from docs/, from every page of the site, and from
rungs modules, whose output stops at name, rung, dependencies and description.
Corrected 2026-08-15, during execution. Opened as “forty”, which was the same measurement error the register already holds twice: the original count came from a command ending in
| head -40, and the truncated output was read as the total.wc -lgives 43. Recorded rather than silently amended — a count is only as good as the command’s whole pipeline, andheadis as capable of falsifying one as a pipe is of hiding an exit code.
They are not cosmetic. backlog.root decides where the backlog lands — the parameter that exists
because the first real install would otherwise have created docs/backlog/ beside an existing
docs/.ai/backlog/, which is the two-places-to-look failure arriving through the installer.
ci.provider, release.stable_branch, instructions.harnesses, adr.id_prefix,
specs.split_lines are all decisions a repo has already made and must be able to state.
So the discovery path today is: read modules/*/module.toml. That is the product’s source, and
asking a user to read it to learn the tool’s configuration surface is the practice this repo
extracts against.
It should be generated, not written. Every field the page needs — description, default,
allowed, consumed_by — is already in the manifests, and rungs modules already parses and
audits them. A hand-written table would be a second inventory of a fact the manifests own, stale on
the first parameter added; the landing page’s module list is marked generate-derivable for exactly
this reason and is the precedent to follow.
Found while assessing first-user documentation completeness on 2026-08-15.
Decision
accepted — 2026-08-15, sequenced after WI-002 so no example is written in a spelling that does
not parse.
Plan
Requirements
- Every parameter of every module is discoverable without opening a manifest.
- Each shows its module, default, allowed values where constrained, and its description.
- Behavioural parameters (
consumed_by) are marked, since they are not substituted into templates and a reader will otherwise look for a{{token}}that does not exist. - The reference cannot go stale: no file restates what a manifest already declares.
- A reader learns how to set one, in a spelling that parses.
Impacts
src/cli.ts—cmdModulesgains--params;FLAGSgains a row.- New
docs/design/parameters.md— prose only: what a parameter is, how to set one, where the values live. It states no parameter’s name or default. README.mdandmodules/README.md— point at both.- No ADR. Criterion 4: the module format is owned by ADR-0003 and
modules/README.md, and this adds no format.
Approach
Render the list from the manifests at the moment it is asked for, and never write it down.
rungs modules --params walks Manifest.params, which is already loaded and already audited by the
same command. A list produced on demand from the source of truth cannot drift from it, which no
generated-and-committed file can honestly claim.
The doc page then has one job: explain, and cite. It says what a parameter is, that --set
takes module.param=value in either spelling, that .ai/rungs.toml records the resolved values,
and that anything outside a managed block is the user’s — then sends the reader to
rungs modules --params for the values. It names no parameter, so there is nothing in it to go
stale. That is the one-definition rule applied to the thing the rule exists for.
Considered and rejected: a committed parameters.md generated by a script. It is the obvious
shape and it is a second inventory — correct the day it is generated, silently wrong the day a
default changes, and requiring a gate of its own to stay honest. The item was opened against exactly
that failure mode; reproducing it in the fix would be poor.
Acceptance criteria / tests
rungs modules --paramslists parameters for all fifteen modules, with defaults.- Its parameter count equals
grep -c '^\[params\.' modules/*/module.tomlsummed — the count is derived from the same manifests, so this checks the renderer, not the number. allowedvalues appear where a manifest declares them;consumed_byparameters are marked.docs/design/parameters.mdcontains no parameter name or default value.rungs moduleswithout the flag is byte-identical to before.rungs check→ 20 pass, 0 fail, and the site builds with the new page on the wiki.
Out of scope
- Making
--setparse the value correctly — WI-002. This item documents the parameters; it must not ship examples in a spelling that does not parse, so it is sequenced behind that one. - Deriving the landing page’s module and profile lists, marked
generate-derivableinsite/src/pages/index.astro. Same technique, different inventory — worth a shared helper, but merging them into one item would give it two purposes. - Adding, renaming or re-defaulting any parameter. This documents what exists. A default that turns out wrong once visible is a new item.
Execution
Branch feature/WI-006-parameter-reference, cut from main 2026-08-15.
src/cli.ts—cmdModules(showParams)renders each manifest’sparamswhen--paramsis passed: name, default, description,allowedvalues, and a note for behavioural ones.FLAGSgains the row, so WI-004’s help lists it.- New
docs/design/parameters.md— prose only. It explains what a parameter is, both--setspellings, that values must be set at install time and why, the substituted/behavioural split, and thereponamespace. It names no parameter’s default. README.mdanddocs/design/README.mdpoint at both.
Deviation: the plan said the page would name no parameter at all. It names backlog.root and
findings.id_prefix inside two --set examples, because an example with a placeholder key teaches
the syntax and not the shape. No default or allowed-value is stated, so nothing in the page goes
stale when one moves — which was the actual requirement.
format() in substitute.ts was the obvious way to print a default, but it is module-private and
exists for template substitution. Widening its API for a display concern would be the wrong trade;
JSON.stringify is used instead, which also quotes strings visibly.
Review
Checked 2026-08-15.
- Pass.
rungs modules --paramslists parameters under all fifteen modules. - Pass, and it caught the item’s own error. Declared
grep -h '^\[params\.' modules/*/module.toml | wc -l→ 43; rendered by the flag → 43. Equal, so the renderer drops nothing. The item was opened claiming 40, from a truncatedhead -40; corrected in the Proposal above. - Pass.
instructions.harnessesshowsone of claude · copilot · cursor · agents-mdand is marked behavioural — changes whatrenderdoes, not a template. - Pass as amended. The page states no default and no allowed-value; two parameter names appear
only as
--setexamples. Recorded as a deviation rather than a pass against the literal wording. - Pass.
rungs moduleswithout the flag prints what it always did — the parameter loop is behindif (!showParams) continue, and the audit line is unchanged. - Pass.
rungs check→ 20 pass, 0 fail. The site builds with the new page routed to/wiki/design/parameters/, links resolving.