spec-controller 0.1.0-alpha.4 → 0.1.0-alpha.40
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 +34 -6
- 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 +57 -0
- package/dist/cli-allocate/cli.js.map +1 -0
- package/dist/cli-allocate/readHistory.d.ts +29 -0
- package/dist/cli-allocate/readHistory.d.ts.map +1 -0
- package/dist/cli-allocate/readHistory.js +136 -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 +28 -0
- package/dist/cli-allocate/readParts.js.map +1 -0
- package/dist/cli-allocate/readTree.d.ts +16 -0
- package/dist/cli-allocate/readTree.d.ts.map +1 -0
- package/dist/cli-allocate/readTree.js +106 -0
- package/dist/cli-allocate/readTree.js.map +1 -0
- package/dist/cli-allocate/refStore.d.ts +3 -0
- package/dist/cli-allocate/refStore.d.ts.map +1 -0
- package/dist/cli-allocate/refStore.js +47 -0
- package/dist/cli-allocate/refStore.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-allocate/unreadable.d.ts +24 -0
- package/dist/cli-allocate/unreadable.d.ts.map +1 -0
- package/dist/cli-allocate/unreadable.js +43 -0
- package/dist/cli-allocate/unreadable.js.map +1 -0
- package/dist/cli-args.d.ts +73 -18
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +244 -22
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-balance/cli.d.ts +31 -13
- package/dist/cli-balance/cli.d.ts.map +1 -1
- package/dist/cli-balance/cli.js +205 -251
- 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-balance/exitStatus.d.ts +3 -0
- package/dist/cli-balance/exitStatus.d.ts.map +1 -0
- package/dist/cli-balance/exitStatus.js +12 -0
- package/dist/cli-balance/exitStatus.js.map +1 -0
- package/dist/cli-balance/reRender.d.ts +22 -0
- package/dist/cli-balance/reRender.d.ts.map +1 -0
- package/dist/cli-balance/reRender.js +36 -0
- package/dist/cli-balance/reRender.js.map +1 -0
- package/dist/cli-balance/unreadableInputs.d.ts +35 -0
- package/dist/cli-balance/unreadableInputs.d.ts.map +1 -0
- package/dist/cli-balance/unreadableInputs.js +101 -0
- package/dist/cli-balance/unreadableInputs.js.map +1 -0
- package/dist/cli-registry.d.ts +28 -0
- package/dist/cli-registry.d.ts.map +1 -1
- package/dist/cli-registry.js +40 -35
- 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 +37 -21
- package/dist/cli.js.map +1 -1
- package/dist/host.d.ts +28 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +137 -17
- package/dist/host.js.map +1 -1
- package/dist/ingest/gherkinValidation.d.ts +3 -7
- package/dist/ingest/gherkinValidation.d.ts.map +1 -1
- package/dist/ingest/gherkinValidation.js +3 -7
- package/dist/ingest/gherkinValidation.js.map +1 -1
- package/dist/ingest/ingestQualityChecks.d.ts +25 -54
- package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
- package/dist/ingest/ingestQualityChecks.js +112 -145
- package/dist/ingest/ingestQualityChecks.js.map +1 -1
- package/dist/ingest/ingestScenarios.d.ts +11 -17
- package/dist/ingest/ingestScenarios.d.ts.map +1 -1
- package/dist/ingest/ingestScenarios.js +52 -62
- package/dist/ingest/ingestScenarios.js.map +1 -1
- package/dist/ingest/inputShapes.d.ts +47 -0
- package/dist/ingest/inputShapes.d.ts.map +1 -0
- package/dist/ingest/inputShapes.js +143 -0
- package/dist/ingest/inputShapes.js.map +1 -0
- 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 +27 -25
- package/dist/run-management/keptRun.d.ts.map +1 -1
- package/dist/run-management/keptRun.js +20 -21
- package/dist/run-management/keptRun.js.map +1 -1
- package/dist/storedRun.d.ts +27 -0
- package/dist/storedRun.d.ts.map +1 -0
- package/dist/storedRun.js +49 -0
- package/dist/storedRun.js.map +1 -0
- package/package.json +2 -2
- 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 -51
- package/dist/mutation-ratchet/index.d.ts.map +0 -1
- package/dist/mutation-ratchet/index.js +0 -51
- 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,156 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE MEASUREMENT — a gate's run, counted out of its mutation report's own mutants
|
|
3
|
-
* (@SCN-MUT-007, 3F-2799, 3F-3337).
|
|
4
|
-
*
|
|
5
|
-
* THE RATCHET THAT RECONCILED THIS IS GONE; THE READER IS NOT (3F-3337). Its one remaining caller
|
|
6
|
-
* is `tests/checks/mutationScoreCli.ts` — `pnpm mutation:score`, the producer that posts
|
|
7
|
-
* SCN-FIT-002's number — which takes the two counts out of this and divides them. @SCN-MUT-007 and
|
|
8
|
-
* @SCN-MUT-008 are what specify it now, and they state the same two things this file states: the
|
|
9
|
-
* valid population is the killed and the timed-out over those plus the survived and the
|
|
10
|
-
* never-covered, and a run with no readable report posts nothing rather than a count of zero.
|
|
11
|
-
*
|
|
12
|
-
* STATED, NEVER INFERRED, AND THAT IS THE WHOLE MODULE. A mutation report groups its mutants by
|
|
13
|
-
* the file they were made in and gives each one a status. The metric scores two of those statuses
|
|
14
|
-
* over four: the kills are the killed and the timed-out, and the population is those plus the
|
|
15
|
-
* survived and the never-covered. Both sets are written down below, member by member, and the four
|
|
16
|
-
* statuses left over — a mutant that would not compile, one that faulted at run time, one the run
|
|
17
|
-
* was told to ignore, and one that never got as far as being tried — are in neither.
|
|
18
|
-
*
|
|
19
|
-
* THE LENIENT READING IS ONE SENTENCE LONG, AND IT IS WRONG. "Everything not detected is
|
|
20
|
-
* undetected" reaches a population without anybody having to write a second set down, and it folds
|
|
21
|
-
* all four of those statuses into the denominator. A mutant that would not compile is not a
|
|
22
|
-
* survivor: nobody's assertion failed to catch it, because there was never anything there to catch.
|
|
23
|
-
* So that reading answers with a score which disagrees with the one the run itself printed —
|
|
24
|
-
* quietly, and in the direction of looking worse — and a reconciler holding a second opinion about
|
|
25
|
-
* the very number it is reconciling has stopped being one. Naming the two sets is what makes that
|
|
26
|
-
* disagreement impossible rather than merely unlikely.
|
|
27
|
-
*
|
|
28
|
-
* AND THE REPORT'S OWN THRESHOLDS ARE NOT READ, WHICH IS THE SAME RULING ONE ARTEFACT FURTHER OUT.
|
|
29
|
-
* A report carries the thresholds its own run was configured against, and reading them would be
|
|
30
|
-
* taking the runner's verdict on its own homework as the measurement. The bar lives in the record
|
|
31
|
-
* (SCN-FIT-002's own row, which `stryker.config.mjs` reads back), and the report is only ever
|
|
32
|
-
* asked what happened. Every figure produced here is
|
|
33
|
-
* counted from the mutants; every other number in the document is left where it lies, however
|
|
34
|
-
* conveniently it is shaped.
|
|
35
|
-
*
|
|
36
|
-
* THE COUNTS ARE TAKEN ACROSS THE WHOLE REPORT RATHER THAN A FILE OF IT. The grouping is
|
|
37
|
-
* presentation and nothing more — a gate's population is every mutant under it, wherever the report
|
|
38
|
-
* chose to file it. A counter that stopped at the first file would be green against every report
|
|
39
|
-
* holding exactly one, which is the shape a small fixture takes by default.
|
|
40
|
-
*
|
|
41
|
-
* AND A REPORT THAT CANNOT BE READ, OR THAT HOLDS NO SCORED MUTANT AT ALL, IS REFUSED RATHER THAN
|
|
42
|
-
* SCORED ZERO (@SCN-MUT-008). Zero is a measurement — a run that mutated the scope and killed none
|
|
43
|
-
* of it — and the two must not be spelled the same, because reconciling a zero reaches a regression
|
|
44
|
-
* whose message sends its reader hunting kills that in this case never happened. The refusal comes
|
|
45
|
-
* back as a value rather than a throw, so a caller cannot drop it by forgetting to catch.
|
|
46
|
-
*
|
|
47
|
-
* NOTHING HERE NAMES A PROJECT, A CHECK, A RUNNER, A WORKFLOW OR A REPOSITORY. The shape read below
|
|
48
|
-
* is the report FORMAT's, which is nobody's installation, and the gate's name arrives from the
|
|
49
|
-
* caller rather than out of the document.
|
|
50
|
-
*/
|
|
51
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
52
|
-
/**
|
|
53
|
-
* The statuses that are a kill.
|
|
54
|
-
*
|
|
55
|
-
* A TIMEOUT IS A KILL AND NOT A NEAR-MISS. The mutant changed the code enough that the suite never
|
|
56
|
-
* finished, which is the suite noticing — the same event as an assertion firing, reached by a
|
|
57
|
-
* slower road.
|
|
58
|
-
*/
|
|
59
|
-
const DETECTED = ["Killed", "Timeout"];
|
|
60
|
-
/**
|
|
61
|
-
* The statuses that are in the population and are not a kill.
|
|
62
|
-
*
|
|
63
|
-
* NEVER-COVERED IS COUNTED, AND THAT IS THE HALF A LENIENT READER LOSES BY LEAVING IT OUT. A mutant
|
|
64
|
-
* no test reached is one this suite would not have noticed, which is precisely what the metric
|
|
65
|
-
* measures; dropping it from the denominator would score untested code as though it were not there.
|
|
66
|
-
*/
|
|
67
|
-
const UNDETECTED = ["Survived", "NoCoverage"];
|
|
68
|
-
/** A refusal, as the value it is. */
|
|
69
|
-
function refused(reason) {
|
|
70
|
-
return { ok: false, reason };
|
|
71
|
-
}
|
|
72
|
-
/** Whatever an error carries by way of a sentence, whatever kind of thing was thrown. */
|
|
73
|
-
function raisedBy(cause) {
|
|
74
|
-
return cause instanceof Error ? cause.message : String(cause);
|
|
75
|
-
}
|
|
76
|
-
/** A JSON object — not a list, and not the null a bare `typeof` reads as one. */
|
|
77
|
-
function isMapping(value) {
|
|
78
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Every mutant in the report, flattened out of the per-file grouping it arrived in — or `null`
|
|
82
|
-
* where the document holds no grouping to flatten.
|
|
83
|
-
*
|
|
84
|
-
* THE TWO EMPTINESSES ARE NOT THE SAME AND ARE NOT ANSWERED THE SAME. `null` is a document that
|
|
85
|
-
* never had a files section; an empty list is a section that holds no mutant. Told apart, one
|
|
86
|
-
* reader is sent to the shape of the artefact and the other to the sweep that filled it; folded
|
|
87
|
-
* together, whichever sentence was chosen sends half of them somewhere useless.
|
|
88
|
-
*/
|
|
89
|
-
function mutantsIn(document) {
|
|
90
|
-
const files = document["files"];
|
|
91
|
-
if (!isMapping(files))
|
|
92
|
-
return null;
|
|
93
|
-
return Object.values(files).flatMap((file) => {
|
|
94
|
-
const mutants = isMapping(file) ? file["mutants"] : undefined;
|
|
95
|
-
return Array.isArray(mutants) ? mutants : [];
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
/** How many of these mutants carry a status the given set names. */
|
|
99
|
-
function countOf(mutants, statuses) {
|
|
100
|
-
return mutants.filter((mutant) => statuses.includes(mutant.status)).length;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Count a gate's measurement out of its report's text, or say why there is not one.
|
|
104
|
-
*
|
|
105
|
-
* THE GATE IS THE CALLER'S WORD FOR IT. A report says which files were mutated and nothing about
|
|
106
|
-
* which gate was being run, so a name taken from the document would be a name this module invented.
|
|
107
|
-
*
|
|
108
|
-
* AND SO IS THE PATH, WHICH IS CARRIED PURELY SO A REFUSAL CAN NAME IT — the same reason
|
|
109
|
-
* `parseGateRecords` carries the record file's name. Text has no path of its own, and "no
|
|
110
|
-
* measurement" over a path nothing writes to and "no measurement" over a sweep that never ran are
|
|
111
|
-
* the same sentence with entirely different fixes.
|
|
112
|
-
*/
|
|
113
|
-
export function measurementFromReport(gate, text, reportPath) {
|
|
114
|
-
let document;
|
|
115
|
-
try {
|
|
116
|
-
document = JSON.parse(text);
|
|
117
|
-
}
|
|
118
|
-
catch (cause) {
|
|
119
|
-
return refused(`the report at ${reportPath} is not readable JSON: ${raisedBy(cause)}`);
|
|
120
|
-
}
|
|
121
|
-
if (!isMapping(document)) {
|
|
122
|
-
return refused(`the report at ${reportPath} is not a mutation-report document.`);
|
|
123
|
-
}
|
|
124
|
-
const mutants = mutantsIn(document);
|
|
125
|
-
if (mutants === null) {
|
|
126
|
-
return refused(`the report at ${reportPath} holds no files section.`);
|
|
127
|
-
}
|
|
128
|
-
const detected = countOf(mutants, DETECTED);
|
|
129
|
-
const undetected = countOf(mutants, UNDETECTED);
|
|
130
|
-
if (detected + undetected === 0) {
|
|
131
|
-
return refused(`the report at ${reportPath} holds no scored mutant — the gate measured nothing.`);
|
|
132
|
-
}
|
|
133
|
-
return { ok: true, measurement: { gate, detected, total: detected + undetected } };
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Read a gate's measurement off the tree, refusing an absent report by the path it was sought at.
|
|
137
|
-
*
|
|
138
|
-
* THE PATH ARRIVES RESOLVED, AND THAT IS THE WHOLE OF THIS MODULE'S OPINION ABOUT WHERE A TREE IS.
|
|
139
|
-
* A reader that joined a root of its own — its own installed location, or wherever the process
|
|
140
|
-
* happened to start — is correct only while those coincide with the caller's, which they stop
|
|
141
|
-
* doing the moment this ships as something another repository installs.
|
|
142
|
-
*/
|
|
143
|
-
export function readMutationReport(gate, reportPath) {
|
|
144
|
-
if (!existsSync(reportPath)) {
|
|
145
|
-
return refused(`no report at ${reportPath} — the gate produced no score, or never ran.`);
|
|
146
|
-
}
|
|
147
|
-
let text;
|
|
148
|
-
try {
|
|
149
|
-
text = readFileSync(reportPath, "utf8");
|
|
150
|
-
}
|
|
151
|
-
catch (cause) {
|
|
152
|
-
return refused(`the report at ${reportPath} could not be read: ${raisedBy(cause)}`);
|
|
153
|
-
}
|
|
154
|
-
return measurementFromReport(gate, text, reportPath);
|
|
155
|
-
}
|
|
156
|
-
//# sourceMappingURL=report.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/mutation-ratchet/report.ts"],"names":[],"mappings":"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"}
|