---
name: cli-command-docs-drift
description: "Adding/changing a CLI command requires `xtask gen` (regen CLI ref) + NO milestone/REQ codes in the clap help — the docs-drift gate is CI-gated"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 30df62c3-0b22-4b14-88de-fef422a5554f
  modified: 2026-07-29T12:05:29.853Z
---

Adding or changing a `spt` CLI command (clap enum variant / args) has TWO CI-gated obligations beyond build+clippy+tests:

1. **Regenerate the CLI reference:** `cargo run -p xtask -- gen` rewrites `docs-site/src/cli/reference.md` from the binary's `--help`. The **docs-drift gate** (`cargo run -p xtask -- check`, CI step "Docs drift gate (CLI ref + llms links)") fails on BOTH runners if the checked-in ref ≠ current `--help`. It fires independently of traceable. Verify with `xtask check: OK` before pushing.
2. **No internal codes in the clap `///` help:** the doc-comment on a clap variant/arg IS the `--help` text, so it lands verbatim in the PUBLIC CLI ref. Keep `M#-W#` / `REQ-*` / "wave" OUT of the user-facing `///` (put them in separate `// [impl->REQ-X]` code-tag comments instead). See [[public-docs-version-not-milestone]].

**Why:** M11-W2 first CI run went RED on the docs-drift gate (both runners) — the new `spt shell drive` / `api drive-poll` were missing from the ref, and my clap help comments leaked `(M11-W2, REQ-SHELL-3)`. Fix = strip the codes + `xtask gen` + commit the regenerated ref (@9d5fb63).

**How to apply:** after any cli.rs / api/mod.rs surface change, run `xtask gen` then `xtask check`, grep the diff of reference.md for `M[0-9]+-W|wave|REQ-` in ADDED lines, and commit the regenerated doc with the code change.

## 3. THE GATE'S BLIND SPOT — a feature must RE-READ its own `--help` (2026-07-25)

The drift gate compares **generated vs committed**. A help string that is merely
WRONG regenerates perfectly consistently and sails through — the gate catches a doc
that disagrees with the code, never one where the code's own words are false.

IDLE-EDGE W1 shipped cross-node `endpoint digest` (Leg D), and the clap help still read
`"Local endpoints only."` / `"The (local) endpoint id to read"`. All gates were green;
`reference.md` published the contradiction verbatim. Caught at the RELEASE CUT, and it
became the last blocker before the v0.42.0 tag (fix = PR #74 @5404199). The
hand-written `json-shapes.md` was correct the whole time — only the generated surface
lied, because nobody re-read it.

**How to apply:** when a change ADDS or REMOVES a capability, grep the clap help for
the constraint you just changed (`local`, `only`, `not supported`, `this node`) BEFORE
committing. And fix by PRECISION, not deletion, when a limit is half-true: the digest
SNAPSHOT crosses nodes but `--follow` genuinely does not, so the limit moved onto
`--follow`'s own help — where a reader hits it — with a pointer to the `--after` polling
that replaces it. doyle ruled that shape correct.

Machine-parseable error prefixes (`CROSS_NODE_FOLLOW_UNSUPPORTED:`, `WORKER_STARTED:`)
are NOT covered by this and are NOT a defect — ruled 2026-07-25: existing convention,
body after the colon is plain words, consumers may legitimately match the prefix.

## 4. RE-BROKEN 2026-07-29 — the note was known, the GATE LEG was missing

W2 (two-key subnet) added the T6 access-refresh verb. PR #121 then went RED on
BOTH platforms with the suites FULLY GREEN (2124+182 Linux / 2103+167 Windows,
zero test failures) — the failing step was the docs-drift gate alone:
`docs-site/src/cli/reference.md drifted from the binary's --help`. My last
`xtask gen` predated the new CLI surface.

**Why:** I HAD this memory and still shipped the drift, because `xtask check`
was not a leg in my gate battery (check → clippy -D warnings → units → int
seam). A remembered obligation with no mechanism enforcing it fails exactly the
way [[rule-failed-its-author-needs-a-mechanism]] predicts.

**How to apply:** `xtask check` is a PERMANENT leg of the gate battery, run in
the same window as the others — not a step to remember after a CLI change,
because the whole point is that you won't notice the CLI surface moved. Run it
under the same redirected `CARGO_TARGET_DIR` as the rest of the battery
(`REQ-XTASK-SPT-BIN-TARGET-DIR` covers the target-dir resolution that used to
make it spuriously fail — verify, don't assume, on the first run in a window).

Diagnosis note worth keeping: a deterministic red on BOTH OSes correctly rules
OUT the Linux-only registry flake, but "both legs red" says nothing about WHICH
LAYER failed. I read it as suites-red when it was a gate step. Discriminate
platform vs layer separately; read the failing STEP name before theorizing about
tests.

Sibling class found the same day: two shipped operator diagnostics
(`ACCESS_STORE_DEGRADED`, `ACCESS_STORE_MINTED`) told the operator to run `spt
access ...`, which clap rejects — the verbs live under `spt endpoint access`.
Same shape as the drift red: a string naming a CLI surface with nothing checking
it. doyle banked a hardening seed for a gate leg that validates CLI-surface
strings found in diagnostics/rustdoc against the real command tree.

Related: [[idle-edge-w1-progress]] · [[w2-two-key-subnet-progress]] · [[gate-rig-mechanisms-not-remembered-steps]]

## 5. THE GATE READS THE BINARY ON DISK — a stale `spt.exe` makes it green over real drift (todlando 2026-08-30)

`xtask check` compares the COMMITTED `reference.md` against `target/debug/spt.exe`'s
`--help` — the binary as it exists on disk, not as the source now reads. So the leg
is only as fresh as the last thing that actually LINKED the `spt` bin.

NOW-SIGNAL W2 (#44): I edited a clap doc-comment in `crates/spt/src/api/mod.rs`, then
ran `xtask check` → **exit 0**. Neither `cargo build -p spt-daemon` nor
`cargo check --workspace` rebuilds the `spt` binary, so the gate read a `spt.exe`
whose help predated my edit and honestly found no disagreement. `xtask gen` then
rewrote reference.md — proving the drift had been there the whole time.

I reported "`xtask check` does not catch reference.md drift, that gate is CI-only"
to the gater. FALSE, and I had not measured it. Restoring the pre-change ref and
re-running gave **exit 1** with the documented message: the gate works. The stale
binary was the whole story.

**How to apply:** treat `xtask check`'s drift verdict as a reading of the BINARY,
not of the source — after any `cli.rs` / `api/mod.rs` help change, make sure
something has LINKED `spt` (a `cargo build -p spt` / a test binary build) in the
same window before believing a green. And: a gate leg agreeing with you is a claim
about the meter until you push a KNOWN-DRIFT control through it — the same rule as
[[identical-readings-across-opposite-outcomes-indict-the-meter]], one layer up from
exit statuses.
