Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
4.6 KiB
Exit code reference
Generated file — do not edit by hand. This page is generated from the exit-code declaration (
msd-core/bin/shared/exit-codes.json) byscripts/gen-exit-code-docs.cjsand kept honest by a drift guard innpm run lint:generated-sync(which runsnode scripts/gen-exit-code-docs.cjs --check). Any manual edit is overwritten on the next generation run. To register a new code, add an entry to the declaration and runnode scripts/gen-exit-code-registry.cjs --write && node scripts/gen-exit-code-docs.cjs --write.
See also: ADR-3889 — one exit-code registry — Adopt the v2 exit contract — JSON error mode
Registered codes (6)
Every process-level exit code msd-tools, its hooks, and its scripts may terminate
with, by name, meaning, and the module that owns it.
| code | name | meaning | owning module | authorized by |
|---|---|---|---|---|
| 2 | HOOK_DENY |
Hook protocol deny — the harness blocks the tool call | hook-adapter |
ADR-3889 |
| 64 | USAGE |
Caller error — bad argv, unknown subcommand, missing argument | generic |
ADR-3889 |
| 66 | NO_INPUT |
Ran; zero units were in scope, and that emptiness is known to be genuine | generic |
ADR-3889 |
| 69 | UNAVAILABLE |
Could not run — prerequisite absent, input unreadable, scope unestablished | generic |
ADR-3889 |
| 70 | INTERNAL |
Self-failure — crash, timeout, killed subprocess | generic |
ADR-3889 |
| 80 | DEGRADED |
Ran to completion and is reporting a condition through its result payload rather than as a process failure | msd-tools |
ADR-3889 + ADR-2980 |
Reserved bands
The registered codes above are not chosen freely — each falls inside one of a fixed set of allocatable bands (ADR-3889 §1). A code outside these bands can never be registered; validation rejects it before it reaches the tables above. This is what makes an unfamiliar number in a CI log actionable: look up its band first, then its registered name if it has one.
| Band | Meaning |
|---|---|
0–1 |
Free — never allocatable. 0 is the universal "succeeded" convention and 1 is the universal "failed, no further detail" convention across nearly every CLI ecosystem. Registering either here would collide with that universal meaning instead of adding a distinct, named signal — so the registry leaves both permanently unallocated. |
2 |
Reserved exclusively to the Claude Code hook-protocol deny (HOOK_DENY) — owned by hook-adapter and no other module. |
3–13 |
Node-reserved. Node.js itself assigns meaning to this range (e.g. internal JavaScript errors, fatal exceptions, invalid argument errors) before a MSD process ever gets a chance to project its own outcome. Allocating one of these would be indistinguishable from a Node-level failure the process never intended to report. |
14–63, 79, 126+ |
Outside every allocatable band — not Node-reserved, but also not opened for MSD use. 126+ additionally collides with the shell convention for "command not executable" / "signal N" (128+N), which a process exit code must never impersonate. |
64–78 |
Generic band. Codes any module may use for caller-facing, non-domain-specific outcomes (bad argv, no input in scope, a missing prerequisite, an internal crash). |
80–125 |
Domain band. Codes reserved for a specific product surface's own vocabulary — currently only msd-tools' DEGRADED (a completed run reporting a condition through its payload rather than as a process failure). |
The v1/v2 exit contract
ADR-3889 §4 adds a version projection on top of this registry, not a second
registry: every registered name above projects to the same code under both
contract versions, with one deliberate exception — DEGRADED. Under the
default, backward-compatible v1 contract, a payload-carried error
(output({error})) still exits 0, exactly as
ADR-2980 ratified
for the pre-existing call sites that already depended on that behavior — 64
call sites across 9 modules per that ADR's own amendment (its original text
said ~60). Under the
opt-in v2 contract, the same outcome exits 80 (DEGRADED) instead, so a
caller that wants to branch on the exit code alone — without parsing stdout —
can opt in without breaking every existing consumer. See
Adopt the v2 exit contract for how to
turn this on, and JSON error mode for the full fault vs.
degraded-result channel taxonomy this registry sits underneath.