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
package/README.md CHANGED
@@ -11,15 +11,17 @@ Requires Node ≥ 22. ESM only.
11
11
  ## Install
12
12
 
13
13
  ```
14
- npm install -g spec-controller
14
+ npm install -g spec-controller@alpha
15
15
  ```
16
16
 
17
17
  Or without installing anything:
18
18
 
19
19
  ```
20
- npx spec-controller balance --help
20
+ npx spec-controller@alpha balance --help
21
21
  ```
22
22
 
23
+ `@alpha` is not optional until `0.1.0` publishes: a bare install resolves `latest`, which npm set to `0.1.0-alpha.1` on the first publish, and that version has no `--ci-steps` and no scenario code errors.
24
+
23
25
  ## Your first run
24
26
 
25
27
  Point it at your scenarios and give it nothing else:
@@ -30,6 +32,20 @@ spec-controller balance --features ./features
30
32
 
31
33
  Every scenario comes back as a row whether or not any evidence exists for it, so on this first run the ones you have supplied no reports for read **missing** and the run comes back out-of-balance. That is the shape of the tool rather than a fault in your repository: the reconciliation starts from what you specified, not from what a tool happened to find, and there is no input for which the right answer is silence.
32
34
 
35
+ **`balance` fails your build out of the box.** An out-of-balance run exits `1`, so the first run above reds any pipeline you put it in. That is a deliberate departure from two tools it sits beside: Stryker's `thresholds.break` defaults to `null` (*"never let your build fail"*), and the Sonar scanner exits `0` whatever its quality gate says unless you set `sonar.qualitygate.wait`. Both make you opt in to gating. `balance` makes you opt out.
36
+
37
+ ### Report first, gate later
38
+
39
+ To bring it into a pipeline you already have without redding it on day one, add `--exit-zero`:
40
+
41
+ ```
42
+ spec-controller balance --features ./features --vitest ./vitest-report.json --exit-zero
43
+ ```
44
+
45
+ The report is byte for byte the one the gate prints: the same rows, the same out-of-balance count, and the same headline naming the code the gate would give. Only the exit status moves. Out-of-balance and scenario code errors (`1`), and pending under `--strict` (`3`), exit `0`. Usage (`2`), unsound (`4`) and nothing to reconcile (`5`) still fail, because each means the run could not give a verdict at all, and a flag that suppresses verdicts does not suppress that.
46
+
47
+ Work the out-of-balance rows down, then delete `--exit-zero`, and the gate is on. Don't wrap the step in `continue-on-error` or `|| true` instead: those swallow the codes that mean the run could not be trusted, and they leave nothing in the command to say the gate is off.
48
+
33
49
  Now give it the evidence:
34
50
 
35
51
  ```
@@ -46,7 +62,7 @@ A scenario tagged `@unit` names an obligation — a unit test must exist and pas
46
62
  | Exit | What it says |
47
63
  | --- | --- |
48
64
  | `0` | balanced — every obligation has evidence, and it holds |
49
- | `1` | out-of-balance — the two records disagree, and the report says where |
65
+ | `1` | out-of-balance — the two records disagree, and the report says where; or a scenario code is misfiled, listed under `## Scenario code errors` |
50
66
  | `2` | usage — the invocation was wrong |
51
67
  | `3` | balanced, but carrying Pending Items, and you asked for `--strict` |
52
68
  | `4` | unsound — a proving suite failed to collect, so the ledger could not be trusted to disagree |
@@ -54,11 +70,23 @@ A scenario tagged `@unit` names an obligation — a unit test must exist and pas
54
70
 
55
71
  The whole report is written before the code is set, so a failing run still tells you why.
56
72
 
73
+ `spec-controller allocate`, which prints the next scenario code for a feature part, reaches no verdict: it exits `0` when it answers and `2` for a usage error or an unknown part. A file or directory it cannot read, whether it reads it itself or through git, is a usage error: it is refused, naming the path and the reason, and no code is given.
74
+
75
+ `--exit-zero` moves `1` and `3` to `0` and leaves every other code alone: see *Report first, gate later*.
76
+
77
+ `balance --render-from-json <saved.json>` re-renders a saved report and exits the code its verdict names, from the same table: a saved run that failed fails again when it is read back. A report saved under `--strict` records it, so its re-render exits `3` too, and `--strict` or `--exit-zero` beside the re-render work as they do live. Any other flag beside it is refused at `2`, because a re-render reads no live input and writes only to stdout.
78
+
57
79
  **Node's default is never one of these.** A run that cannot reconcile ends on an enumerated code of
58
80
  its own rather than falling out of the process — a crash that exits `1` would be indistinguishable,
59
81
  by status, from an honest disagreement. **An input the tool cannot read is part of `2`**: a mistyped
60
- path, an unparseable report or a corpus the Gherkin parser rejects are all the invocation being
61
- wrong, never a verdict about your code.
82
+ path, a path it is not permitted to read, a file where a directory belongs or the reverse, an
83
+ unparseable report, a report that parses but is not in the shape its runner writes, a saved
84
+ reconciliation it cannot render, or a corpus the Gherkin parser rejects are all the invocation
85
+ being wrong, never a verdict about your code. The refusal names the input, the path, and what was
86
+ wrong with it. A well-formed report that holds nothing, such as a Vitest run that matched no test
87
+ file, is read, not refused. **So is an output location it cannot write**: a `--format` path that is
88
+ read-only, a directory, under a regular file or in a directory that does not exist, and a
89
+ `--store` root the run directory cannot be created under, are refused at `2`, naming the location and the operating system's reason, before any report is printed.
62
90
 
63
91
  **The enumeration is open at the top, and that is the one thing to design your pipeline around.** A
64
92
  state that is genuinely none of the above gets a **new** code rather than being folded into the
@@ -83,7 +111,7 @@ spec-controller balance --features ./features \
83
111
  ## Where to go next
84
112
 
85
113
  - **Full flags, worked examples and CI wiring** — [`doc/how_to_use.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/how_to_use.md)
86
- - **Bringing a check you already have under the reconciliation** — [`doc/converting-a-fitness-check.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/converting-a-fitness-check.md)
114
+ - **Bringing a check you already have under the reconciliation** — [`doc/adopting-fitness-checks.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/adopting-fitness-checks.md)
87
115
  - **Why `0.x` promises nothing, and what changes at `1.0`** — [`doc/compatibility.md`](https://github.com/3f-consulting/spec-controller/blob/main/doc/compatibility.md)
88
116
  - **Building your own tooling on the engine instead of running a command** — [`@3f-consulting/spec-controller-core`](https://www.npmjs.com/package/@3f-consulting/spec-controller-core), the same reconciliation logic as a pure library with no CLI and no I/O.
89
117
 
@@ -0,0 +1,2 @@
1
+ export declare function runAllocate(argv: string[]): void;
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/cli.ts"],"names":[],"mappings":"AAWA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAMhD"}
@@ -0,0 +1,60 @@
1
+ import { join } from "node:path";
2
+ import { nextScnCode } from "@3f-consulting/spec-controller-core";
3
+ import { cliRegistry, renderCommandHelp } from "../cli-registry.js";
4
+ import { resolveToolIdentity } from "../run-management/resolveRunInputs.js";
5
+ import { readHeaderCodes } from "./readParts.js";
6
+ import { readRequest } from "./request.js";
7
+ import { readOrRefuse, refusalLine, UnreadableInput } from "./unreadable.js";
8
+ import { historyBoundaryOf, readHistory, repositoryTop } from "./readHistory.js";
9
+ import { readTree, walkTree } from "./readTree.js";
10
+ import { alreadyHeadedNote, highestSeenLine, historyBoundaryLine, unknownPartRefusal } from "./stderr.js";
11
+ export function runAllocate(argv) {
12
+ if (asksForHelp(argv)) {
13
+ process.stdout.write(renderCommandHelp(cliRegistry, "allocate") + "\n");
14
+ return;
15
+ }
16
+ answerOrRefuse(readRequest(argv, cliRegistry, resolveToolIdentity().toolVersion));
17
+ }
18
+ function asksForHelp(argv) {
19
+ return argv.includes("--help") || argv.includes("-h");
20
+ }
21
+ function answerOrRefuse(request) {
22
+ if ("usageError" in request) {
23
+ refuseUsage(request.usageError);
24
+ return;
25
+ }
26
+ try {
27
+ answerRequest(request);
28
+ }
29
+ catch (err) {
30
+ if (!(err instanceof UnreadableInput))
31
+ throw err;
32
+ refuseUsage(refusalLine(err));
33
+ }
34
+ }
35
+ function refuseUsage(line) {
36
+ process.stderr.write(line + "\n");
37
+ process.exitCode = 2;
38
+ }
39
+ function answerRequest({ part, isNew }) {
40
+ const cwd = readOrRefuse("the working directory", "", () => process.cwd());
41
+ const top = repositoryTop(cwd);
42
+ const headerCodes = readHeaderCodes(join(top ?? cwd, "features"));
43
+ const answer = nextScnCode({ part, headerCodes, isNew }, sightingsFrom(cwd, part, top));
44
+ if (answer.kind === "unknown-part") {
45
+ refuseUsage(unknownPartRefusal(answer));
46
+ return;
47
+ }
48
+ writeLineIfAny(historyBoundaryLine(historyBoundaryOf(cwd), answer));
49
+ process.stderr.write(highestSeenLine(answer) + "\n");
50
+ writeLineIfAny(alreadyHeadedNote(answer));
51
+ process.stdout.write(answer.code + "\n");
52
+ }
53
+ function writeLineIfAny(line) {
54
+ if (line !== null)
55
+ process.stderr.write(line + "\n");
56
+ }
57
+ function sightingsFrom(cwd, part, top) {
58
+ return top !== null ? [...readTree(top, part), ...readHistory(cwd, part)] : walkTree(cwd, part);
59
+ }
60
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli-allocate/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ScnSighting } from "@3f-consulting/spec-controller-core";
2
+ export type HistoryBoundary = {
3
+ kind: "complete";
4
+ } | {
5
+ kind: "not-a-repository";
6
+ } | {
7
+ kind: "shallow";
8
+ before: string;
9
+ };
10
+ export declare function readHistory(cwd: string, part: string): ScnSighting[];
11
+ export declare function repositoryTop(cwd: string): string | null;
12
+ export declare function isGitRepository(cwd: string): boolean;
13
+ export declare function historyBoundaryOf(cwd: string): HistoryBoundary;
14
+ export declare function diffLineSightings(logOutput: string): ScnSighting[];
15
+ //# sourceMappingURL=readHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readHistory.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/readHistory.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAIvE,MAAM,MAAM,eAAe,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMxH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAapE;AAOD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAUD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAI9D;AAuBD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAQlE"}
@@ -0,0 +1,108 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { lstatSync, readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { proveRefsReadable } from "./refStore.js";
5
+ import { readOrRefuse, refuse, UnreadableInput } from "./unreadable.js";
6
+ const MAX_OUTPUT_BYTES = 1024 * 1024 * 1024;
7
+ const COMMIT_MARKER = "\u0001";
8
+ export function readHistory(cwd, part) {
9
+ proveRefsReadable(cwd);
10
+ const result = spawnSync("git", ["log", "--all", "-p", "-U0", "--no-color", "--no-ext-diff", "--format=%x01%h", "-G", `SCN-${part}-`], { cwd, encoding: "utf8", maxBuffer: MAX_OUTPUT_BYTES });
11
+ if (result.error !== undefined)
12
+ refuse("the repository's history", cwd, result.error);
13
+ if (result.status !== 0) {
14
+ const said = result.stderr.split("\n")[0] ?? "";
15
+ throw new UnreadableInput("the repository's history", cwd, `git log exited ${result.status}: ${said}`);
16
+ }
17
+ return diffLineSightings(result.stdout);
18
+ }
19
+ function gitAnswer(cwd, args) {
20
+ const result = spawnSync("git", args, { cwd, encoding: "utf8" });
21
+ return result.status === 0 ? result.stdout.trim() : null;
22
+ }
23
+ export function repositoryTop(cwd) {
24
+ const result = spawnSync("git", ["rev-parse", "--show-toplevel"], { cwd, encoding: "utf8" });
25
+ if (result.status === 0)
26
+ return result.stdout.trim();
27
+ const gitEntry = result.error === undefined ? gitEntryAtOrAbove(cwd) : null;
28
+ if (gitEntry === null)
29
+ return null;
30
+ const said = result.stderr.split("\n")[0] ?? "";
31
+ throw new UnreadableInput("the repository", gitEntry, `git rev-parse exited ${result.status}: ${said}`);
32
+ }
33
+ function gitEntryAtOrAbove(dir) {
34
+ for (let at = dir;; at = dirname(at)) {
35
+ const entry = join(at, ".git");
36
+ if (lstatSync(entry, { throwIfNoEntry: false }) !== undefined)
37
+ return entry;
38
+ if (dirname(at) === at)
39
+ return null;
40
+ }
41
+ }
42
+ export function isGitRepository(cwd) {
43
+ return gitAnswer(cwd, ["rev-parse", "--git-dir"]) !== null;
44
+ }
45
+ export function historyBoundaryOf(cwd) {
46
+ if (!isGitRepository(cwd))
47
+ return { kind: "not-a-repository" };
48
+ if (gitAnswer(cwd, ["rev-parse", "--is-shallow-repository"]) !== "true")
49
+ return { kind: "complete" };
50
+ return shallowBoundaryOf(cwd);
51
+ }
52
+ function shallowBoundaryOf(cwd) {
53
+ const shallowPath = shallowRecordPath(cwd);
54
+ const record = readOrRefuse("the repository's history", shallowPath, () => readFileSync(shallowPath, "utf8"));
55
+ const edge = record.split("\n")[0] ?? "";
56
+ return { kind: "shallow", before: gitAnswer(cwd, ["rev-parse", "--short", edge]) ?? edge };
57
+ }
58
+ function shallowRecordPath(cwd) {
59
+ const shallowFile = gitAnswer(cwd, ["rev-parse", "--git-path", "shallow"]) ?? "";
60
+ return shallowFile.startsWith("/") ? shallowFile : `${cwd}/${shallowFile}`;
61
+ }
62
+ export function diffLineSightings(logOutput) {
63
+ const at = { inFileHeader: false, oldPath: "", newPath: "", oldLine: 0, newLine: 0 };
64
+ const sightings = [];
65
+ for (const line of logOutput.split("\n")) {
66
+ const sighting = readLine(line, at);
67
+ if (sighting !== undefined)
68
+ sightings.push(sighting);
69
+ }
70
+ return sightings;
71
+ }
72
+ function readLine(line, at) {
73
+ if (line.startsWith(COMMIT_MARKER))
74
+ at.commit = line.slice(COMMIT_MARKER.length);
75
+ else if (line.startsWith("diff --git "))
76
+ at.inFileHeader = true;
77
+ else if (at.inFileHeader)
78
+ readFileHeader(line, at);
79
+ else if (line.startsWith("-"))
80
+ return sightingAt(line, at.oldPath, at.oldLine++, at.commit);
81
+ else if (line.startsWith("+"))
82
+ return sightingAt(line, at.newPath, at.newLine++, at.commit);
83
+ else if (line.startsWith("@@ "))
84
+ readHunkHeader(line, at);
85
+ return undefined;
86
+ }
87
+ function readFileHeader(line, at) {
88
+ if (line.startsWith("--- "))
89
+ at.oldPath = pathOf(line);
90
+ else if (line.startsWith("+++ "))
91
+ at.newPath = pathOf(line);
92
+ else if (line.startsWith("@@ ")) {
93
+ at.inFileHeader = false;
94
+ readHunkHeader(line, at);
95
+ }
96
+ }
97
+ function pathOf(header) {
98
+ return header.slice(4).replace(/^[ab]\//, "");
99
+ }
100
+ function readHunkHeader(line, at) {
101
+ const match = /^@@ -(\d+)(?:,\d+)? \+(\d+)/.exec(line);
102
+ at.oldLine = Number(match?.[1] ?? 0);
103
+ at.newLine = Number(match?.[2] ?? 0);
104
+ }
105
+ function sightingAt(text, path, line, commit) {
106
+ return commit === undefined ? { text, path, line } : { text, path, line, commit };
107
+ }
108
+ //# sourceMappingURL=readHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readHistory.js","sourceRoot":"","sources":["../../src/cli-allocate/readHistory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function readHeaderCodes(featuresDir: string): string[];
2
+ //# sourceMappingURL=readParts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readParts.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/readParts.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAM7D"}
@@ -0,0 +1,22 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { extractFeatureCode } from "../ingest/ingestScenarios.js";
4
+ import { readOrRefuse, refuse } from "./unreadable.js";
5
+ export function readHeaderCodes(featuresDir) {
6
+ return featureFilesIn(featuresDir).flatMap((name) => {
7
+ const path = join(featuresDir, name);
8
+ const code = extractFeatureCode(readOrRefuse("a feature file", path, () => readFileSync(path, "utf8")));
9
+ return code === null ? [] : [code];
10
+ });
11
+ }
12
+ function featureFilesIn(dir) {
13
+ try {
14
+ return readdirSync(dir).filter((name) => name.endsWith(".feature"));
15
+ }
16
+ catch (err) {
17
+ if (err.code === "ENOENT")
18
+ return [];
19
+ return refuse("the feature corpus", dir, err);
20
+ }
21
+ }
22
+ //# sourceMappingURL=readParts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readParts.js","sourceRoot":"","sources":["../../src/cli-allocate/readParts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,kBAAkB,CAAC,YAAY,CAAC,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACxG,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QAChE,OAAO,MAAM,CAAC,oBAAoB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ScnSighting } from "@3f-consulting/spec-controller-core";
2
+ export declare function readTree(top: string, part: string): ScnSighting[];
3
+ export declare function isWalkedDirectory(name: string): boolean;
4
+ export declare function walkTree(root: string, part: string): ScnSighting[];
5
+ //# sourceMappingURL=readTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readTree.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/readTree.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAOvE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAKjE;AA8CD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAKlE"}
@@ -0,0 +1,74 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { accessSync, constants, lstatSync, readdirSync, readFileSync } from "node:fs";
3
+ import { join, relative, sep } from "node:path";
4
+ import { readOrRefuse, refuse, UnreadableInput } from "./unreadable.js";
5
+ const MAX_OUTPUT_BYTES = 1024 * 1024 * 1024;
6
+ const BINARY_PROBE_BYTES = 8000;
7
+ export function readTree(top, part) {
8
+ const listed = gitListing(top, ["ls-files", "-z", "--cached", "--others", "--exclude-standard"]);
9
+ const ignored = gitListing(top, ["ls-files", "-z", "--others", "--ignored", "--exclude-standard", "--directory"]);
10
+ proveListable(top, "", new Set(ignored.filter(isDirectoryEntry).map((entry) => entry.slice(0, -1))));
11
+ return listed.filter((entry) => !isDirectoryEntry(entry)).flatMap((path) => sightingsInListed(top, path, `SCN-${part}-`));
12
+ }
13
+ function gitListing(top, args) {
14
+ const result = spawnSync("git", args, { cwd: top, encoding: "utf8", maxBuffer: MAX_OUTPUT_BYTES });
15
+ if (result.error !== undefined)
16
+ refuse("the tree", top, result.error);
17
+ if (result.status !== 0) {
18
+ const said = result.stderr.split("\n")[0] ?? "";
19
+ throw new UnreadableInput("the tree", top, `git ls-files exited ${result.status}: ${said}`);
20
+ }
21
+ return result.stdout.split("\0").filter((entry) => entry !== "");
22
+ }
23
+ function isDirectoryEntry(entry) {
24
+ return entry.endsWith("/");
25
+ }
26
+ function proveListable(top, dir, ignored) {
27
+ const path = dir === "" ? top : join(top, dir);
28
+ const entries = readOrRefuse("a directory in the tree", path, () => listedAndEntered(path));
29
+ if (dir !== "" && entries.some((entry) => entry.name === ".git"))
30
+ return;
31
+ for (const entry of entries) {
32
+ const child = dir === "" ? entry.name : `${dir}/${entry.name}`;
33
+ if (entry.isDirectory() && entry.name !== ".git" && !ignored.has(child))
34
+ proveListable(top, child, ignored);
35
+ }
36
+ }
37
+ function listedAndEntered(path) {
38
+ accessSync(path, constants.R_OK | constants.X_OK);
39
+ return readdirSync(path, { withFileTypes: true });
40
+ }
41
+ function sightingsInListed(top, path, needle) {
42
+ const file = join(top, path);
43
+ const kind = readOrRefuse("a file in the tree", file, () => lstatSync(file, { throwIfNoEntry: false }));
44
+ if (kind === undefined || !kind.isFile())
45
+ return [];
46
+ return linesCarrying(path, readOrRefuse("a file in the tree", file, () => readFileSync(file)), needle);
47
+ }
48
+ function linesCarrying(path, content, needle) {
49
+ if (content.subarray(0, BINARY_PROBE_BYTES).includes(0))
50
+ return [];
51
+ return content
52
+ .toString("utf8")
53
+ .split("\n")
54
+ .flatMap((line, i) => (line.includes(needle) ? [{ path, line: i + 1, text: line }] : []));
55
+ }
56
+ export function isWalkedDirectory(name) {
57
+ return name !== "node_modules" && !name.startsWith(".");
58
+ }
59
+ export function walkTree(root, part) {
60
+ return filesUnder(root).flatMap((file) => {
61
+ const content = readOrRefuse("a file in the tree", file, () => readFileSync(file));
62
+ return linesCarrying(relative(root, file).split(sep).join("/"), content, `SCN-${part}-`);
63
+ });
64
+ }
65
+ function filesUnder(dir) {
66
+ const entries = readOrRefuse("a directory in the tree", dir, () => readdirSync(dir, { withFileTypes: true }));
67
+ return entries.flatMap((entry) => {
68
+ const path = join(dir, entry.name);
69
+ if (entry.isDirectory())
70
+ return isWalkedDirectory(entry.name) ? filesUnder(path) : [];
71
+ return entry.isFile() ? [path] : [];
72
+ });
73
+ }
74
+ //# sourceMappingURL=readTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readTree.js","sourceRoot":"","sources":["../../src/cli-allocate/readTree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function proveRefsReadable(cwd: string): void;
2
+ //# sourceMappingURL=refStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refStore.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/refStore.ts"],"names":[],"mappings":"AAOA,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAInD"}
@@ -0,0 +1,34 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { lstatSync, readdirSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { readOrRefuse } from "./unreadable.js";
5
+ const REF_STORES = ["refs", "packed-refs", "reftable"];
6
+ export function proveRefsReadable(cwd) {
7
+ for (const gitDir of gitDirsOf(cwd)) {
8
+ for (const store of REF_STORES)
9
+ readEveryEntry(join(gitDir, store));
10
+ }
11
+ }
12
+ function gitDirsOf(cwd) {
13
+ const result = spawnSync("git", ["rev-parse", "--path-format=absolute", "--git-common-dir", "--git-dir"], {
14
+ cwd,
15
+ encoding: "utf8",
16
+ });
17
+ if (result.status !== 0)
18
+ return [];
19
+ return [...new Set(result.stdout.split("\n").filter((line) => line !== ""))];
20
+ }
21
+ function readEveryEntry(path) {
22
+ const kind = readOrRefuse("the repository's history", path, () => lstatSync(path, { throwIfNoEntry: false }));
23
+ if (kind === undefined)
24
+ return;
25
+ if (kind.isDirectory()) {
26
+ const names = readOrRefuse("the repository's history", path, () => readdirSync(path));
27
+ for (const name of names)
28
+ readEveryEntry(join(path, name));
29
+ }
30
+ else if (kind.isFile()) {
31
+ readOrRefuse("the repository's history", path, () => readFileSync(path));
32
+ }
33
+ }
34
+ //# sourceMappingURL=refStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refStore.js","sourceRoot":"","sources":["../../src/cli-allocate/refStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAU,CAAC;AAEhE,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,UAAU;YAAE,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,WAAW,CAAC,EAAE;QACxG,GAAG;QACH,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,YAAY,CAAC,0BAA0B,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9G,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO;IAC/B,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,YAAY,CAAC,0BAA0B,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACzB,YAAY,CAAC,0BAA0B,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CliRegistry } from "../cli-registry.js";
2
+ export interface AllocateRequest {
3
+ readonly part: string;
4
+ readonly isNew: boolean;
5
+ }
6
+ export declare function readRequest(argv: readonly string[], registry: CliRegistry, toolVersion: string): AllocateRequest | {
7
+ readonly usageError: string;
8
+ };
9
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/request.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,QAAQ,EAAE,WAAW,EACrB,WAAW,EAAE,MAAM,GAClB,eAAe,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAInD"}
@@ -0,0 +1,22 @@
1
+ import { isFeaturePart } from "@3f-consulting/spec-controller-core";
2
+ import { checkArgvShape, checkMisplacedHostModifiers, checkUnknownFlags, parseArgs, positionalArguments, } from "../cli-args.js";
3
+ export function readRequest(argv, registry, toolVersion) {
4
+ const why = argvRefusal(argv, registry, toolVersion) ?? partRefusal(positionalArguments(argv, registry, "allocate")[0]);
5
+ if (why !== null)
6
+ return { usageError: `spec-controller allocate: usage error — ${why}` };
7
+ return { part: positionalArguments(argv, registry, "allocate")[0] ?? "", isNew: argv.includes("--new") };
8
+ }
9
+ function argvRefusal(argv, registry, toolVersion) {
10
+ const args = parseArgs(argv);
11
+ return (checkMisplacedHostModifiers(args, registry, "allocate") ??
12
+ checkArgvShape(argv, registry, "allocate") ??
13
+ checkUnknownFlags(args, registry, "allocate", toolVersion));
14
+ }
15
+ function partRefusal(part) {
16
+ if (part === undefined)
17
+ return "no feature part was given: 'spec-controller allocate <FFF>' takes one, a feature file's header code.";
18
+ if (isFeaturePart(part))
19
+ return null;
20
+ return `'${part}' is not a feature part in canon's form: two to five characters, each A-Z or 0-9.`;
21
+ }
22
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/cli-allocate/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EACL,cAAc,EACd,2BAA2B,EAC3B,iBAAiB,EACjB,SAAS,EACT,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAQxB,MAAM,UAAU,WAAW,CACzB,IAAuB,EACvB,QAAqB,EACrB,WAAmB;IAEnB,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,IAAI,WAAW,CAAC,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxH,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,UAAU,EAAE,2CAA2C,GAAG,EAAE,EAAE,CAAC;IAC1F,OAAO,EAAE,IAAI,EAAE,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED,SAAS,WAAW,CAAC,IAAuB,EAAE,QAAqB,EAAE,WAAmB;IACtF,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,CACL,2BAA2B,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;QACvD,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC;QAC1C,iBAAiB,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAC3D,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAwB;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,sGAAsG,CAAC;IACtI,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,IAAI,IAAI,mFAAmF,CAAC;AACrG,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type Allocation, type UnknownPart } from "@3f-consulting/spec-controller-core";
2
+ import type { HistoryBoundary } from "./readHistory.js";
3
+ export declare function historyBoundaryLine(boundary: HistoryBoundary, allocation: Allocation): string | null;
4
+ export declare function highestSeenLine(allocation: Allocation): string;
5
+ export declare function unknownPartRefusal(refusal: UnknownPart): string;
6
+ export declare function alreadyHeadedNote(allocation: Allocation): string | null;
7
+ //# sourceMappingURL=stderr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stderr.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/stderr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,qCAAqC,CAAC;AACvG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAKpG;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAK9D;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAM/D;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGvE"}
@@ -0,0 +1,26 @@
1
+ import { featureCodeOf } from "@3f-consulting/spec-controller-core";
2
+ export function historyBoundaryLine(boundary, allocation) {
3
+ if (boundary.kind === "complete")
4
+ return null;
5
+ const unread = boundary.kind === "shallow" ? `shallow clone — history before ${boundary.before} unread` : "not a git repository — none read";
6
+ const risk = allocation.highest === null ? `a code of ${featureCodeOf(allocation.code) ?? ""}` : `a code above ${allocation.highest.code}`;
7
+ return `history: ${unread}; ${risk} may have been used before`;
8
+ }
9
+ export function highestSeenLine(allocation) {
10
+ const highest = allocation.highest;
11
+ if (highest === null)
12
+ return "highest seen: none";
13
+ const { path, line, commit } = highest.sighting;
14
+ return `highest seen: ${highest.code}, ${path}:${line}${commit === undefined ? "" : ` in ${commit}`}`;
15
+ }
16
+ export function unknownPartRefusal(refusal) {
17
+ const parts = refusal.headerCodes.length === 0 ? "none" : refusal.headerCodes.join(", ");
18
+ return (`spec-controller allocate: unknown part — no feature file's header carries ${refusal.part}.\n` +
19
+ `The parts this corpus's feature files carry: ${parts}.`);
20
+ }
21
+ export function alreadyHeadedNote(allocation) {
22
+ if (allocation.alreadyHeaded !== true)
23
+ return null;
24
+ return `note: a feature file's header already carries ${featureCodeOf(allocation.code) ?? ""}, so --new was not needed`;
25
+ }
26
+ //# sourceMappingURL=stderr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stderr.js","sourceRoot":"","sources":["../../src/cli-allocate/stderr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqC,MAAM,qCAAqC,CAAC;AAGvG,MAAM,UAAU,mBAAmB,CAAC,QAAyB,EAAE,UAAsB;IACnF,IAAI,QAAQ,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,kCAAkC,QAAQ,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,kCAAkC,CAAC;IAC7I,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC3I,OAAO,YAAY,MAAM,KAAK,IAAI,4BAA4B,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAsB;IACpD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;IACnC,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,oBAAoB,CAAC;IAClD,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;IAChD,OAAO,iBAAiB,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,EAAE,CAAC;AACxG,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAoB;IACrD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzF,OAAO,CACL,6EAA6E,OAAO,CAAC,IAAI,KAAK;QAC9F,gDAAgD,KAAK,GAAG,CACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAsB;IACtD,IAAI,UAAU,CAAC,aAAa,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnD,OAAO,iDAAiD,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,2BAA2B,CAAC;AAC1H,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare class UnreadableInput extends Error {
2
+ readonly subject: string;
3
+ readonly path: string;
4
+ readonly reason: string;
5
+ readonly name = "UnreadableInput";
6
+ constructor(subject: string, path: string, reason: string);
7
+ }
8
+ export declare function readOrRefuse<T>(subject: string, path: string, read: () => T): T;
9
+ export declare function refuse(subject: string, path: string, err: unknown): never;
10
+ export declare function refusalLine(refusal: UnreadableInput): string;
11
+ //# sourceMappingURL=unreadable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unreadable.d.ts","sourceRoot":"","sources":["../../src/cli-allocate/unreadable.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;IAItC,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB,SAAkB,IAAI,qBAAqB;gBAGhC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAI1B;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAM/E;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,KAAK,CAIzE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,30 @@
1
+ export class UnreadableInput extends Error {
2
+ subject;
3
+ path;
4
+ reason;
5
+ name = "UnreadableInput";
6
+ constructor(subject, path, reason) {
7
+ super(path === "" ? `${subject} could not be read (${reason})` : `${subject} could not be read: ${path} (${reason})`);
8
+ this.subject = subject;
9
+ this.path = path;
10
+ this.reason = reason;
11
+ }
12
+ }
13
+ export function readOrRefuse(subject, path, read) {
14
+ try {
15
+ return read();
16
+ }
17
+ catch (err) {
18
+ return refuse(subject, path, err);
19
+ }
20
+ }
21
+ export function refuse(subject, path, err) {
22
+ const errno = err;
23
+ if (!(err instanceof Error) || typeof errno.code !== "string")
24
+ throw err;
25
+ throw new UnreadableInput(subject, errno.path ?? path, err.message);
26
+ }
27
+ export function refusalLine(refusal) {
28
+ return `spec-controller allocate: usage error — ${refusal.message}`;
29
+ }
30
+ //# sourceMappingURL=unreadable.js.map