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

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 (69) 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/dist/run-management/resolveRunInputs.d.ts +24 -11
  50. package/dist/run-management/resolveRunInputs.d.ts.map +1 -1
  51. package/dist/run-management/resolveRunInputs.js +49 -13
  52. package/dist/run-management/resolveRunInputs.js.map +1 -1
  53. package/package.json +7 -2
  54. package/dist/mutation-ratchet/ratchet.d.ts +0 -129
  55. package/dist/mutation-ratchet/ratchet.d.ts.map +0 -1
  56. package/dist/mutation-ratchet/ratchet.js +0 -222
  57. package/dist/mutation-ratchet/ratchet.js.map +0 -1
  58. package/dist/mutation-ratchet/ratchetCli.d.ts +0 -57
  59. package/dist/mutation-ratchet/ratchetCli.d.ts.map +0 -1
  60. package/dist/mutation-ratchet/ratchetCli.js +0 -139
  61. package/dist/mutation-ratchet/ratchetCli.js.map +0 -1
  62. package/dist/mutation-ratchet/reconcile.d.ts +0 -82
  63. package/dist/mutation-ratchet/reconcile.d.ts.map +0 -1
  64. package/dist/mutation-ratchet/reconcile.js +0 -67
  65. package/dist/mutation-ratchet/reconcile.js.map +0 -1
  66. package/dist/mutation-ratchet/verdict.d.ts +0 -177
  67. package/dist/mutation-ratchet/verdict.d.ts.map +0 -1
  68. package/dist/mutation-ratchet/verdict.js +0 -387
  69. package/dist/mutation-ratchet/verdict.js.map +0 -1
@@ -5,14 +5,22 @@
5
5
  * - `global` — the host modifiers recognised BEFORE the command (`--store`,
6
6
  * `--run-id`), consumed by the top-level dispatcher; rendered by
7
7
  * `spec-controller --help` (the sibling @SCN-CLI-007 surface).
8
- * - `commands` — the per-command scopes; `balance`'s 9 flags (+ `--help`/`-h`),
9
- * rendered by `balance --help`.
8
+ * - `commands` — the per-command scopes; each command's own flags (+ `--help`/`-h`),
9
+ * rendered by `<command> --help`. No count is written here: @SCN-CLI-008 holds
10
+ * registry and render together whatever the number is, and a figure repeated in
11
+ * prose is one nothing reads (3F-3277).
10
12
  *
11
13
  * A flag exists ⇒ a registry entry ⇒ it appears in help, by construction — the
12
14
  * single-source discipline the completeness guard (@SCN-CLI-008) will enforce and the
13
- * registry-bounded parser (@SCN-CLI-009) will reject against. Flag descriptions are
14
- * migrated from doc/how_to_use.md's flag table, which the registry now supersedes as the
15
- * source of truth. Registry + renderers live in the CLI/app layer, never the domain.
15
+ * registry-bounded parser (@SCN-CLI-009) will reject against. Registry + renderers live in the
16
+ * CLI/app layer, never the domain.
17
+ *
18
+ * THE REGISTRY IS THE SOURCE OF TRUTH FOR A FLAG'S DESCRIPTION AND NOTHING RECONCILES THE DOC
19
+ * AGAINST IT. This docblock used to say the doc was reconciled by @SCN-CLI-007/008; it is not —
20
+ * those two are about the registry and the two RENDERERS, and nothing in `tests/` or `features/`
21
+ * reads doc/how_to_use.md at all (3F-3256 deleted the checks that read documentation). So the
22
+ * flag table in that page is kept in step by hand, and it has drifted in BOTH directions before
23
+ * now: ahead of the registry on one sentence and behind it on the next (3F-3083).
16
24
  */
17
25
  /** One flag in a scope: its canonical name, optional aliases, value placeholder, help. */
18
26
  export interface FlagSpec {
@@ -27,7 +35,7 @@ export interface FlagSpec {
27
35
  /** One-line help text — the description migrated from doc/how_to_use.md. */
28
36
  description: string;
29
37
  }
30
- /** A command: its token, a one-line summary, and its per-command flag scope. */
38
+ /** A command: its token, a one-line summary, its per-command flag scope, and any config it reads. */
31
39
  export interface CommandSpec {
32
40
  /** The command token (e.g. "balance"). */
33
41
  name: string;
@@ -35,6 +43,14 @@ export interface CommandSpec {
35
43
  summary: string;
36
44
  /** The command's per-command flag scope. */
37
45
  flags: FlagSpec[];
46
+ /**
47
+ * Trailing help lines documenting `package.json` config THIS command reads, rendered
48
+ * verbatim after the flag list. It lives on the command's entry rather than in the
49
+ * renderer because a config field belongs to whichever command consumes it: appended
50
+ * unconditionally, `balance`'s `specController.deferralTags` block would document, under
51
+ * every later command, a field that command does not read (3F-3298). Omit when none.
52
+ */
53
+ configHelp?: string[];
38
54
  }
39
55
  /** The two-scope registry: the global host-modifier scope, and the per-command scopes. */
40
56
  export interface CliRegistry {
@@ -48,17 +64,24 @@ export interface CliRegistry {
48
64
  */
49
65
  export declare const cliRegistry: CliRegistry;
50
66
  /**
51
- * Render the `balance` command's per-command scope as help text: one line per registered
52
- * flag (name + arg-placeholder + description), driven BY the registry — so a flag that
53
- * exists is a flag that appears, by construction. Returns the help block WITHOUT a
54
- * trailing newline (the caller adds it, matching the writer's stdout convention).
67
+ * Render THE NAMED command's per-command scope as help text: one line per registered flag
68
+ * (name + arg-placeholder + description), then whatever config lines that command's entry
69
+ * carries — driven BY the registry, so a flag that exists is a flag that appears, by
70
+ * construction. Returns the help block WITHOUT a trailing newline (the caller adds it,
71
+ * matching the writer's stdout convention).
72
+ *
73
+ * THE COMMAND IS A PARAMETER (3F-3298). It used to be the literal `"balance"`, found by name
74
+ * inside this function, which is what the single registered command made look general. A
75
+ * second command had no help surface at all under that signature — not an empty one; there
76
+ * was no argument by which to ask. What the renderer covers is now the registry's shape
77
+ * rather than the command set's size on the day it was written.
55
78
  */
56
- export declare function renderBalanceHelp(registry: CliRegistry): string;
79
+ export declare function renderCommandHelp(registry: CliRegistry, command: string): string;
57
80
  /**
58
81
  * Render the top-level `spec-controller --help` surface (@SCN-CLI-007) FROM the registry:
59
82
  * a Commands section (each command's name + one-line summary) and a Host modifiers section
60
83
  * (each global-scope flag: name + arg-placeholder + one-line description). The global-scope
61
- * half of the two-scope registry — the counterpart to `renderBalanceHelp`'s per-command
84
+ * half of the two-scope registry — the counterpart to `renderCommandHelp`'s per-command
62
85
  * half — so the top-level usage no longer hand-keeps (and can no longer silently drift
63
86
  * from) the command set or the host modifiers; both are sourced from `cliRegistry`.
64
87
  * Summaries and descriptions render on a single line (no wrapping) so a registered string
@@ -1 +1 @@
1
- {"version":3,"file":"cli-registry.d.ts","sourceRoot":"","sources":["../src/cli-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,0FAA0F;AAC1F,MAAM,WAAW,QAAQ;IACvB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,0FAA0F;AAC1F,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,8BAA8B;IAC9B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAsFD;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,WAUzB,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CA2B/D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CA0BhE"}
1
+ {"version":3,"file":"cli-registry.d.ts","sourceRoot":"","sources":["../src/cli-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,0FAA0F;AAC1F,MAAM,WAAW,QAAQ;IACvB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qGAAqG;AACrG,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,0FAA0F;AAC1F,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,8BAA8B;IAC9B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAgJD;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,WAiBzB,CAAC;AAQF;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CA0BhE"}
@@ -5,26 +5,34 @@
5
5
  * - `global` — the host modifiers recognised BEFORE the command (`--store`,
6
6
  * `--run-id`), consumed by the top-level dispatcher; rendered by
7
7
  * `spec-controller --help` (the sibling @SCN-CLI-007 surface).
8
- * - `commands` — the per-command scopes; `balance`'s 9 flags (+ `--help`/`-h`),
9
- * rendered by `balance --help`.
8
+ * - `commands` — the per-command scopes; each command's own flags (+ `--help`/`-h`),
9
+ * rendered by `<command> --help`. No count is written here: @SCN-CLI-008 holds
10
+ * registry and render together whatever the number is, and a figure repeated in
11
+ * prose is one nothing reads (3F-3277).
10
12
  *
11
13
  * A flag exists ⇒ a registry entry ⇒ it appears in help, by construction — the
12
14
  * single-source discipline the completeness guard (@SCN-CLI-008) will enforce and the
13
- * registry-bounded parser (@SCN-CLI-009) will reject against. Flag descriptions are
14
- * migrated from doc/how_to_use.md's flag table, which the registry now supersedes as the
15
- * source of truth. Registry + renderers live in the CLI/app layer, never the domain.
15
+ * registry-bounded parser (@SCN-CLI-009) will reject against. Registry + renderers live in the
16
+ * CLI/app layer, never the domain.
17
+ *
18
+ * THE REGISTRY IS THE SOURCE OF TRUTH FOR A FLAG'S DESCRIPTION AND NOTHING RECONCILES THE DOC
19
+ * AGAINST IT. This docblock used to say the doc was reconciled by @SCN-CLI-007/008; it is not —
20
+ * those two are about the registry and the two RENDERERS, and nothing in `tests/` or `features/`
21
+ * reads doc/how_to_use.md at all (3F-3256 deleted the checks that read documentation). So the
22
+ * flag table in that page is kept in step by hand, and it has drifted in BOTH directions before
23
+ * now: ahead of the registry on one sentence and behind it on the next (3F-3083).
16
24
  */
17
25
  import { DEFAULT_DEFERRAL_TAGS } from "./deferralTags.js";
18
26
  /**
19
- * The `balance` command's per-command scope — its 9 reconciliation flags plus `--help`/
20
- * `-h`. Descriptions migrated from doc/how_to_use.md's flag table (the registry now the
21
- * source of truth; the doc is reconciled against it by @SCN-CLI-007/008).
27
+ * The `balance` command's per-command scope — its reconciliation flags plus `--help`/`-h`.
28
+ * This registry is where a flag's description LIVES; doc/how_to_use.md's flag table restates it
29
+ * by hand, reconciled by nobody (see the header).
22
30
  */
23
31
  const balanceFlags = [
24
32
  {
25
33
  name: "--features",
26
34
  arg: "<dir>",
27
- description: "Directory of Gherkin .feature files — the scenarios.",
35
+ description: "Directory of Gherkin .feature files — the scenarios, and the `@`-tags naming what each must prove (@unit, @integration, @fitness, …).",
28
36
  },
29
37
  {
30
38
  name: "--vitest",
@@ -39,18 +47,23 @@ const balanceFlags = [
39
47
  {
40
48
  name: "--ci",
41
49
  arg: "<ci.yml>",
42
- description: "Your CI workflow — used to check whether @lint guards actually run over the real source.",
50
+ description: "Your CI workflows — a file, or a directory of them (default .github/workflows). Where a static check you have not converted is found running over the real source, and where a check step's `id:` supplies the @SCN its result cites.",
43
51
  },
44
52
  {
45
53
  name: "--package-json",
46
54
  arg: "<path>",
47
- description: "package.json — used to check a named guard's script exists.",
55
+ description: "The target's package.json — its `scripts`, and its specController.fitnessChecks rows: each names a scenario's @SCN, a characteristic, and the command that is the check.",
48
56
  },
49
57
  {
50
58
  name: "--measurements",
51
59
  arg: "<report.json>",
52
60
  description: "A measurement report — the number each measured check posted, evidence for the measured fitness checks.",
53
61
  },
62
+ {
63
+ name: "--ci-steps",
64
+ arg: "<record.json>",
65
+ description: "The CI run's own record of what each of its steps did — your pipeline's `toJSON(steps)` dump, evidence for the converted fitness checks. Omit it if you have converted none.",
66
+ },
54
67
  {
55
68
  name: "--target",
56
69
  arg: "<name>",
@@ -82,6 +95,51 @@ const balanceFlags = [
82
95
  description: "Show this help and exit.",
83
96
  },
84
97
  ];
98
+ /**
99
+ * `balance`'s config block: the `specController.deferralTags` field it reads, with its
100
+ * recognised starter set SINGLE-SOURCED from DEFAULT_DEFERRAL_TAGS (@SCN-PND-021 / the
101
+ * 3F-1405 completeness discipline — the lines are built FROM the constant, never a
102
+ * hand-kept copy, so the documented set cannot drift from the recognised one). It hangs
103
+ * off balance's registry entry, not off the renderer, so it renders under `balance --help`
104
+ * and under nothing else.
105
+ */
106
+ const balanceConfigHelp = [
107
+ "Configuration (in the target repo's package.json):",
108
+ " specController.deferralTags: string[]",
109
+ " Extra recognised deferral tags. A scenario carrying one defers every obligation it",
110
+ " names to a Pending Item, extending (never replacing) the built-in set.",
111
+ ` Built-in deferral tags: ${DEFAULT_DEFERRAL_TAGS.map((tag) => `@${tag}`).join(", ")}`,
112
+ ];
113
+ /**
114
+ * The `tags` command's per-command scope (3F-3300). Two input flags and `--help`/`-h`, and the
115
+ * two are `balance`'s own spellings on purpose: a consumer pointing one command at a corpus and a
116
+ * manifest should not have to learn a second name for each when they point the other at the same
117
+ * two files. The descriptions are this command's — what it reads them FOR is not what `balance`
118
+ * reads them for — but the flags are the same flags.
119
+ *
120
+ * NO `configHelp`. A command's config block documents the `package.json` fields THAT command
121
+ * reads, and `tags` reads none yet: the check-tag union and the recognised deferral set arrive
122
+ * with the grammar rules (3F-3302 onward), and the entry gains its block then. Appending
123
+ * `balance`'s block here would document, under this command, fields this command does not read —
124
+ * which is the fault 3F-3298 moved that block onto a command entry to prevent.
125
+ */
126
+ const tagsFlags = [
127
+ {
128
+ name: "--features",
129
+ arg: "<dir>",
130
+ description: "Directory of Gherkin .feature files — the corpus these rules are asked about (default ./features).",
131
+ },
132
+ {
133
+ name: "--package-json",
134
+ arg: "<path>",
135
+ description: "The target's package.json — its specController block, from which the words that name a check and the tags that park a scenario are resolved (default ./package.json).",
136
+ },
137
+ {
138
+ name: "--help",
139
+ aliases: ["-h"],
140
+ description: "Show this help and exit.",
141
+ },
142
+ ];
85
143
  /** The global host-modifier scope — recognised before the command; the CLI-007 surface. */
86
144
  const globalFlags = [
87
145
  {
@@ -105,6 +163,12 @@ export const cliRegistry = {
105
163
  name: "balance",
106
164
  summary: "Reconcile Gherkin scenarios against test/CI evidence and emit the Evidence Reconciliation (Markdown to stdout by default).",
107
165
  flags: balanceFlags,
166
+ configHelp: balanceConfigHelp,
167
+ },
168
+ {
169
+ name: "tags",
170
+ summary: "Police the @SCN scheme over your Gherkin corpus — the rules the scheme itself imposes on the tags and header codes a feature file carries (exit 1 on findings, 2 on a corpus that cannot be read).",
171
+ flags: tagsFlags,
108
172
  },
109
173
  ],
110
174
  };
@@ -114,42 +178,38 @@ function flagLabel(flag) {
114
178
  return flag.arg !== undefined ? `${names} ${flag.arg}` : names;
115
179
  }
116
180
  /**
117
- * Render the `balance` command's per-command scope as help text: one line per registered
118
- * flag (name + arg-placeholder + description), driven BY the registry — so a flag that
119
- * exists is a flag that appears, by construction. Returns the help block WITHOUT a
120
- * trailing newline (the caller adds it, matching the writer's stdout convention).
181
+ * Render THE NAMED command's per-command scope as help text: one line per registered flag
182
+ * (name + arg-placeholder + description), then whatever config lines that command's entry
183
+ * carries — driven BY the registry, so a flag that exists is a flag that appears, by
184
+ * construction. Returns the help block WITHOUT a trailing newline (the caller adds it,
185
+ * matching the writer's stdout convention).
186
+ *
187
+ * THE COMMAND IS A PARAMETER (3F-3298). It used to be the literal `"balance"`, found by name
188
+ * inside this function, which is what the single registered command made look general. A
189
+ * second command had no help surface at all under that signature — not an empty one; there
190
+ * was no argument by which to ask. What the renderer covers is now the registry's shape
191
+ * rather than the command set's size on the day it was written.
121
192
  */
122
- export function renderBalanceHelp(registry) {
123
- const command = registry.commands.find((c) => c.name === "balance");
124
- const flags = command?.flags ?? [];
193
+ export function renderCommandHelp(registry, command) {
194
+ const entry = registry.commands.find((c) => c.name === command);
195
+ const flags = entry?.flags ?? [];
125
196
  const gutter = 2;
126
197
  const labelWidth = Math.max(0, ...flags.map((f) => flagLabel(f).length));
127
198
  const lines = flags.map((flag) => ` ${flagLabel(flag).padEnd(labelWidth + gutter)}${flag.description}`);
128
- // The `specController.deferralTags` config field, with its recognised starter set SINGLE-SOURCED
129
- // from DEFAULT_DEFERRAL_TAGS (@SCN-PND-021 / the 3F-1405 completeness discipline — the render reads
130
- // the constant, never a hand-kept copy, so the documented set cannot drift from the recognised one).
131
- const starterSet = DEFAULT_DEFERRAL_TAGS.map((tag) => `@${tag}`).join(", ");
132
- const configLines = [
133
- "Configuration (in the target repo's package.json):",
134
- " specController.deferralTags: string[]",
135
- " Extra recognised deferral tags. A scenario carrying one defers every obligation it",
136
- " names to a Pending Item, extending (never replacing) the built-in set.",
137
- ` Built-in deferral tags: ${starterSet}`,
138
- ];
199
+ const configHelp = entry?.configHelp ?? [];
139
200
  return [
140
- `spec-controller balance — ${command?.summary ?? ""}`,
201
+ `spec-controller ${command} — ${entry?.summary ?? ""}`,
141
202
  "",
142
203
  "Options:",
143
204
  ...lines,
144
- "",
145
- ...configLines,
205
+ ...(configHelp.length > 0 ? ["", ...configHelp] : []),
146
206
  ].join("\n");
147
207
  }
148
208
  /**
149
209
  * Render the top-level `spec-controller --help` surface (@SCN-CLI-007) FROM the registry:
150
210
  * a Commands section (each command's name + one-line summary) and a Host modifiers section
151
211
  * (each global-scope flag: name + arg-placeholder + one-line description). The global-scope
152
- * half of the two-scope registry — the counterpart to `renderBalanceHelp`'s per-command
212
+ * half of the two-scope registry — the counterpart to `renderCommandHelp`'s per-command
153
213
  * half — so the top-level usage no longer hand-keeps (and can no longer silently drift
154
214
  * from) the command set or the host modifiers; both are sourced from `cliRegistry`.
155
215
  * Summaries and descriptions render on a single line (no wrapping) so a registered string
@@ -1 +1 @@
1
- {"version":3,"file":"cli-registry.js","sourceRoot":"","sources":["../src/cli-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-registry.js","sourceRoot":"","sources":["../src/cli-registry.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -6,9 +6,11 @@
6
6
  * spec-controller [--store <root>] [--run-id <id>] <command> [command-args]
7
7
  *
8
8
  * Commands: `balance` — the deterministic reconciliation of scenarios against
9
- * observed evidence, standalone on the public core + app layer (no engine). The
10
- * `analyse` / `migrate` capabilities are a separate, closed offering built on the same
11
- * core.
9
+ * observed evidence, standalone on the public core + app layer (no engine); `tags` — the
10
+ * @SCN scheme policing itself over the same corpus, which is a fault about the corpus rather
11
+ * than a verdict about its evidence, and so has its own status ladder rather than a fifth
12
+ * meaning on balance's. The `analyse` / `migrate` capabilities are a separate, closed offering
13
+ * built on the same core.
12
14
  *
13
15
  * Storage is a CROSS-CUTTING host modifier, not a command. A leading `--store <root>`
14
16
  * turns any command into a STORED run: the host wraps the command via the kept-run
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;GAoBG"}
package/dist/cli.js CHANGED
@@ -6,9 +6,11 @@
6
6
  * spec-controller [--store <root>] [--run-id <id>] <command> [command-args]
7
7
  *
8
8
  * Commands: `balance` — the deterministic reconciliation of scenarios against
9
- * observed evidence, standalone on the public core + app layer (no engine). The
10
- * `analyse` / `migrate` capabilities are a separate, closed offering built on the same
11
- * core.
9
+ * observed evidence, standalone on the public core + app layer (no engine); `tags` — the
10
+ * @SCN scheme policing itself over the same corpus, which is a fault about the corpus rather
11
+ * than a verdict about its evidence, and so has its own status ladder rather than a fifth
12
+ * meaning on balance's. The `analyse` / `migrate` capabilities are a separate, closed offering
13
+ * built on the same core.
12
14
  *
13
15
  * Storage is a CROSS-CUTTING host modifier, not a command. A leading `--store <root>`
14
16
  * turns any command into a STORED run: the host wraps the command via the kept-run
@@ -20,6 +22,7 @@
20
22
  */
21
23
  import { dirname } from "node:path";
22
24
  import { runBalance } from "./cli-balance/cli.js";
25
+ import { runTags } from "./corpus/cli.js";
23
26
  import { resolveSourceSha, resolveToolIdentity } from "./run-management/resolveRunInputs.js";
24
27
  import { executeKeptRun, resolveRunId, } from "./run-management/keptRun.js";
25
28
  import { parseHostInvocation, wrapCommandArgv, peekFlag } from "./host.js";
@@ -30,6 +33,9 @@ function runCommand(command, argv) {
30
33
  case "balance":
31
34
  runBalance(argv);
32
35
  return;
36
+ case "tags":
37
+ runTags(argv);
38
+ return;
33
39
  default:
34
40
  process.stderr.write(`spec-controller: unknown command "${command}".\n\n${renderTopLevelHelp(cliRegistry)}\n`);
35
41
  process.exit(1);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The `tags` command — `spec-controller tags`, the `@SCN` scheme policing itself over a
3
+ * target's Gherkin corpus.
4
+ *
5
+ * THIS EDGE OWNS ONLY THE READS. The rule is `corpusFaults`, in core, reached through the ROOT
6
+ * barrel and nothing else: `./internal` is dropped by `publishConfig.exports` at pack time, and
7
+ * this module travels in the tarball. That is not a style preference — an installed
8
+ * `balance --help` once threw ERR_PACKAGE_PATH_NOT_EXPORTED behind thirteen green gates because a
9
+ * published module reached that subpath (3F-3086). So what happens here is: discover the corpus,
10
+ * read the manifest, build the mutation-record reader, hand over the bytes.
11
+ *
12
+ * ITS OWN COMMAND RATHER THAN A `balance` FLAG. `balance`'s exit code IS its verdict — 0
13
+ * balanced, 1 out of balance, 3 pending-under-strict, 4 unsound, 5 nothing to reconcile — and a
14
+ * corpus FAULT is not a reconciliation verdict. A flag would either overload one of those codes or
15
+ * add a further meaning to a status a consumer's CI branches on. A second command costs one registry entry and gives
16
+ * the fault its own ladder:
17
+ *
18
+ * 0 — the corpus obeys the scheme.
19
+ * 1 — findings; the corpus was read and it breaks a rule.
20
+ * 2 — the corpus (or the manifest) could not be READ at all. Not a verdict, because nothing was
21
+ * concluded. Sibling to @SCN-CLI-014/015/016 on `balance`, and the same argument: an input
22
+ * the tool cannot read is a usage error, never a verdict.
23
+ *
24
+ * Usage:
25
+ * spec-controller tags [--features <dir>] [--package-json <path>]
26
+ */
27
+ /**
28
+ * Police a target's corpus against the `@SCN` scheme's own rules.
29
+ *
30
+ * `process.exitCode` RATHER THAN `process.exit`, so whatever has been written is flushed intact
31
+ * rather than truncated mid-write — the convention `balance`'s own gate settled on.
32
+ */
33
+ export declare function runTags(argv: string[]): void;
34
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/corpus/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAiEH;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkD5C"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The `tags` command — `spec-controller tags`, the `@SCN` scheme policing itself over a
3
+ * target's Gherkin corpus.
4
+ *
5
+ * THIS EDGE OWNS ONLY THE READS. The rule is `corpusFaults`, in core, reached through the ROOT
6
+ * barrel and nothing else: `./internal` is dropped by `publishConfig.exports` at pack time, and
7
+ * this module travels in the tarball. That is not a style preference — an installed
8
+ * `balance --help` once threw ERR_PACKAGE_PATH_NOT_EXPORTED behind thirteen green gates because a
9
+ * published module reached that subpath (3F-3086). So what happens here is: discover the corpus,
10
+ * read the manifest, build the mutation-record reader, hand over the bytes.
11
+ *
12
+ * ITS OWN COMMAND RATHER THAN A `balance` FLAG. `balance`'s exit code IS its verdict — 0
13
+ * balanced, 1 out of balance, 3 pending-under-strict, 4 unsound, 5 nothing to reconcile — and a
14
+ * corpus FAULT is not a reconciliation verdict. A flag would either overload one of those codes or
15
+ * add a further meaning to a status a consumer's CI branches on. A second command costs one registry entry and gives
16
+ * the fault its own ladder:
17
+ *
18
+ * 0 — the corpus obeys the scheme.
19
+ * 1 — findings; the corpus was read and it breaks a rule.
20
+ * 2 — the corpus (or the manifest) could not be READ at all. Not a verdict, because nothing was
21
+ * concluded. Sibling to @SCN-CLI-014/015/016 on `balance`, and the same argument: an input
22
+ * the tool cannot read is a usage error, never a verdict.
23
+ *
24
+ * Usage:
25
+ * spec-controller tags [--features <dir>] [--package-json <path>]
26
+ */
27
+ import { existsSync, readFileSync } from "node:fs";
28
+ import { corpusFaults } from "@3f-consulting/spec-controller-core";
29
+ import { cliRegistry, renderCommandHelp } from "../cli-registry.js";
30
+ import { checkUnknownFlags, parseArgs } from "../cli-args.js";
31
+ import { DEFAULT_DEFERRAL_TAGS } from "../deferralTags.js";
32
+ import { UnreadableFeatureCorpusError } from "../ingest/gherkinValidation.js";
33
+ import { discoverFeatures } from "../ingest/ingestScenarios.js";
34
+ import { killFloorReaderFor } from "../ingest/ingestQualityChecks.js";
35
+ import { resolveTargetRoot, resolveToolIdentity } from "../run-management/resolveRunInputs.js";
36
+ /**
37
+ * Read everything the rule takes, or say why it could not be read.
38
+ *
39
+ * ONE PLACE, ONE STATUS, because it is one Rule. A corpus the Gherkin parser rejects, a features
40
+ * directory that is not there, and a manifest that is not JSON are three spellings of "the tool
41
+ * could not read its input" — and every one of them, left to escape, lands on Node's default exit
42
+ * 1, which is this command's code for FINDINGS. A crashed invocation would then be
43
+ * indistinguishable by status from a corpus that genuinely breaks a rule, which is exactly the
44
+ * collision 3F-1742 closed on `balance`.
45
+ *
46
+ * THE PARSE REFUSAL IS INHERITED, NOT RESTATED (@SCN-GPG-001). `discoverFeatures` refuses a corpus
47
+ * cucumber could not run rather than returning one, so this command gets that refusal by going
48
+ * through the shared discovery — the same way `balance` does — and what is left here is turning
49
+ * it into this command's status. Its message carries the parser's own words verbatim.
50
+ *
51
+ * THE SOURCES ARE READ HERE because the rule is pure and takes bytes. `DiscoveredFeature` carries
52
+ * the header code and the scenario ids but not the file's text, and the grammar rules that follow
53
+ * this one need the text to walk the tags.
54
+ */
55
+ function readCorpusInputs(featuresDir, manifestPath) {
56
+ try {
57
+ const discovered = featuresDir === undefined ? discoverFeatures() : discoverFeatures(featuresDir);
58
+ return {
59
+ ok: true,
60
+ features: discovered.map((f) => ({
61
+ slug: f.slug,
62
+ featureCode: f.featureCode,
63
+ source: readFileSync(f.path, "utf8"),
64
+ })),
65
+ packageJson: existsSync(manifestPath)
66
+ ? JSON.parse(readFileSync(manifestPath, "utf8"))
67
+ : {},
68
+ root: resolveTargetRoot({ features: featuresDir }),
69
+ };
70
+ }
71
+ catch (err) {
72
+ if (err instanceof UnreadableFeatureCorpusError)
73
+ return { ok: false, error: err.message };
74
+ const failure = err instanceof Error ? err.message : String(err);
75
+ return { ok: false, error: `The corpus could not be read: ${failure}` };
76
+ }
77
+ }
78
+ /**
79
+ * Police a target's corpus against the `@SCN` scheme's own rules.
80
+ *
81
+ * `process.exitCode` RATHER THAN `process.exit`, so whatever has been written is flushed intact
82
+ * rather than truncated mid-write — the convention `balance`'s own gate settled on.
83
+ */
84
+ export function runTags(argv) {
85
+ // Answer `--help`/`-h` from the registry BEFORE any parse, so it never falls through as a stray
86
+ // flag while the command runs anyway. The registry is the single source, so a flag that exists
87
+ // is a flag that appears in help — there is no hand-kept list here to drift.
88
+ if (argv.includes("--help") || argv.includes("-h")) {
89
+ process.stdout.write(renderCommandHelp(cliRegistry, "tags") + "\n");
90
+ return;
91
+ }
92
+ const args = parseArgs(argv);
93
+ // Registry-bounded parse (@SCN-CLI-009's rule, applied to this command's own scope): `tags`
94
+ // accepts ONLY the flags its registry entry lists. By construction, not by assertion — the
95
+ // helper is the one `balance` uses, given this command's name.
96
+ const unknownFlagError = checkUnknownFlags(args, cliRegistry, "tags", resolveToolIdentity().toolVersion);
97
+ if (unknownFlagError) {
98
+ process.stderr.write(unknownFlagError + "\n");
99
+ process.exitCode = 2;
100
+ return;
101
+ }
102
+ // `--package-json` defaults to the manifest at the cwd, matching `balance`'s default: the
103
+ // target is the tree you are standing in unless you say otherwise.
104
+ const inputs = readCorpusInputs(args["features"], args["package-json"] ?? "package.json");
105
+ if (!inputs.ok) {
106
+ process.stderr.write(inputs.error + "\n");
107
+ process.exitCode = 2;
108
+ return;
109
+ }
110
+ const faults = corpusFaults({
111
+ features: inputs.features,
112
+ packageJson: inputs.packageJson,
113
+ // The STARTER deferral set — the application layer's own policy, which a target's config may
114
+ // only extend. Single-sourced here for the reason the reconcile composition takes it as a
115
+ // parameter: which words the community recognises is the product's answer, not the engine's.
116
+ deferralTags: DEFAULT_DEFERRAL_TAGS,
117
+ killFloor: killFloorReaderFor(inputs.root),
118
+ });
119
+ if (faults.length === 0) {
120
+ process.stdout.write("tags: OK — every feature code names one feature file, and every tag on the corpus obeys the @SCN scheme's own rules.\n");
121
+ return;
122
+ }
123
+ process.stderr.write(`tags: FAILED — ${faults.length} finding(s):\n`);
124
+ for (const fault of faults)
125
+ process.stderr.write(` ${fault.message}\n`);
126
+ process.exitCode = 1;
127
+ }
128
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/corpus/cli.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  * handed (its default is `[]`, a policy-free pure core); the app is the single source
11
11
  * of the starter policy and always passes the resolved set (starter ∪ configured) into
12
12
  * the parser at the ingest edge. Both `resolveDeferralTags` (the `@SCN-PND-021` config
13
- * union) and `renderBalanceHelp`'s `--help` listing source this constant.
13
+ * union) and `renderCommandHelp`'s `--help` listing source this constant.
14
14
  */
15
15
  export declare const DEFAULT_DEFERRAL_TAGS: readonly string[];
16
16
  //# sourceMappingURL=deferralTags.d.ts.map
@@ -10,7 +10,7 @@
10
10
  * handed (its default is `[]`, a policy-free pure core); the app is the single source
11
11
  * of the starter policy and always passes the resolved set (starter ∪ configured) into
12
12
  * the parser at the ingest edge. Both `resolveDeferralTags` (the `@SCN-PND-021` config
13
- * union) and `renderBalanceHelp`'s `--help` listing source this constant.
13
+ * union) and `renderCommandHelp`'s `--help` listing source this constant.
14
14
  */
15
15
  export const DEFAULT_DEFERRAL_TAGS = [
16
16
  "wip",
@@ -67,4 +67,27 @@ export declare class UnreadableFeatureCorpusError extends Error {
67
67
  readonly errors: readonly GherkinParseError[];
68
68
  constructor(errors: readonly GherkinParseError[]);
69
69
  }
70
+ /**
71
+ * The corpus-level ABSENCE refusal (@SCN-CLI-017, 3F-3345) — sibling to the parse refusal above,
72
+ * and deliberately the same shape: the reader refuses ONCE, and each command decides what the
73
+ * refusal means for it.
74
+ *
75
+ * WHY A TYPED ERROR RATHER THAN AN EMPTY CORPUS. The obvious fix is for `discoverFeatures` to hand
76
+ * back `[]` when the directory is not there. Measured, that would ship a NEW false green in a
77
+ * second command: `spec-controller tags` reaches the same reader through `readCorpusInputs`, whose
78
+ * GENERIC catch is the only thing turning an absent corpus — and, since `tags` carries no
79
+ * `checkInputsExist`, a supplied-but-absent `--features` too — into `The corpus could not be
80
+ * read: …` at exit 2. Tolerance at the reader turns both into `tags: OK …` at exit 0, inside the
81
+ * slice whose whole purpose is killing a vacuous certification. Typed, both survive untouched:
82
+ * this IS an `Error`, so it still lands in that generic catch.
83
+ *
84
+ * IT CARRIES THE DIRECTORY because the report is owed the name of what it examined — "I found no
85
+ * record" and "I found no regression" must never wear one word (3F-2947), and a consumer told
86
+ * their corpus is empty deserves to know which directory was read to reach that.
87
+ */
88
+ export declare class MissingFeatureCorpusError extends Error {
89
+ /** The directory that is not there — as resolved, so a reader can print the path examined. */
90
+ readonly directory: string;
91
+ constructor(directory: string);
92
+ }
70
93
  //# sourceMappingURL=gherkinValidation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gherkinValidation.d.ts","sourceRoot":"","sources":["../../src/ingest/gherkinValidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAa/E;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;gBAElC,MAAM,EAAE,SAAS,iBAAiB,EAAE;CAUjD"}
1
+ {"version":3,"file":"gherkinValidation.d.ts","sourceRoot":"","sources":["../../src/ingest/gherkinValidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAa/E;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,CAAC;gBAElC,MAAM,EAAE,SAAS,iBAAiB,EAAE;CAUjD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,SAAS,EAAE,MAAM;CAK9B"}