pub const EXIT_CODES_HELP: &str = "\
Exit codes:
0 success
1 generic failure (catch-all for non-classified errors)
2 usage error (clap argument-parse failure — unknown flag, bad value)
3 not found (entity / mem / resource missing)
4 hash mismatch (optimistic-locking failure on a mutation)
5 validation / schema / policy refusal
6 findings present — the measurement COMPLETED and recorded
something you asked to be gated on
(`projection verify --fail-on-findings`). A run that could not
complete returns its own code above, so a CI job can tell \"the
mem and its source disagree\" from \"the engine could not run\".
An artifact the pass could not read is a finding, not an error:
it was observed, and not being able to adjudicate it is the
measurement's answer.
For programmatic branching, prefer `--json` over the exit code:
memstead <subcommand> ... --json | jq -r .code
One caveat, and it bites exactly where code 6 matters: a gate-mode run
that exits 6 emits TWO documents on stdout — the report, then the typed
error. The recipe above reads only the first and prints `null`. Read the
stream instead:
memstead ... --fail-on-findings --json | jq -s -r '.[-1].code'
The JSON envelope's `code` field carries the typed token
(e.g. INVALID_TITLE, HAS_INCOMING_REFS, CROSS_MEM_LINK_NOT_ALLOWED)
with structured recovery details under `.details`.";Expand description
Top-level --help epilog describing the exit-code posture. The
taxonomy is intentionally coarse — success vs failure — because
agents read JSON, not exit codes, and shell scripts can lift the
granular code from --json | jq .code.
Code 6 breaks that success/failure symmetry on purpose: it means the measurement completed and the caller asked to be gated on what it found. A CI job needs three outcomes, not two, and it cannot get the third from a code that also means “the engine failed to boot”. Keep it exclusive to explicit opt-in gate modes — the moment a run that FAILED returns 6, the distinction stops being worth anything.
The line is “did the measurement complete”, not “was everything
well”. An artifact the pass could not read is a finding: it was
observed and could not be adjudicated, which is an answer. An
unreadable anchors sidecar is not: nothing could be observed at all,
so verify refuses with ANCHORS_SIDECAR_UNREADABLE rather than
reporting every artifact uncovered — that was a live defect, found
2026-08-21, where a corrupt file produced a red build blaming the
mem.
This string is the source the published reference renders from
(docs-site/.../reference/cli/cli.md, xtask-generated and
drift-gated). Editing the table here and not regenerating leaves the
published page asserting an exit-code space the binary no longer has.