spec-controller 0.1.0-alpha.3 → 0.1.0-alpha.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -5
- package/dist/cli-allocate/cli.d.ts +2 -0
- package/dist/cli-allocate/cli.d.ts.map +1 -0
- package/dist/cli-allocate/cli.js +45 -0
- package/dist/cli-allocate/cli.js.map +1 -0
- package/dist/cli-allocate/readHistory.d.ts +21 -0
- package/dist/cli-allocate/readHistory.d.ts.map +1 -0
- package/dist/cli-allocate/readHistory.js +97 -0
- package/dist/cli-allocate/readHistory.js.map +1 -0
- package/dist/cli-allocate/readParts.d.ts +3 -0
- package/dist/cli-allocate/readParts.d.ts.map +1 -0
- package/dist/cli-allocate/readParts.js +25 -0
- package/dist/cli-allocate/readParts.js.map +1 -0
- package/dist/cli-allocate/readTree.d.ts +17 -0
- package/dist/cli-allocate/readTree.d.ts.map +1 -0
- package/dist/cli-allocate/readTree.js +63 -0
- package/dist/cli-allocate/readTree.js.map +1 -0
- package/dist/cli-allocate/request.d.ts +11 -0
- package/dist/cli-allocate/request.d.ts.map +1 -0
- package/dist/cli-allocate/request.js +29 -0
- package/dist/cli-allocate/request.js.map +1 -0
- package/dist/cli-allocate/stderr.d.ts +14 -0
- package/dist/cli-allocate/stderr.d.ts.map +1 -0
- package/dist/cli-allocate/stderr.js +33 -0
- package/dist/cli-allocate/stderr.js.map +1 -0
- package/dist/cli-args.d.ts +70 -14
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +239 -18
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-balance/cli.d.ts +18 -1
- package/dist/cli-balance/cli.d.ts.map +1 -1
- package/dist/cli-balance/cli.js +185 -161
- package/dist/cli-balance/cli.js.map +1 -1
- package/dist/cli-balance/emit/writer.d.ts +8 -23
- package/dist/cli-balance/emit/writer.d.ts.map +1 -1
- package/dist/cli-balance/emit/writer.js +24 -32
- package/dist/cli-balance/emit/writer.js.map +1 -1
- package/dist/cli-registry.d.ts +28 -0
- package/dist/cli-registry.d.ts.map +1 -1
- package/dist/cli-registry.js +39 -34
- package/dist/cli-registry.js.map +1 -1
- package/dist/cli.d.ts +4 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +26 -12
- package/dist/cli.js.map +1 -1
- package/dist/deferralTags.d.ts +2 -2
- package/dist/deferralTags.js +2 -2
- package/dist/host.d.ts +25 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +119 -15
- package/dist/host.js.map +1 -1
- package/dist/ingest/gherkinValidation.d.ts +9 -12
- package/dist/ingest/gherkinValidation.d.ts.map +1 -1
- package/dist/ingest/gherkinValidation.js +9 -12
- package/dist/ingest/gherkinValidation.js.map +1 -1
- package/dist/ingest/ingestQualityChecks.d.ts +3 -49
- package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
- package/dist/ingest/ingestQualityChecks.js +27 -120
- package/dist/ingest/ingestQualityChecks.js.map +1 -1
- package/dist/ingest/ingestScenarios.d.ts +8 -14
- package/dist/ingest/ingestScenarios.d.ts.map +1 -1
- package/dist/ingest/ingestScenarios.js +32 -55
- package/dist/ingest/ingestScenarios.js.map +1 -1
- package/dist/outputLocation.d.ts +15 -0
- package/dist/outputLocation.d.ts.map +1 -0
- package/dist/outputLocation.js +39 -0
- package/dist/outputLocation.js.map +1 -0
- package/dist/run-management/keptRun.d.ts +14 -19
- package/dist/run-management/keptRun.d.ts.map +1 -1
- package/dist/run-management/keptRun.js +15 -20
- package/dist/run-management/keptRun.js.map +1 -1
- package/package.json +2 -7
- package/dist/corpus/cli.d.ts +0 -34
- package/dist/corpus/cli.d.ts.map +0 -1
- package/dist/corpus/cli.js +0 -128
- package/dist/corpus/cli.js.map +0 -1
- package/dist/mutation-ratchet/index.d.ts +0 -46
- package/dist/mutation-ratchet/index.d.ts.map +0 -1
- package/dist/mutation-ratchet/index.js +0 -46
- package/dist/mutation-ratchet/index.js.map +0 -1
- package/dist/mutation-ratchet/record.d.ts +0 -178
- package/dist/mutation-ratchet/record.d.ts.map +0 -1
- package/dist/mutation-ratchet/record.js +0 -314
- package/dist/mutation-ratchet/record.js.map +0 -1
- package/dist/mutation-ratchet/report.d.ts +0 -109
- package/dist/mutation-ratchet/report.d.ts.map +0 -1
- package/dist/mutation-ratchet/report.js +0 -156
- package/dist/mutation-ratchet/report.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestQualityChecks.js","sourceRoot":"","sources":["../../src/ingest/ingestQualityChecks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"ingestQualityChecks.js","sourceRoot":"","sources":["../../src/ingest/ingestQualityChecks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ingest the target's feature files — the IMPURE reader that walks features/ on disk
|
|
3
|
-
* and
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
3
|
+
* and reads each file's header code into DiscoveredFeature records (split out of the old
|
|
4
|
+
* spec/featureCodes.ts). The pure header parser (extractFeatureCode) lives here with its sole
|
|
5
|
+
* consumer; the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
7
6
|
* featureCode.ts); the duplicate-code lint is engine-side too since 3F-3313, as @SCN-STG-010 in
|
|
8
|
-
* parse/
|
|
7
|
+
* parse/scenarioCodeErrors.ts, and no longer a private check under tests/checks/.
|
|
8
|
+
*
|
|
9
|
+
* NO PER-FILE LIST OF SCENARIO CODES (3F-3636). One used to ride here, read by a copy of the
|
|
10
|
+
* @SCN grammar of its own, and nothing but its own test read it; a scenario's code is read by the
|
|
11
|
+
* engine's scenario walk, which is the reading the ledger's accounts are minted from.
|
|
9
12
|
*
|
|
10
13
|
* The foundation, folded into the @LDG runtime spine.
|
|
11
14
|
*/
|
|
@@ -16,8 +19,6 @@ export interface DiscoveredFeature {
|
|
|
16
19
|
/** Absolute path to the feature file. */
|
|
17
20
|
path: string;
|
|
18
21
|
featureCode: string | null;
|
|
19
|
-
/** Every @SCN-<FFF>-<NNN> scenario code in the file, in order, duplicates kept. */
|
|
20
|
-
scenarioCodes: string[];
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* Read the Feature-level @<FFF> header tag from a feature file's source — the
|
|
@@ -25,13 +26,6 @@ export interface DiscoveredFeature {
|
|
|
25
26
|
* or a recognised evidence/routing tag. Returns null if absent.
|
|
26
27
|
*/
|
|
27
28
|
export declare function extractFeatureCode(source: string): string | null;
|
|
28
|
-
/**
|
|
29
|
-
* Parse every @SCN-<FFF>-<NNN> scenario code in a feature file's source, in
|
|
30
|
-
* document order, duplicates preserved. Only genuine TAG LINES are scanned (a
|
|
31
|
-
* line whose first non-blank character is `@` and whose every whitespace-
|
|
32
|
-
* separated token is a tag) — prose that merely mentions a code is skipped.
|
|
33
|
-
*/
|
|
34
|
-
export declare function parseScenarioCodes(source: string): string[];
|
|
35
29
|
/**
|
|
36
30
|
* Discover every feature file on disk and its header code — REFUSING a corpus the Gherkin
|
|
37
31
|
* parser rejects (@SCN-GPG-001, 3F-2817).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestScenarios.d.ts","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingestScenarios.d.ts","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKhE;AA8DD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAsB,GAAG,iBAAiB,EAAE,CAiBjF"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ingest the target's feature files — the IMPURE reader that walks features/ on disk
|
|
3
|
-
* and
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
3
|
+
* and reads each file's header code into DiscoveredFeature records (split out of the old
|
|
4
|
+
* spec/featureCodes.ts). The pure header parser (extractFeatureCode) lives here with its sole
|
|
5
|
+
* consumer; the `scnId → feature-code` grammar helper is engine-side (packages/core/src/lib/
|
|
7
6
|
* featureCode.ts); the duplicate-code lint is engine-side too since 3F-3313, as @SCN-STG-010 in
|
|
8
|
-
* parse/
|
|
7
|
+
* parse/scenarioCodeErrors.ts, and no longer a private check under tests/checks/.
|
|
8
|
+
*
|
|
9
|
+
* NO PER-FILE LIST OF SCENARIO CODES (3F-3636). One used to ride here, read by a copy of the
|
|
10
|
+
* @SCN grammar of its own, and nothing but its own test read it; a scenario's code is read by the
|
|
11
|
+
* engine's scenario walk, which is the reading the ledger's accounts are minted from.
|
|
9
12
|
*
|
|
10
13
|
* The foundation, folded into the @LDG runtime spine.
|
|
11
14
|
*/
|
|
@@ -21,56 +24,32 @@ const CODE_PATTERN = /^[A-Z0-9]{2,5}$/;
|
|
|
21
24
|
*/
|
|
22
25
|
export function extractFeatureCode(source) {
|
|
23
26
|
const lines = source.split(/\r?\n/);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
break;
|
|
35
|
-
const tags = prev.split(/\s+/).filter((t) => t.startsWith("@"));
|
|
36
|
-
for (const tag of tags) {
|
|
37
|
-
const bare = tag.slice(1);
|
|
38
|
-
if (bare.startsWith("SCN-"))
|
|
39
|
-
continue;
|
|
40
|
-
if (["unit", "integration", "e2e", "performance", "smoke"].includes(bare))
|
|
41
|
-
continue;
|
|
42
|
-
if (CODE_PATTERN.test(bare))
|
|
43
|
-
return bare;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
27
|
+
const featureLine = lines.findIndex((line) => line.trim().startsWith("Feature:"));
|
|
28
|
+
if (featureLine < 0)
|
|
29
|
+
return null;
|
|
30
|
+
return headerTagsAbove(lines, featureLine).find(isHeaderCode) ?? null;
|
|
31
|
+
}
|
|
32
|
+
/** The tags a tier or routing concern owns, which are never a file's header code. */
|
|
33
|
+
const NON_CODE_TAGS = ["unit", "integration", "e2e", "performance", "smoke"];
|
|
34
|
+
/** Is this bare tag the file's header code — not an @SCN id, not a tier tag, and code-shaped? */
|
|
35
|
+
function isHeaderCode(bare) {
|
|
36
|
+
return !bare.startsWith("SCN-") && !NON_CODE_TAGS.includes(bare) && CODE_PATTERN.test(bare);
|
|
50
37
|
}
|
|
51
38
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* line whose first non-blank character is `@` and whose every whitespace-
|
|
55
|
-
* separated token is a tag) — prose that merely mentions a code is skipped.
|
|
39
|
+
* The bare tags on the tag lines directly above the `Feature:` line, nearest line first and each
|
|
40
|
+
* line left to right. Blank lines are passed over; the first line that is not a tag line ends it.
|
|
56
41
|
*/
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!line.startsWith("@"))
|
|
63
|
-
continue;
|
|
64
|
-
const tokens = line.split(/\s+/);
|
|
65
|
-
if (!tokens.every((t) => t.startsWith("@")))
|
|
42
|
+
function headerTagsAbove(lines, featureLine) {
|
|
43
|
+
const tags = [];
|
|
44
|
+
for (let j = featureLine - 1; j >= 0; j--) {
|
|
45
|
+
const prev = lines[j].trim();
|
|
46
|
+
if (prev === "")
|
|
66
47
|
continue;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
codes.push(bare);
|
|
71
|
-
}
|
|
48
|
+
if (!prev.startsWith("@"))
|
|
49
|
+
break;
|
|
50
|
+
tags.push(...prev.split(/\s+/).filter((t) => t.startsWith("@")).map((t) => t.slice(1)));
|
|
72
51
|
}
|
|
73
|
-
return
|
|
52
|
+
return tags;
|
|
74
53
|
}
|
|
75
54
|
/**
|
|
76
55
|
* Locate the default features/ directory — `./features` under the current
|
|
@@ -88,10 +67,9 @@ function featuresDir() {
|
|
|
88
67
|
*
|
|
89
68
|
* Absence stays a REFUSAL AT THE READER — what changed is that it is typed, so a caller can decide.
|
|
90
69
|
* `balance` opts in to reporting on a target that has no corpus (most targets have no `features/`
|
|
91
|
-
* at all, and `new-client` is a supported adoption state)
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* into `tags: OK …` at exit 0.
|
|
70
|
+
* at all, and `new-client` is a supported adoption state) by catching `MissingFeatureCorpusError` by
|
|
71
|
+
* name. Returning `[]` here instead would make that decision for every caller, and one that
|
|
72
|
+
* certifies a corpus would certify an absent one as empty.
|
|
95
73
|
*
|
|
96
74
|
* ONLY `ENOENT`. A `features` path that exists but is a FILE, or one the process may not read, is
|
|
97
75
|
* a different fault and is not ours to reinterpret — it rethrows.
|
|
@@ -142,7 +120,6 @@ export function discoverFeatures(dir = featuresDir()) {
|
|
|
142
120
|
slug: name.replace(/\.feature$/, ""),
|
|
143
121
|
path,
|
|
144
122
|
featureCode: extractFeatureCode(source),
|
|
145
|
-
scenarioCodes: parseScenarioCodes(source),
|
|
146
123
|
}));
|
|
147
124
|
}
|
|
148
125
|
//# sourceMappingURL=ingestScenarios.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingestScenarios.js","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ingestScenarios.js","sourceRoot":"","sources":["../../src/ingest/ingestScenarios.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function unwritableRefusal(subject: string, path: string, err: unknown): string;
|
|
2
|
+
/**
|
|
3
|
+
* The catch sits on the one write it guards rather than on the process, so a refusal can only ever
|
|
4
|
+
* name a location this call was asked to write, and a crash anywhere else is not dressed up as one.
|
|
5
|
+
*/
|
|
6
|
+
export declare function writeOrRefuse(subject: string, path: string, write: () => void): void;
|
|
7
|
+
/**
|
|
8
|
+
* Throws the operating system's own error when `path` cannot be written as a file, and leaves the
|
|
9
|
+
* path as it found it: an existing file is opened write-only without truncation (not "r+", which
|
|
10
|
+
* would also demand read permission), and an absent one is created exclusively and removed again,
|
|
11
|
+
* so a missing, read-only or non-directory parent answers with its real reason instead of one this
|
|
12
|
+
* module would have to invent.
|
|
13
|
+
*/
|
|
14
|
+
export declare function probeWritable(path: string): void;
|
|
15
|
+
//# sourceMappingURL=outputLocation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outputLocation.d.ts","sourceRoot":"","sources":["../src/outputLocation.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAGrF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAOpF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAShD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { closeSync, constants, openSync, unlinkSync } from "node:fs";
|
|
2
|
+
const USAGE_EXIT_CODE = 2;
|
|
3
|
+
export function unwritableRefusal(subject, path, err) {
|
|
4
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
5
|
+
return `${subject}: ${path} (${reason})`;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The catch sits on the one write it guards rather than on the process, so a refusal can only ever
|
|
9
|
+
* name a location this call was asked to write, and a crash anywhere else is not dressed up as one.
|
|
10
|
+
*/
|
|
11
|
+
export function writeOrRefuse(subject, path, write) {
|
|
12
|
+
try {
|
|
13
|
+
write();
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
process.stderr.write(unwritableRefusal(subject, path, err) + "\n");
|
|
17
|
+
process.exit(USAGE_EXIT_CODE);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Throws the operating system's own error when `path` cannot be written as a file, and leaves the
|
|
22
|
+
* path as it found it: an existing file is opened write-only without truncation (not "r+", which
|
|
23
|
+
* would also demand read permission), and an absent one is created exclusively and removed again,
|
|
24
|
+
* so a missing, read-only or non-directory parent answers with its real reason instead of one this
|
|
25
|
+
* module would have to invent.
|
|
26
|
+
*/
|
|
27
|
+
export function probeWritable(path) {
|
|
28
|
+
try {
|
|
29
|
+
closeSync(openSync(path, constants.O_WRONLY));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
if (err.code !== "ENOENT")
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
closeSync(openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL));
|
|
37
|
+
unlinkSync(path);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=outputLocation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outputLocation.js","sourceRoot":"","sources":["../src/outputLocation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErE,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAY,EAAE,GAAY;IAC3E,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChE,OAAO,GAAG,OAAO,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,IAAY,EAAE,KAAiB;IAC5E,IAAI,CAAC;QACH,KAAK,EAAE,CAAC;IACV,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;IAClE,CAAC;IACD,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACrF,UAAU,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -15,24 +15,20 @@
|
|
|
15
15
|
* files under a temp root + the repo untouched — never a planner re-run).
|
|
16
16
|
*
|
|
17
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).
|
|
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.
|
|
18
|
+
* location-agnostic (proven against a temp root; the repo is never written).
|
|
23
19
|
*/
|
|
24
20
|
/** The two artefact filenames a kept run routes the tool's outputs into. */
|
|
25
21
|
export declare const RECONCILIATION_DOCUMENT = "spec-reconciliation.md";
|
|
26
22
|
/**
|
|
27
|
-
* The machine artefact filename
|
|
23
|
+
* The machine artefact filename — renamed `ledger.json` →
|
|
28
24
|
* `spec-reconciliation.json` (parity with `spec-reconciliation.md`): it is the machine form
|
|
29
25
|
* of the WHOLE reconciliation document, not just the ledger.
|
|
30
26
|
*/
|
|
31
27
|
export declare const RECONCILIATION_JSON = "spec-reconciliation.json";
|
|
32
|
-
/** The manifest filename a kept run stamps in the run dir
|
|
28
|
+
/** The manifest filename a kept run stamps in the run dir. */
|
|
33
29
|
export declare const RUN_MANIFEST = "run.yaml";
|
|
34
30
|
/**
|
|
35
|
-
* The run.yaml schema version this scaffold stamps. Bumped 1 → 2
|
|
31
|
+
* The run.yaml schema version this scaffold stamps. Bumped 1 → 2 when it added
|
|
36
32
|
* the tool identity (`tool_sha` / `tool_version`) — so a reader can tell a run that
|
|
37
33
|
* predates tool-identity recording (schema 1) from one that should carry it (schema 2).
|
|
38
34
|
* run.yaml is write-only (no production reader), so the bump breaks no read path.
|
|
@@ -47,7 +43,7 @@ export type RunMode = "balance" | "analyse" | "migrate";
|
|
|
47
43
|
export interface RunManifestMeta {
|
|
48
44
|
readonly sourceSha: string;
|
|
49
45
|
/**
|
|
50
|
-
* The TOOL's own git SHA — which spec-controller produced this run
|
|
46
|
+
* The TOOL's own git SHA — which spec-controller produced this run, distinct
|
|
51
47
|
* from the target's `sourceSha`. A string ("unknown" when the tool is not a git
|
|
52
48
|
* checkout), mirroring `sourceSha`'s own "unknown" fallback — so run.yaml is internally
|
|
53
49
|
* consistent (both facts use the same absent-marker, never a bare null).
|
|
@@ -73,7 +69,7 @@ export interface RunManifest {
|
|
|
73
69
|
readonly run_id: string;
|
|
74
70
|
readonly target: string;
|
|
75
71
|
readonly source_sha: string;
|
|
76
|
-
/** The TOOL's identity
|
|
72
|
+
/** The TOOL's identity — which spec-controller produced the run. */
|
|
77
73
|
readonly tool_sha: string;
|
|
78
74
|
readonly tool_version: string;
|
|
79
75
|
readonly mode: RunMode;
|
|
@@ -112,7 +108,7 @@ export type RouteOutputs = (formatSpecs: readonly string[]) => void;
|
|
|
112
108
|
*/
|
|
113
109
|
export declare function planKeptRun(spec: KeptRunSpec): KeptRunPlan;
|
|
114
110
|
/**
|
|
115
|
-
* Options for the pure run-id resolver
|
|
111
|
+
* Options for the pure run-id resolver: the operator's OPTIONAL `--run-id` mnemonic
|
|
116
112
|
* and the INJECTED clock instant the default timestamp derives from.
|
|
117
113
|
*/
|
|
118
114
|
export interface ResolveRunIdOptions {
|
|
@@ -129,14 +125,14 @@ export interface ResolveRunIdOptions {
|
|
|
129
125
|
* run-id naming the run dir (feeds `KeptRunSpec.runId`). No `--run-id` → an ISO-8601 UTC
|
|
130
126
|
* timestamp derived from the INJECTED `now` (filesystem-safe: no colons, no millis — matching
|
|
131
127
|
* 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
|
|
128
|
+
* — an earlier precedent), which ignores the clock. No IO — proven `@unit`.
|
|
133
129
|
* The clock is injected (never a bare `new Date()`) so the default timestamp is deterministic
|
|
134
130
|
* under test (the discipline the old `formatRunTimestamp` used). Just default-vs-override — no
|
|
135
131
|
* sanitisation / collision policy (deferred).
|
|
136
132
|
*/
|
|
137
133
|
export declare function resolveRunId(options: ResolveRunIdOptions): string;
|
|
138
134
|
/**
|
|
139
|
-
* PURE: build the run.yaml manifest object from the run metadata
|
|
135
|
+
* PURE: build the run.yaml manifest object from the run metadata. `purpose` and
|
|
140
136
|
* `links` are stamped EMPTY (the ad-hoc default; slugs are added by operator hand-edit of
|
|
141
137
|
* run.yaml afterward — the documented curation convention); `artefacts` carry the decided
|
|
142
138
|
* filenames. No IO — proven `@unit`.
|
|
@@ -145,12 +141,11 @@ export declare function planRunManifest(input: RunManifestInput): RunManifest;
|
|
|
145
141
|
/** PURE: serialise the manifest to YAML text the impure runner writes verbatim. */
|
|
146
142
|
export declare function serialiseRunManifest(manifest: RunManifest): string;
|
|
147
143
|
/**
|
|
148
|
-
* IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
* creates the dir the location-agnostic tool writes into.
|
|
144
|
+
* IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two files
|
|
145
|
+
* via the injected `route` — the document as `md:<documentPath>`, the reconciliation JSON as
|
|
146
|
+
* `json:<reconciliationJsonPath>` — and stamp `run.yaml` from the spec + `meta`. Returns the
|
|
147
|
+
* plan it realised. The `mkdir` is load-bearing: the tool's writer creates no directories, so the
|
|
148
|
+
* scaffold creates the one the location-agnostic tool writes into.
|
|
154
149
|
*/
|
|
155
150
|
export declare function executeKeptRun(spec: KeptRunSpec, meta: RunManifestMeta, route: RouteOutputs): KeptRunPlan;
|
|
156
151
|
//# sourceMappingURL=keptRun.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keptRun.d.ts","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"keptRun.d.ts","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,2BAA2B,CAAC;AAChE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,6BAA6B,CAAC;AAE9D,8DAA8D;AAC9D,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,8CAA8C;AAC9C,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,6FAA6F;AAC7F,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,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,oEAAoE;IACpE,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,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,2EAA2E;AAC3E,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;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;AAEpE;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAO1D;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAOjE;AAYD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAmBpE;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAElE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,eAAe,EACrB,KAAK,EAAE,YAAY,GAClB,WAAW,CAYb"}
|
|
@@ -15,27 +15,24 @@
|
|
|
15
15
|
* files under a temp root + the repo untouched — never a planner re-run).
|
|
16
16
|
*
|
|
17
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).
|
|
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.
|
|
18
|
+
* location-agnostic (proven against a temp root; the repo is never written).
|
|
23
19
|
*/
|
|
24
20
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
25
21
|
import { join } from "node:path";
|
|
26
22
|
import { stringify } from "yaml";
|
|
23
|
+
import { writeOrRefuse } from "../outputLocation.js";
|
|
27
24
|
/** The two artefact filenames a kept run routes the tool's outputs into. */
|
|
28
25
|
export const RECONCILIATION_DOCUMENT = "spec-reconciliation.md";
|
|
29
26
|
/**
|
|
30
|
-
* The machine artefact filename
|
|
27
|
+
* The machine artefact filename — renamed `ledger.json` →
|
|
31
28
|
* `spec-reconciliation.json` (parity with `spec-reconciliation.md`): it is the machine form
|
|
32
29
|
* of the WHOLE reconciliation document, not just the ledger.
|
|
33
30
|
*/
|
|
34
31
|
export const RECONCILIATION_JSON = "spec-reconciliation.json";
|
|
35
|
-
/** The manifest filename a kept run stamps in the run dir
|
|
32
|
+
/** The manifest filename a kept run stamps in the run dir. */
|
|
36
33
|
export const RUN_MANIFEST = "run.yaml";
|
|
37
34
|
/**
|
|
38
|
-
* The run.yaml schema version this scaffold stamps. Bumped 1 → 2
|
|
35
|
+
* The run.yaml schema version this scaffold stamps. Bumped 1 → 2 when it added
|
|
39
36
|
* the tool identity (`tool_sha` / `tool_version`) — so a reader can tell a run that
|
|
40
37
|
* predates tool-identity recording (schema 1) from one that should carry it (schema 2).
|
|
41
38
|
* run.yaml is write-only (no production reader), so the bump breaks no read path.
|
|
@@ -60,7 +57,7 @@ export function planKeptRun(spec) {
|
|
|
60
57
|
* run-id naming the run dir (feeds `KeptRunSpec.runId`). No `--run-id` → an ISO-8601 UTC
|
|
61
58
|
* timestamp derived from the INJECTED `now` (filesystem-safe: no colons, no millis — matching
|
|
62
59
|
* 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
|
|
60
|
+
* — an earlier precedent), which ignores the clock. No IO — proven `@unit`.
|
|
64
61
|
* The clock is injected (never a bare `new Date()`) so the default timestamp is deterministic
|
|
65
62
|
* under test (the discipline the old `formatRunTimestamp` used). Just default-vs-override — no
|
|
66
63
|
* sanitisation / collision policy (deferred).
|
|
@@ -83,7 +80,7 @@ function formatRunTimestamp(instant) {
|
|
|
83
80
|
return instant.toISOString().replace(/\.\d+Z$/, "Z").replace(/:/g, "-");
|
|
84
81
|
}
|
|
85
82
|
/**
|
|
86
|
-
* PURE: build the run.yaml manifest object from the run metadata
|
|
83
|
+
* PURE: build the run.yaml manifest object from the run metadata. `purpose` and
|
|
87
84
|
* `links` are stamped EMPTY (the ad-hoc default; slugs are added by operator hand-edit of
|
|
88
85
|
* run.yaml afterward — the documented curation convention); `artefacts` carry the decided
|
|
89
86
|
* filenames. No IO — proven `@unit`.
|
|
@@ -113,21 +110,19 @@ export function serialiseRunManifest(manifest) {
|
|
|
113
110
|
return stringify(manifest);
|
|
114
111
|
}
|
|
115
112
|
/**
|
|
116
|
-
* IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* creates the dir the location-agnostic tool writes into.
|
|
113
|
+
* IMPURE runner: `mkdir -p` the run dir, route the tool's `--format` outputs into the two files
|
|
114
|
+
* via the injected `route` — the document as `md:<documentPath>`, the reconciliation JSON as
|
|
115
|
+
* `json:<reconciliationJsonPath>` — and stamp `run.yaml` from the spec + `meta`. Returns the
|
|
116
|
+
* plan it realised. The `mkdir` is load-bearing: the tool's writer creates no directories, so the
|
|
117
|
+
* scaffold creates the one the location-agnostic tool writes into.
|
|
122
118
|
*/
|
|
123
119
|
export function executeKeptRun(spec, meta, route) {
|
|
124
120
|
const plan = planKeptRun(spec);
|
|
125
|
-
mkdirSync(plan.runDir, { recursive: true });
|
|
121
|
+
writeOrRefuse("The stored run's directory could not be created", plan.runDir, () => mkdirSync(plan.runDir, { recursive: true }));
|
|
126
122
|
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.
|
|
129
123
|
const manifest = planRunManifest({ runId: spec.runId, target: spec.target, ...meta });
|
|
130
|
-
|
|
124
|
+
const manifestPath = join(plan.runDir, RUN_MANIFEST);
|
|
125
|
+
writeOrRefuse("The stored run's run.yaml could not be written", manifestPath, () => writeFileSync(manifestPath, serialiseRunManifest(manifest)));
|
|
131
126
|
return plan;
|
|
132
127
|
}
|
|
133
128
|
//# sourceMappingURL=keptRun.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keptRun.js","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"keptRun.js","sourceRoot":"","sources":["../../src/run-management/keptRun.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAChE;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,0BAA0B,CAAC;AAE9D,8DAA8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AA2E7C;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAiB;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,OAAO;QACL,MAAM;QACN,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,uBAAuB,CAAC;QACnD,sBAAsB,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC;KAC1D,CAAC;AACJ,CAAC;AAgBD;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,OAA4B;IACvD,wFAAwF;IACxF,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC;IACD,wFAAwF;IACxF,OAAO,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,OAAa;IACvC,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAuB;IACrD,OAAO;QACL,cAAc,EAAE,2BAA2B;QAC3C,MAAM,EAAE,KAAK,CAAC,KAAK;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,SAAS;QAC3B,QAAQ,EAAE,KAAK,CAAC,OAAO;QACvB,YAAY,EAAE,KAAK,CAAC,WAAW;QAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,kFAAkF;QAClF,gFAAgF;QAChF,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,EAAE;QACT,SAAS,EAAE;YACT,QAAQ,EAAE,uBAAuB;YACjC,cAAc,EAAE,mBAAmB;SACpC;KACF,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,oBAAoB,CAAC,QAAqB;IACxD,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAiB,EACjB,IAAqB,EACrB,KAAmB;IAEnB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,aAAa,CAAC,iDAAiD,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CACjF,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAC5C,CAAC;IACF,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;IACtF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrD,aAAa,CAAC,gDAAgD,EAAE,YAAY,EAAE,GAAG,EAAE,CACjF,aAAa,CAAC,YAAY,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAC5D,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-controller",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.31",
|
|
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",
|
|
@@ -10,11 +10,6 @@
|
|
|
10
10
|
"double-entry",
|
|
11
11
|
"cli"
|
|
12
12
|
],
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/3f-consulting/spec-controller.git",
|
|
16
|
-
"directory": "packages/spec-controller"
|
|
17
|
-
},
|
|
18
13
|
"license": "MIT",
|
|
19
14
|
"type": "module",
|
|
20
15
|
"engines": {
|
|
@@ -30,7 +25,7 @@
|
|
|
30
25
|
"@cucumber/gherkin": "^41.0.0",
|
|
31
26
|
"@cucumber/messages": "^34.0.1",
|
|
32
27
|
"yaml": "^2.9.0",
|
|
33
|
-
"@3f-consulting/spec-controller-core": "0.1.0-alpha.
|
|
28
|
+
"@3f-consulting/spec-controller-core": "0.1.0-alpha.31"
|
|
34
29
|
},
|
|
35
30
|
"publishConfig": {
|
|
36
31
|
"access": "public"
|
package/dist/corpus/cli.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
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
|
package/dist/corpus/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|