# EasySpecs CLI — error codes

Single reference for **process exit codes**, structured **`failureExitId`** subcodes, and how they appear in **`--json`** and stderr. **Normative:** **[SRS-39](../../.easyspecs/docs/srs/srs-39.md)** (**R1.3**), **[SRS-70](../../.easyspecs/docs/srs/srs-70.md)** / **[PLAN-SRS-70](../../.easyspecs/docs/srs/PLAN-SRS-70.md)** (retired OS **5**; dedicated integers **49–87**), **[SRS-57](../../.easyspecs/docs/srs/srs-57.md)**, **[SRS-58](../../.easyspecs/docs/srs/srs-58.md)**, **[SRS-72](../../.easyspecs/docs/srs/srs-72.md)** (readiness **84–87**).

**Maintenance:** When you add an **`OsExit`** value or change **`describeExitCode`**, update this file **in the same change** as [`src/cli/exitCodes.ts`](../../src/cli/exitCodes.ts), [`src/factory/factoryValidationFailures.ts`](../../src/factory/factoryValidationFailures.ts), and [`src/cli/failureExitRegistry.ts`](../../src/cli/failureExitRegistry.ts).

---

## 1. Process exit codes (OS / `process.exit`)

**Breaking (SRS-70):** The CLI **never** exits with **OS code `5`**. Former “validation / factory pipeline” outcomes use **dedicated integers** (**49–87**) so **`$?`** in CI is actionable without parsing JSON.

**`failureExitId`:** string **`{major}.{minor}`** where **`major`** is the **decimal digits of the same integer** passed to **`process.exit`**.

| Code | Meaning |
|:----:|--------|
| **0** | Success. |
| **2** | Usage — invalid arguments, unknown subcommand, help not applicable. |
| **3** | Misconfiguration — config, repo layout, prerequisites, paths. |
| **4** | OpenCode (agent runner) failed. |
| **6** | Auth — session / token / login. |
| **7** | Upload / cloud sync failed. |
| **8** | Cancelled. |
| **99** | Internal unexpected error. |
| **49** | Factory unknown / unclassified failure. |
| **50–58** | Generate Context — one code per pipeline phase (after readiness; worktree → cloud sync). |
| **59** | Multiple failed generate_context phases with **distinct** phase codes in one run (rollup). |
| **60–64** | Context drift — validation-class drift outcomes (see §3.2). |
| **70–79** | `diagnose` / `context link-graph` / `run synthesis resume-*` index failures (see **PLAN-SRS-70 §2.4**). |
| **80** | `run synthesis` (standalone pipeline) failed. |
| **81–82** | `ace learn` / `ace auto-learn` failures. |
| **83** | `update context` factory failure (non-readiness). |
| **84** | **SRS-72:** OpenCode CLI not installed / not callable (`analysis`, `update context`, `context drift` readiness). |
| **85** | **SRS-72:** OpenCode credentials not ready (readiness gate **b**). |
| **86** | **SRS-72:** *Reserved:* readiness **does not** exit with **86** for a missing default model when **(a)** and **(b)** pass; **`describeExitCode(86)`** documents legacy expectations. |
| **87** | **SRS-72:** *Reserved:* readiness **does not** exit with **87** for a missing repo-root **`opencode.json`**; **`describeExitCode(87)`** documents reserved semantics. |

**SRS-61:** HTTP **`HttpApiError`** handling unchanged — may map to **3**, **6**, **7**, or **99** per existing rules.

One-line summaries for **49–87** live in **`describeExitCode`** in **`exitCodes.ts`**.

---

## 2. Structured IDs: `failureExitId` / `validationExitId`

- **`failureExitId`:** required; **`major`** = OS exit for this invocation (after finalize all `factoryFailures[].exitCode` match **`process.exit`** per PLAN-SRS-58).
- **`validationExitId`:** legacy JSON alias; **mirrors `failureExitId`** when present (SRS-70).

**JSON `factoryFailures[]` row:** `factory`, `phase`, `exitCode`, `failureExitId`, `title`, optional `detail`, `validationSubcode`, optional `validationExitId` (duplicate).

---

## 3. Tables by scope

### 3.1 Generate Context (`analysis`)

| Phase (`factoryFailures[].phase`) | OS exit | `failureExitId` (single-phase) |
|-----------------------------------|--------:|-------------------------------|
| `unknown_factory_phase` | **49** | `49.0` |
| `create_analysis_worktree` | **50** | `50.0` |
| `materialize_opencode_agents` | **51** | `51.0` |
| `synthesis_convergence` | **52** | `52.0` |
| `reference_coverage` | **53** | `53.0` |
| `zero_reference_remediation_convergence` | **54** | `54.0` |
| `reference_coverage_execution_report` | **55** | `55.0` |
| `link_mapping_pipeline` | **56** | `56.0` |
| `assemble_application_context_index` | **57** | `57.0` |
| `backend_context_sync` | **58** | `58.0` |

Multiple distinct failures → **`process.exit(59)`**, **`failureExitId`** `59.0`, `59.1`, …

### 3.2 Context drift (`context drift`)

[`failureExitRegistry.ts`](../../src/cli/failureExitRegistry.ts). **`INVALID_REFERENCE_PATH`** resolves to **3.1** / **3.2** via error text.

| Drift `code` | OS exit | `failureExitId` |
|--------------|--------:|-----------------|
| `INVALID_REFERENCE_PATH` (bundle) | 3 | **3.1** |
| `INVALID_REFERENCE_PATH` (`--index`) | 3 | **3.2** |
| `WORKTREE_PREP_FAILED` | 3 | **3.3** |
| `AGENT_FAILED` | 4 | **4.1** |
| `INVALID_AGENT_PAYLOAD` | 4 | **4.2** |
| `EMPTY_BUNDLE` | **60** | **60.0** |
| `UNRESOLVED_REFERENCE_ROOT` | **61** | **61.0** |
| `MANIFEST_FAILED` | **62** | **62.0** |
| `REPORT_WRITE_FAILED` | **63** | **63.0** |
| `INDEX_PATCH_FAILED` | **64** | **64.0** |
| `PROMOTE_FAILED` | 7 | **7.1** |

### 3.3 Other commands

See **PLAN-SRS-70 §2.4–2.6** for **`diagnose`**, **`run synthesis`**, **`ace`**, **`update context`** integers **70–83**.

---

## 4. Related files

| File | Role |
|------|------|
| [`src/cli/exitCodes.ts`](../../src/cli/exitCodes.ts) | `ExitCode`, `OsExit`, `describeExitCode`, `failureExitIdFromParts`, `isSrs70FactoryOrDiagnoseExit` |
| [`src/factory/factoryValidationFailures.ts`](../../src/factory/factoryValidationFailures.ts) | Generate Context **`factoryFailures`**, rollup **59** |
| [`src/cli/failureExitRegistry.ts`](../../src/cli/failureExitRegistry.ts) | Context drift registry |
| [`src/cli/jsonReporter.ts`](../../src/cli/jsonReporter.ts) | JSON envelope typing |
| [commands.md](./commands.md) | Per-command behaviour |

---

## 5. Revision history

| Date | Notes |
|------|--------|
| 2026-05-06 | Initial **`error-code.md`**. |
| 2026-05-13 | **SRS-70:** retire OS **5**; document **49–83**; drift **60–64**; rollup **59**. |
