spec-controller 0.1.0-alpha.1 → 0.1.0-alpha.2

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.
Files changed (65) hide show
  1. package/README.md +94 -0
  2. package/dist/cli-args.d.ts +73 -0
  3. package/dist/cli-args.d.ts.map +1 -0
  4. package/dist/cli-args.js +114 -0
  5. package/dist/cli-args.js.map +1 -0
  6. package/dist/cli-balance/cli.d.ts +2 -19
  7. package/dist/cli-balance/cli.d.ts.map +1 -1
  8. package/dist/cli-balance/cli.js +76 -78
  9. package/dist/cli-balance/cli.js.map +1 -1
  10. package/dist/cli-balance/emit/writer.d.ts +1 -1
  11. package/dist/cli-registry.d.ts +35 -12
  12. package/dist/cli-registry.d.ts.map +1 -1
  13. package/dist/cli-registry.js +93 -33
  14. package/dist/cli-registry.js.map +1 -1
  15. package/dist/cli.d.ts +5 -3
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +9 -3
  18. package/dist/cli.js.map +1 -1
  19. package/dist/corpus/cli.d.ts +34 -0
  20. package/dist/corpus/cli.d.ts.map +1 -0
  21. package/dist/corpus/cli.js +128 -0
  22. package/dist/corpus/cli.js.map +1 -0
  23. package/dist/deferralTags.d.ts +1 -1
  24. package/dist/deferralTags.js +1 -1
  25. package/dist/ingest/gherkinValidation.d.ts +23 -0
  26. package/dist/ingest/gherkinValidation.d.ts.map +1 -1
  27. package/dist/ingest/gherkinValidation.js +27 -0
  28. package/dist/ingest/gherkinValidation.js.map +1 -1
  29. package/dist/ingest/ingestQualityChecks.d.ts +17 -2
  30. package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
  31. package/dist/ingest/ingestQualityChecks.js +94 -39
  32. package/dist/ingest/ingestQualityChecks.js.map +1 -1
  33. package/dist/ingest/ingestScenarios.d.ts +2 -1
  34. package/dist/ingest/ingestScenarios.d.ts.map +1 -1
  35. package/dist/ingest/ingestScenarios.js +32 -3
  36. package/dist/ingest/ingestScenarios.js.map +1 -1
  37. package/dist/mutation-ratchet/index.d.ts +36 -38
  38. package/dist/mutation-ratchet/index.d.ts.map +1 -1
  39. package/dist/mutation-ratchet/index.js +35 -37
  40. package/dist/mutation-ratchet/index.js.map +1 -1
  41. package/dist/mutation-ratchet/record.d.ts +21 -53
  42. package/dist/mutation-ratchet/record.d.ts.map +1 -1
  43. package/dist/mutation-ratchet/record.js +28 -44
  44. package/dist/mutation-ratchet/record.js.map +1 -1
  45. package/dist/mutation-ratchet/report.d.ts +31 -5
  46. package/dist/mutation-ratchet/report.d.ts.map +1 -1
  47. package/dist/mutation-ratchet/report.js +11 -3
  48. package/dist/mutation-ratchet/report.js.map +1 -1
  49. package/package.json +7 -2
  50. package/dist/mutation-ratchet/ratchet.d.ts +0 -129
  51. package/dist/mutation-ratchet/ratchet.d.ts.map +0 -1
  52. package/dist/mutation-ratchet/ratchet.js +0 -222
  53. package/dist/mutation-ratchet/ratchet.js.map +0 -1
  54. package/dist/mutation-ratchet/ratchetCli.d.ts +0 -57
  55. package/dist/mutation-ratchet/ratchetCli.d.ts.map +0 -1
  56. package/dist/mutation-ratchet/ratchetCli.js +0 -139
  57. package/dist/mutation-ratchet/ratchetCli.js.map +0 -1
  58. package/dist/mutation-ratchet/reconcile.d.ts +0 -82
  59. package/dist/mutation-ratchet/reconcile.d.ts.map +0 -1
  60. package/dist/mutation-ratchet/reconcile.js +0 -67
  61. package/dist/mutation-ratchet/reconcile.js.map +0 -1
  62. package/dist/mutation-ratchet/verdict.d.ts +0 -177
  63. package/dist/mutation-ratchet/verdict.d.ts.map +0 -1
  64. package/dist/mutation-ratchet/verdict.js +0 -387
  65. package/dist/mutation-ratchet/verdict.js.map +0 -1
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # spec-controller
2
+
3
+ **One command, `balance`, that reconciles the behaviour your scenarios name against the evidence that actually ran.**
4
+
5
+ You hand it your Gherkin scenarios and the reports your tools already produce — a Vitest report, a Cucumber report, your CI run's own record of what its steps did — and it prints one table: which scenarios have living evidence, which do not, and which evidence ran that no scenario asked for.
6
+
7
+ It runs nothing itself. It reads what your pipeline already wrote.
8
+
9
+ Requires Node ≥ 22. ESM only.
10
+
11
+ ## Install
12
+
13
+ ```
14
+ npm install -g spec-controller
15
+ ```
16
+
17
+ Or without installing anything:
18
+
19
+ ```
20
+ npx spec-controller balance --help
21
+ ```
22
+
23
+ ## Your first run
24
+
25
+ Point it at your scenarios and give it nothing else:
26
+
27
+ ```
28
+ spec-controller balance --features ./features
29
+ ```
30
+
31
+ Every scenario comes back as a row whether or not any evidence exists for it, so on this first run the ones you have supplied no reports for read **missing** and the run comes back out-of-balance. That is the shape of the tool rather than a fault in your repository: the reconciliation starts from what you specified, not from what a tool happened to find, and there is no input for which the right answer is silence.
32
+
33
+ Now give it the evidence:
34
+
35
+ ```
36
+ spec-controller balance \
37
+ --features ./features \
38
+ --vitest ./vitest-report.json \
39
+ --cucumber ./cucumber-report.json
40
+ ```
41
+
42
+ A scenario tagged `@unit` names an obligation — a unit test must exist and pass — and the evidence posts back by citing the scenario's `@SCN` code in its test name. Where the two agree the row is **balanced**. Where they do not, the row says which way: evidence missing, evidence failing, or evidence that cites a scenario nobody wrote.
43
+
44
+ ## What the exit code tells your pipeline
45
+
46
+ | Exit | What it says |
47
+ | --- | --- |
48
+ | `0` | balanced — every obligation has evidence, and it holds |
49
+ | `1` | out-of-balance — the two records disagree, and the report says where |
50
+ | `2` | usage — the invocation was wrong |
51
+ | `3` | balanced, but carrying Pending Items, and you asked for `--strict` |
52
+ | `4` | unsound — a proving suite failed to collect, so the ledger could not be trusted to disagree |
53
+ | `5` | nothing to reconcile — no scenario was declared and no evidence was produced, so the run had no basis for a verdict |
54
+
55
+ The whole report is written before the code is set, so a failing run still tells you why.
56
+
57
+ **Node's default is never one of these.** A run that cannot reconcile ends on an enumerated code of
58
+ its own rather than falling out of the process — a crash that exits `1` would be indistinguishable,
59
+ by status, from an honest disagreement. **An input the tool cannot read is part of `2`**: a mistyped
60
+ path, an unparseable report or a corpus the Gherkin parser rejects are all the invocation being
61
+ wrong, never a verdict about your code.
62
+
63
+ **The enumeration is open at the top, and that is the one thing to design your pipeline around.** A
64
+ state that is genuinely none of the above gets a **new** code rather than being folded into the
65
+ nearest one — `5` is the most recent, added when a run over a target that had declared nothing and
66
+ produced nothing was found reporting `0`. So **treat an unrecognised non-zero code as a failure you
67
+ have not seen before**, not as a synonym for `1`. Matching `1` exactly is unaffected by a code being
68
+ added; treating *non-zero* as a red build is already correct, and only imprecise about why.
69
+
70
+ ## On CI
71
+
72
+ ```
73
+ spec-controller balance --features ./features \
74
+ --vitest ./vitest-report.json \
75
+ --format md:$GITHUB_STEP_SUMMARY \
76
+ --format json:reconciliation.json
77
+ ```
78
+
79
+ `--format` is repeatable and takes an optional `:<path>`. On GitHub Actions, writing Markdown to `$GITHUB_STEP_SUMMARY` puts the reconciliation on the run's summary page — the report is a table and that is the channel GitHub provides for one. No action, no plugin, no permission.
80
+
81
+ `spec-controller balance --help` lists every flag with a line each.
82
+
83
+ ## Where to go next
84
+
85
+ - **Full flags, worked examples and CI wiring** — [`doc/how_to_use.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/how_to_use.md)
86
+ - **Bringing a check you already have under the reconciliation** — [`doc/converting-a-fitness-check.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/converting-a-fitness-check.md)
87
+ - **Why `0.x` promises nothing, and what changes at `1.0`** — [`doc/compatibility.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/compatibility.md)
88
+ - **Building your own tooling on the engine instead of running a command** — [`@3f-consulting/spec-controller-core`](https://www.npmjs.com/package/@3f-consulting/spec-controller-core), the same reconciliation logic as a pure library with no CLI and no I/O.
89
+
90
+ Source, issues and history: [github.com/3f-consulting/spec-controller](https://github.com/3f-consulting/spec-controller).
91
+
92
+ ## Licence
93
+
94
+ MIT — see `LICENSE`, which travels in this package. © 2026 3F Consulting Ltd.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * THE ONE READING OF A COMMAND'S ARGV, and the one bounding of it against the registry.
3
+ *
4
+ * WHY IT IS ITS OWN MODULE (3F-3300). Both halves lived inside `cli-balance/cli.ts` while
5
+ * `balance` was the only command — `parseArgs` private to it, `checkUnknownFlags` exported for
6
+ * its own `@unit` arm. A second command needs both, and the two ways of giving it them were
7
+ * worse than moving them: copying `parseArgs` would put a second reading of argv in a tree whose
8
+ * whole subject is second readings, and importing them from `cli-balance/cli.ts` would have the
9
+ * corpus command pull the entire reconcile ingest chain into memory to answer a question about
10
+ * feature files.
11
+ *
12
+ * THE BOUNDING IS PER-COMMAND, which is what makes "accepted = registry = help" hold for every
13
+ * command rather than for the one this code was written beside. `checkUnknownFlags` took the
14
+ * registry and looked `balance` up inside itself; the command is a parameter now, exactly as it
15
+ * became one for `renderCommandHelp` (3F-3298). @SCN-CLI-009's scenario is unchanged and still
16
+ * asks about `balance`: what a second command gets is the same bounding BY CONSTRUCTION, and the
17
+ * residual — that an unregistered flag to `tags` is unproven by a scenario of its own — is named
18
+ * on 3F-3286 rather than left silent.
19
+ */
20
+ import type { CliRegistry } from "./cli-registry.js";
21
+ /**
22
+ * Parse `--flag value` pairs from a command's argv into a record, keys with the `--` stripped.
23
+ *
24
+ * A flag whose next token is another flag (or absent) records the string `"true"`, which is how
25
+ * the boolean flags — `--strict`, `--help` — are recognised: presence is what matters, so callers
26
+ * read them with `!== undefined`.
27
+ *
28
+ * PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given, including a
29
+ * flag no registry names; `checkUnknownFlags` below is what turns that into a usage error. The
30
+ * split is deliberate — the parse has no opinion about which command it is reading for, and the
31
+ * bounding has nothing else to do.
32
+ */
33
+ export declare function parseArgs(argv: readonly string[]): Record<string, string>;
34
+ /**
35
+ * The registry-bounded flag check at a command's CLI edge (@SCN-CLI-009). A command accepts ONLY
36
+ * the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered flag — a
37
+ * typo like `--strcit`, a stray `--bogus` — is a usage error, NOT silently swallowed the way the
38
+ * permissive parse above would leave it. This is the structural teeth behind "accepted = registry
39
+ * = help": a flag cannot affect behaviour without a registry entry, and so (by @SCN-CLI-008's
40
+ * guard) without appearing in that command's help.
41
+ *
42
+ * PURE and `@unit`-testable: the parsed args (keys already `--`-stripped) plus the registry and
43
+ * the command to bound against, returning the FIRST unregistered flag as a typed usage error
44
+ * naming it WITH its dashes — routed to stderr and the enumerated usage status 2 by the caller,
45
+ * never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers never reach
46
+ * here: the top-level dispatcher consumes them BEFORE any command is dispatched, so a bounded
47
+ * parse sees only the command's own args.
48
+ *
49
+ * A COMMAND THE REGISTRY DOES NOT NAME ACCEPTS NOTHING, which is the honest reading rather than a
50
+ * degenerate one: an unregistered command has no scope, so every flag given to it is outside it.
51
+ * The dispatcher refuses such a command before this is ever reached, so the case is unreachable
52
+ * today and stated here so it cannot become a silent "accept everything" later.
53
+ *
54
+ * IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-SLF-008).
55
+ * A consumer pins spec-controller and then moves their own tree; the pinned reader is handed argv
56
+ * it was published too early — or too late — to understand, and an unadorned "unknown flag" is
57
+ * indistinguishable from a typo. Naming the running version makes version skew legible from the CI
58
+ * log alone, and naming the bump says what to do about it. `toolVersion` is a PARAMETER rather than
59
+ * a read performed here so this stays pure and `@unit`-testable; the callers pass
60
+ * `resolveToolIdentity().toolVersion`, the same value the report provenance carries.
61
+ *
62
+ * WHY THE PRODUCT SAYS THIS AND NOT THE CONSUMER. spec-controller's own repository is a consumer of
63
+ * its published self, and the ruling there is that it does NOT wrap itself — a dependency, a `run:`
64
+ * step, and the verdict its exit code gives. A consumer-side translator turning exit 2 into a skew
65
+ * refusal is exactly that forbidden wrapper, and no other adopter could write one either. So the
66
+ * refusal is the tool's own, which makes it universal rather than local.
67
+ *
68
+ * THE STATUS DOES NOT MOVE. The caller still routes this to stderr and exit 2. A mistyped `--strcit`
69
+ * is still a usage fault, and giving skew its own status would cost every adopter the ordinary
70
+ * reading to serve the rarer one.
71
+ */
72
+ export declare function checkUnknownFlags(args: Record<string, string>, registry: CliRegistry, command: string, toolVersion: string): string | null;
73
+ //# sourceMappingURL=cli-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CA0Bf"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * THE ONE READING OF A COMMAND'S ARGV, and the one bounding of it against the registry.
3
+ *
4
+ * WHY IT IS ITS OWN MODULE (3F-3300). Both halves lived inside `cli-balance/cli.ts` while
5
+ * `balance` was the only command — `parseArgs` private to it, `checkUnknownFlags` exported for
6
+ * its own `@unit` arm. A second command needs both, and the two ways of giving it them were
7
+ * worse than moving them: copying `parseArgs` would put a second reading of argv in a tree whose
8
+ * whole subject is second readings, and importing them from `cli-balance/cli.ts` would have the
9
+ * corpus command pull the entire reconcile ingest chain into memory to answer a question about
10
+ * feature files.
11
+ *
12
+ * THE BOUNDING IS PER-COMMAND, which is what makes "accepted = registry = help" hold for every
13
+ * command rather than for the one this code was written beside. `checkUnknownFlags` took the
14
+ * registry and looked `balance` up inside itself; the command is a parameter now, exactly as it
15
+ * became one for `renderCommandHelp` (3F-3298). @SCN-CLI-009's scenario is unchanged and still
16
+ * asks about `balance`: what a second command gets is the same bounding BY CONSTRUCTION, and the
17
+ * residual — that an unregistered flag to `tags` is unproven by a scenario of its own — is named
18
+ * on 3F-3286 rather than left silent.
19
+ */
20
+ /**
21
+ * Parse `--flag value` pairs from a command's argv into a record, keys with the `--` stripped.
22
+ *
23
+ * A flag whose next token is another flag (or absent) records the string `"true"`, which is how
24
+ * the boolean flags — `--strict`, `--help` — are recognised: presence is what matters, so callers
25
+ * read them with `!== undefined`.
26
+ *
27
+ * PERMISSIVE BY ITSELF, AND BOUNDED BY THE CALLER. It records whatever it is given, including a
28
+ * flag no registry names; `checkUnknownFlags` below is what turns that into a usage error. The
29
+ * split is deliberate — the parse has no opinion about which command it is reading for, and the
30
+ * bounding has nothing else to do.
31
+ */
32
+ export function parseArgs(argv) {
33
+ const args = {};
34
+ for (let i = 0; i < argv.length; i++) {
35
+ const a = argv[i];
36
+ if (a !== undefined && a.startsWith("--")) {
37
+ const key = a.slice(2);
38
+ const value = argv[i + 1];
39
+ if (value !== undefined && !value.startsWith("--")) {
40
+ args[key] = value;
41
+ i++;
42
+ }
43
+ else {
44
+ args[key] = "true";
45
+ }
46
+ }
47
+ }
48
+ return args;
49
+ }
50
+ /**
51
+ * The registry-bounded flag check at a command's CLI edge (@SCN-CLI-009). A command accepts ONLY
52
+ * the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered flag — a
53
+ * typo like `--strcit`, a stray `--bogus` — is a usage error, NOT silently swallowed the way the
54
+ * permissive parse above would leave it. This is the structural teeth behind "accepted = registry
55
+ * = help": a flag cannot affect behaviour without a registry entry, and so (by @SCN-CLI-008's
56
+ * guard) without appearing in that command's help.
57
+ *
58
+ * PURE and `@unit`-testable: the parsed args (keys already `--`-stripped) plus the registry and
59
+ * the command to bound against, returning the FIRST unregistered flag as a typed usage error
60
+ * naming it WITH its dashes — routed to stderr and the enumerated usage status 2 by the caller,
61
+ * never 1, never a silent run — else null. The global `--store`/`--run-id` modifiers never reach
62
+ * here: the top-level dispatcher consumes them BEFORE any command is dispatched, so a bounded
63
+ * parse sees only the command's own args.
64
+ *
65
+ * A COMMAND THE REGISTRY DOES NOT NAME ACCEPTS NOTHING, which is the honest reading rather than a
66
+ * degenerate one: an unregistered command has no scope, so every flag given to it is outside it.
67
+ * The dispatcher refuses such a command before this is ever reached, so the case is unreachable
68
+ * today and stated here so it cannot become a silent "accept everything" later.
69
+ *
70
+ * IT NAMES THE VERSION THAT REFUSED, AND THAT IS FOR THE PINNED READER (3F-3105, @SCN-SLF-008).
71
+ * A consumer pins spec-controller and then moves their own tree; the pinned reader is handed argv
72
+ * it was published too early — or too late — to understand, and an unadorned "unknown flag" is
73
+ * indistinguishable from a typo. Naming the running version makes version skew legible from the CI
74
+ * log alone, and naming the bump says what to do about it. `toolVersion` is a PARAMETER rather than
75
+ * a read performed here so this stays pure and `@unit`-testable; the callers pass
76
+ * `resolveToolIdentity().toolVersion`, the same value the report provenance carries.
77
+ *
78
+ * WHY THE PRODUCT SAYS THIS AND NOT THE CONSUMER. spec-controller's own repository is a consumer of
79
+ * its published self, and the ruling there is that it does NOT wrap itself — a dependency, a `run:`
80
+ * step, and the verdict its exit code gives. A consumer-side translator turning exit 2 into a skew
81
+ * refusal is exactly that forbidden wrapper, and no other adopter could write one either. So the
82
+ * refusal is the tool's own, which makes it universal rather than local.
83
+ *
84
+ * THE STATUS DOES NOT MOVE. The caller still routes this to stderr and exit 2. A mistyped `--strcit`
85
+ * is still a usage fault, and giving skew its own status would cost every adopter the ordinary
86
+ * reading to serve the rarer one.
87
+ */
88
+ export function checkUnknownFlags(args, registry, command, toolVersion) {
89
+ // The accepted set: every flag name AND alias in THIS command's scope, with the leading dashes
90
+ // stripped so it compares against the parse's `--`-stripped keys (e.g. "--features" and "-h"
91
+ // become "features" and "h"). Built from the registry alone — the single source — so
92
+ // "accepted = registry" holds by construction.
93
+ const entry = registry.commands.find((c) => c.name === command);
94
+ const accepted = new Set();
95
+ for (const flag of entry?.flags ?? []) {
96
+ accepted.add(flag.name.replace(/^-+/, ""));
97
+ for (const alias of flag.aliases ?? [])
98
+ accepted.add(alias.replace(/^-+/, ""));
99
+ }
100
+ // The FIRST parsed flag not in the accepted set is the reported error (Object.keys is argv
101
+ // order, so this is deterministic). The message names the flag WITH its dashes, and the command
102
+ // whose scope refused it — a consumer running two commands needs to know which help to open.
103
+ for (const key of Object.keys(args)) {
104
+ if (!accepted.has(key)) {
105
+ return (`Unknown flag --${key} for 'spec-controller ${command}' — this is spec-controller ` +
106
+ `${toolVersion}, and that flag is not in its ${command} scope.\n` +
107
+ `If this version is pinned, the pin and the tree it is reading have drifted apart: ` +
108
+ `bump the pin to a version whose '${command}' accepts --${key}.\n` +
109
+ `Otherwise run 'spec-controller ${command} --help' to see the flags this version accepts.`);
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ //# sourceMappingURL=cli-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-args.js","sourceRoot":"","sources":["../src/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAuB;IAC/C,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBAClB,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAA4B,EAC5B,QAAqB,EACrB,OAAe,EACf,WAAmB;IAEnB,+FAA+F;IAC/F,6FAA6F;IAC7F,qFAAqF;IACrF,+CAA+C;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAChE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;QACtC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE;YAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,2FAA2F;IAC3F,gGAAgG;IAChG,6FAA6F;IAC7F,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CACL,kBAAkB,GAAG,yBAAyB,OAAO,8BAA8B;gBACnF,GAAG,WAAW,iCAAiC,OAAO,WAAW;gBACjE,oFAAoF;gBACpF,oCAAoC,OAAO,eAAe,GAAG,KAAK;gBAClE,kCAAkC,OAAO,iDAAiD,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -7,10 +7,10 @@
7
7
  *
8
8
  * Usage:
9
9
  * pnpm reconcile [--features <dir>] [--vitest <report.json>]
10
- * [--cucumber <report.json>] [--ci <ci.yml>]
10
+ * [--cucumber <report.json>] [--ci-steps <record.json>]
11
+ * [--ci <ci.yml>]
11
12
  * [--format <fmt>[:<path>]]
12
13
  */
13
- import type { CliRegistry } from "../cli-registry.js";
14
14
  /**
15
15
  * The legacy-`--json` guard at the CLI edge (@SCN-FMT-006). The earlier
16
16
  * `--json <path>` flag is removed; supplying it must fail fast with a migration hint to
@@ -66,22 +66,5 @@ export declare function checkInputsParse(args: Record<string, string>, read: (pa
66
66
  * not an error (the ordinary reconcile path).
67
67
  */
68
68
  export declare function checkRenderFromJson(args: Record<string, string>, read: (path: string) => string): string | null;
69
- /**
70
- * The registry-bounded flag check at the CLI edge (@SCN-CLI-009). `balance` accepts ONLY
71
- * the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered
72
- * flag — a typo like `--strcit`, a stray `--bogus` — is a usage error, NOT silently
73
- * swallowed the way the old permissive `parseArgs` did. This is the structural teeth behind
74
- * "accepted = registry = help": a flag can't affect behaviour without a registry entry (and
75
- * so, by CLI-008's guard, without appearing in help).
76
- *
77
- * PURE and `@unit`-testable like `checkLegacyJson` / `checkInputsExist`: reads the parsed
78
- * args (keys are the `--`-stripped flag names) + the registry, returns the FIRST unregistered
79
- * flag as a typed usage error naming it WITH its dashes — routed to stderr + exit 2 by
80
- * `runBalance` (per 3F-1414's `0` balanced / `1` out-of-balance / `2` usage taxonomy),
81
- * never exit 1, never a silent reconcile — else null. The global `--store`/`--run-id`
82
- * modifiers never reach here: the top-level dispatcher (`parseHostInvocation`) consumes them
83
- * BEFORE `balance` is dispatched, so the bounded parser sees only the command's own args.
84
- */
85
- export declare function checkUnknownFlags(args: Record<string, string>, registry: CliRegistry): string | null;
86
69
  export declare function runBalance(argv: string[]): void;
87
70
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAsBH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA0CtD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAEjE;AAqCD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,GAAG,IAAI,CAYf;AAUD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAef;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAcf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAmBpG;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA8P/C"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiDH;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAEjE;AAuCD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,GAAG,IAAI,CAcf;AAYD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAef;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,GAAG,IAAI,CAcf;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsR/C"}
@@ -7,7 +7,8 @@
7
7
  *
8
8
  * Usage:
9
9
  * pnpm reconcile [--features <dir>] [--vitest <report.json>]
10
- * [--cucumber <report.json>] [--ci <ci.yml>]
10
+ * [--cucumber <report.json>] [--ci-steps <record.json>]
11
+ * [--ci <ci.yml>]
11
12
  * [--format <fmt>[:<path>]]
12
13
  */
13
14
  import { existsSync, readFileSync } from "node:fs";
@@ -15,28 +16,13 @@ import { dirname } from "node:path";
15
16
  import { runReconcile, readEvidenceObligations, readFeatureNames, featureCorpusParseErrors, featureCorpusDuplicateScnIds, } from "../ingest/ingestQualityChecks.js";
16
17
  import { planOutput } from "./emit/format.js";
17
18
  import { writeOutputs } from "./emit/writer.js";
18
- import { renderReportFromJson, isBalanced, hasPendingItems, hasBrokenEvidence, } from "@3f-consulting/spec-controller-core";
19
+ import { renderReportFromJson, isBalanced, hasPendingItems, hasBrokenEvidence, hasNothingToReconcile, } from "@3f-consulting/spec-controller-core";
19
20
  import { resolveSourceSha, resolveTargetRoot, resolveToolIdentity } from "../run-management/resolveRunInputs.js";
20
- import { cliRegistry, renderBalanceHelp } from "../cli-registry.js";
21
- /** Parse `--flag value` pairs from argv into a record. */
22
- function parseArgs(argv) {
23
- const args = {};
24
- for (let i = 0; i < argv.length; i++) {
25
- const a = argv[i];
26
- if (a !== undefined && a.startsWith("--")) {
27
- const key = a.slice(2);
28
- const value = argv[i + 1];
29
- if (value !== undefined && !value.startsWith("--")) {
30
- args[key] = value;
31
- i++;
32
- }
33
- else {
34
- args[key] = "true";
35
- }
36
- }
37
- }
38
- return args;
39
- }
21
+ import { cliRegistry, renderCommandHelp } from "../cli-registry.js";
22
+ // THE ARGV READING AND ITS REGISTRY BOUNDING, SHARED WITH EVERY OTHER COMMAND (3F-3300). Both
23
+ // lived here while `balance` was the only command; a second command needs them, and a second
24
+ // copy of "what did the operator type" is the one thing this tree least wants two of.
25
+ import { parseArgs, checkUnknownFlags } from "../cli-args.js";
40
26
  /**
41
27
  * Collect the `--format <spec>` values from argv in order (the flag is REPEATABLE, unlike
42
28
  * the single-valued flags `parseArgs` records) — the raw specs `planOutput` parses. Empty
@@ -91,8 +77,9 @@ export function sourceTarget(args) {
91
77
  * mistyped `--vitest` / `--cucumber` / `--features` / `--ci` / `--package-json`
92
78
  * pointing at a non-existent path used to reconcile silently against ZERO evidence —
93
79
  * a terrifying false all-red report meaning "you forgot the reports", not "your code
94
- * is broken" (the dogfooding fault). The five flags are Examples of ONE boundary
95
- * rule: a supplied-but-absent input path is a hard error. Scope is existence only
80
+ * is broken" (the dogfooding fault). These flags are Examples of ONE boundary
81
+ * rule: a supplied-but-absent input path is a hard error, and a flag added to the set
82
+ * inherits it rather than restating it. Scope is existence only
96
83
  * (readability / file-vs-dir type-correctness out of scope; `exists` covers the dir
97
84
  * flag and the file flags alike).
98
85
  *
@@ -118,13 +105,16 @@ function reconcileInputsOf(args) {
118
105
  ci: args["ci"],
119
106
  packageJson: args["package-json"],
120
107
  measurements: args["measurements"],
108
+ ciSteps: args["ci-steps"],
121
109
  };
122
110
  }
123
111
  export function checkInputsExist(args, exists) {
124
- // The five input flags in a fixed order — the FIRST supplied-but-absent one is the
112
+ // The input flags in a fixed order — the FIRST supplied-but-absent one is the
125
113
  // reported error (deterministic; the operator fixes and re-runs). Keys are the
126
114
  // parseArgs form (the `--` stripped); the message names the flag WITH its dashes.
127
- const flags = ["vitest", "cucumber", "features", "ci", "package-json", "measurements"];
115
+ const flags = [
116
+ "vitest", "cucumber", "features", "ci", "package-json", "measurements", "ci-steps",
117
+ ];
128
118
  for (const flag of flags) {
129
119
  const path = args[flag];
130
120
  if (path !== undefined && !exists(path)) {
@@ -139,7 +129,9 @@ export function checkInputsExist(args, exists) {
139
129
  * read as raw TEXT and scanned for `run:` steps — neither is JSON, neither can crash the
140
130
  * process, and on garbage both reconcile normally (verified, 3F-1742 Discovery).
141
131
  */
142
- const JSON_INPUT_FLAGS = ["vitest", "cucumber", "package-json", "measurements"];
132
+ const JSON_INPUT_FLAGS = [
133
+ "vitest", "cucumber", "package-json", "measurements", "ci-steps",
134
+ ];
143
135
  /**
144
136
  * Guard the READABILITY of the supplied JSON inputs at the CLI edge (@SCN-CLI-014).
145
137
  * `checkInputsExist` already guards their PRESENCE — but a path that is present yet
@@ -204,43 +196,6 @@ export function checkRenderFromJson(args, read) {
204
196
  }
205
197
  return null;
206
198
  }
207
- /**
208
- * The registry-bounded flag check at the CLI edge (@SCN-CLI-009). `balance` accepts ONLY
209
- * the flags its per-command registry scope LISTS (by `name` or `alias`); an unregistered
210
- * flag — a typo like `--strcit`, a stray `--bogus` — is a usage error, NOT silently
211
- * swallowed the way the old permissive `parseArgs` did. This is the structural teeth behind
212
- * "accepted = registry = help": a flag can't affect behaviour without a registry entry (and
213
- * so, by CLI-008's guard, without appearing in help).
214
- *
215
- * PURE and `@unit`-testable like `checkLegacyJson` / `checkInputsExist`: reads the parsed
216
- * args (keys are the `--`-stripped flag names) + the registry, returns the FIRST unregistered
217
- * flag as a typed usage error naming it WITH its dashes — routed to stderr + exit 2 by
218
- * `runBalance` (per 3F-1414's `0` balanced / `1` out-of-balance / `2` usage taxonomy),
219
- * never exit 1, never a silent reconcile — else null. The global `--store`/`--run-id`
220
- * modifiers never reach here: the top-level dispatcher (`parseHostInvocation`) consumes them
221
- * BEFORE `balance` is dispatched, so the bounded parser sees only the command's own args.
222
- */
223
- export function checkUnknownFlags(args, registry) {
224
- // The accepted set: every balance-scope flag name AND alias, with the leading dashes
225
- // stripped so it compares against parseArgs's `--`-stripped keys (e.g. "--features" and
226
- // "-h" become "features" and "h"). Built from the registry alone — the single source — so
227
- // "accepted = registry" holds by construction.
228
- const balance = registry.commands.find((command) => command.name === "balance");
229
- const accepted = new Set();
230
- for (const flag of balance?.flags ?? []) {
231
- accepted.add(flag.name.replace(/^-+/, ""));
232
- for (const alias of flag.aliases ?? [])
233
- accepted.add(alias.replace(/^-+/, ""));
234
- }
235
- // The FIRST parsed flag not in the accepted set is the reported error (Object.keys is
236
- // argv order, so this is deterministic). The message names the flag WITH its dashes.
237
- for (const key of Object.keys(args)) {
238
- if (!accepted.has(key)) {
239
- return `Unknown flag --${key} for 'spec-controller balance'. Run 'spec-controller balance --help' to see the accepted flags.`;
240
- }
241
- }
242
- return null;
243
- }
244
199
  export function runBalance(argv) {
245
200
  // Answer `--help`/`-h` from the command/flag registry (@SCN-CLI-006) BEFORE any
246
201
  // parse or reconcile: render the balance command's per-command scope (a line per
@@ -249,7 +204,7 @@ export function runBalance(argv) {
249
204
  // while balance runs anyway. The registry is the single source, so a flag that exists is
250
205
  // a flag that appears in help — no hand-kept list to drift.
251
206
  if (argv.includes("--help") || argv.includes("-h")) {
252
- process.stdout.write(renderBalanceHelp(cliRegistry) + "\n");
207
+ process.stdout.write(renderCommandHelp(cliRegistry, "balance") + "\n");
253
208
  return;
254
209
  }
255
210
  // Capture the run-start instant up front — the run provenance's UTC timestamp,
@@ -277,7 +232,7 @@ export function runBalance(argv) {
277
232
  // hint; the global `--store`/`--run-id` modifiers were consumed by the dispatcher before
278
233
  // balance, so they never reach here. This is the structural teeth behind "accepted =
279
234
  // registry = help" — a flag can't affect behaviour without a registry entry.
280
- const unknownFlagError = checkUnknownFlags(args, cliRegistry);
235
+ const unknownFlagError = checkUnknownFlags(args, cliRegistry, "balance", resolveToolIdentity().toolVersion);
281
236
  if (unknownFlagError) {
282
237
  process.stderr.write(unknownFlagError + "\n");
283
238
  process.exitCode = 2;
@@ -444,7 +399,8 @@ export function runBalance(argv) {
444
399
  // The --strict escalation (@SCN-CLI-011): Pending Items are run-neutral by DEFAULT
445
400
  // (@SCN-PND-008 — they never red a build), but `--strict` is the OPT-IN that fails an
446
401
  // OTHERWISE-BALANCED run carrying them, exiting the DISTINCT code 3 (taxonomy 0 balanced /
447
- // 1 out-of-balance / 2 usage / 3 pending-under-strict — a Pending Item is not out-of-balance,
402
+ // 1 out-of-balance / 2 usage / 3 pending-under-strict / 4 unsound / 5 nothing to reconcile —
403
+ // a Pending Item is not out-of-balance,
448
404
  // so it must NEVER share code 1). Out-of-balance DOMINATES: the escalation is checked ONLY in
449
405
  // the `isBalanced` branch, so an out-of-balance run exits 1 regardless of --strict. Like the
450
406
  // CLI-004 gate this SETS process.exitCode (never process.exit) AFTER writeOutputs, so the
@@ -453,7 +409,8 @@ export function runBalance(argv) {
453
409
  //
454
410
  // The UNSOUND pre-emption (@SCN-CLI-012): a run carrying BROKEN evidence — a proving suite
455
411
  // that failed to COLLECT, so the behaviour was never exercised — exits the DISTINCT code 4
456
- // (taxonomy 0 balanced / 1 out-of-balance / 2 usage / 3 pending-under-strict / 4 unsound).
412
+ // (taxonomy 0 balanced / 1 out-of-balance / 2 usage / 3 pending-under-strict / 4 unsound /
413
+ // 5 nothing to reconcile).
457
414
  // Exit 1 says "the ledger disagrees"; exit 4 says "the ledger could not be TRUSTED to
458
415
  // disagree" — you cannot trust a reconciliation whose evidence never materialised, so
459
416
  // unsound DOMINATES.
@@ -466,16 +423,57 @@ export function runBalance(argv) {
466
423
  // would otherwise be swallowed by. @SCN-CLI-004 is a BYSTANDER, not an Update: its fixture
467
424
  // is a SOUND out-of-balance run (no broken item), so it falls through this branch and still
468
425
  // exits exactly 1 — the pre-emption fires only when evidence genuinely failed to collect.
469
- const strict = args["strict"] !== undefined;
470
- if (hasBrokenEvidence(balance.ledger)) {
471
- process.exitCode = 4;
472
- }
473
- else if (!isBalanced(balance.ledger)) {
474
- process.exitCode = 1;
475
- }
476
- else if (strict && hasPendingItems(balance.ledger)) {
477
- process.exitCode = 3;
478
- }
426
+ //
427
+ // THE NOTHING-TO-RECONCILE PRE-EMPTION (@SCN-CLI-019): a run whose ledger carries ZERO Scenario
428
+ // Reconciliation rows — a target that declared nothing AND produced nothing — exits the DISTINCT
429
+ // code 5. It is its own state: not balanced (no accounts to agree), not out-of-balance (nothing
430
+ // disagrees), not a usage fault (the invocation was valid and `new-client` is a supported
431
+ // adoption state), not unsound (no proof failed; none was owed).
432
+ //
433
+ // IT IS NOT THE UNSOUND PRE-EMPTION ONE CODE FURTHER ON, THOUGH IT LOOKS LIKE IT — measured,
434
+ // because the ticket predicted it was. An empty ledger is MUTUALLY EXCLUSIVE with all three
435
+ // predicates above: with no rows there is no row to carry a broken item, a reconciling item or a
436
+ // Pending Item, so it fires none of them. Moved below `!isBalanced`, this branch STILL returns 5
437
+ // (the prescribed plant stayed green). Its position among the predicates is free, and it is
438
+ // first only so this ladder and `runVerdictSection` read in the SAME order — the shape
439
+ // @SCN-CLI-013's invariant leans on.
440
+ //
441
+ // WHAT IS LOAD-BEARING is its position against the DEFAULT below. "Balanced" is not a branch
442
+ // here, it is the `return 0` a run reaches by failing every test — so there is no "after the
443
+ // balanced case" to append a fifth code to. Appended after that return the branch is dead code
444
+ // and an empty run exits 0 (measured: the plant that DID red). That is why the fault survived a
445
+ // taxonomy that had already grown twice: a fifth code cannot be ADDED to this chain, it has to
446
+ // DISPLACE the default, and nothing about the other three says so.
447
+ //
448
+ // Keyed on the EMPTY LEDGER, never on the empty corpus: a corpus-less run carrying uncited
449
+ // credits HAS a row — its suspense row — and is an ordinary out-of-balance report at exit 1
450
+ // (@SCN-CLI-020). @SCN-CLI-004/005/010/012 are BYSTANDERS: every one of their fixtures carries
451
+ // rows, so none reaches this branch.
452
+ const code = verdictExitCode(balance.ledger, args["strict"] !== undefined);
453
+ // Assigned only when NON-ZERO, so a balanced run still LEAVES process.exitCode at its default
454
+ // rather than writing a 0 over it — the distinction @SCN-CLI-005 and @SCN-CLI-010 both rest on.
455
+ if (code !== 0)
456
+ process.exitCode = code;
457
+ }
458
+ /**
459
+ * THE DOMINANCE LADDER — the whole-run verdict as the enumerated status a consumer's CI branches
460
+ * on, and the ONE place the order argued for above is written down. Extracted from `runBalance`
461
+ * (3F-3344) so the ladder is a named thing with its own reading rather than a tail the reader
462
+ * arrives at, and so the pre-emption argument sits ON it.
463
+ *
464
+ * ENUMERATED, NEVER A COUNT — a count would 8-bit `& 0xFF` wrap into a false pass. Returns 0 for a
465
+ * balanced run; the caller leaves the process's default alone rather than writing that 0 back.
466
+ */
467
+ function verdictExitCode(ledger, strict) {
468
+ if (hasNothingToReconcile(ledger))
469
+ return 5;
470
+ if (hasBrokenEvidence(ledger))
471
+ return 4;
472
+ if (!isBalanced(ledger))
473
+ return 1;
474
+ if (strict && hasPendingItems(ledger))
475
+ return 3;
476
+ return 0;
479
477
  }
480
478
  // Only run the balance command when this module is executed directly
481
479
  // (`tsx cli-balance/cli.ts`), NOT when imported by the top-level `spec-controller`
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli-balance/cli.ts"],"names":[],"mappings":"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"}
@@ -22,7 +22,7 @@ import type { EvidenceObligations } from "@3f-consulting/spec-controller-core";
22
22
  import type { EvidenceReconciliation } from "@3f-consulting/spec-controller-core";
23
23
  /**
24
24
  * The reconciliation payloads the writer renders — the balance plus its sibling reads
25
- * (ctx / corpus / guards / featureNames), exactly the arguments the pure renderers take. Threaded
25
+ * (ctx / evidenceObligations / featureNames), exactly the arguments the pure renderers take. Threaded
26
26
  * from `cli.ts` (built once, rendered per planned output). `withRuntimeObservations` and
27
27
  * `withStaticChecks` are the GATES for the two observation axes (Test volume + the evidence grid;
28
28
  * the Static checks cut): the renderers fold BOTH off the Ledger themselves (3F-2103 / 3F-2118 —