Documentation
¶
Overview ¶
Purpose: decide whether the env vars a command's own source reads are
documented in .github/wiki/Config-Env-Vars.md.
Inputs: cmd/commands/<name>*.go (per cli/.claude/rules/go.md, a
command's subcommands split into "<name>_<subgroup>.go" files sharing the same prefix — the same convention tools/wikigen and tools/cmdinventory rely on for one-command-per-file), plus the Config-Env-Vars.md wiki page.
Outputs: scoreEnvVars returns "n/a" (no direct env reads found),
"documented" (every found var is documented), or "undocumented: VAR, VAR" (lists the gaps).
Constraints: DELIBERATELY CONSERVATIVE / UNDER-COUNTS. Only direct
os.Getenv/os.LookupEnv/viper.Get*/viper.IsSet/viper.BindEnv calls in the command's own cmd/commands files are seen — env vars read transitively through internal/* packages (the common case; most commands delegate to internal/config, internal/database, etc.) are invisible to this check and will not appear here. That is a known, documented limitation, not a bug: a false "n/a" undercounts but never wrongly flags a documented var as missing. This is why the CI gate treats this column as a WARN, never a FAIL.
Purpose: list the top-level commands of the v1.5 surface as the parity
matrix's rows.
Inputs: the registry of the prepared tree (commands.BuildRegistry). Outputs: one inventoryEntry per visible top-level command, sorted by name. Constraints: same selection as tools/cmdinventory's projection at depth 1:
`help`, hidden commands and canon "plugin" entries are dropped. Subcommands are intentionally ignored: CLI-R17 scores top-level commands only. The tree must already be prepared (prepareV15).
Command parity builds the four-surface parity matrix: one row per top-level CLI command, scored against wiki docs, MCP tools, env var docs, and HTTP API routes.
Purpose: CLI-R17, P7-SURF-23. The four surfaces a command can ship on
(wiki page, MCP tool, documented env vars, HTTP route) drift independently unless something compares them. This generator makes the gap visible and, for the wiki column, blocks CI on it. The MCP and HTTP columns are read from the registry the generators read, so they hold by construction; a new surface-less command shows as "no".
Mode: documents the v1.5 surface. main sets NSELF_V15=1 in its own
process (compat.V15 reads the environment on every call), points HOME and the plugin dir at an empty temp dir and calls commands.PrepareTreeForGeneration; the top-level command list is the prepared tree's registry (builtin families only, never an installed plugin, canon "plugin" entries dropped), the same list tools/cmdinventory projects.
Inputs: the prepared command registry (see Mode),
commands.MachineRegistry plus mcpgen.Tools (MCP column, see surfaces.go), invoke.Exposure for the HTTP transport (route column), .github/wiki/cmd-<name>.md (wiki column), cmd/commands/<name>*.go + .github/wiki/Config-Env-Vars.md (env column, see envvars.go for the extraction rule).
Outputs: .github/surface-parity.md (human table) and
.github/surface-parity.json (machine-readable) by default; -check verifies the committed copies match and writes nothing.
Constraints: read-only against everything except its own two output files.
Idempotent: running twice with no source changes produces byte-identical output (see internal/repoqa's drift test).
Purpose: render the parity matrix as committed markdown + JSON. Inputs: the scored []Row from buildMatrix. Outputs: renderMarkdown returns the full .github/surface-parity.md
content (with the GENERATED BY header and column-rule notes); renderJSON returns the .github/surface-parity.json bytes.
Constraints: both must be pure functions of rows (no timestamps, no
non-deterministic map iteration) so two runs against the same source produce byte-identical output — required by internal/repoqa's drift test and by the idempotency requirement in the CLI-R17 ticket.
Purpose: count, per top-level command, the MCP tools and HTTP routes the
generators serve for it (P7-SURF-23).
Inputs: the machine registry of the prepared v1.5 tree and the tool list
mcpgen.Tools builds from it. Nothing is text-scanned: a command has an MCP tool exactly when the generator lists the tool name the registry derives for it, and an HTTP route exactly when internal/httpapi's OpenAPI rule (invoke.Exposure for the HTTP transport) exposes it.
Outputs: surfaceCounts per top-level command name. A count covers the
command and every command below it (`nself db seed` counts for `db`).
Constraints: legacy alias names are not counted: they are extra names for a
command that already has its own tool. Installed plugins are out of reach (prepareV15 points the plugin dir at an empty temp dir), so the matrix describes the core surface only and is the same on every host.
Purpose: check whether a top-level command has a published wiki page. Inputs: the wiki directory and a command name. Outputs: bool — true when .github/wiki/cmd-<name>.md exists. Constraints: matches tools/wikigen's pageName convention (cmd-<name>.md,
pages live at the wiki root per its CLI-R08 flattening note) so this column can never disagree with what wikigen itself expects.