[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: refactor (guard test). Source: review 8.5 F; register row C33. Child 1 of tracking #948.
Problem
The contract's argument and env-var tables are maintained entirely by hand:
Nothing compares them with the parser:
- The
cli_parse_* tests, which the contract cites as its guard, call Cli::try_parse_from and never read the document.
GLOBAL_ARG_ENV_VARS / LOCAL_ARG_ENV_VARS drive the empty-var scrub and the clean-env harness, but they aren't compared with the contract or with the parser.
- The only tests that read
CLI_CONTRACT.md check codes: contract_gradle_codes.rs for Gradle/JVM and scripts/tests/test_vlt_coverage.py for vlt.
On 9c43dfc the tables are complete apart from the two small gaps in items 4 and 6 below. A debug build's --help for all nine visible subcommands lists no --long flag and no [env: SOCKET_*] that the tables miss. The tables' only flags absent from --help are the hidden deprecated spellings (--apply, --vendor, --no-apply) and the removed --redirect/--detached (exit 2). Two runs gave the same result. The test needs only those two fixes to land green, and then it stops the next flag from shipping undocumented.
Symptoms
None open. The same class of drift exists for codes (#930, #931) and for core-read env vars (#678). Impact: low risk, small size; it is mostly preventive.
Proposed change
Add crates/socket-patch-cli/tests/contract_cli_tables.rs, modelled on contract_gradle_codes.rs. It walks socket_patch_cli::Cli::command(), including hidden arguments, and checks:
-
Every non-hidden subcommand appears in the Subcommands table, with its visible aliases.
-
Every global argument (those on GlobalArgs) has a Global-arguments row naming its --long, its -short when it has one, and its env when it has one.
-
Every local argument of each subcommand appears in backticks in a Per-subcommand row whose first cell names that subcommand. Hidden deprecated spellings must appear too, so their mapping stays documented.
-
Every clap env binding appears by its full name in the Environment-variables section. Today four don't. The SOCKET_VEX row abbreviates SOCKET_VEX_PRODUCT, SOCKET_VEX_NO_VERIFY, SOCKET_VEX_DOC_ID and SOCKET_VEX_COMPACT as "the SOCKET_VEX_* knobs (_PRODUCT, …)", and they are spelled out only in the per-subcommand table. Give each one a row.
-
Reverse direction: every backticked --flag in those tables either exists in Cli::command() or is on a short explicit list of removed spellings that the test asserts clap rejects (today --redirect and --detached).
-
GLOBAL_ARG_ENV_VARS ∪ LOCAL_ARG_ENV_VARS equals the set of clap env bindings (hidden subcommands included), so the scrub list can't fall behind the parser. This fails today:
scan's clap-bound SOCKET_NO_SOCKET_YML is in neither list.
SOCKET_MIN_SEVERITY is read by scan itself, not by clap, although its help text carries a hand-written [env: SOCKET_MIN_SEVERITY]. It is in neither list either.
- So the
with_env_cleared harness clears neither one, and an ambient SOCKET_NO_SOCKET_YML=1 can leak into the in-process scan tests that rely on that harness.
- An exported-but-empty value is harmless, because both parsers treat empty as unset (checked twice on a debug build).
Add SOCKET_NO_SOCKET_YML to LOCAL_ARG_ENV_VARS. Have the test also require the help-text-only [env: …] names to be on the harness list, so SOCKET_MIN_SEVERITY joins LOCAL_ARG_ENV_VARS too.
Also replace the "How the contract is enforced" bullet that says the parser snapshots lock flag names with one that names this test. Nothing is deleted. Generating the tables is a possible later step; this child only pins them.
Size and scope
One new test file (~200 lines), a line or two in args.rs and a few lines in CLI_CONTRACT.md. Out of scope: core-read env vars (#678), error codes (#930) and exit codes (a later child of #948). It changes no flag, env var or default.
Acceptance criteria
Dependencies
None; it can start now. It doesn't block other work, but #678 can extend the same test to the core-read registry.
Backlog review — 2026-10-08
Consolidated into #948. The retained tracker(s) preserve this issue’s implementation scope and acceptance criteria. Closing this separate scheduling item as not planned, not as completed.
Explicit CLI-contract freshness-test child; track it inside the parent documentation-contract work.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: refactor (guard test). Source: review 8.5 F; register row C33. Child 1 of tracking #948.
Problem
The contract's argument and env-var tables are maintained entirely by hand:
Nothing compares them with the parser:
cli_parse_*tests, which the contract cites as its guard, callCli::try_parse_fromand never read the document.GLOBAL_ARG_ENV_VARS/LOCAL_ARG_ENV_VARSdrive the empty-var scrub and the clean-env harness, but they aren't compared with the contract or with the parser.CLI_CONTRACT.mdcheck codes:contract_gradle_codes.rsfor Gradle/JVM andscripts/tests/test_vlt_coverage.pyfor vlt.On
9c43dfcthe tables are complete apart from the two small gaps in items 4 and 6 below. A debug build's--helpfor all nine visible subcommands lists no--longflag and no[env: SOCKET_*]that the tables miss. The tables' only flags absent from--helpare the hidden deprecated spellings (--apply,--vendor,--no-apply) and the removed--redirect/--detached(exit 2). Two runs gave the same result. The test needs only those two fixes to land green, and then it stops the next flag from shipping undocumented.Symptoms
None open. The same class of drift exists for codes (#930, #931) and for core-read env vars (#678). Impact: low risk, small size; it is mostly preventive.
Proposed change
Add
crates/socket-patch-cli/tests/contract_cli_tables.rs, modelled oncontract_gradle_codes.rs. It walkssocket_patch_cli::Cli::command(), including hidden arguments, and checks:Every non-hidden subcommand appears in the Subcommands table, with its visible aliases.
Every global argument (those on
GlobalArgs) has a Global-arguments row naming its--long, its-shortwhen it has one, and itsenvwhen it has one.Every local argument of each subcommand appears in backticks in a Per-subcommand row whose first cell names that subcommand. Hidden deprecated spellings must appear too, so their mapping stays documented.
Every clap
envbinding appears by its full name in the Environment-variables section. Today four don't. TheSOCKET_VEXrow abbreviatesSOCKET_VEX_PRODUCT,SOCKET_VEX_NO_VERIFY,SOCKET_VEX_DOC_IDandSOCKET_VEX_COMPACTas "theSOCKET_VEX_*knobs (_PRODUCT, …)", and they are spelled out only in the per-subcommand table. Give each one a row.Reverse direction: every backticked
--flagin those tables either exists inCli::command()or is on a short explicit list of removed spellings that the test asserts clap rejects (today--redirectand--detached).GLOBAL_ARG_ENV_VARS∪LOCAL_ARG_ENV_VARSequals the set of clapenvbindings (hidden subcommands included), so the scrub list can't fall behind the parser. This fails today:scan's clap-boundSOCKET_NO_SOCKET_YMLis in neither list.SOCKET_MIN_SEVERITYis read by scan itself, not by clap, although its help text carries a hand-written[env: SOCKET_MIN_SEVERITY]. It is in neither list either.with_env_clearedharness clears neither one, and an ambientSOCKET_NO_SOCKET_YML=1can leak into the in-process scan tests that rely on that harness.Add
SOCKET_NO_SOCKET_YMLtoLOCAL_ARG_ENV_VARS. Have the test also require the help-text-only[env: …]names to be on the harness list, soSOCKET_MIN_SEVERITYjoinsLOCAL_ARG_ENV_VARStoo.Also replace the "How the contract is enforced" bullet that says the parser snapshots lock flag names with one that names this test. Nothing is deleted. Generating the tables is a possible later step; this child only pins them.
Size and scope
One new test file (~200 lines), a line or two in
args.rsand a few lines inCLI_CONTRACT.md. Out of scope: core-read env vars (#678), error codes (#930) and exit codes (a later child of #948). It changes no flag, env var or default.Acceptance criteria
cargo test -p socket-patch-cli --test contract_cli_tablespasses onmain.#[arg(long)]field without documenting it, makes the test fail with a message naming the flag or variable (check locally once each way).cli_parse_*,cli_global_argsandhelp_text_hygienetests stay green.LOCAL_ARG_ENV_VARSentries.Dependencies
None; it can start now. It doesn't block other work, but #678 can extend the same test to the core-read registry.
Backlog review — 2026-10-08
Consolidated into #948. The retained tracker(s) preserve this issue’s implementation scope and acceptance criteria. Closing this separate scheduling item as not planned, not as completed.
Explicit CLI-contract freshness-test child; track it inside the parent documentation-contract work.