parity

command
v1.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 8 Imported by: 0

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: load the committed command inventory (tools/cmdinventory's

output) as the parity matrix's list of top-level commands.

Inputs: path to .github/command-inventory.json. Outputs: one inventoryEntry per top-level command, sorted as committed. Constraints: the JSON shape must mirror tools/cmdinventory.Command; only the

top-level fields are read here, subcommands are intentionally
ignored — CLI-R17 scores top-level commands only.

Command parity builds the four-surface parity matrix: one row per top-level CLI command, scored against wiki docs, MCP tool coverage, env var docs, and OpenAPI routes.

Purpose: CLI-R17. The four surfaces a command can ship on (wiki page,

MCP tool, documented env vars, OpenAPI route) drift independently
today — nothing catches a new command that ships without a wiki
page, or an MCP tool whose backing command got renamed. This
generator makes the gap visible and, for the wiki column, blocks
CI on it.

Inputs: .github/command-inventory.json (tools/cmdinventory's output —

reused as the authoritative top-level command list rather than
re-walking the cobra tree, so this tool needs no cmd/commands
import), .github/wiki/cmd-<name>.md (wiki column), cmd/commands/
mcp.go + mcp_sentry.go (MCP column, read as text — see mcptools.go
for the matching rule), 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.

The OpenAPI Route column is always "n/a": internal/apidocs exists
and is wired into `nself build` (internal/build/orchestrator.go),
but it documents the generated backend's HTTP surface, not the
CLI's own commands — see openapi.go in this package for the full
investigation and citations. Idempotent: running twice with no
source changes produces byte-identical output (see internal/repoqa's
drift test).

Purpose: decide which top-level commands are covered by an MCP tool.

Inputs: the two files that register MCP tools: cmd/commands/mcp.go

(6 infra tools) and cmd/commands/mcp_sentry.go (5 ɳSentry tools),
read as plain text — this tool does not import cmd/commands.

Outputs: a set of command names considered MCP-covered.

Constraints: MATCHING RULE (deliberately conservative, exact-token only —

no fuzzy/substring matching, so it never over-claims coverage):
every mcp.NewTool("tool_name", ...) call is split on '_' into
tokens (e.g. "sentry_monitors_list" -> sentry, monitors, list).
A command is covered iff its exact Name appears as one of those
tokens for ANY registered tool. This intentionally does NOT
credit near-misses: nself_run_migration does not cover "migrate"
(token is "migration", not "migrate"), nself_list_plugins does not
cover "plugin" (token is "plugins", not "plugin"). It DOES credit
nself_doctor -> doctor, nself_tail_logs -> logs, sentry_* -> sentry,
and sentry_status -> status. Verified by main_test.go against the
actual tool names registered as of CLI-R17.

Purpose: decide what the OpenAPI Route column reports.

Inputs: none at runtime — this file records a one-time investigation

of internal/apidocs/{openapi.go,plugin_routes.go} done for CLI-R17.

Outputs: openAPIColumnValue, the constant string used for every row.

Constraints: internal/apidocs DOES exist (openapi.go, openapi_test.go,

plugin_routes.go, scalar.html) and IS wired into the CLI, from
internal/build/orchestrator.go (apidocs.Generate /
apidocs.CollectPluginRoutes / apidocs.NginxConf are all called from
there, guarded by cfg.ApiDocs.Enabled during `nself build`). An
earlier version of this file wrongly claimed the package did not
exist; it does, and the finding below is corrected accordingly.

What it does NOT do is describe the CLI's own commands. Reading
internal/apidocs/openapi.go's buildSpec: the paths it emits are
(a) five hardcoded /auth/v1/* endpoints, (b) /v1/graphql (+ its
/subscriptions variant) when cfg.GraphQLEnabled, and (c) REST
routes read from each installed plugin's plugin.json rest_routes
key at build time (plugin_routes.go's CollectPluginRoutes walks
~/.nself/plugins/*/plugin.json, not this repo's source tree). All
three describe the HTTP surface of the *generated backend stack*
nself provisions (Hasura/Auth/GraphQL/plugin REST) — served at
docs.<domain>/api-docs — not the `nself <command>` CLI surface
this matrix's other three columns score. There is no field on
either side (cobra.Command, OpenAPIOperation, PluginRoute) linking
a CLI command name to an OpenAPI path, so no per-command match is
possible without inventing one. Grepped cmd/commands/api.go too
(the closest-named top-level command): it never references the
apidocs package, confirming the two surfaces are unrelated.

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: 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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL