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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +112 -0
  2. package/dist/cli-args.d.ts +73 -0
  3. package/dist/cli-args.d.ts.map +1 -0
  4. package/dist/cli-args.js +114 -0
  5. package/dist/cli-args.js.map +1 -0
  6. package/dist/cli-balance/cli.d.ts +20 -20
  7. package/dist/cli-balance/cli.d.ts.map +1 -1
  8. package/dist/cli-balance/cli.js +221 -202
  9. package/dist/cli-balance/cli.js.map +1 -1
  10. package/dist/cli-balance/emit/writer.d.ts +1 -1
  11. package/dist/cli-registry.d.ts +35 -12
  12. package/dist/cli-registry.d.ts.map +1 -1
  13. package/dist/cli-registry.js +95 -36
  14. package/dist/cli-registry.js.map +1 -1
  15. package/dist/cli.d.ts +5 -3
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +9 -3
  18. package/dist/cli.js.map +1 -1
  19. package/dist/corpus/cli.d.ts +34 -0
  20. package/dist/corpus/cli.d.ts.map +1 -0
  21. package/dist/corpus/cli.js +125 -0
  22. package/dist/corpus/cli.js.map +1 -0
  23. package/dist/deferralTags.d.ts +3 -3
  24. package/dist/deferralTags.js +3 -3
  25. package/dist/ingest/gherkinValidation.d.ts +29 -5
  26. package/dist/ingest/gherkinValidation.d.ts.map +1 -1
  27. package/dist/ingest/gherkinValidation.js +33 -5
  28. package/dist/ingest/gherkinValidation.js.map +1 -1
  29. package/dist/ingest/ingestQualityChecks.d.ts +15 -25
  30. package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
  31. package/dist/ingest/ingestQualityChecks.js +87 -104
  32. package/dist/ingest/ingestQualityChecks.js.map +1 -1
  33. package/dist/ingest/ingestScenarios.d.ts +2 -1
  34. package/dist/ingest/ingestScenarios.d.ts.map +1 -1
  35. package/dist/ingest/ingestScenarios.js +32 -3
  36. package/dist/ingest/ingestScenarios.js.map +1 -1
  37. package/dist/run-management/resolveRunInputs.d.ts +24 -11
  38. package/dist/run-management/resolveRunInputs.d.ts.map +1 -1
  39. package/dist/run-management/resolveRunInputs.js +49 -13
  40. package/dist/run-management/resolveRunInputs.js.map +1 -1
  41. package/package.json +2 -2
  42. package/dist/mutation-ratchet/index.d.ts +0 -48
  43. package/dist/mutation-ratchet/index.d.ts.map +0 -1
  44. package/dist/mutation-ratchet/index.js +0 -48
  45. package/dist/mutation-ratchet/index.js.map +0 -1
  46. package/dist/mutation-ratchet/ratchet.d.ts +0 -129
  47. package/dist/mutation-ratchet/ratchet.d.ts.map +0 -1
  48. package/dist/mutation-ratchet/ratchet.js +0 -222
  49. package/dist/mutation-ratchet/ratchet.js.map +0 -1
  50. package/dist/mutation-ratchet/ratchetCli.d.ts +0 -57
  51. package/dist/mutation-ratchet/ratchetCli.d.ts.map +0 -1
  52. package/dist/mutation-ratchet/ratchetCli.js +0 -139
  53. package/dist/mutation-ratchet/ratchetCli.js.map +0 -1
  54. package/dist/mutation-ratchet/reconcile.d.ts +0 -82
  55. package/dist/mutation-ratchet/reconcile.d.ts.map +0 -1
  56. package/dist/mutation-ratchet/reconcile.js +0 -67
  57. package/dist/mutation-ratchet/reconcile.js.map +0 -1
  58. package/dist/mutation-ratchet/record.d.ts +0 -210
  59. package/dist/mutation-ratchet/record.d.ts.map +0 -1
  60. package/dist/mutation-ratchet/record.js +0 -330
  61. package/dist/mutation-ratchet/record.js.map +0 -1
  62. package/dist/mutation-ratchet/report.d.ts +0 -83
  63. package/dist/mutation-ratchet/report.d.ts.map +0 -1
  64. package/dist/mutation-ratchet/report.js +0 -148
  65. package/dist/mutation-ratchet/report.js.map +0 -1
  66. package/dist/mutation-ratchet/verdict.d.ts +0 -177
  67. package/dist/mutation-ratchet/verdict.d.ts.map +0 -1
  68. package/dist/mutation-ratchet/verdict.js +0 -387
  69. package/dist/mutation-ratchet/verdict.js.map +0 -1
@@ -1,222 +0,0 @@
1
- /**
2
- * THE RECORDER — a measurement written into the record as a surgical text edit (@SCN-RAT-011,
3
- * 3F-2801), refused outright when it is not a raise (@SCN-RAT-012, 3F-2802), and kept inside the
4
- * block it names when a sibling gate banks the very same counts (@SCN-RAT-013, 3F-2803).
5
- *
6
- * A SURGICAL TEXT EDIT, NEVER A RE-DUMP, AND THAT IS THE WHOLE OF THIS MODULE'S DIFFICULTY.
7
- * Emitting the parsed document back out is the obvious way to write two figures into a record, and
8
- * it throws away every comment on the way through — comments are not part of the document a parser
9
- * hands back. A record file is MOSTLY comment: every allowance's justification lives there, and so
10
- * does the argument for the bar sitting where it sits. So a recorder that re-serialised would
11
- * delete the reasoning for the very bar it was raising, quietly, in the same commit that claims to
12
- * be strengthening it, and with the two figures perfectly correct.
13
- *
14
- * SO THE TEXT ARRIVES AS TEXT AND LEAVES AS TEXT. Nothing below reaches for a document model. The
15
- * record is split on its own line breaks, two lines are rewritten where they lie, and the pieces
16
- * are joined back up — which is why what comes back is the bytes it was handed with two numerals
17
- * different, down to the blank lines, the indent style, the quoting and the trailing newline.
18
- *
19
- * AND THE EDIT IS BOUNDED BY THE NAMED GATE'S OWN BLOCK. A record is a wall of near-identical
20
- * blocks holding identically-named lines, so a rewriter that took the first `detected` line it met
21
- * would raise whichever gate happens to be written first and report success on the one it was
22
- * asked about. The block runs from the gate's key line to the first line after it indented no
23
- * further than that key — the next gate, or the comment introducing it. The search for that key
24
- * starts at the gates section rather than the top of the file, because a record is a project's own
25
- * policy document and may hold anything else it likes above the bars.
26
- *
27
- * THE LINES ARE THEN FOUND BY POSITION INSIDE THAT BLOCK, NEVER BY THE FIGURES THEY CARRY, and the
28
- * difference is invisible over almost every record. A rewriter that struck the OLD numerals out
29
- * wherever they first appeared would be byte-preserving, would move exactly two lines, would keep
30
- * every comment, and would write precisely the right two lines over any record whose gates hold
31
- * distinct figures. It writes the WRONG gate only when two gates bank the same counts — and then
32
- * silently, leaving the two gates stating figures neither of the trees they describe ever measured.
33
- * @SCN-RAT-013's record plants that collision on purpose, and authors it with the named gate above
34
- * its twin and below it, because either rewriter is right by luck when the gate it wants is first.
35
- *
36
- * A LINE THE BLOCK DOES NOT HOLD IS AN ERROR NAMING THE LINE, NEVER A NO-OP. Both of the other
37
- * answers are worse than a refusal: skipping quietly banks half a measurement and reports a raise
38
- * that did not happen, and searching on past the block's end rewrites some other gate's figure with
39
- * this gate's count.
40
- *
41
- * EVERY FAULT IN THE RECORD IS `record.ts`'s ONE REFUSAL TYPE, and its section name and gate
42
- * placeholder are imported rather than respelled. A caller is told to catch `MalformedRecordError`
43
- * for a record it cannot read, so a record fault raised here under a second type is one that caller
44
- * sails past — and a second copy of the section's name is the agreeing-until-somebody-edits-one
45
- * shape this library exists to remove.
46
- *
47
- * AND THE UP-ONLY REFUSAL IS THE ONE THING HERE THAT IS NOT A RECORD FAULT, WHICH IS WHY IT CARRIES
48
- * ITS OWN TYPE. Every fault that other refusal names is a record somebody wrote badly, sitting in
49
- * the file its reader is being sent to open. A run that is not a raise arrives over a record that
50
- * reads perfectly, so borrowing that type would send its reader hunting through a file with nothing
51
- * wrong in it — the exact harm `record.ts` refuses to do to the caller who mistyped a gate name.
52
- *
53
- * THE RATCHET ONLY EVER RAISES, AND AN EQUAL MEASUREMENT IS REFUSED TOO. Writing the same two
54
- * figures back changes nothing, and a no-op that reports success reads, in a shell history or a
55
- * run's own log, as a ratchet that happened; the refusal is what keeps "I banked it" meaning
56
- * something. It is the SCORE that is compared rather than the pair, because a run can move both of
57
- * its counts and hold its ratio exactly — over a record already stating that score, writing it
58
- * raises nothing.
59
- *
60
- * AND THE REFUSAL HAS NO OVERRIDE, DELIBERATELY. A fall that is honest — code deleted, a scope
61
- * narrowed — is a conscious bump: a human edits the two figures and puts the reason in the commit,
62
- * which is the route the refusal names and the same route the shrunk-population red already sends
63
- * its reader down. An escape hatch a tool offers is one nobody has to justify, and it would be
64
- * reached for on the first red night rather than the first honest one. So there is no input here
65
- * that writes a fall — not a flag, not a defaulted parameter, not a setting — and @SCN-RAT-012's
66
- * arm asserts that over this module's own bytes rather than trusting it.
67
- *
68
- * NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY. The gate, the
69
- * record's own name and the tree it sits in all arrive from the caller.
70
- */
71
- import { readFileSync, writeFileSync } from "node:fs";
72
- import { join } from "node:path";
73
- import { counts, MalformedRecordError, MUTATION_GATES, scoreRoseOver, WHOLE_GATE, } from "./record.js";
74
- /**
75
- * Raised when a run is not a raise — the up-only refusal (@SCN-RAT-012, 3F-2802).
76
- *
77
- * A SECOND TYPE, AND DELIBERATELY NOT `MalformedRecordError`. Every fault that refusal names is a
78
- * record somebody wrote badly, sitting in the file its reader is being sent to open. This one is a
79
- * record that reads perfectly and an ASK that is not a raise, so borrowing the other type would
80
- * send a reader off to hunt for a fault in a file that has none.
81
- */
82
- export class FallRefusedError extends Error {
83
- recordFile;
84
- gate;
85
- constructor(
86
- /** The name the record was filed under, as the caller handed it over. */
87
- recordFile,
88
- /** The gate that was to have been raised, as the caller names it. */
89
- gate, banked, measurement) {
90
- super(`${gate}: NOT A RAISE — measured ${counts(measurement.detected, measurement.total)} against ` +
91
- `a recorded ${counts(banked.detected, banked.total)}. The ratchet only ever raises, and ` +
92
- "this run does not: a measurement below the record would give the bar away, and one " +
93
- "scoring exactly what the record already states would write it back unchanged — a no-op " +
94
- "that reads, in a shell history or a run's own log, as a ratchet that happened. Nothing " +
95
- "here lowers a record for you. If the fall is honest — code deleted, a scope narrowed — " +
96
- `edit ${recordFile} by hand and put the reason in the commit, because an escape hatch a ` +
97
- "tool holds open is one nobody ever has to justify.");
98
- this.recordFile = recordFile;
99
- this.gate = gate;
100
- this.name = "FallRefusedError";
101
- }
102
- }
103
- /** How far a line is indented, in characters. */
104
- function indentOf(line) {
105
- return line.length - line.trimStart().length;
106
- }
107
- /**
108
- * The line one field is written on: its key at any indent, its whole-number value, and whatever
109
- * spacing the author put around both.
110
- *
111
- * THE SPACING IS CAPTURED SO IT CAN BE PUT BACK. `detected: 202` and `detected: 202` are the same
112
- * record and different bytes, and a rewriter that normalised one into the other would be re-dumping
113
- * one line at a time.
114
- */
115
- function fieldLine(field) {
116
- return new RegExp(`^(\\s*${field}\\s*:\\s*)(\\d+)(\\s*)$`);
117
- }
118
- /** Where the gates section's own key line sits, refused when the record is not written as one. */
119
- function gatesSectionAt(lines, gate, recordFile) {
120
- const at = lines.findIndex((line) => line.trim() === `${MUTATION_GATES}:`);
121
- if (at === -1) {
122
- throw new MalformedRecordError(recordFile, MUTATION_GATES, gate, MUTATION_GATES, "the section is not written as a block of gates, so it holds no block to rewrite.");
123
- }
124
- return at;
125
- }
126
- /**
127
- * The lines holding one gate's block, refused when the record writes no block for that gate.
128
- *
129
- * ENDING AT THE FIRST LINE INDENTED NO FURTHER THAN THE KEY — the next gate, or the comment
130
- * introducing it. That boundary is what keeps a rewrite inside the gate it was asked about when the
131
- * line it is looking for is not there to be found.
132
- */
133
- function gateBlockOf(lines, gate, recordFile) {
134
- const section = gatesSectionAt(lines, gate, recordFile);
135
- const sectionIndent = indentOf(lines[section] ?? "");
136
- const key = lines.findIndex((line, at) => at > section && line.trim() === `${gate}:` && indentOf(line) > sectionIndent);
137
- if (key === -1) {
138
- throw new MalformedRecordError(recordFile, MUTATION_GATES, gate, WHOLE_GATE, "the record writes no block for this gate, so there is nothing to raise.");
139
- }
140
- const indent = indentOf(lines[key] ?? "");
141
- const ends = lines.findIndex((line, at) => at > key && line.trim() !== "" && indentOf(line) <= indent);
142
- return { from: key + 1, to: ends === -1 ? lines.length : ends };
143
- }
144
- /**
145
- * One field's line inside a block, refused by the field's name when the block holds no such line.
146
- *
147
- * BOTH FIGURES ARE FOUND BEFORE EITHER IS COMPARED OR WRITTEN, which is what keeps this refusal
148
- * ahead of the up-only one: a block missing a line is a record fault, and a reader sent to argue
149
- * about scores over a half-written block has been sent to the wrong question.
150
- */
151
- function figureIn(lines, block, field, gate, recordFile) {
152
- const pattern = fieldLine(field);
153
- for (let at = block.from; at < block.to; at += 1) {
154
- const written = pattern.exec(lines[at] ?? "");
155
- if (written !== null)
156
- return { at, value: Number(written[2]) };
157
- }
158
- throw new MalformedRecordError(recordFile, MUTATION_GATES, gate, field, "the gate's block holds no such line, so there is nothing to rewrite it into.");
159
- }
160
- /**
161
- * Refuse a measurement that is not a raise, naming both scores and the one route down.
162
- *
163
- * ASKED OF THE SCORE, NEVER OF THE PAIR. A run that moved both of its counts and held its ratio
164
- * exactly is a run that raises nothing, and a recorder written as "the very same two figures" writes
165
- * it — a record rewritten to say what it already said.
166
- */
167
- function refuseUnlessRaised(gate, banked, measurement, recordFile) {
168
- if (scoreRoseOver(measurement.detected, measurement.total, banked.detected, banked.total))
169
- return;
170
- throw new FallRefusedError(recordFile, gate, banked, measurement);
171
- }
172
- /** One located line with its figure rewritten, and every byte of its spacing kept. */
173
- function rewritten(line, field, value) {
174
- return line.replace(fieldLine(field), `$1${value}$3`);
175
- }
176
- /**
177
- * Raise a gate's two recorded figures to a measurement, leaving every other byte alone.
178
- *
179
- * @param text the record file's own bytes, as authored
180
- * @param gate the gate to raise, as the caller names it
181
- * @param measurement the run whose counts are being banked
182
- * @param recordFile the name the record is filed under, so a refusal can say which file it read
183
- * @returns the same bytes with two numerals different
184
- * @throws MalformedRecordError when the record writes no block for the gate, or that block holds no
185
- * line to rewrite — named by the line, never passed over and never sought outside the block.
186
- * @throws FallRefusedError when the measurement does not score above what the gate already banks.
187
- * There is no input that writes it anyway.
188
- */
189
- export function raisedRecordText(text, gate, measurement, recordFile) {
190
- const lines = text.split("\n");
191
- const block = gateBlockOf(lines, gate, recordFile);
192
- const detected = figureIn(lines, block, "detected", gate, recordFile);
193
- const total = figureIn(lines, block, "total", gate, recordFile);
194
- refuseUnlessRaised(gate, { detected: detected.value, total: total.value }, measurement, recordFile);
195
- lines[detected.at] = rewritten(lines[detected.at] ?? "", "detected", measurement.detected);
196
- lines[total.at] = rewritten(lines[total.at] ?? "", "total", measurement.total);
197
- return lines.join("\n");
198
- }
199
- /**
200
- * Write a raised record back over the file it was read from, resolved against the caller's tree.
201
- *
202
- * THE ROOT ARRIVES, AND IS NEVER THIS MODULE'S OWN LOCATION. A recorder that joined the directory it
203
- * was installed into is correct only while it sits inside the tree it is writing to, and stops
204
- * being so the moment it is installed as a dependency of one.
205
- *
206
- * READ AND WRITTEN IN THE SAME ENCODING, so the round trip through the filesystem is a round trip
207
- * rather than a transcoding — the whole promise of this module being that what comes back out is
208
- * what went in.
209
- *
210
- * @param root the CONSUMER'S workspace
211
- * @param recordFile where the record sits, relative to that root
212
- * @param gate the gate to raise, as the caller names it
213
- * @param measurement the run whose counts are being banked
214
- * @returns the path that was written, so a caller can say where the record now stands
215
- */
216
- export function bankRaisedRecord(root, recordFile, gate, measurement) {
217
- const at = join(root, recordFile);
218
- const raised = raisedRecordText(readFileSync(at, "utf8"), gate, measurement, recordFile);
219
- writeFileSync(at, raised, "utf8");
220
- return at;
221
- }
222
- //# sourceMappingURL=ratchet.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ratchet.js","sourceRoot":"","sources":["../../src/mutation-ratchet/ratchet.ts"],"names":[],"mappings":"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"}
@@ -1,57 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * THE COMMAND — one gate's run reconciled against its record, and the run that asked ending on the
4
- * answer (@SCN-RAT-015, 3F-2805).
5
- *
6
- * --gate <name> --report <path> [--root <dir>] [--record-file <path>]
7
- * [--bank-command <text>] [--record]
8
- *
9
- * WHY THERE IS A COMMAND AT ALL. Every module beneath this one settles what the verdict IS, and a
10
- * verdict handed back as a value is a verdict nobody's pipeline can read. A pipeline observes one
11
- * thing about a step — how it ended — so the last piece of this library is the piece that ends.
12
- *
13
- * THREE ENDINGS, AND THE THIRD IS THE ONE WORTH BUILDING FOR. A gate that stands ends cleanly and a
14
- * gate that does not ends in failure; between them they are what a pipeline is watching for, and
15
- * telling them apart is arithmetic that is already done by the time this file runs. The third is a
16
- * run that was CALLED wrong, and it must wear neither of the other two. A name left off, reported as
17
- * a gate that does not stand, sends somebody hunting through their code for a regression that never
18
- * happened; reported as a gate that stands, it is a bar that quietly stopped being read at all. So
19
- * it takes the ending this repository already reserves for "this run is broken" as against "the code
20
- * is wrong", which every other step here that can be misused already uses.
21
- *
22
- * A FLAG NEVER SWALLOWS THE NEXT FLAG AS ITS VALUE. `--report --record` read leniently is a report
23
- * sought at a path called `--record`, found missing, and answered with a sweep that never ran — a
24
- * reading that sends its reader to look at their runner when what happened was a typo one character
25
- * long. Anything beginning with two dashes is a flag, never a value.
26
- *
27
- * THE REPORT'S PATH IS REQUIRED AND THE RECORD'S NAME IS NOT, and the asymmetry is a ruling rather
28
- * than an oversight, carried up from the composition beneath. Where a sweep drops its output is a
29
- * RUNNER'S convention, so a default there would be this file naming a runner. The record's name
30
- * belongs to whoever owns the record, so the conventional one stands in and a caller who files their
31
- * bars elsewhere writes it over.
32
- *
33
- * AND THE TREE DEFAULTS TO A RELATIVE ONE RATHER THAN TO ANYWHERE THIS FILE CAN FIND. `.` is the
34
- * caller's own working directory, resolved by the platform at the moment of the read; a root taken
35
- * from where this file is INSTALLED agrees with its caller for exactly as long as it sits beside
36
- * that caller's code, and stops the day it ships as a dependency — resolving quietly into a package
37
- * folder, reading nothing, and reporting a gate that measured perfectly as a gate that never ran.
38
- *
39
- * A REFUSAL TO BANK IS AN EXPECTED ENDING RATHER THAN A CRASH. Asking whether there is anything to
40
- * bank is what an operator types, and most of the time the answer is no. Handed out as an unhandled
41
- * fall it arrives as a stack trace — a reading that says the tool broke where what happened was the
42
- * tool working, and one that buries the refusal's own sentence, which is the only part of it anybody
43
- * needed. So the refusal is caught by its own type, its reason is what the reader gets, and the run
44
- * ends in failure because there was nothing to bank.
45
- *
46
- * AND THERE IS NO WAY PAST THAT REFUSAL HERE EITHER. The recorder beneath takes four inputs and
47
- * offers no fifth; this file adds no flag that would ask it to write a fall, and @SCN-RAT-012 reads
48
- * these bytes to say so rather than trusting them. A record that must come down comes down by hand,
49
- * with the reason in the commit, because an escape hatch a tool holds open is one nobody ever has to
50
- * justify.
51
- *
52
- * NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY — the usage line
53
- * included, which is where such a name most easily hides, being read by people rather than by tests.
54
- * @SCN-RAT-014 reads these bytes for that too.
55
- */
56
- export {};
57
- //# sourceMappingURL=ratchetCli.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ratchetCli.d.ts","sourceRoot":"","sources":["../../src/mutation-ratchet/ratchetCli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG"}
@@ -1,139 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * THE COMMAND — one gate's run reconciled against its record, and the run that asked ending on the
4
- * answer (@SCN-RAT-015, 3F-2805).
5
- *
6
- * --gate <name> --report <path> [--root <dir>] [--record-file <path>]
7
- * [--bank-command <text>] [--record]
8
- *
9
- * WHY THERE IS A COMMAND AT ALL. Every module beneath this one settles what the verdict IS, and a
10
- * verdict handed back as a value is a verdict nobody's pipeline can read. A pipeline observes one
11
- * thing about a step — how it ended — so the last piece of this library is the piece that ends.
12
- *
13
- * THREE ENDINGS, AND THE THIRD IS THE ONE WORTH BUILDING FOR. A gate that stands ends cleanly and a
14
- * gate that does not ends in failure; between them they are what a pipeline is watching for, and
15
- * telling them apart is arithmetic that is already done by the time this file runs. The third is a
16
- * run that was CALLED wrong, and it must wear neither of the other two. A name left off, reported as
17
- * a gate that does not stand, sends somebody hunting through their code for a regression that never
18
- * happened; reported as a gate that stands, it is a bar that quietly stopped being read at all. So
19
- * it takes the ending this repository already reserves for "this run is broken" as against "the code
20
- * is wrong", which every other step here that can be misused already uses.
21
- *
22
- * A FLAG NEVER SWALLOWS THE NEXT FLAG AS ITS VALUE. `--report --record` read leniently is a report
23
- * sought at a path called `--record`, found missing, and answered with a sweep that never ran — a
24
- * reading that sends its reader to look at their runner when what happened was a typo one character
25
- * long. Anything beginning with two dashes is a flag, never a value.
26
- *
27
- * THE REPORT'S PATH IS REQUIRED AND THE RECORD'S NAME IS NOT, and the asymmetry is a ruling rather
28
- * than an oversight, carried up from the composition beneath. Where a sweep drops its output is a
29
- * RUNNER'S convention, so a default there would be this file naming a runner. The record's name
30
- * belongs to whoever owns the record, so the conventional one stands in and a caller who files their
31
- * bars elsewhere writes it over.
32
- *
33
- * AND THE TREE DEFAULTS TO A RELATIVE ONE RATHER THAN TO ANYWHERE THIS FILE CAN FIND. `.` is the
34
- * caller's own working directory, resolved by the platform at the moment of the read; a root taken
35
- * from where this file is INSTALLED agrees with its caller for exactly as long as it sits beside
36
- * that caller's code, and stops the day it ships as a dependency — resolving quietly into a package
37
- * folder, reading nothing, and reporting a gate that measured perfectly as a gate that never ran.
38
- *
39
- * A REFUSAL TO BANK IS AN EXPECTED ENDING RATHER THAN A CRASH. Asking whether there is anything to
40
- * bank is what an operator types, and most of the time the answer is no. Handed out as an unhandled
41
- * fall it arrives as a stack trace — a reading that says the tool broke where what happened was the
42
- * tool working, and one that buries the refusal's own sentence, which is the only part of it anybody
43
- * needed. So the refusal is caught by its own type, its reason is what the reader gets, and the run
44
- * ends in failure because there was nothing to bank.
45
- *
46
- * AND THERE IS NO WAY PAST THAT REFUSAL HERE EITHER. The recorder beneath takes four inputs and
47
- * offers no fifth; this file adds no flag that would ask it to write a fall, and @SCN-RAT-012 reads
48
- * these bytes to say so rather than trusting them. A record that must come down comes down by hand,
49
- * with the reason in the commit, because an escape hatch a tool holds open is one nobody ever has to
50
- * justify.
51
- *
52
- * NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY — the usage line
53
- * included, which is where such a name most easily hides, being read by people rather than by tests.
54
- * @SCN-RAT-014 reads these bytes for that too.
55
- */
56
- import { join } from "node:path";
57
- import { bankRaisedRecord, FallRefusedError } from "./ratchet.js";
58
- import { RECORD_FILE, reconcileGate } from "./reconcile.js";
59
- import { readMutationReport } from "./report.js";
60
- /**
61
- * What to type to bank a measurement, when the caller has not said.
62
- *
63
- * TRUE OF EVERY CALLER, WHICH IS THE ONLY KIND OF DEFAULT THIS TERM CAN HAVE. A project's real
64
- * instruction is its own sentence — its script, its runner, its file — so one written here would be
65
- * somebody else's, sitting inside a message, reached only on the runs nobody reads twice. What is
66
- * left that is true anywhere is this command itself, which can bank a measurement and is already in
67
- * the reader's hand.
68
- */
69
- const BANK_IT_WITH = "this same command, asked to bank the measurement";
70
- /**
71
- * A fault in how this was CALLED — the ending reserved for "this run is broken".
72
- *
73
- * ONLY how it was called. What the record holds and what the report measured never come here: a
74
- * gate that lost kills is the code being wrong, which is a verdict, and a verdict has an ending of
75
- * its own two lines below.
76
- */
77
- function usage(problem) {
78
- console.error(`ratchet: ${problem}`);
79
- console.error("ratchet: usage — --gate <name> --report <path> [--root <dir>] " +
80
- "[--record-file <path>] [--bank-command <text>] [--record]");
81
- process.exit(2);
82
- }
83
- /** The value a `--flag` was given, or undefined where the flag is absent. */
84
- function flagValue(flags, name) {
85
- const at = flags.indexOf(name);
86
- if (at === -1)
87
- return undefined;
88
- const value = flags[at + 1];
89
- // Two dashes are a flag, never a value: see the argument at the head of this file.
90
- if (value === undefined || value.startsWith("--"))
91
- usage(`${name} needs a value`);
92
- return value;
93
- }
94
- /** Read the command line into the reconciliation it names. */
95
- function reconciliationOf(argv) {
96
- return {
97
- gate: flagValue(argv, "--gate") ?? usage("--gate names the gate to reconcile"),
98
- reportPath: flagValue(argv, "--report") ?? usage("--report names where this gate's run left its report"),
99
- root: flagValue(argv, "--root") ?? ".",
100
- recordFile: flagValue(argv, "--record-file") ?? RECORD_FILE,
101
- bankCommand: flagValue(argv, "--bank-command") ?? BANK_IT_WITH,
102
- banking: argv.includes("--record"),
103
- };
104
- }
105
- const asked = reconciliationOf(process.argv.slice(2));
106
- const verdict = reconcileGate({
107
- gate: asked.gate,
108
- root: asked.root,
109
- reportPath: asked.reportPath,
110
- bankCommand: asked.bankCommand,
111
- recordFile: asked.recordFile,
112
- });
113
- // EVERY RUN, AND BEFORE ANYTHING ELSE HAPPENS. The verdict is what was asked for, whichever way the
114
- // run goes on to end, and a reader whose run banked a measurement still wants to know what it was
115
- // that made banking worth doing.
116
- console.log(verdict.message);
117
- if (!asked.banking)
118
- process.exit(verdict.ok ? 0 : 1);
119
- // A run with nothing measured has nothing to bank, and the verdict above has already said so in the
120
- // sentence that belongs to it. There is no second reading of the same absence to write here.
121
- const read = readMutationReport(asked.gate, join(asked.root, asked.reportPath));
122
- if (!read.ok)
123
- process.exit(1);
124
- try {
125
- const at = bankRaisedRecord(asked.root, asked.recordFile, asked.gate, read.measurement);
126
- console.log(`ratchet: ${asked.gate} — the record at ${at} now states ` +
127
- `${read.measurement.detected} of ${read.measurement.total}.`);
128
- }
129
- catch (raised) {
130
- // BY ITS OWN TYPE, AND NOTHING WIDER. A blanket catch here would answer a record nobody can read,
131
- // a tree that is not there and a fault nobody has thought of yet with the one sentence written for
132
- // a run that simply had nothing to bank — which is the reading that sends its reader hunting for a
133
- // measurement when what they have is a broken file.
134
- if (!(raised instanceof FallRefusedError))
135
- throw raised;
136
- console.error(raised.message);
137
- process.exit(1);
138
- }
139
- //# sourceMappingURL=ratchetCli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ratchetCli.js","sourceRoot":"","sources":["../../src/mutation-ratchet/ratchetCli.ts"],"names":[],"mappings":"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"}
@@ -1,82 +0,0 @@
1
- /**
2
- * THE COMPOSITION — one gate's run reconciled against its record, with every term a project owns
3
- * arriving from that project (@SCN-RAT-014, 3F-2804).
4
- *
5
- * FIVE TERMS, AND FOUR OF THEM ARE WHY THIS MODULE EXISTS RATHER THAN A CALLER WIRING THE PIECES
6
- * TOGETHER ITSELF. The reader, the report and the verdict below were each built generic, and the
7
- * reference implementation this library was lifted from was generic in all of them too — right up
8
- * to the point where something had to say WHICH tree, WHICH file, WHICH report and WHAT to type
9
- * next. Those four answers were written into the code there, and they are the four that arrive
10
- * here as a request instead.
11
- *
12
- * THE ROOT IS THE CONSUMER'S WORKSPACE, NEVER THIS MODULE'S OWN LOCATION, and that is the term
13
- * that fails silently rather than loudly. A module finding the tree from where it is installed
14
- * agrees with its caller for exactly as long as it sits beside that caller's code — which it does
15
- * in the repository it was written in, and stops doing the day it is installed as a dependency,
16
- * when it resolves into its own directory inside a package folder and finds nothing there. There
17
- * is no way to notice from inside: the paths are well-formed, the reads fail as absent files, and
18
- * a gate that measured perfectly reads as a gate that never ran. So the root arrives, and every
19
- * path below is joined onto it.
20
- *
21
- * THE RECORD FILE IS DEFAULTED AND THE REPORT PATH IS NOT, and the asymmetry is a ruling rather
22
- * than an oversight. Where a mutation sweep drops its output is a RUNNER'S convention, so a
23
- * default there would be this module naming a runner — the exact leak the Rule above it forbids.
24
- * The record's name is owned by whoever owns the record, so a conventional default costs its
25
- * owner nothing and a caller who wants another writes one.
26
- *
27
- * AND THE BANK-IT INSTRUCTION IS CARRIED WHOLE, because the two verdicts that ask for a record to
28
- * be banked have to say what to type, and what to type is a sentence only the calling project can
29
- * write. Left to this module it would be somebody's script name, sitting inside a message, reached
30
- * only on the runs nobody reads twice.
31
- *
32
- * NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY, and @SCN-RAT-014
33
- * asserts that over this module's own bytes rather than trusting it.
34
- */
35
- import { type MutationVerdict } from "./verdict.js";
36
- /**
37
- * The name a record is filed under when its caller does not choose one.
38
- *
39
- * A DEFAULT, NEVER A CONSTANT THE READER GOES LOOKING FOR. Which file holds a project's bars is
40
- * that project's own fact, and a caller naming its own is answered by that name — this is only
41
- * what stands in when none is given, and it is exported so a caller happy with the convention does
42
- * not have to respell it and get one character of it wrong.
43
- */
44
- export declare const RECORD_FILE = "quality-thresholds.yml";
45
- /**
46
- * One reconciliation, as the calling project states it.
47
- *
48
- * EVERY FIELD IS A TERM THE PROJECT OWNS. There is nothing else here — no setting, no mode, no
49
- * threshold of this module's own. The bar is in the project's record and the run is in the
50
- * project's report; what this asks for is where those two are and what to call things.
51
- */
52
- export interface RatchetRequest {
53
- /** The gate to reconcile, as the project's own record names it. */
54
- readonly gate: string;
55
- /**
56
- * The CONSUMER'S workspace — the tree the record and the report both sit in.
57
- *
58
- * Never this module's own installed location, which is the same tree only by coincidence and
59
- * only until the day this ships as something another repository installs.
60
- */
61
- readonly root: string;
62
- /**
63
- * Where the gate's run left its report, relative to that root.
64
- *
65
- * REQUIRED, AND THAT IS THE RULING. A default here would be a runner's output convention wearing
66
- * this module's name.
67
- */
68
- readonly reportPath: string;
69
- /** What the project's own people type to bank a measurement, carried into the verdicts that ask. */
70
- readonly bankCommand: string;
71
- /** Where the project's record sits, relative to that root. Defaults to {@link RECORD_FILE}. */
72
- readonly recordFile?: string;
73
- }
74
- /**
75
- * Reconcile one gate's run against the bar its project's record states.
76
- *
77
- * @param request the five terms the calling project owns
78
- * @returns the verdict, red or green, carrying the line its reader gets
79
- * @throws MalformedRecordError when the record cannot be read as a bar, or holds no such gate
80
- */
81
- export declare function reconcileGate(request: RatchetRequest): MutationVerdict;
82
- //# sourceMappingURL=reconcile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/mutation-ratchet/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAOH,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/E;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,2BAA2B,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,oGAAoG;IACpG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,+FAA+F;IAC/F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CAWtE"}
@@ -1,67 +0,0 @@
1
- /**
2
- * THE COMPOSITION — one gate's run reconciled against its record, with every term a project owns
3
- * arriving from that project (@SCN-RAT-014, 3F-2804).
4
- *
5
- * FIVE TERMS, AND FOUR OF THEM ARE WHY THIS MODULE EXISTS RATHER THAN A CALLER WIRING THE PIECES
6
- * TOGETHER ITSELF. The reader, the report and the verdict below were each built generic, and the
7
- * reference implementation this library was lifted from was generic in all of them too — right up
8
- * to the point where something had to say WHICH tree, WHICH file, WHICH report and WHAT to type
9
- * next. Those four answers were written into the code there, and they are the four that arrive
10
- * here as a request instead.
11
- *
12
- * THE ROOT IS THE CONSUMER'S WORKSPACE, NEVER THIS MODULE'S OWN LOCATION, and that is the term
13
- * that fails silently rather than loudly. A module finding the tree from where it is installed
14
- * agrees with its caller for exactly as long as it sits beside that caller's code — which it does
15
- * in the repository it was written in, and stops doing the day it is installed as a dependency,
16
- * when it resolves into its own directory inside a package folder and finds nothing there. There
17
- * is no way to notice from inside: the paths are well-formed, the reads fail as absent files, and
18
- * a gate that measured perfectly reads as a gate that never ran. So the root arrives, and every
19
- * path below is joined onto it.
20
- *
21
- * THE RECORD FILE IS DEFAULTED AND THE REPORT PATH IS NOT, and the asymmetry is a ruling rather
22
- * than an oversight. Where a mutation sweep drops its output is a RUNNER'S convention, so a
23
- * default there would be this module naming a runner — the exact leak the Rule above it forbids.
24
- * The record's name is owned by whoever owns the record, so a conventional default costs its
25
- * owner nothing and a caller who wants another writes one.
26
- *
27
- * AND THE BANK-IT INSTRUCTION IS CARRIED WHOLE, because the two verdicts that ask for a record to
28
- * be banked have to say what to type, and what to type is a sentence only the calling project can
29
- * write. Left to this module it would be somebody's script name, sitting inside a message, reached
30
- * only on the runs nobody reads twice.
31
- *
32
- * NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY, and @SCN-RAT-014
33
- * asserts that over this module's own bytes rather than trusting it.
34
- */
35
- import { readFileSync } from "node:fs";
36
- import { join } from "node:path";
37
- import { gateRecordFor, parseGateRecords } from "./record.js";
38
- import { readMutationReport } from "./report.js";
39
- import { noMeasurement, verdictFor } from "./verdict.js";
40
- /**
41
- * The name a record is filed under when its caller does not choose one.
42
- *
43
- * A DEFAULT, NEVER A CONSTANT THE READER GOES LOOKING FOR. Which file holds a project's bars is
44
- * that project's own fact, and a caller naming its own is answered by that name — this is only
45
- * what stands in when none is given, and it is exported so a caller happy with the convention does
46
- * not have to respell it and get one character of it wrong.
47
- */
48
- export const RECORD_FILE = "quality-thresholds.yml";
49
- /**
50
- * Reconcile one gate's run against the bar its project's record states.
51
- *
52
- * @param request the five terms the calling project owns
53
- * @returns the verdict, red or green, carrying the line its reader gets
54
- * @throws MalformedRecordError when the record cannot be read as a bar, or holds no such gate
55
- */
56
- export function reconcileGate(request) {
57
- const recordFile = request.recordFile ?? RECORD_FILE;
58
- const records = parseGateRecords(readFileSync(join(request.root, recordFile), "utf8"), recordFile);
59
- const record = gateRecordFor(request.gate, records, recordFile);
60
- const read = readMutationReport(request.gate, join(request.root, request.reportPath));
61
- // A refusal is carried through as the verdict it implies rather than as an absence: a report that
62
- // is not there is a gate that produced no score, which is not a gate that passed.
63
- return read.ok
64
- ? verdictFor(record, read.measurement, request.bankCommand)
65
- : noMeasurement(request.gate, read.reason);
66
- }
67
- //# sourceMappingURL=reconcile.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/mutation-ratchet/reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAwB,MAAM,cAAc,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,wBAAwB,CAAC;AAgCpD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,OAAuB;IACnD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,WAAW,CAAC;IACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;IACnG,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAEtF,kGAAkG;IAClG,kFAAkF;IAClF,OAAO,IAAI,CAAC,EAAE;QACZ,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC;QAC3D,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC"}