spec-controller 0.1.0-alpha.5 → 0.1.0-alpha.51

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 (122) hide show
  1. package/README.md +34 -6
  2. package/dist/cli-allocate/cli.d.ts +2 -0
  3. package/dist/cli-allocate/cli.d.ts.map +1 -0
  4. package/dist/cli-allocate/cli.js +60 -0
  5. package/dist/cli-allocate/cli.js.map +1 -0
  6. package/dist/cli-allocate/readHistory.d.ts +15 -0
  7. package/dist/cli-allocate/readHistory.d.ts.map +1 -0
  8. package/dist/cli-allocate/readHistory.js +108 -0
  9. package/dist/cli-allocate/readHistory.js.map +1 -0
  10. package/dist/cli-allocate/readParts.d.ts +2 -0
  11. package/dist/cli-allocate/readParts.d.ts.map +1 -0
  12. package/dist/cli-allocate/readParts.js +22 -0
  13. package/dist/cli-allocate/readParts.js.map +1 -0
  14. package/dist/cli-allocate/readTree.d.ts +5 -0
  15. package/dist/cli-allocate/readTree.d.ts.map +1 -0
  16. package/dist/cli-allocate/readTree.js +74 -0
  17. package/dist/cli-allocate/readTree.js.map +1 -0
  18. package/dist/cli-allocate/refStore.d.ts +2 -0
  19. package/dist/cli-allocate/refStore.d.ts.map +1 -0
  20. package/dist/cli-allocate/refStore.js +34 -0
  21. package/dist/cli-allocate/refStore.js.map +1 -0
  22. package/dist/cli-allocate/request.d.ts +9 -0
  23. package/dist/cli-allocate/request.d.ts.map +1 -0
  24. package/dist/cli-allocate/request.js +22 -0
  25. package/dist/cli-allocate/request.js.map +1 -0
  26. package/dist/cli-allocate/stderr.d.ts +7 -0
  27. package/dist/cli-allocate/stderr.d.ts.map +1 -0
  28. package/dist/cli-allocate/stderr.js +26 -0
  29. package/dist/cli-allocate/stderr.js.map +1 -0
  30. package/dist/cli-allocate/unreadable.d.ts +11 -0
  31. package/dist/cli-allocate/unreadable.d.ts.map +1 -0
  32. package/dist/cli-allocate/unreadable.js +30 -0
  33. package/dist/cli-allocate/unreadable.js.map +1 -0
  34. package/dist/cli-args.d.ts +12 -70
  35. package/dist/cli-args.d.ts.map +1 -1
  36. package/dist/cli-args.js +158 -81
  37. package/dist/cli-args.js.map +1 -1
  38. package/dist/cli-balance/cli.d.ts +1 -81
  39. package/dist/cli-balance/cli.d.ts.map +1 -1
  40. package/dist/cli-balance/cli.js +71 -357
  41. package/dist/cli-balance/cli.js.map +1 -1
  42. package/dist/cli-balance/emit/format.d.ts +16 -38
  43. package/dist/cli-balance/emit/format.d.ts.map +1 -1
  44. package/dist/cli-balance/emit/format.js +31 -58
  45. package/dist/cli-balance/emit/format.js.map +1 -1
  46. package/dist/cli-balance/emit/writer.d.ts +2 -32
  47. package/dist/cli-balance/emit/writer.d.ts.map +1 -1
  48. package/dist/cli-balance/emit/writer.js +50 -37
  49. package/dist/cli-balance/emit/writer.js.map +1 -1
  50. package/dist/cli-balance/exitStatus.d.ts +2 -0
  51. package/dist/cli-balance/exitStatus.d.ts.map +1 -0
  52. package/dist/cli-balance/exitStatus.js +5 -0
  53. package/dist/cli-balance/exitStatus.js.map +1 -0
  54. package/dist/cli-balance/inputsRead.d.ts +11 -0
  55. package/dist/cli-balance/inputsRead.d.ts.map +1 -0
  56. package/dist/cli-balance/inputsRead.js +53 -0
  57. package/dist/cli-balance/inputsRead.js.map +1 -0
  58. package/dist/cli-balance/reRender.d.ts +8 -0
  59. package/dist/cli-balance/reRender.d.ts.map +1 -0
  60. package/dist/cli-balance/reRender.js +21 -0
  61. package/dist/cli-balance/reRender.js.map +1 -0
  62. package/dist/cli-balance/unreadableInputs.d.ts +14 -0
  63. package/dist/cli-balance/unreadableInputs.d.ts.map +1 -0
  64. package/dist/cli-balance/unreadableInputs.js +80 -0
  65. package/dist/cli-balance/unreadableInputs.js.map +1 -0
  66. package/dist/cli-registry.d.ts +12 -70
  67. package/dist/cli-registry.d.ts.map +1 -1
  68. package/dist/cli-registry.js +37 -97
  69. package/dist/cli-registry.js.map +1 -1
  70. package/dist/cli.d.ts +0 -21
  71. package/dist/cli.d.ts.map +1 -1
  72. package/dist/cli.js +62 -55
  73. package/dist/cli.js.map +1 -1
  74. package/dist/deferralTags.d.ts +0 -14
  75. package/dist/deferralTags.d.ts.map +1 -1
  76. package/dist/deferralTags.js +0 -14
  77. package/dist/deferralTags.js.map +1 -1
  78. package/dist/host.d.ts +10 -41
  79. package/dist/host.d.ts.map +1 -1
  80. package/dist/host.js +103 -50
  81. package/dist/host.js.map +1 -1
  82. package/dist/ingest/ciSourcePaths.d.ts +0 -38
  83. package/dist/ingest/ciSourcePaths.d.ts.map +1 -1
  84. package/dist/ingest/ciSourcePaths.js +0 -38
  85. package/dist/ingest/ciSourcePaths.js.map +1 -1
  86. package/dist/ingest/gherkinValidation.d.ts +0 -80
  87. package/dist/ingest/gherkinValidation.d.ts.map +1 -1
  88. package/dist/ingest/gherkinValidation.js +0 -80
  89. package/dist/ingest/gherkinValidation.js.map +1 -1
  90. package/dist/ingest/ingestQualityChecks.d.ts +8 -93
  91. package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
  92. package/dist/ingest/ingestQualityChecks.js +57 -214
  93. package/dist/ingest/ingestQualityChecks.js.map +1 -1
  94. package/dist/ingest/ingestScenarios.d.ts +0 -45
  95. package/dist/ingest/ingestScenarios.d.ts.map +1 -1
  96. package/dist/ingest/ingestScenarios.js +28 -108
  97. package/dist/ingest/ingestScenarios.js.map +1 -1
  98. package/dist/ingest/inputShapes.d.ts +16 -0
  99. package/dist/ingest/inputShapes.d.ts.map +1 -0
  100. package/dist/ingest/inputShapes.js +113 -0
  101. package/dist/ingest/inputShapes.js.map +1 -0
  102. package/dist/outputLocation.d.ts +27 -0
  103. package/dist/outputLocation.d.ts.map +1 -0
  104. package/dist/outputLocation.js +135 -0
  105. package/dist/outputLocation.js.map +1 -0
  106. package/dist/run-management/keptRun.d.ts +5 -105
  107. package/dist/run-management/keptRun.d.ts.map +1 -1
  108. package/dist/run-management/keptRun.js +16 -82
  109. package/dist/run-management/keptRun.js.map +1 -1
  110. package/dist/run-management/resolveRunInputs.d.ts +0 -67
  111. package/dist/run-management/resolveRunInputs.d.ts.map +1 -1
  112. package/dist/run-management/resolveRunInputs.js +0 -88
  113. package/dist/run-management/resolveRunInputs.js.map +1 -1
  114. package/dist/storedRun.d.ts +6 -0
  115. package/dist/storedRun.d.ts.map +1 -0
  116. package/dist/storedRun.js +28 -0
  117. package/dist/storedRun.js.map +1 -0
  118. package/package.json +2 -2
  119. package/dist/corpus/cli.d.ts +0 -34
  120. package/dist/corpus/cli.d.ts.map +0 -1
  121. package/dist/corpus/cli.js +0 -125
  122. package/dist/corpus/cli.js.map +0 -1
@@ -1,79 +1,25 @@
1
- /**
2
- * The KEPT-RUN scaffold — the thin app-layer that turns a bare tool invocation into a
3
- * STORED run (the run-management layer). A kept run is a consultancy / product-dev artefact (NOT CI):
4
- * it makes a per-run directory under a caller-INJECTED store root and routes the tool's
5
- * `--format` outputs into it. The tool holds no storage opinion (the `--format` surface); this
6
- * scaffold adds only the directory + the routing.
7
- *
8
- * Split by the three-layer architecture:
9
- * - PURE planner (`planKeptRun`): given `{ storeRoot, target, runId }`, yields the run
10
- * dir `<storeRoot>/<target>/<runId>/` and the two file-dest paths — no IO, proven
11
- * `@unit`.
12
- * - IMPURE runner (`executeKeptRun`): `mkdir -p` the run dir, then route the tool's
13
- * `--format` outputs into the two files by handing an injected tool-invoker the two
14
- * file-dest `--format` specs. The ONLY IO, proven `@integration` (the real on-disk
15
- * files under a temp root + the repo untouched — never a planner re-run).
16
- *
17
- * The store root is an INJECTED parameter — never hardcoded — so the scaffold is
18
- * location-agnostic (proven against a temp root; the repo is never written). RMG-001 is
19
- * the dir + the routed outputs; the `run.yaml` stamp (RMG-002) and the `--run-id` mnemonic
20
- * override (RMG-003) land in later sub-issues.
21
- *
22
- * Parent: @SCN-RMG-001 — the run-management layer.
23
- */
24
- /** The two artefact filenames a kept run routes the tool's outputs into. */
1
+ import { type ReadInput } from "../outputLocation.js";
25
2
  export declare const RECONCILIATION_DOCUMENT = "spec-reconciliation.md";
26
- /**
27
- * The machine artefact filename (@SCN-RMD-001) — renamed `ledger.json` →
28
- * `spec-reconciliation.json` (parity with `spec-reconciliation.md`): it is the machine form
29
- * of the WHOLE reconciliation document, not just the ledger.
30
- */
31
3
  export declare const RECONCILIATION_JSON = "spec-reconciliation.json";
32
- /** The manifest filename a kept run stamps in the run dir (RMG-002). */
33
4
  export declare const RUN_MANIFEST = "run.yaml";
34
- /**
35
- * The run.yaml schema version this scaffold stamps. Bumped 1 → 2 by 3F-1916, which added
36
- * the tool identity (`tool_sha` / `tool_version`) — so a reader can tell a run that
37
- * predates tool-identity recording (schema 1) from one that should carry it (schema 2).
38
- * run.yaml is write-only (no production reader), so the bump breaks no read path.
39
- */
40
5
  export declare const RUN_MANIFEST_SCHEMA_VERSION = 2;
41
- /** The stored-run modes (run.yaml `mode`). */
42
6
  export type RunMode = "balance" | "analyse" | "migrate";
43
- /**
44
- * The manifest-only metadata a kept run stamps that the path spec (`KeptRunSpec`) does not
45
- * carry — the source SHA, the run mode, and the ISO date.
46
- */
47
7
  export interface RunManifestMeta {
48
8
  readonly sourceSha: string;
49
- /**
50
- * The TOOL's own git SHA — which spec-controller produced this run (3F-1916), distinct
51
- * from the target's `sourceSha`. A string ("unknown" when the tool is not a git
52
- * checkout), mirroring `sourceSha`'s own "unknown" fallback — so run.yaml is internally
53
- * consistent (both facts use the same absent-marker, never a bare null).
54
- */
55
9
  readonly toolSha: string;
56
- /** The tool's package version — always present. */
57
10
  readonly toolVersion: string;
58
11
  readonly mode: RunMode;
59
12
  readonly date: string;
60
13
  }
61
- /** The full manifest input: the path spec's run-id + target, plus the manifest-only meta. */
62
14
  export interface RunManifestInput extends RunManifestMeta {
63
15
  readonly runId: string;
64
16
  readonly target: string;
65
17
  }
66
- /**
67
- * The run.yaml manifest — the decided light field set. `purpose`/`links` default EMPTY (the ad-hoc default; slugs are
68
- * added by operator hand-edit afterward). `category`/`use_case` are NOT stamped (`purpose`
69
- * subsumes them). Keys are listed in the decided stamp order.
70
- */
71
18
  export interface RunManifest {
72
19
  readonly schema_version: number;
73
20
  readonly run_id: string;
74
21
  readonly target: string;
75
22
  readonly source_sha: string;
76
- /** The TOOL's identity (3F-1916) — which spec-controller produced the run. */
77
23
  readonly tool_sha: string;
78
24
  readonly tool_version: string;
79
25
  readonly mode: RunMode;
@@ -85,72 +31,26 @@ export interface RunManifest {
85
31
  readonly reconciliation: string;
86
32
  };
87
33
  }
88
- /** The kept-run inputs: the injected store root, the target, and the run-id. */
89
34
  export interface KeptRunSpec {
90
35
  readonly storeRoot: string;
91
36
  readonly target: string;
92
37
  readonly runId: string;
38
+ readonly formatPaths?: readonly string[];
39
+ readonly inputs?: readonly ReadInput[];
93
40
  }
94
- /** The planned run: the run dir plus the two file-dest paths inside it. */
95
41
  export interface KeptRunPlan {
96
42
  readonly runDir: string;
97
43
  readonly documentPath: string;
98
44
  readonly reconciliationJsonPath: string;
99
45
  }
100
- /**
101
- * Invokes the reconciliation tool with the given `--format <fmt>:<path>` specs. INJECTED so
102
- * the scaffold stays the tool's black-box caller (the real CLI subprocess in the
103
- * `@integration` arm) and holds no opinion on HOW the tool is run — only WHERE its outputs
104
- * land (the two file-dest paths the runner hands it).
105
- */
106
- export type RouteOutputs = (formatSpecs: readonly string[]) => void;
107
- /**
108
- * PURE planner: yield the run dir `<storeRoot>/<target>/<runId>/` and the two file-dest
109
- * paths (`<dir>/spec-reconciliation.md`, `<dir>/spec-reconciliation.json`) from the spec. No
110
- * IO — the store root is threaded straight through `join`, so it is a parameter, never
111
- * hardcoded.
112
- */
46
+ export type RouteOutputs = (formatSpecs: readonly string[]) => boolean;
113
47
  export declare function planKeptRun(spec: KeptRunSpec): KeptRunPlan;
114
- /**
115
- * Options for the pure run-id resolver (RMG-003): the operator's OPTIONAL `--run-id` mnemonic
116
- * and the INJECTED clock instant the default timestamp derives from.
117
- */
118
48
  export interface ResolveRunIdOptions {
119
- /** The operator's `--run-id` mnemonic when supplied; overrides the timestamp default, verbatim. */
120
49
  readonly runId?: string;
121
- /**
122
- * The injected instant the default ISO-timestamp run-id derives from — the deterministic-@unit
123
- * seam. Never a bare `new Date()` inside the resolver, so the default run-id is pin-testable.
124
- */
125
50
  readonly now: Date;
126
51
  }
127
- /**
128
- * PURE run-id resolver — the CLI/edge seam that turns an OPTIONAL `--run-id` into the concrete
129
- * run-id naming the run dir (feeds `KeptRunSpec.runId`). No `--run-id` → an ISO-8601 UTC
130
- * timestamp derived from the INJECTED `now` (filesystem-safe: no colons, no millis — matching
131
- * the existing store run dir); `--run-id <mnemonic>` → that mnemonic verbatim (`acme-q3`, `e1`
132
- * — an earlier precedent), which ignores the clock. No IO — proven `@unit` (RMG-003).
133
- * The clock is injected (never a bare `new Date()`) so the default timestamp is deterministic
134
- * under test (the discipline the old `formatRunTimestamp` used). Just default-vs-override — no
135
- * sanitisation / collision policy (deferred).
136
- */
137
52
  export declare function resolveRunId(options: ResolveRunIdOptions): string;
138
- /**
139
- * PURE: build the run.yaml manifest object from the run metadata (RMG-002). `purpose` and
140
- * `links` are stamped EMPTY (the ad-hoc default; slugs are added by operator hand-edit of
141
- * run.yaml afterward — the documented curation convention); `artefacts` carry the decided
142
- * filenames. No IO — proven `@unit`.
143
- */
144
53
  export declare function planRunManifest(input: RunManifestInput): RunManifest;
145
- /** PURE: serialise the manifest to YAML text the impure runner writes verbatim. */
146
54
  export declare function serialiseRunManifest(manifest: RunManifest): string;
147
- /**
148
- * IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two
149
- * files via the injected `route` — the document as `md:<documentPath>`, the reconciliation
150
- * JSON as `json:<reconciliationJsonPath>` — and stamp `run.yaml` with the manifest built from the spec + `meta`
151
- * (RMG-002). Returns the plan it realised. The only IO. The `mkdir` is load-bearing: the
152
- * tool's writer uses `writeFileSync`, which needs the parent dir to exist — so the scaffold
153
- * creates the dir the location-agnostic tool writes into.
154
- */
155
- export declare function executeKeptRun(spec: KeptRunSpec, meta: RunManifestMeta, route: RouteOutputs): KeptRunPlan;
55
+ export declare function executeKeptRun(spec: KeptRunSpec, meta: RunManifestMeta, route: RouteOutputs): KeptRunPlan | undefined;
156
56
  //# sourceMappingURL=keptRun.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keptRun.d.ts","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keptRun.d.ts","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAExG,eAAO,MAAM,uBAAuB,2BAA2B,CAAC;AAChE,eAAO,MAAM,mBAAmB,6BAA6B,CAAC;AAE9D,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC;AAEvE,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAO1D;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAKjE;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAiBpE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAElE;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,YAAY,GAClB,WAAW,GAAG,SAAS,CA0BzB"}
@@ -1,52 +1,11 @@
1
- /**
2
- * The KEPT-RUN scaffold — the thin app-layer that turns a bare tool invocation into a
3
- * STORED run (the run-management layer). A kept run is a consultancy / product-dev artefact (NOT CI):
4
- * it makes a per-run directory under a caller-INJECTED store root and routes the tool's
5
- * `--format` outputs into it. The tool holds no storage opinion (the `--format` surface); this
6
- * scaffold adds only the directory + the routing.
7
- *
8
- * Split by the three-layer architecture:
9
- * - PURE planner (`planKeptRun`): given `{ storeRoot, target, runId }`, yields the run
10
- * dir `<storeRoot>/<target>/<runId>/` and the two file-dest paths — no IO, proven
11
- * `@unit`.
12
- * - IMPURE runner (`executeKeptRun`): `mkdir -p` the run dir, then route the tool's
13
- * `--format` outputs into the two files by handing an injected tool-invoker the two
14
- * file-dest `--format` specs. The ONLY IO, proven `@integration` (the real on-disk
15
- * files under a temp root + the repo untouched — never a planner re-run).
16
- *
17
- * The store root is an INJECTED parameter — never hardcoded — so the scaffold is
18
- * location-agnostic (proven against a temp root; the repo is never written). RMG-001 is
19
- * the dir + the routed outputs; the `run.yaml` stamp (RMG-002) and the `--run-id` mnemonic
20
- * override (RMG-003) land in later sub-issues.
21
- *
22
- * Parent: @SCN-RMG-001 — the run-management layer.
23
- */
24
1
  import { mkdirSync, writeFileSync } from "node:fs";
25
2
  import { join } from "node:path";
26
3
  import { stringify } from "yaml";
27
- /** The two artefact filenames a kept run routes the tool's outputs into. */
4
+ import { firstSharingFile, inputAt, refuse, writeOrRefuse } from "../outputLocation.js";
28
5
  export const RECONCILIATION_DOCUMENT = "spec-reconciliation.md";
29
- /**
30
- * The machine artefact filename (@SCN-RMD-001) — renamed `ledger.json` →
31
- * `spec-reconciliation.json` (parity with `spec-reconciliation.md`): it is the machine form
32
- * of the WHOLE reconciliation document, not just the ledger.
33
- */
34
6
  export const RECONCILIATION_JSON = "spec-reconciliation.json";
35
- /** The manifest filename a kept run stamps in the run dir (RMG-002). */
36
7
  export const RUN_MANIFEST = "run.yaml";
37
- /**
38
- * The run.yaml schema version this scaffold stamps. Bumped 1 → 2 by 3F-1916, which added
39
- * the tool identity (`tool_sha` / `tool_version`) — so a reader can tell a run that
40
- * predates tool-identity recording (schema 1) from one that should carry it (schema 2).
41
- * run.yaml is write-only (no production reader), so the bump breaks no read path.
42
- */
43
8
  export const RUN_MANIFEST_SCHEMA_VERSION = 2;
44
- /**
45
- * PURE planner: yield the run dir `<storeRoot>/<target>/<runId>/` and the two file-dest
46
- * paths (`<dir>/spec-reconciliation.md`, `<dir>/spec-reconciliation.json`) from the spec. No
47
- * IO — the store root is threaded straight through `join`, so it is a parameter, never
48
- * hardcoded.
49
- */
50
9
  export function planKeptRun(spec) {
51
10
  const runDir = join(spec.storeRoot, spec.target, spec.runId);
52
11
  return {
@@ -55,39 +14,15 @@ export function planKeptRun(spec) {
55
14
  reconciliationJsonPath: join(runDir, RECONCILIATION_JSON),
56
15
  };
57
16
  }
58
- /**
59
- * PURE run-id resolver — the CLI/edge seam that turns an OPTIONAL `--run-id` into the concrete
60
- * run-id naming the run dir (feeds `KeptRunSpec.runId`). No `--run-id` → an ISO-8601 UTC
61
- * timestamp derived from the INJECTED `now` (filesystem-safe: no colons, no millis — matching
62
- * the existing store run dir); `--run-id <mnemonic>` → that mnemonic verbatim (`acme-q3`, `e1`
63
- * — an earlier precedent), which ignores the clock. No IO — proven `@unit` (RMG-003).
64
- * The clock is injected (never a bare `new Date()`) so the default timestamp is deterministic
65
- * under test (the discipline the old `formatRunTimestamp` used). Just default-vs-override — no
66
- * sanitisation / collision policy (deferred).
67
- */
68
17
  export function resolveRunId(options) {
69
- // The operator mnemonic, when given, names the run dir verbatim — the clock is ignored.
70
18
  if (options.runId !== undefined) {
71
19
  return options.runId;
72
20
  }
73
- // Otherwise the run-id defaults to the injected instant as a filesystem-safe timestamp.
74
21
  return formatRunTimestamp(options.now);
75
22
  }
76
- /**
77
- * Format an injected instant as a filesystem-safe ISO-8601 UTC timestamp: `toISOString()`
78
- * yields `2026-06-30T10:04:01.123Z`; drop the milliseconds, then swap the time-separator
79
- * colons for hyphens so the string is a safe directory name (`2026-06-30T10-04-01Z` — the
80
- * form the existing store run dir uses).
81
- */
82
23
  function formatRunTimestamp(instant) {
83
24
  return instant.toISOString().replace(/\.\d+Z$/, "Z").replace(/:/g, "-");
84
25
  }
85
- /**
86
- * PURE: build the run.yaml manifest object from the run metadata (RMG-002). `purpose` and
87
- * `links` are stamped EMPTY (the ad-hoc default; slugs are added by operator hand-edit of
88
- * run.yaml afterward — the documented curation convention); `artefacts` carry the decided
89
- * filenames. No IO — proven `@unit`.
90
- */
91
26
  export function planRunManifest(input) {
92
27
  return {
93
28
  schema_version: RUN_MANIFEST_SCHEMA_VERSION,
@@ -98,8 +33,6 @@ export function planRunManifest(input) {
98
33
  tool_version: input.toolVersion,
99
34
  mode: input.mode,
100
35
  date: input.date,
101
- // EMPTY defaults — the ad-hoc run; slugs/links are added by operator hand-edit of
102
- // run.yaml afterward (no --purpose flag, no vocab enforcement — both deferred).
103
36
  purpose: [],
104
37
  links: [],
105
38
  artefacts: {
@@ -108,26 +41,27 @@ export function planRunManifest(input) {
108
41
  },
109
42
  };
110
43
  }
111
- /** PURE: serialise the manifest to YAML text the impure runner writes verbatim. */
112
44
  export function serialiseRunManifest(manifest) {
113
45
  return stringify(manifest);
114
46
  }
115
- /**
116
- * IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two
117
- * files via the injected `route` — the document as `md:<documentPath>`, the reconciliation
118
- * JSON as `json:<reconciliationJsonPath>` — and stamp `run.yaml` with the manifest built from the spec + `meta`
119
- * (RMG-002). Returns the plan it realised. The only IO. The `mkdir` is load-bearing: the
120
- * tool's writer uses `writeFileSync`, which needs the parent dir to exist — so the scaffold
121
- * creates the dir the location-agnostic tool writes into.
122
- */
123
47
  export function executeKeptRun(spec, meta, route) {
124
48
  const plan = planKeptRun(spec);
125
- mkdirSync(plan.runDir, { recursive: true });
126
- route([`md:${plan.documentPath}`, `json:${plan.reconciliationJsonPath}`]);
127
- // Stamp run.yaml from the spec's run-id/target (so it can't drift from the run dir) + the
128
- // manifest-only meta. The serialised YAML is valid — the @integration parses it back.
49
+ writeOrRefuse("The stored run's directory could not be created", plan.runDir, () => mkdirSync(plan.runDir, { recursive: true }));
50
+ const manifestPath = join(plan.runDir, RUN_MANIFEST);
51
+ const sharesManifest = firstSharingFile(manifestPath, spec.formatPaths ?? []);
52
+ if (sharesManifest !== undefined) {
53
+ refuse(`A --format output names ${sharesManifest}, which is this stored run's own ${manifestPath}. ` +
54
+ `Give the report a path outside ${plan.runDir}.`);
55
+ }
56
+ const readManifest = inputAt(manifestPath, spec.inputs ?? []);
57
+ if (readManifest !== undefined) {
58
+ refuse(`A file this stored run reads is its own ${manifestPath}: ${readManifest.path} is ${readManifest.subject}. ` +
59
+ `Give the store a root outside the files the run reads.`);
60
+ }
61
+ if (!route([`md:${plan.documentPath}`, `json:${plan.reconciliationJsonPath}`]))
62
+ return undefined;
129
63
  const manifest = planRunManifest({ runId: spec.runId, target: spec.target, ...meta });
130
- writeFileSync(join(plan.runDir, RUN_MANIFEST), serialiseRunManifest(manifest));
64
+ writeOrRefuse("The stored run's run.yaml could not be written", manifestPath, () => writeFileSync(manifestPath, serialiseRunManifest(manifest)));
131
65
  return plan;
132
66
  }
133
67
  //# sourceMappingURL=keptRun.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keptRun.js","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keptRun.js","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"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"}
@@ -1,82 +1,15 @@
1
- /**
2
- * Resolve a run's git-derived inputs — the target's source SHA and repo root. The
3
- * IMPURE half of the old run/runContext.ts: both shell out to `git` over the
4
- * target tree, so they live in the app's run-management layer, apart from the pure
5
- * provenance projection (packages/core/src/provenance/provenance.ts) they feed. The
6
- * CLI (cli-balance/cli.ts) calls these once to build the RunContext.
7
- *
8
- * Scenarios: @SCN-RPT-001 (the run-provenance slice); the --source-sha override;
9
- * @SCN-RPT-016 (target-root derivation); @SCN-RPT-026 / @SCN-RPT-029 (the tool's own identity).
10
- */
11
- /**
12
- * Resolve the target's source SHA (project design §4). An explicit non-empty
13
- * `sourceSha` wins — the override for non-git / zip / detached-HEAD targets (the
14
- * --source-sha flag). Otherwise `git -C <targetDir> rev-parse HEAD` (trimmed) as a
15
- * READ-ONLY pure read. On any throw —
16
- * a non-git target, git absent, an empty answer — resolve to `null` ("unknown")
17
- * rather than crashing. `targetDir` = dirname(--features) when given, else cwd.
18
- */
19
1
  export declare function resolveSourceSha(opts: {
20
2
  sourceSha?: string;
21
3
  targetDir?: string;
22
4
  }): string | null;
23
- /** The tool's own identity — which spec-controller produced a run (3F-1916). */
24
5
  export interface ToolIdentity {
25
- /** The tool's own git HEAD, or null when the tool is not a git checkout (an installed package). */
26
6
  toolSha: string | null;
27
- /** The tool's package version — always present (read from the tool's own package.json). */
28
7
  toolVersion: string;
29
8
  }
30
- /**
31
- * Resolve the TOOL's own identity (3F-1916) — which spec-controller produced this run,
32
- * distinct from the TARGET's `sourceSha`. Two facts, one call, threaded to both the
33
- * report provenance (RunContext) and the run.yaml manifest.
34
- *
35
- * **TWO TRAPS, AND THIS DOCBLOCK ONLY NAMED THE FIRST FOR ELEVEN WEEKS** (@SCN-RPT-029,
36
- * 3F-3418). Nothing typechecks a comment, and the sentence below — true, and the whole of
37
- * what was written here — is what made the second trap read as already-handled.
38
- *
39
- * **Trap one, cwd:** at run time the process cwd is the TARGET repo (reconcile runs
40
- * there), so a bare `git rev-parse HEAD` would re-record the TARGET's SHA. So the SHA is
41
- * read `git -C <the tool's OWN dir>`, derived from `import.meta.url`, never cwd (3F-1916).
42
- *
43
- * **Trap two, which the `-C` guard could not see:** the tool's own dir is ITSELF inside the
44
- * target. For an installed package that dir is `<consumer>/node_modules/…`, which is inside
45
- * the consumer's worktree, so `git -C` walks up to the consumer's `.git` and answers with
46
- * the consumer's HEAD — being `.gitignore`d makes no difference, git does not stop at
47
- * ignored directories. That is not an absent tool SHA, it is a WRONG one, and nothing on
48
- * the rendered report distinguishes it from a genuine one. It is also the only case a
49
- * consumer ever sees: every adopter installs into a git repository. `resolveToolSha`
50
- * therefore answers a `node_modules` SEGMENT before it asks git at all.
51
- *
52
- * `toolSha` is `null` for a tool resolved out of `node_modules`, and otherwise
53
- * `git -C <toolDir> rev-parse HEAD` (trimmed) or `null` on any throw — no `.git` above the
54
- * tool, git absent, or an empty answer — mirroring `resolveSourceSha`'s fail-soft.
55
- * `toolVersion` is read from the tool's own `package.json` (walked up from `toolDir`), or
56
- * `"unknown"` when none is found — so a run stays attributable by version even when no SHA
57
- * can be read. `toolDir` / `packageJsonPath` are injectable for the `@unit` teeth
58
- * (@SCN-RPT-026, @SCN-RPT-029).
59
- */
60
9
  export declare function resolveToolIdentity(opts?: {
61
10
  toolDir?: string;
62
11
  packageJsonPath?: string;
63
12
  }): ToolIdentity;
64
- /**
65
- * Resolve the TARGET repo root — the root the recorded input paths (`presentInputs`)
66
- * and the evidence-observation locators (`countRuntimeEvidenceObservationKinds`) are both made
67
- * portable against (@SCN-RPT-016). The bug it fixes: the prior CLI relativized
68
- * against `process.cwd()` — the TOOL's own repo — so a cross-repo reconcile
69
- * (cwd ≠ target) kept the target's absolute paths (they aren't under cwd → the
70
- * "absolute-not-under-root" branch of `relativizeToRoot` → leaked verbatim).
71
- *
72
- * The rule (mirrors `resolveSourceSha`'s targetDir derivation): the root is derived from
73
- * the TARGET, never the run cwd — the git top-level of `dirname(--features)` when the
74
- * target is a git repo (the robust case: `--features` may sit in a nested dir), else
75
- * `dirname(--features)` itself (a non-git target — a zip / extracted tree), else
76
- * `process.cwd()` for a self-reconcile with no `--features` (the legacy cwd = target
77
- * assumption, preserved as the fallback). A READ-ONLY `git -C … rev-parse --show-toplevel`
78
- * (read-only-target-safe); any throw falls back to `dirname(--features)`.
79
- */
80
13
  export declare function resolveTargetRoot(opts: {
81
14
  features?: string;
82
15
  }): string;
@@ -1 +1 @@
1
- {"version":3,"file":"resolveRunInputs.d.ts","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAiBhG;AAED,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,mGAAmG;IACnG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2FAA2F;IAC3F,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAQ3G;AAiED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAerE"}
1
+ {"version":3,"file":"resolveRunInputs.d.ts","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAiBhG;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAQ3G;AAyCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAerE"}
@@ -1,25 +1,7 @@
1
- /**
2
- * Resolve a run's git-derived inputs — the target's source SHA and repo root. The
3
- * IMPURE half of the old run/runContext.ts: both shell out to `git` over the
4
- * target tree, so they live in the app's run-management layer, apart from the pure
5
- * provenance projection (packages/core/src/provenance/provenance.ts) they feed. The
6
- * CLI (cli-balance/cli.ts) calls these once to build the RunContext.
7
- *
8
- * Scenarios: @SCN-RPT-001 (the run-provenance slice); the --source-sha override;
9
- * @SCN-RPT-016 (target-root derivation); @SCN-RPT-026 / @SCN-RPT-029 (the tool's own identity).
10
- */
11
1
  import { execFileSync } from "node:child_process";
12
2
  import { readFileSync } from "node:fs";
13
3
  import { dirname, join, sep } from "node:path";
14
4
  import { fileURLToPath } from "node:url";
15
- /**
16
- * Resolve the target's source SHA (project design §4). An explicit non-empty
17
- * `sourceSha` wins — the override for non-git / zip / detached-HEAD targets (the
18
- * --source-sha flag). Otherwise `git -C <targetDir> rev-parse HEAD` (trimmed) as a
19
- * READ-ONLY pure read. On any throw —
20
- * a non-git target, git absent, an empty answer — resolve to `null` ("unknown")
21
- * rather than crashing. `targetDir` = dirname(--features) when given, else cwd.
22
- */
23
5
  export function resolveSourceSha(opts) {
24
6
  if (opts.sourceSha !== undefined && opts.sourceSha.trim() !== "") {
25
7
  return opts.sourceSha.trim();
@@ -39,36 +21,6 @@ export function resolveSourceSha(opts) {
39
21
  return null;
40
22
  }
41
23
  }
42
- /**
43
- * Resolve the TOOL's own identity (3F-1916) — which spec-controller produced this run,
44
- * distinct from the TARGET's `sourceSha`. Two facts, one call, threaded to both the
45
- * report provenance (RunContext) and the run.yaml manifest.
46
- *
47
- * **TWO TRAPS, AND THIS DOCBLOCK ONLY NAMED THE FIRST FOR ELEVEN WEEKS** (@SCN-RPT-029,
48
- * 3F-3418). Nothing typechecks a comment, and the sentence below — true, and the whole of
49
- * what was written here — is what made the second trap read as already-handled.
50
- *
51
- * **Trap one, cwd:** at run time the process cwd is the TARGET repo (reconcile runs
52
- * there), so a bare `git rev-parse HEAD` would re-record the TARGET's SHA. So the SHA is
53
- * read `git -C <the tool's OWN dir>`, derived from `import.meta.url`, never cwd (3F-1916).
54
- *
55
- * **Trap two, which the `-C` guard could not see:** the tool's own dir is ITSELF inside the
56
- * target. For an installed package that dir is `<consumer>/node_modules/…`, which is inside
57
- * the consumer's worktree, so `git -C` walks up to the consumer's `.git` and answers with
58
- * the consumer's HEAD — being `.gitignore`d makes no difference, git does not stop at
59
- * ignored directories. That is not an absent tool SHA, it is a WRONG one, and nothing on
60
- * the rendered report distinguishes it from a genuine one. It is also the only case a
61
- * consumer ever sees: every adopter installs into a git repository. `resolveToolSha`
62
- * therefore answers a `node_modules` SEGMENT before it asks git at all.
63
- *
64
- * `toolSha` is `null` for a tool resolved out of `node_modules`, and otherwise
65
- * `git -C <toolDir> rev-parse HEAD` (trimmed) or `null` on any throw — no `.git` above the
66
- * tool, git absent, or an empty answer — mirroring `resolveSourceSha`'s fail-soft.
67
- * `toolVersion` is read from the tool's own `package.json` (walked up from `toolDir`), or
68
- * `"unknown"` when none is found — so a run stays attributable by version even when no SHA
69
- * can be read. `toolDir` / `packageJsonPath` are injectable for the `@unit` teeth
70
- * (@SCN-RPT-026, @SCN-RPT-029).
71
- */
72
24
  export function resolveToolIdentity(opts = {}) {
73
25
  const toolDir = opts.toolDir !== undefined && opts.toolDir.trim() !== ""
74
26
  ? opts.toolDir
@@ -78,28 +30,6 @@ export function resolveToolIdentity(opts = {}) {
78
30
  toolVersion: resolveToolVersion(opts.packageJsonPath ?? findPackageJson(toolDir)),
79
31
  };
80
32
  }
81
- /**
82
- * The tool's own git HEAD, read `-C <toolDir>` (never cwd), null on any throw — and null
83
- * without asking at all for a tool resolved out of `node_modules` (@SCN-RPT-029).
84
- *
85
- * A SEGMENT, NEVER A SUBSTRING. A directory honestly named `my_node_modules_backup` is not an
86
- * install, and a checkout living under a directory literally named `node_modules` reporting null is
87
- * the pathological trade every tool making this distinction takes.
88
- *
89
- * `sep`, NOT A REGEX OVER BOTH SEPARATORS. `[/\\]` would carry a branch no arm on this platform can
90
- * reach, so a mutant deleting its second half would survive the mutation gate while nothing was
91
- * worse. `sep` is what `fileURLToPath` produces on each platform, which is the only thing `toolDir`
92
- * is ever built from.
93
- *
94
- * IT ANSWERS BEFORE THE `try`, NOT INSIDE IT. Returning null from a thrown git read and returning
95
- * null because the tool is an install are the same recorded answer and not the same fact, and only
96
- * the first of them is allowed to depend on git being present.
97
- *
98
- * WHAT IT DOES NOT CLAIM. Under `--preserve-symlinks` Node reports the symlink path rather than the
99
- * realpath, so a linked development checkout would carry a `node_modules` segment and report null.
100
- * That is a strictly safer wrong answer than today's, nothing in this repository passes the flag,
101
- * and no arm covers it — named rather than guarded.
102
- */
103
33
  function resolveToolSha(toolDir) {
104
34
  if (toolDir.split(sep).includes("node_modules"))
105
35
  return null;
@@ -115,7 +45,6 @@ function resolveToolSha(toolDir) {
115
45
  return null;
116
46
  }
117
47
  }
118
- /** Read the `version` from a package.json, or "unknown" when the path is null / unreadable / versionless. */
119
48
  function resolveToolVersion(packageJsonPath) {
120
49
  if (packageJsonPath === null)
121
50
  return "unknown";
@@ -127,7 +56,6 @@ function resolveToolVersion(packageJsonPath) {
127
56
  return "unknown";
128
57
  }
129
58
  }
130
- /** Walk up from a dir to the nearest package.json, or null when the filesystem root is reached. */
131
59
  function findPackageJson(fromDir) {
132
60
  let dir = fromDir;
133
61
  for (;;) {
@@ -144,22 +72,6 @@ function findPackageJson(fromDir) {
144
72
  }
145
73
  }
146
74
  }
147
- /**
148
- * Resolve the TARGET repo root — the root the recorded input paths (`presentInputs`)
149
- * and the evidence-observation locators (`countRuntimeEvidenceObservationKinds`) are both made
150
- * portable against (@SCN-RPT-016). The bug it fixes: the prior CLI relativized
151
- * against `process.cwd()` — the TOOL's own repo — so a cross-repo reconcile
152
- * (cwd ≠ target) kept the target's absolute paths (they aren't under cwd → the
153
- * "absolute-not-under-root" branch of `relativizeToRoot` → leaked verbatim).
154
- *
155
- * The rule (mirrors `resolveSourceSha`'s targetDir derivation): the root is derived from
156
- * the TARGET, never the run cwd — the git top-level of `dirname(--features)` when the
157
- * target is a git repo (the robust case: `--features` may sit in a nested dir), else
158
- * `dirname(--features)` itself (a non-git target — a zip / extracted tree), else
159
- * `process.cwd()` for a self-reconcile with no `--features` (the legacy cwd = target
160
- * assumption, preserved as the fallback). A READ-ONLY `git -C … rev-parse --show-toplevel`
161
- * (read-only-target-safe); any throw falls back to `dirname(--features)`.
162
- */
163
75
  export function resolveTargetRoot(opts) {
164
76
  if (opts.features === undefined || opts.features.trim() === "") {
165
77
  return process.cwd();
@@ -1 +1 @@
1
- {"version":3,"file":"resolveRunInputs.js","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveRunInputs.js","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,gBAAgB,CAAC,IAAgD;IAC/E,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;YACtE,CAAC,CAAC,IAAI,CAAC,SAAS;YAChB,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE;YAChE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,mBAAmB,CAAC,OAAuD,EAAE;IAC3F,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;QACtE,CAAC,CAAC,IAAI,CAAC,OAAO;QACd,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,OAAO;QACL,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC;QAChC,WAAW,EAAE,kBAAkB,CAAC,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;KAClF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAAe;IACrC,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE;YACpE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,eAA8B;IACxD,IAAI,eAAe,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAA0B,CAAC;QACvF,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,IAAI,GAAG,GAAG,OAAO,CAAC;IAClB,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAChC,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAChC,GAAG,GAAG,MAAM,CAAC;QACf,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAA2B;IAC3D,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC/D,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;IACvB,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE;YACjF,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { type CommandSpec } from "./cli-registry.js";
2
+ import type { HostInvocation } from "./host.js";
3
+ export declare function dispatchesUnstored(inv: HostInvocation): boolean;
4
+ export declare function storedReRenderRefusal(inv: HostInvocation): string | undefined;
5
+ export declare function unstoredRunIdRefusal(inv: HostInvocation, commands?: readonly CommandSpec[]): string | undefined;
6
+ //# sourceMappingURL=storedRun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storedRun.d.ts","sourceRoot":"","sources":["../src/storedRun.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAE/D;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAU7E;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,cAAc,EACnB,QAAQ,GAAE,SAAS,WAAW,EAAyB,GACtD,MAAM,GAAG,SAAS,CASpB"}
@@ -0,0 +1,28 @@
1
+ import { asksForHelp } from "./cli-args.js";
2
+ import { cliRegistry } from "./cli-registry.js";
3
+ export function dispatchesUnstored(inv) {
4
+ return inv.store === undefined || asksForHelp(inv.commandArgs);
5
+ }
6
+ export function storedReRenderRefusal(inv) {
7
+ if (inv.command !== "balance" || asksForHelp(inv.commandArgs))
8
+ return undefined;
9
+ if (!inv.commandArgs.includes("--render-from-json"))
10
+ return undefined;
11
+ const given = [inv.store === undefined ? [] : ["--store"], inv.runId === undefined ? [] : ["--run-id"]].flat();
12
+ if (given.length === 0)
13
+ return undefined;
14
+ return (`spec-controller: usage error — 'balance --render-from-json' re-renders a saved report to stdout and keeps no run, ` +
15
+ `and was given ${given.join(", ")}: a re-render is not stored.\n` +
16
+ `Run 'spec-controller balance --render-from-json <path>' without ${given.length === 1 ? "it" : "them"}.`);
17
+ }
18
+ export function unstoredRunIdRefusal(inv, commands = cliRegistry.commands) {
19
+ if (inv.runId === undefined || inv.store !== undefined || asksForHelp(inv.commandArgs))
20
+ return undefined;
21
+ const entry = commands.find((command) => command.name === inv.command);
22
+ if (entry === undefined || entry.acceptsHostModifiers === false)
23
+ return undefined;
24
+ return (`spec-controller: usage error — --run-id names a stored run, and was given '${inv.runId}' with no --store, ` +
25
+ `so no run is kept under it.\n` +
26
+ `To keep the run under that name, give --store <root> as well; otherwise run '${entry.name}' without --run-id.`);
27
+ }
28
+ //# sourceMappingURL=storedRun.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storedRun.js","sourceRoot":"","sources":["../src/storedRun.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAC;AAGlE,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IACpD,OAAO,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAmB;IACvD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAC;IAChF,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/G,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACzC,OAAO,CACL,oHAAoH;QACpH,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gCAAgC;QACjE,mEAAmE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CACzG,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,GAAmB,EACnB,WAAmC,WAAW,CAAC,QAAQ;IAEvD,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,SAAS,CAAC;IACzG,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;IACvE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,oBAAoB,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IAClF,OAAO,CACL,8EAA8E,GAAG,CAAC,KAAK,qBAAqB;QAC5G,+BAA+B;QAC/B,gFAAgF,KAAK,CAAC,IAAI,qBAAqB,CAChH,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-controller",
3
- "version": "0.1.0-alpha.5",
3
+ "version": "0.1.0-alpha.51",
4
4
  "description": "Reconcile the behaviour your scenarios name against the evidence that actually ran — the deterministic `balance` CLI.",
5
5
  "keywords": [
6
6
  "reconciliation",
@@ -25,7 +25,7 @@
25
25
  "@cucumber/gherkin": "^41.0.0",
26
26
  "@cucumber/messages": "^34.0.1",
27
27
  "yaml": "^2.9.0",
28
- "@3f-consulting/spec-controller-core": "0.1.0-alpha.5"
28
+ "@3f-consulting/spec-controller-core": "0.1.0-alpha.51"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"