scrumrun 2.1.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,15 +4,44 @@ All notable changes follow Semantic Versioning.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 2.3.0 - 2026-07-23
8
+
9
+ ### Added
10
+
11
+ - Stable error catalog in [`lib/errors.js`](lib/errors.js) exposing a `ScrumRunError` class plus `describe`/`codes` accessors, and a human view in [`docs/ERROR-CODES.md`](docs/ERROR-CODES.md). Codes follow `SR-E-NNN` with reserved ranges per subsystem and are guaranteed stable once assigned.
12
+ - `sc config doctor --recover --dry-run` previews every pending kernel transaction, describes each planned rollback or commit-verification, warns about unsafe paths, journal integrity failures, or owner-touched files, and exits non-zero when at least one transaction cannot be recovered safely — never writes.
13
+ - Invariant `I-22`: the semantic index's declared search backend must match the runtime's actual capabilities. Conformance now emits a `high` `SEARCH_BACKEND_MISMATCH` finding when a cache advertises `fts5` on a runtime that cannot execute it, replacing the previous lazy-rebuild-only behaviour that hid the drift.
14
+ - `previewPendingRecovery` exported from `lib/v2/transaction` for library consumers.
15
+ - Property-based intake tests: 200 adversarial inputs per run (NUL bytes, ANSI escapes, homoglyphs, injection shapes, oversize strings) proving `planRequest` is total, never throws unclassified errors, and does not mutate `.scrumrun/`.
16
+
17
+ ### Changed
18
+
19
+ - `sc plan run --render RUN-NNN` prints the ledger as a chronological, human-readable timeline with actors, transitions, reasons, evidence, and total span. Complements the existing `--show` (raw Markdown) so auditing no longer requires reading JSON blocks by hand.
20
+ - `sc plan run --stats [--task TASK-NNN] [--feature FEAT-NNN] [--sprint SPRINT-NNN] [--json]` aggregates every Run in the project into status mix, p50/p95/max time in `VALIDATING` and `EXECUTING`, retry counts per Task, completions after prior failure, and guardrail/mutation event totals — computed straight over the canonical ledger, no separate index.
21
+ - New modules `lib/commands/run-render` and `lib/commands/run-stats` expose `renderRun`, `renderRunFromDisk`, `computeStats`, and `renderStats` for library consumers.
22
+
23
+ ### Documentation
24
+
25
+ - Added [`docs/QUICKSTART.md`](docs/QUICKSTART.md): first Run in under 10 minutes, no `SPEC.md` reading required. Now includes the new `sc plan run --render` and `sc plan run --stats` commands.
26
+ - Added [`docs/DEMO.md`](docs/DEMO.md) with the exact asciinema script for a 40-second intake → approve → render → stats demo the owner can record and embed in the README and LP.
27
+ - Added [`docs/INDEX.md`](docs/INDEX.md) with reading-order recommendations by intent (fresh install, integrating a client, upgrading from v1, browsing rationale, troubleshooting).
28
+ - Added a **Terminology quick reference** in the README that maps internal names (`Mutation Gateway`, `Policy Engine`, `Guardrail obligation`, `Canonical projection`, `Executable schema`) to friendlier user-facing forms; both are treated as synonyms.
29
+ - Bumped README package badge to `2.2.0` and linked the Quickstart from the top.
30
+ - Created `.scrumrun/features/FEAT-001.md` to record the ongoing "Method 2.x — Onboarding, Visible Auditability, and Stable Diagnostics" initiative and its four-wave scope.
31
+
32
+ ## 2.2.0 - 2026-07-23
33
+
7
34
  ### Security
8
35
 
9
36
  - Added fail-closed, 15-minute, path-scoped Mutation Gateway permits with policy/workspace binding, before/after hashes, read-only and symlink checks, new-secret detection, and append-only Run evidence.
10
37
  - Deferred Guardrails now become persisted Run obligations; unresolved obligations, policy drift, workspace bypass, and pending canonical transactions block completion.
11
38
  - Fresh and explicitly migrated projects require structured `Status`, `Enforcement`, `Scope`, and `Rule` fields and advertise Guardrail, obligation, and Mutation Gateway schemas in `method.json`.
39
+ - Added per-project `allow_secrets_in` config.md allowlist so owners can exempt non-canonical descriptive files (e.g. v1 `history.md`, `sprint.md`) from secret-like content detection without weakening canonical artifact policy. Exact paths, directory prefixes, and glob patterns are supported. Real `sk-…` / `AKIA…` / JWT / PEM shapes are never exempted because they always carry a real value.
12
40
 
13
41
  ### Changed
14
42
 
15
43
  - Project conformance now covers 21 executable invariants and detects active Run mutation bypasses.
44
+ - `lib/security/secrets` exports `loadSecretAllowlist`, `isSecretAllowed`, `containsSecretWithAllowlist`, and `parseFrontmatter` for use by intake, migration, and conformance.
16
45
 
17
46
  ## 2.1.1 - 2026-07-22
18
47
 
package/README.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  ScrumRun gives an agent a small command surface and a precise project memory: what should be done, how each attempt happened, which decisions constrain the code, and why the architecture exists in its current form.
6
6
 
7
- **Package:** `2.1.1` · **Method target:** `2.0.0` · **Runtime:** Node.js `>=22.13.0` · **License:** MIT
7
+ **Package:** `2.3.0` · **Method target:** `2.0.0` · **Runtime:** Node.js `>=22.13.0` · **License:** MIT
8
+
9
+ **New here?** Read the [Quickstart](docs/QUICKSTART.md) — first Run in under 10 minutes, no `SPEC.md` reading required. Full docs map in [`docs/INDEX.md`](docs/INDEX.md).
8
10
 
9
11
  ## The model
10
12
 
@@ -75,6 +77,20 @@ Each Run contains a machine-validated event ledger. Events have stable ids such
75
77
 
76
78
  Linked Task/Run writes use a durable ignored transaction journal. Captured failures roll back immediately; interrupted operations are recovered byte-exactly on retry or through explicit `doctor --recover`. Read-only audit reports pending recovery and never repairs state silently.
77
79
 
80
+ ## Terminology quick reference
81
+
82
+ Internal names in the code and spec are precise but occasionally heavy. When they surface in CLI output or docs, the shorter form works too.
83
+
84
+ | Internal (SPEC/CORE) | User-facing (docs, output) | What it means |
85
+ |---|---|---|
86
+ | Mutation Gateway | edit permit | The 15-minute, path-scoped permission an approved Run needs to edit source files. |
87
+ | Policy Engine | guardrail check | The executable evaluation of every active `GR-NNN` rule before planning and before execution. |
88
+ | Guardrail obligation | pending guardrail | A deferred guardrail check persisted on a Run; must resolve before completion. |
89
+ | Canonical projection | derived view | Generated navigation files such as `state.md` and `map.md` — always regenerable, never authority. |
90
+ | Executable schema | frozen contract | The single machine-checked shape for ids, transitions, and cardinalities. |
91
+
92
+ The short forms are synonyms — safe to use in issues, PRs, and everyday conversation.
93
+
78
94
  ## Semantic project memory
79
95
 
80
96
  Canonical memory is human-readable Markdown:
@@ -159,6 +175,32 @@ npx scrumrun@latest doctor codex --strict
159
175
 
160
176
  Approved Runs persist every deferred result as an append-only obligation and bind the exact policy plus workspace baseline. Material source edits use a 15-minute, path-scoped Mutation Gateway permit. Recording verifies before/after hashes, owner/read-only scope, symlinks, new secret-like content, and workspace drift. Validation and completion fail closed when edits bypass that chain or obligations remain unresolved.
161
177
 
178
+ ### Owner-controlled allowlist for descriptive files
179
+
180
+ Secret-like content detection is canonical-policy-level and applies to every file outside `vault.local.md`. Owners can exempt specific **non-canonical descriptive paths** from the keyword heuristic by adding frontmatter to `.scrumrun/config.md`:
181
+
182
+ ```yaml
183
+ ---
184
+ allow_secrets_in:
185
+ - goals/main/history.md
186
+ - goals/main/sprint.md
187
+ - docs/migration-notes/
188
+ - "*.legacy.md"
189
+ ---
190
+ ```
191
+
192
+ Supported matchers per entry:
193
+
194
+ - exact path (`goals/main/history.md`)
195
+ - directory prefix ending in `/` (`docs/legacy/`)
196
+ - glob pattern (`*.legacy.md`)
197
+
198
+ Rules:
199
+
200
+ - Canonical artifacts (Task, Sprint, Run, Feature, Review, Memory) are **never** eligible — a secret in a canonical file always fails conformance.
201
+ - High-confidence shapes (`sk-…`, `AKIA…`, JWT three-part tokens, PEM private keys, long bearer tokens) are never exempted regardless of path.
202
+ - The allowlist is recorded as evidence of an explicit owner decision and is reviewed by `doctor`.
203
+
162
204
  ## Useful commands
163
205
 
164
206
  ```bash
@@ -186,19 +228,35 @@ npx scrumrun@latest sc knowledge study calculateFinalPrice
186
228
  # rebuild or inspect the derived graph
187
229
  npx scrumrun@latest sc knowledge map --build
188
230
  npx scrumrun@latest sc knowledge map --show
231
+
232
+ # read a Run as a human timeline instead of raw ledger JSON
233
+ npx scrumrun@latest sc plan run --render RUN-001
234
+
235
+ # aggregate every Run in the project (p50/p95 durations, retries, guardrail counts)
236
+ npx scrumrun@latest sc plan run --stats
237
+ npx scrumrun@latest sc plan run --stats --task TASK-001 --json
238
+
239
+ # preview a canonical-transaction recovery before touching disk
240
+ npx scrumrun@latest sc config doctor --recover --dry-run
189
241
  ```
190
242
 
191
243
  The command manifest in `lib/commands/manifest.js` generates help and compatibility adapters, preventing client grammar drift. A recorded artifact Review cannot self-declare success: ScrumRun reruns the audit and derives the `REV-NNN` verdict from the result.
192
244
 
245
+ Every user-facing failure carries a stable [`SR-E-NNN` code](docs/ERROR-CODES.md) with a permanent meaning, a short summary, and an exact remediation.
246
+
193
247
  ## Documentation
194
248
 
195
249
  | File | Purpose |
196
250
  |---|---|
251
+ | [`docs/QUICKSTART.md`](docs/QUICKSTART.md) | First Run in under 10 minutes, no `SPEC.md` reading required. |
252
+ | [`docs/INDEX.md`](docs/INDEX.md) | Reading-order recommendations across every doc, by intent. |
197
253
  | [`CORE.md`](./CORE.md) | Operational runtime guide for agents. |
198
254
  | [`SPEC.md`](./SPEC.md) | Normative 2.0 state machines, invariants, and conformance rules. |
199
255
  | [`DECISIONS.md`](./DECISIONS.md) | Architectural decisions and trade-offs. |
256
+ | [`docs/ERROR-CODES.md`](docs/ERROR-CODES.md) | Stable `SR-E-NNN` catalog with remediation for every failure. |
200
257
  | `MIGRATION-1-to-2.md` | Upgrade, verification, rollback, and recovery guide. |
201
258
  | [`docs/RELEASE-SCORECARD.md`](docs/RELEASE-SCORECARD.md) | Evidence-backed local readiness scores and residual release risks. |
259
+ | [`docs/DEMO.md`](docs/DEMO.md) | Script for a 40-second asciinema demo of the full intake → approve → render → stats loop. |
202
260
 
203
261
  ScrumRun remains client-independent: any agent that reads Markdown can follow `CORE.md`; Codex, Claude Code, and OpenCode integrations are accelerators.
204
262
 
@@ -213,4 +271,4 @@ The release gates cover artifact/state conformance, read-only intake, migration
213
271
 
214
272
  ## License
215
273
 
216
- MIT © Leander Costa
274
+ MIT © Leander Costa · [hi@scrumrun.dev](mailto:hi@scrumrun.dev)
package/SPEC.md CHANGED
@@ -220,6 +220,8 @@ Configuration controls preferences but cannot weaken higher levels. Missing or s
220
220
 
221
221
  Every project Guardrail has a stable `GR-NNN` identity, lifecycle status, rule text, enforcement mode, and optional scope/source. Intake evaluates active Guardrails into structured `passed`, `blocked`, or `deferred` results. A block names the responsible Guardrail and machine-readable reason code; a deferred result is shown explicitly and must be enforced at the mutation, migration, review, or owner gate it names. Deferred checks do not become evidence of a pass.
222
222
 
223
+ Secret-like content detection is canonical-policy-level and applies to every artifact, evidence, intake payload, and source file outside the local vault. Owners may exempt specific **non-canonical descriptive paths** from the keyword heuristic through `config.md` frontmatter `allow_secrets_in: [paths...]` (exact paths, directory prefixes ending in `/`, or glob patterns). Canonical artifacts (Task, Sprint, Run, Feature, Review, Memory) are never eligible for the allowlist: a secret in a canonical file always fails conformance. Exemption never applies to high-confidence shapes (`sk-…`, `AKIA…`, JWT, PEM private keys, long bearer tokens) regardless of path. The allowlist is recorded as evidence of an explicit owner decision and is reviewed by `doctor`.
224
+
223
225
  The executable Policy Engine may infer enforcement for migrated prose, but fresh v2 policy declares it explicitly. Unknown enforcement, duplicate ids, inactive-only policy, configuration that disables approval, and unsafe read-only paths fail conformance. Configuration can tune presentation and workflow preferences; it cannot retire, bypass, or weaken active Guardrails.
224
226
 
225
227
  ## 7. Semantic memory and code intelligence
@@ -306,6 +308,7 @@ Legacy sprint entries become Tasks. History entries become Runs only with an evi
306
308
  - **I-19** Code intelligence is derived, adapter-based, fingerprinted, and cannot silently confirm memory.
307
309
  - **I-20** Post-validation learning proposes candidates and never blocks Task/Run completion.
308
310
  - **I-21** Material mutations are policy-bound, path-scoped, hash-verified, append-only, and fail closed on bypass; unresolved Guardrail obligations block completion.
311
+ - **I-22** The semantic index's declared search backend must match the runtime capabilities of the current Node.js SQLite build; conformance flags a mismatch instead of relying on lazy runtime fallback.
309
312
 
310
313
  ## 11. Command grammar
311
314
 
@@ -323,7 +326,7 @@ Unknown syntax fails deterministically and never guesses a mutation.
323
326
 
324
327
  An implementation may claim ScrumRun method 2.0.0 only when it:
325
328
 
326
- 1. passes positive and negative tests for I-01 through I-21;
329
+ 1. passes positive and negative tests for I-01 through I-22;
327
330
  2. enforces every exposed state machine and schema;
328
331
  3. proves read-only intake and dry-run migration through full-tree fingerprints;
329
332
  4. proves migration failure recovery, rollback safety, and vault exclusion;
package/bin/scrumrun.js CHANGED
@@ -25,7 +25,7 @@ const { recordArtifactReview } = require(path.join(root, "lib", "runtime", "revi
25
25
  const { createMemory, listMemory, showMemory, transitionMemory } = require(path.join(root, "lib", "memory", "service"));
26
26
  const { indexPath, indexStatus, mapStatus, queryIndex, rebuildIndex, writeMap } = require(path.join(root, "lib", "memory", "index"));
27
27
  const { auditProject } = require(path.join(root, "lib", "v2", "conformance"));
28
- const { recoverPendingTransactions } = require(path.join(root, "lib", "v2", "transaction"));
28
+ const { recoverPendingTransactions, previewPendingRecovery } = require(path.join(root, "lib", "v2", "transaction"));
29
29
  const { containsSecret } = require(path.join(root, "lib", "security", "secrets"));
30
30
 
31
31
  const COMMANDS = ["sc"];
@@ -1371,6 +1371,37 @@ function executeRootRoute(route) {
1371
1371
  console.log(`Created retry ${result.run.id} for ${result.task.id} (attempt ${result.run.attempt}).`);
1372
1372
  return;
1373
1373
  }
1374
+ if (noun === "plan" && subject === "run" && routeArgs[0] === "--render") {
1375
+ const { renderRunFromDisk } = require(path.join(root, "lib", "commands", "run-render"));
1376
+ const runId = routeArgs[1];
1377
+ if (!runId) {
1378
+ console.error("--render requires a RUN-NNN id.");
1379
+ process.exitCode = 1;
1380
+ return;
1381
+ }
1382
+ try {
1383
+ console.log(renderRunFromDisk(process.cwd(), runId));
1384
+ } catch (error) {
1385
+ console.error(error.message);
1386
+ process.exitCode = 1;
1387
+ }
1388
+ return;
1389
+ }
1390
+ if (noun === "plan" && subject === "run" && routeArgs[0] === "--stats") {
1391
+ const { computeStats, renderStats } = require(path.join(root, "lib", "commands", "run-stats"));
1392
+ const filters = {
1393
+ task: optionValue(routeArgs.slice(1), "--task"),
1394
+ feature: optionValue(routeArgs.slice(1), "--feature"),
1395
+ sprint: optionValue(routeArgs.slice(1), "--sprint")
1396
+ };
1397
+ const summary = computeStats(process.cwd(), filters);
1398
+ if (routeArgs.includes("--json")) {
1399
+ console.log(JSON.stringify({ filters, summary }, null, 2));
1400
+ } else {
1401
+ console.log(renderStats(summary, filters));
1402
+ }
1403
+ return;
1404
+ }
1374
1405
  if (noun === "plan" && ["task", "run"].includes(subject) && ["--list", "--show"].includes(routeArgs[0])) {
1375
1406
  const repository = new ArtifactRepository(projectFile());
1376
1407
  if (routeArgs[0] === "--list") {
@@ -1462,7 +1493,7 @@ function executeRootRoute(route) {
1462
1493
  if (noun === "config" && subject === "migrate") return runMigration(routeArgs);
1463
1494
  if (noun === "config" && subject === "doctor") {
1464
1495
  const target = ["all", "codex", "opencode", "claude"].includes(routeArgs[0]) ? routeArgs[0] : "all";
1465
- return doctor(target, { strict: routeArgs.includes("--strict"), recover: routeArgs.includes("--recover") });
1496
+ return doctor(target, { strict: routeArgs.includes("--strict"), recover: routeArgs.includes("--recover"), dryRun: routeArgs.includes("--dry-run") });
1466
1497
  }
1467
1498
  if (noun === "config" && subject === "update") {
1468
1499
  const target = ["all", "codex", "opencode", "claude"].includes(routeArgs[0]) ? routeArgs[0] : "all";
@@ -2279,7 +2310,7 @@ function runMigration(parts) {
2279
2310
  }
2280
2311
  }
2281
2312
 
2282
- function doctor(target = "all", { compatibility = false, strict = false, recover = false } = {}) {
2313
+ function doctor(target = "all", { compatibility = false, strict = false, recover = false, dryRun = false } = {}) {
2283
2314
  const home = os.homedir();
2284
2315
  const checks = [];
2285
2316
  const commands = compatibility ? [...COMMANDS, ...COMPATIBILITY_COMMANDS] : COMMANDS;
@@ -2288,6 +2319,33 @@ function doctor(target = "all", { compatibility = false, strict = false, recover
2288
2319
  if (recover) {
2289
2320
  const scrumDir = path.join(process.cwd(), ".scrumrun");
2290
2321
  if (!fs.existsSync(scrumDir)) throw new Error("Cannot recover transactions outside a ScrumRun project.");
2322
+ if (dryRun) {
2323
+ const preview = previewPendingRecovery(scrumDir);
2324
+ if (preview.errors.length) {
2325
+ for (const err of preview.errors) console.error(`dry-run: ${err}`);
2326
+ process.exitCode = 1;
2327
+ return;
2328
+ }
2329
+ if (!preview.plans.length) {
2330
+ console.log("dry-run: no pending kernel transactions to recover");
2331
+ } else {
2332
+ console.log(`dry-run: ${preview.plans.length} pending transaction(s) would be handled as follows:`);
2333
+ for (const plan of preview.plans) {
2334
+ const header = ` ${plan.id} (${plan.status}) → ${plan.action}${plan.name ? ` [${plan.name}]` : ""}`;
2335
+ console.log(header);
2336
+ for (const warning of plan.warnings) console.log(` ! ${warning}`);
2337
+ for (const file of plan.files) console.log(` · ${file.relative} (${file.from} → ${file.to})`);
2338
+ }
2339
+ const blocked = preview.plans.filter((plan) => plan.action === "blocked").length;
2340
+ if (blocked) {
2341
+ console.log(`dry-run: ${blocked} transaction(s) cannot be recovered automatically.`);
2342
+ process.exitCode = 1;
2343
+ } else {
2344
+ console.log("dry-run: safe to re-run without --dry-run to apply.");
2345
+ }
2346
+ }
2347
+ return;
2348
+ }
2291
2349
  const recovered = recoverPendingTransactions(scrumDir);
2292
2350
  console.log(recovered.length
2293
2351
  ? `recovered ${recovered.map((item) => `${item.id}:${item.action}`).join(", ")}`
@@ -2409,7 +2467,7 @@ if (!command || command === "--help" || command === "-h") {
2409
2467
  runMigration(args.slice(1));
2410
2468
  } else if (command === "doctor") {
2411
2469
  const target = ["all", "codex", "opencode", "claude"].includes(args[1]) ? args[1] : "all";
2412
- doctor(target, { compatibility: args.includes("--compat"), strict: args.includes("--strict"), recover: args.includes("--recover") });
2470
+ doctor(target, { compatibility: args.includes("--compat"), strict: args.includes("--strict"), recover: args.includes("--recover"), dryRun: args.includes("--dry-run") });
2413
2471
  } else if (command === "claude") {
2414
2472
  const sub = args[1];
2415
2473
  if (sub === "install" || sub === "update") {
package/docs/DEMO.md ADDED
@@ -0,0 +1,67 @@
1
+ # Demo recording script
2
+
3
+ 40-second asciicast that shows a real intake → approve → run → memory
4
+ loop. Aim for a public URL you can embed in the README under the pitch.
5
+
6
+ ## Setup
7
+
8
+ ```bash
9
+ brew install asciinema # or: sudo apt install asciinema
10
+ asciinema --version # confirm >= 2.4
11
+ ```
12
+
13
+ Optional but recommended: `agg` to convert the `.cast` file to an SVG or
14
+ animated GIF for wider viewer support.
15
+
16
+ ## Recording
17
+
18
+ ```bash
19
+ # 1. Start a clean throwaway project
20
+ mkdir /tmp/scrumrun-demo && cd /tmp/scrumrun-demo
21
+ git init -q
22
+
23
+ # 2. Start recording
24
+ asciinema rec -c "zsh" --idle-time-limit 2 --title "ScrumRun in 40 seconds" demo.cast
25
+ ```
26
+
27
+ Inside the recording, run these commands slowly (about 5 seconds of
28
+ reading between each), typing them yourself so viewers see the cadence:
29
+
30
+ ```bash
31
+ npx scrumrun@latest install --client claude
32
+ npx scrumrun@latest init
33
+ npx scrumrun@latest sc plan intake "Fix duplicate charges after refresh"
34
+ # copy the approval token printed above
35
+ npx scrumrun@latest sc plan intake --approve <token>
36
+ npx scrumrun@latest sc plan run --render RUN-001
37
+ npx scrumrun@latest sc plan run --stats
38
+ ```
39
+
40
+ Exit the shell (`exit`) to stop the recording.
41
+
42
+ ## Publishing
43
+
44
+ ```bash
45
+ asciinema upload demo.cast # returns a URL like https://asciinema.org/a/<id>
46
+ ```
47
+
48
+ Or, for a self-hosted, browser-friendly SVG:
49
+
50
+ ```bash
51
+ agg demo.cast demo.svg
52
+ ```
53
+
54
+ ## Where to link it
55
+
56
+ - `README.md`, immediately after the tagline and before "The model".
57
+ - LP hero on `scrumrun.dev`, as a small "Watch (40s)" link near the
58
+ `Start with ScrumRun` CTA.
59
+
60
+ ## Script notes
61
+
62
+ - Keep it under 45 seconds. Cut any dead air on export with
63
+ `asciinema play --idle-time-limit 1`.
64
+ - Use a light-on-dark terminal theme that matches the LP palette
65
+ (`#08090a` background, `#c9ff5c` cursor if possible).
66
+ - Do not record real secrets — the throwaway project keeps
67
+ `.scrumrun/vault.local.md` empty.
@@ -0,0 +1,141 @@
1
+ # Error codes
2
+
3
+ Every failure that ScrumRun surfaces to the user carries a stable
4
+ `SR-E-NNN` code. Codes never change meaning once assigned; retired
5
+ entries stay in the catalog with `retired: true` so historical logs
6
+ remain resolvable.
7
+
8
+ The canonical source is [`lib/errors.js`](../lib/errors.js). This document
9
+ is a human view of the same catalog, grouped by area.
10
+
11
+ Roll-out is incremental: high-visibility error sites (intake, approval,
12
+ run transitions, doctor, edit permits, transactions) adopt the codes
13
+ first. Uncoded errors are still valid — they simply do not carry an
14
+ `SR-E-NNN` prefix yet.
15
+
16
+ ## How to use them
17
+
18
+ When a CLI output looks like:
19
+
20
+ ```
21
+ SR-E-102 Run transition rejected: missing validation or learning evidence.
22
+ ```
23
+
24
+ - The **code** is a stable anchor for logs, dashboards, and support
25
+ conversations. Grep it. Link to it.
26
+ - The **summary** describes what went wrong.
27
+ - The **remediation** describes what to try next; the CLI copy is
28
+ identical to the entry in this document.
29
+
30
+ ## Ranges
31
+
32
+ | Range | Area |
33
+ |---|---|
34
+ | `SR-E-001..049` | Request and intake |
35
+ | `SR-E-050..099` | Approvals, tokens |
36
+ | `SR-E-100..149` | Runs and ledger |
37
+ | `SR-E-150..199` | Guardrails, policy, obligations |
38
+ | `SR-E-200..249` | Edit permits (Mutation Gateway) |
39
+ | `SR-E-250..299` | Transactions and recovery |
40
+ | `SR-E-300..349` | Memory (facts, decisions, insights, dossiers, vault) |
41
+ | `SR-E-350..399` | Semantic index and code intelligence |
42
+ | `SR-E-400..449` | Migration and update |
43
+ | `SR-E-450..499` | Conformance and doctor |
44
+ | `SR-E-500..549` | Configuration and installation |
45
+
46
+ ## Catalog
47
+
48
+ ### Request and intake
49
+
50
+ | Code | Summary | Remediation |
51
+ |---|---|---|
52
+ | `SR-E-001` | Intake request is missing. | Provide a natural-language request or use `--request "..."`. |
53
+ | `SR-E-002` | Intake payload contains secret-like content. | Remove the secret from the request or reference a vault entry by path. |
54
+ | `SR-E-003` | Intake classification could not be produced. | Rephrase the request in one sentence describing the observable problem. |
55
+
56
+ ### Approvals
57
+
58
+ | Code | Summary | Remediation |
59
+ |---|---|---|
60
+ | `SR-E-050` | Approval token is malformed. | Re-run the intake and copy the token exactly as printed after `Approval:`. |
61
+ | `SR-E-051` | Approval token signature does not match this repository. | Tokens are bound to the project fingerprint. Re-run intake from the repo the change targets. |
62
+ | `SR-E-052` | Approval token expired. | Re-run intake to obtain a fresh token before approving. |
63
+
64
+ ### Runs and ledger
65
+
66
+ | Code | Summary | Remediation |
67
+ |---|---|---|
68
+ | `SR-E-100` | Run not found. | Check the RUN-NNN id with `sc plan run --list`. |
69
+ | `SR-E-101` | Run ledger contains an invalid event. | Inspect the reported event id; use `sc plan run --render` for a human view or restore from git history. |
70
+ | `SR-E-102` | Run transition rejected: missing validation or learning evidence. | Complete `--validate` and `--learn` with typed evidence before `--complete`. |
71
+ | `SR-E-103` | Retry rejected because the previous Run is still active. | Complete, fail, or block the current Run before creating a retry. |
72
+
73
+ ### Guardrails
74
+
75
+ | Code | Summary | Remediation |
76
+ |---|---|---|
77
+ | `SR-E-150` | Guardrail check blocked the operation. | Read the reported GR-NNN, satisfy or retire it explicitly; guardrails never bypass silently. |
78
+ | `SR-E-151` | Guardrail obligation is still pending. | Resolve each pending guardrail via `sc plan run --satisfy-guardrail` before completing the Run. |
79
+ | `SR-E-152` | Guardrail declaration is malformed. | Every active guardrail requires Status, Enforcement, Scope, and Rule fields; check `.scrumrun/guardrails.md`. |
80
+
81
+ ### Edit permits (Mutation Gateway)
82
+
83
+ | Code | Summary | Remediation |
84
+ |---|---|---|
85
+ | `SR-E-200` | No edit permit for this path. | Request one with `sc plan run --authorize-mutation RUN-NNN --path <path>` before editing canonical or source files. |
86
+ | `SR-E-201` | Edit permit expired. | Permits last 15 minutes. Authorize a new one and record the change immediately. |
87
+ | `SR-E-202` | Edit permit path scope mismatch. | The permit does not cover the modified path. Request a new permit that lists it. |
88
+ | `SR-E-203` | File hash changed unexpectedly since the permit was issued. | Someone else modified the file. Re-plan the change and request a fresh permit. |
89
+
90
+ ### Transactions and recovery
91
+
92
+ | Code | Summary | Remediation |
93
+ |---|---|---|
94
+ | `SR-E-250` | Pending kernel transaction cannot be recovered automatically. | Run `sc config doctor --recover --dry-run` to preview; if it shows "would overwrite owner changes", reconcile the file manually before applying. |
95
+ | `SR-E-251` | Journal fails integrity check. | Inspect `.scrumrun/.transactions/pending`. Do not delete; contact support or restore from backup. |
96
+
97
+ ### Memory
98
+
99
+ | Code | Summary | Remediation |
100
+ |---|---|---|
101
+ | `SR-E-300` | Memory candidate rejected: missing resolvable evidence. | Attach at least one `--evidence` path or `sc knowledge <subject> --propose` before `--confirm`. |
102
+ | `SR-E-301` | Attempt to write into vault via canonical channel. | `vault.local.md` is local-only and never indexed. Edit the file directly. |
103
+
104
+ ### Semantic index and code intelligence
105
+
106
+ | Code | Summary | Remediation |
107
+ |---|---|---|
108
+ | `SR-E-350` | Semantic index is stale. | Rebuild with `sc knowledge map --build`. Cache is disposable; canonical memory is unaffected. |
109
+ | `SR-E-351` | Search backend advertised in the cache does not match this runtime. | Delete `.scrumrun/.cache/semantic-index.sqlite` and re-run any `sc knowledge` query to rebuild against the current runtime. |
110
+
111
+ ### Migration
112
+
113
+ | Code | Summary | Remediation |
114
+ |---|---|---|
115
+ | `SR-E-400` | Migration preflight failed. | Run `npx scrumrun@latest update` (dry) to see blockers, resolve them, then apply with `--migrate`. |
116
+ | `SR-E-401` | Migration rollback requested but no backup was found. | Rollback needs the ignored byte-exact backup created during `--migrate`. Restore from version control if the backup is gone. |
117
+
118
+ ### Conformance and doctor
119
+
120
+ | Code | Summary | Remediation |
121
+ |---|---|---|
122
+ | `SR-E-450` | Conformance check failed. | The reported invariant identifies the exact violation; the message includes the file and expected shape. |
123
+ | `SR-E-451` | Installed client asset is stale. | Re-run `npx scrumrun@latest update` for the specific client. `doctor --strict` shows which files diverge. |
124
+
125
+ ### Configuration and installation
126
+
127
+ | Code | Summary | Remediation |
128
+ |---|---|---|
129
+ | `SR-E-500` | ScrumRun project not initialized. | Run `npx scrumrun@latest init` in the repository root. |
130
+ | `SR-E-501` | Unsupported Node.js runtime. | ScrumRun requires Node.js >=22.13.0 for native SQLite. Upgrade Node and retry. |
131
+
132
+ ## Adding a new code
133
+
134
+ 1. Reserve the next number in the appropriate range.
135
+ 2. Add an entry to `CATALOG` in `lib/errors.js` with `summary` and
136
+ `remediation`.
137
+ 3. Throw `new ScrumRunError("SR-E-XYZ", "...")` from the site that
138
+ raises it.
139
+ 4. Add or update the row in this document.
140
+ 5. Never rename or reassign an existing code. If a code is no longer
141
+ thrown, mark it `retired: true` and keep the entry.
package/docs/INDEX.md ADDED
@@ -0,0 +1,53 @@
1
+ # Documentation index
2
+
3
+ Read in the order that matches how deep you want to go.
4
+
5
+ ## Start here
6
+
7
+ | Doc | For | Time |
8
+ |---|---|---|
9
+ | [`QUICKSTART.md`](QUICKSTART.md) | Your first Run in under 10 minutes. Zero jargon. | 5 min |
10
+ | [`../README.md`](../README.md) | Pitch, install, useful commands. | 8 min |
11
+
12
+ ## Understand the method
13
+
14
+ | Doc | For | Time |
15
+ |---|---|---|
16
+ | [`../CORE.md`](../CORE.md) | The operational guide agents follow at runtime. Portable across clients. | 15 min |
17
+ | [`SEMANTIC-MEMORY.md`](SEMANTIC-MEMORY.md) | How facts, decisions, insights, and dossiers fit together. | 10 min |
18
+ | [`SCHEMA.md`](SCHEMA.md) | The generated executable schema: ids, cardinalities, initial states, transitions. | 10 min |
19
+
20
+ ## Verify and troubleshoot
21
+
22
+ | Doc | For | Time |
23
+ |---|---|---|
24
+ | [`TROUBLESHOOTING.md`](TROUBLESHOOTING.md) | Install, migration, and daily-use issues with fixes. | as needed |
25
+ | [`ERROR-CODES.md`](ERROR-CODES.md) | Catalog of stable `SR-E-NNN` codes with summary + remediation for every user-facing failure. | as needed |
26
+ | [`RELEASE-SCORECARD.md`](RELEASE-SCORECARD.md) | Evidence-backed local readiness signals per release. | 5 min |
27
+
28
+ ## Go deep
29
+
30
+ | Doc | For | Time |
31
+ |---|---|---|
32
+ | [`../SPEC.md`](../SPEC.md) | The normative specification: state machines, invariants, composition, precedence, conformance. | 30 min |
33
+ | [`../DECISIONS.md`](../DECISIONS.md) | Architecture Decision Records: why the method is the way it is. Every ADR carries context, decision, alternatives considered, consequences. | browse |
34
+ | [`../CHANGELOG.md`](../CHANGELOG.md) | What shipped, what broke, what got safer. | as needed |
35
+ | [`../MIGRATION-1-to-2.md`](../MIGRATION-1-to-2.md) | Upgrade, verify, rollback, and recover for existing v1 projects. | as needed |
36
+
37
+ ## Reading order recommendations
38
+
39
+ **You just installed ScrumRun.**
40
+ `QUICKSTART.md` → `README.md` → `CORE.md` when you want more.
41
+
42
+ **You are integrating ScrumRun with a new AI client.**
43
+ `CORE.md` → `SCHEMA.md` → `SPEC.md`.
44
+
45
+ **You are upgrading from v1.**
46
+ `../MIGRATION-1-to-2.md` → `../CHANGELOG.md` → `TROUBLESHOOTING.md`.
47
+
48
+ **You want to know why a design choice exists.**
49
+ `../DECISIONS.md`. Search for the topic; every ADR is self-contained.
50
+
51
+ **Something broke.**
52
+ `TROUBLESHOOTING.md` first. If the code shown starts with `SR-E-`, the
53
+ message points to the exact remediation step.