spec-controller 0.1.0-alpha.2 → 0.1.0-alpha.20

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 (49) hide show
  1. package/README.md +22 -3
  2. package/dist/cli-args.d.ts +4 -1
  3. package/dist/cli-args.d.ts.map +1 -1
  4. package/dist/cli-args.js +27 -6
  5. package/dist/cli-args.js.map +1 -1
  6. package/dist/cli-balance/cli.d.ts +18 -1
  7. package/dist/cli-balance/cli.d.ts.map +1 -1
  8. package/dist/cli-balance/cli.js +153 -151
  9. package/dist/cli-balance/cli.js.map +1 -1
  10. package/dist/cli-registry.d.ts +17 -0
  11. package/dist/cli-registry.d.ts.map +1 -1
  12. package/dist/cli-registry.js +18 -7
  13. package/dist/cli-registry.js.map +1 -1
  14. package/dist/cli.js +6 -4
  15. package/dist/cli.js.map +1 -1
  16. package/dist/corpus/cli.d.ts.map +1 -1
  17. package/dist/corpus/cli.js +1 -4
  18. package/dist/corpus/cli.js.map +1 -1
  19. package/dist/deferralTags.d.ts +2 -2
  20. package/dist/deferralTags.js +2 -2
  21. package/dist/host.d.ts +21 -0
  22. package/dist/host.d.ts.map +1 -1
  23. package/dist/host.js +21 -0
  24. package/dist/host.js.map +1 -1
  25. package/dist/ingest/gherkinValidation.d.ts +6 -5
  26. package/dist/ingest/gherkinValidation.d.ts.map +1 -1
  27. package/dist/ingest/gherkinValidation.js +6 -5
  28. package/dist/ingest/gherkinValidation.js.map +1 -1
  29. package/dist/ingest/ingestQualityChecks.d.ts +0 -45
  30. package/dist/ingest/ingestQualityChecks.d.ts.map +1 -1
  31. package/dist/ingest/ingestQualityChecks.js +11 -110
  32. package/dist/ingest/ingestQualityChecks.js.map +1 -1
  33. package/dist/run-management/resolveRunInputs.d.ts +24 -11
  34. package/dist/run-management/resolveRunInputs.d.ts.map +1 -1
  35. package/dist/run-management/resolveRunInputs.js +49 -13
  36. package/dist/run-management/resolveRunInputs.js.map +1 -1
  37. package/package.json +2 -7
  38. package/dist/mutation-ratchet/index.d.ts +0 -46
  39. package/dist/mutation-ratchet/index.d.ts.map +0 -1
  40. package/dist/mutation-ratchet/index.js +0 -46
  41. package/dist/mutation-ratchet/index.js.map +0 -1
  42. package/dist/mutation-ratchet/record.d.ts +0 -178
  43. package/dist/mutation-ratchet/record.d.ts.map +0 -1
  44. package/dist/mutation-ratchet/record.js +0 -314
  45. package/dist/mutation-ratchet/record.js.map +0 -1
  46. package/dist/mutation-ratchet/report.d.ts +0 -109
  47. package/dist/mutation-ratchet/report.d.ts.map +0 -1
  48. package/dist/mutation-ratchet/report.js +0 -156
  49. package/dist/mutation-ratchet/report.js.map +0 -1
@@ -13,10 +13,10 @@
13
13
  * `package.json` to observe each fitness check the corpus cites.
14
14
  */
15
15
  import { readFileSync, existsSync } from "node:fs";
16
- import { basename, join } from "node:path";
16
+ import { basename } from "node:path";
17
17
  import { ciSourcePathsOf } from "./ciSourcePaths.js";
18
18
  import { discoverFeatures } from "./ingestScenarios.js";
19
- import { parseScenarios, countScnOccurrences, parseUntaggedScenarios, proseOnlyCodes, } from "@3f-consulting/spec-controller-core";
19
+ import { parseScenarios, countScnOccurrences, parseUntaggedScenarios, proseOnlyCodes, sharedScnCodesOf, } from "@3f-consulting/spec-controller-core";
20
20
  import { MissingFeatureCorpusError, UnreadableFeatureCorpusError, } from "./gherkinValidation.js";
21
21
  import { DEFAULT_DEFERRAL_TAGS } from "../deferralTags.js";
22
22
  import { evidenceObligations, } from "@3f-consulting/spec-controller-core";
@@ -30,12 +30,6 @@ import { parseCucumberEvidenceObservations, } from "@3f-consulting/spec-controll
30
30
  // their CALLER. What is left here is the reads: this edge opens the files and hands the bytes over.
31
31
  import { evidenceReconciliationFromSources } from "@3f-consulting/spec-controller-core";
32
32
  import { resolveTargetRoot } from "../run-management/resolveRunInputs.js";
33
- // The record reader, reached for the RECORD half of a bar that names a gate (@SCN-MUT-012): its
34
- // conventional record name, its parser, and the floor a gate's own figures imply. Through the
35
- // barrel, which is the surface a caller holds. (The directory is still spelled `mutation-ratchet`
36
- // and the ratchet it was named for is deleted — 3F-3337 left the name standing rather than move a
37
- // module inside a delete; filed as a finding.)
38
- import { gateRecordFor, killFloorOf, MalformedRecordError, parseGateRecords, RECORD_FILE, } from "../mutation-ratchet/index.js";
39
33
  /**
40
34
  * The per-input FALLBACK quality-check for each JS-ecosystem result source — the
41
35
  * source→quality-check mapping, SET at the CLI edge rather than hardcoded in the core
@@ -61,67 +55,6 @@ const CUCUMBER_QUALITY_CHECK = "integration";
61
55
  * (`parse/commandRuns`), so this names the reconciliation and nothing else the tool can do.
62
56
  */
63
57
  const RECONCILER_INVOCATION = "spec-controller balance";
64
- /**
65
- * A refusal met with an absent bar rather than let out of this edge.
66
- *
67
- * NOTHING IS THROWN OUT OF HERE, and that is the stance rather than caution. A refusal that escapes
68
- * costs the whole run its verdict over one bad character in a file nobody may even be reading — a
69
- * fault that is loud nowhere, where an absent bar is loud on the ledger. It is `thresholdsOf`'s own
70
- * stance for a malformed entry, applied to the half of a bar that now lives in a second file.
71
- *
72
- * TWO CLASSES AND NO MORE. The record library normalises every fault it can see — the YAML parser's
73
- * own included — into `MalformedRecordError` precisely so a caller catches all of them by catching
74
- * one; beside it sits the read that never got as far as a record. A bare catch would swallow a
75
- * defect in this edge as well, and answer it with the same silent absence.
76
- */
77
- function orNoBar(read) {
78
- try {
79
- return read();
80
- }
81
- catch (cause) {
82
- if (cause instanceof MalformedRecordError || isReadRefusal(cause))
83
- return null;
84
- throw cause;
85
- }
86
- }
87
- /** A filesystem refusal — the record was not there, or could not be opened. */
88
- function isReadRefusal(cause) {
89
- return cause instanceof Error && typeof cause.code === "string";
90
- }
91
- /**
92
- * A reader over ONE resolution pass's records.
93
- *
94
- * EACH RECORD IS OPENED ONCE, WHICH IS WHY THIS IS A CLOSURE AND NOT A FUNCTION PER REFERENCE. A
95
- * manifest may name several gates of one record, and a reader opening it per entry would let two
96
- * references answer for two different states of the same file — a rewrite landing mid-pass, a gate
97
- * present for one and gone for the next. One read makes the pass's bars one reading of one record.
98
- *
99
- * THE REFUSAL IS REMEMBERED TOO. Cacheing only the successes would re-open an absent or unreadable
100
- * record per reference, which is the same disagreement by the other door — and the likelier door,
101
- * since a record being rewritten is unreadable for exactly the window that matters.
102
- *
103
- * THE SUBTRACTION IS THE RECORD'S, NOT THIS EDGE'S. `killFloorOf` spends the allowance; an edge
104
- * computing `detected - slack` itself would be a second place holding a fact about the record.
105
- */
106
- export function killFloorReaderFor(root
107
- // The reader's shape is SPELLED here rather than imported, and that is the boundary working
108
- // rather than a duplication. `KillFloorReader` and the reference it takes are core-internal —
109
- // the registry-home question (increment D) still governs them — and this module is published, so
110
- // naming them by their `./internal` types would put an unpublished specifier back in the tarball
111
- // for a type alone. Structural typing is what makes the closure the engine's parameter accepts.
112
- ) {
113
- const opened = new Map();
114
- return (reference) => {
115
- const recordFile = reference.recordFile ?? RECORD_FILE;
116
- if (!opened.has(recordFile)) {
117
- opened.set(recordFile, orNoBar(() => parseGateRecords(readFileSync(join(root, recordFile), "utf8"), recordFile)));
118
- }
119
- const records = opened.get(recordFile);
120
- if (records == null)
121
- return null;
122
- return orNoBar(() => killFloorOf(gateRecordFor(reference.mutationGate, records, recordFile)));
123
- };
124
- }
125
58
  /** Read + JSON-parse a file if present, else return undefined. */
126
59
  function readJsonIfPresent(path) {
127
60
  if (!path || !existsSync(path))
@@ -217,35 +150,6 @@ export function featureCorpusParseErrors(featuresDir) {
217
150
  throw err;
218
151
  }
219
152
  }
220
- /**
221
- * The `@SCN` ids the feature corpus CARRIES MORE THAN ONCE (@SCN-LDG-020's guardrail, 3F-1775).
222
- *
223
- * An `@SCN` identifies exactly ONE scenario — that is the whole basis of attributing evidence to
224
- * it. If two scenarios carry the same id, a test citing it could be proving EITHER, and the tool
225
- * cannot know which: the corpus is ambiguous, and any verdict over it is a guess.
226
- *
227
- * WHY THIS EXISTS. Tag inheritance made this reachable: an `@SCN` hoisted to a `Feature:`/`Rule:`
228
- * is inherited by every scenario beneath it (cucumber does this, so we do — parity). Left
229
- * unhandled, ONE passing test then marked EVERY scenario sharing that id `balanced`, including
230
- * scenarios nothing proves — a BALANCED-WHEN-BROKEN run, exit 0. A new silent false-green,
231
- * introduced by the very fix that closed the last one.
232
- *
233
- * Refused at the edge (exit 2) rather than reconciled, under the Rule already shipped for the
234
- * observed side and the corrupt corpus (@SCN-CLI-014/015/016): an input the tool cannot read is a
235
- * usage error, never a verdict. Whether hoisting an `@SCN` is an authoring fault worth a richer
236
- * diagnostic is the deferred policy question (3F-1774's sibling); refusing to reconcile a corpus we
237
- * cannot read is not a policy — it is the floor.
238
- */
239
- export function featureCorpusDuplicateScnIds(featuresDir) {
240
- const seen = new Set();
241
- const duplicates = new Set();
242
- for (const scenario of scenariosFromFeatures(featuresDir)) {
243
- if (seen.has(scenario.scnId))
244
- duplicates.add(scenario.scnId);
245
- seen.add(scenario.scnId);
246
- }
247
- return [...duplicates].sort();
248
- }
249
153
  /**
250
154
  * Read the target's `feature-code → slug` map over the same `discoverFeatures` corpus
251
155
  * (@SCN-RPT-006) — each coded feature file's `@<FFF>` header (`featureCode`)
@@ -283,9 +187,11 @@ export function readEvidenceObligations(features) {
283
187
  let scenarioCount = 0;
284
188
  const untagged = [];
285
189
  const sources = [];
190
+ const files = [];
286
191
  for (const f of featureFiles) {
287
192
  const source = readFileSync(f.path, "utf8");
288
193
  sources.push(source);
194
+ files.push({ feature: `${f.slug}.feature`, source });
289
195
  raw += countScnOccurrences(source);
290
196
  scenarioCount += parseScenarios(source).length;
291
197
  for (const scenario of parseUntaggedScenarios(source)) {
@@ -295,7 +201,7 @@ export function readEvidenceObligations(features) {
295
201
  untagged.sort((a, b) => a.feature.localeCompare(b.feature) || a.scenario.localeCompare(b.scenario));
296
202
  // The prose-only codes are a CROSS-CORPUS difference (a code tagged in any file isn't
297
203
  // dangling), so it reads all sources at once — not per-file like the others.
298
- return evidenceObligations(raw, scenarioCount, untagged, proseOnlyCodes(sources));
204
+ return evidenceObligations(raw, scenarioCount, untagged, proseOnlyCodes(sources), sharedScnCodesOf(files));
299
205
  }
300
206
  /**
301
207
  * Parse the target's RUNTIME observations ONCE — the tag-derived, per-tier observation set
@@ -323,9 +229,8 @@ export function runReconcile(opts) {
323
229
  const pkgPath = opts.packageJson ?? "package.json";
324
230
  const packageJson = readJsonIfPresent(pkgPath) ?? {};
325
231
  // The TARGET repo root — the credit locators are made relative to it, so a phantom-scenario row's
326
- // where-to-fix (ruling Q5) stays portable in a banked artefact, and a bar naming a mutation gate
327
- // finds that target's record rather than this tool's own (@SCN-MUT-012). Resolved ONCE here and
328
- // threaded, which is also what keeps `execFileSync` and `process.cwd()` out of the engine.
232
+ // where-to-fix (ruling Q5) stays portable in a banked artefact. Resolved ONCE here and threaded,
233
+ // which is also what keeps `execFileSync` and `process.cwd()` out of the engine.
329
234
  const root = resolveTargetRoot({ features: opts.features });
330
235
  // `--ci` names a workflow FILE or a DIRECTORY of them, and defaults to the directory
331
236
  // (@SCN-USG-006, 3F-2238): a pipeline split across files enforces its checks just as one
@@ -355,26 +260,22 @@ export function runReconcile(opts) {
355
260
  // half of the entry that does not come out of the workflow's own text. The directory it sits
356
261
  // in is the caller's `--ci`, not the consumer's subject, so it is not part of what they write.
357
262
  ciSourceNames: ciPaths.map((path) => basename(path)),
358
- measurements: readJsonIfPresent(opts.measurements) ?? {},
359
263
  // The CONVERTED checks' credit stream, read at this edge like every other report. Absent it is
360
264
  // undefined rather than empty, and that distinction reaches the reader (@SCN-LNT-027): "no
361
265
  // record" is a run nobody recorded, "a record holding nothing" is a run that recorded none of
362
266
  // these steps, and those are opposite facts.
363
- // STRUCTURALLY, NOT BY NAME, for the reason `measurements` above is read that way: this module
364
- // travels in the tarball and reaches core through the PUBLIC barrel alone (3F-3086), and
267
+ // STRUCTURALLY, NOT BY NAME: this module travels in the tarball and reaches core through the PUBLIC barrel alone (3F-3086), and
365
268
  // `CiStepRecord` is not on it. The shape is the document's, which is the consumer's, so what is
366
269
  // written here is what the file holds rather than a contract owed to anyone.
367
270
  ciStepRecord: readJsonIfPresent(opts.ciSteps),
368
271
  runtimeObservations: parseRuntimeObservations(opts, root),
369
- // The three things the engine's resolvers cannot hold, and each for its own reason: the
370
- // starter deferral set is the application layer's own policy, how this tool is invoked to
371
- // reconcile is a fact about this product's command line, and the reader opens a file on the
372
- // target's tree. THE PREFIX SET USED TO SIT HERE AND IS GONE (@SCN-USG-004, 3F-3343): the
272
+ // The two things the engine's resolvers cannot hold, and each for its own reason: the
273
+ // starter deferral set is the application layer's own policy, and how this tool is invoked to
274
+ // reconcile is a fact about this product's command line. THE PREFIX SET USED TO SIT HERE AND IS GONE (@SCN-USG-004, 3F-3343): the
373
275
  // engine no longer decides a check's membership by its name, so there is no convention left
374
276
  // for this edge to own.
375
277
  deferralTags: DEFAULT_DEFERRAL_TAGS,
376
278
  reconcilerInvocation: RECONCILER_INVOCATION,
377
- killFloor: killFloorReaderFor(root),
378
279
  });
379
280
  }
380
281
  // The static-check kind-counts are no longer read as a parallel census (@SCN-USG-001 / 3F-2118):
@@ -1 +1 @@
1
- {"version":3,"file":"ingestQualityChecks.js","sourceRoot":"","sources":["../../src/ingest/ingestQualityChecks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAA0B,MAAM,sBAAsB,CAAC;AAChF,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,GACf,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,yBAAyB,EACzB,4BAA4B,GAE7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EACL,mBAAmB,GAGpB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,+BAA+B,GAEhC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,iCAAiC,GAElC,MAAM,qCAAqC,CAAC;AAC7C,mGAAmG;AACnG,yFAAyF;AACzF,yFAAyF;AACzF,gGAAgG;AAChG,iGAAiG;AACjG,oGAAoG;AACpG,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAExF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,gGAAgG;AAChG,8FAA8F;AAC9F,kGAAkG;AAClG,kGAAkG;AAClG,+CAA+C;AAC/C,OAAO,EACL,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,GAEZ,MAAM,8BAA8B,CAAC;AAQtC;;;;;;GAMG;AACH,MAAM,oBAAoB,GAAwB,MAAM,CAAC;AACzD,MAAM,sBAAsB,GAAwB,aAAa,CAAC;AAElE;;;;;;;;;;;;;;GAcG;AACH,MAAM,qBAAqB,GAAG,yBAAyB,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,SAAS,OAAO,CAAI,IAAa;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,oBAAoB,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,YAAY,KAAK,IAAI,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,CAAC;AAC7F,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY;AACZ,4FAA4F;AAC5F,8FAA8F;AAC9F,iGAAiG;AACjG,iGAAiG;AACjG,gGAAgG;;IAEhG,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkD,CAAC;IACzE,OAAO,CAAC,SAAS,EAAE,EAAE;QACnB,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,IAAI,WAAW,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,CACR,UAAU,EACV,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC,CAC1F,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,OAAO,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAChG,CAAC,CAAC;AACJ,CAAC;AAqCD,kEAAkE;AAClE,SAAS,iBAAiB,CAAI,IAAwB;IACpD,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAM,CAAC;AACrD,CAAC;AACD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAS,aAAa,CAAC,WAA+B;IACpD,IAAI,CAAC;QACH,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,yBAAyB;YAAE,OAAO,EAAE,CAAC;QACxD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,WAA+B;IACrD,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,qBAAqB,CAC5B,WAA+B,EAC/B,eAAkC,qBAAqB;IAEvD,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,6BAA6B,CAAC,WAA+B;IACpE,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,sBAAsB,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CACtD,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,cAAc,QAAQ,EAAE,CAChD,CACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAA+B;IACtE,IAAI,CAAC;QACH,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,4BAA4B;YAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACxE,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,4BAA4B,CAAC,WAA+B;IAC1E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,KAAK,MAAM,QAAQ,IAAI,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1D,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAoB;IACnD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAiB;IACvD,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACnC,aAAa,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;QAC/C,KAAK,MAAM,QAAQ,IAAI,sBAAsB,CAAC,MAAM,CAAC,EAAE,CAAC;YACtD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,IAAI,CACX,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CACrF,CAAC;IACF,sFAAsF;IACtF,6EAA6E;IAC7E,OAAO,mBAAmB,CAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,wBAAwB,CAAC,IAAsB,EAAE,IAAwB;IAChF,MAAM,GAAG,GAA0B,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,iBAAiB,CAAmB,IAAI,CAAC,MAAM,CAAC,CAAC;IACtE,IAAI,YAAY;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,+BAA+B,CAAC,YAAY,EAAE,oBAAoB,EAAE,IAAI,CAAC,CAAC,CAAC;IACzG,MAAM,cAAc,GAAG,iBAAiB,CAAqB,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5E,IAAI,cAAc;QAAE,GAAG,CAAC,IAAI,CAAC,GAAG,iCAAiC,CAAC,cAAc,EAAE,sBAAsB,EAAE,IAAI,CAAC,CAAC,CAAC;IACjH,OAAO,GAAG,CAAC;AACb,CAAC;AA0BD,MAAM,UAAU,YAAY,CAAC,IAAsB;IACjD,gGAAgG;IAChG,gGAAgG;IAChG,yFAAyF;IACzF,iCAAiC;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,IAAI,cAAc,CAAC;IACnD,MAAM,WAAW,GAAG,iBAAiB,CAAiB,OAAO,CAAC,IAAI,EAAE,CAAC;IACrE,kGAAkG;IAClG,iGAAiG;IACjG,gGAAgG;IAChG,2FAA2F;IAC3F,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5D,qFAAqF;IACrF,yFAAyF;IACzF,wFAAwF;IACxF,oFAAoF;IACpF,0FAA0F;IAC1F,8BAA8B;IAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,IAAI,mBAAmB,CAAC;IAC9C,gGAAgG;IAChG,6FAA6F;IAC7F,+FAA+F;IAC/F,gGAAgG;IAChG,mEAAmE;IACnE,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAExC,OAAO,iCAAiC,CAAC;QACvC,6FAA6F;QAC7F,wFAAwF;QACxF,6DAA6D;QAC7D,cAAc,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7C,8FAA8F;QAC9F,0EAA0E;QAC1E,iBAAiB,EAAE,6BAA6B,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC/D,WAAW;QACX,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5D,6FAA6F;QAC7F,2FAA2F;QAC3F,6FAA6F;QAC7F,+FAA+F;QAC/F,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpD,YAAY,EAAE,iBAAiB,CAA6B,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QACpF,+FAA+F;QAC/F,2FAA2F;QAC3F,8FAA8F;QAC9F,6CAA6C;QAC7C,+FAA+F;QAC/F,yFAAyF;QACzF,gGAAgG;QAChG,6EAA6E;QAC7E,YAAY,EAAE,iBAAiB,CAC7B,IAAI,CAAC,OAAO,CACb;QACD,mBAAmB,EAAE,wBAAwB,CAAC,IAAI,EAAE,IAAI,CAAC;QACzD,wFAAwF;QACxF,0FAA0F;QAC1F,4FAA4F;QAC5F,0FAA0F;QAC1F,4FAA4F;QAC5F,wBAAwB;QACxB,YAAY,EAAE,qBAAqB;QACnC,oBAAoB,EAAE,qBAAqB;QAC3C,SAAS,EAAE,kBAAkB,CAAC,IAAI,CAAC;KACpC,CAAC,CAAC;AACL,CAAC;AAED,iGAAiG;AACjG,8FAA8F;AAC9F,gGAAgG;AAChG,+FAA+F;AAC/F,oGAAoG;AACpG,yFAAyF"}
1
+ {"version":3,"file":"ingestQualityChecks.js","sourceRoot":"","sources":["../../src/ingest/ingestQualityChecks.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@
6
6
  * CLI (cli-balance/cli.ts) calls these once to build the RunContext.
7
7
  *
8
8
  * Scenarios: @SCN-RPT-001 (the run-provenance slice); the --source-sha override;
9
- * @SCN-RPT-016 (target-root derivation).
9
+ * @SCN-RPT-016 (target-root derivation); @SCN-RPT-026 / @SCN-RPT-029 (the tool's own identity).
10
10
  */
11
11
  /**
12
12
  * Resolve the target's source SHA (project design §4). An explicit non-empty
@@ -32,17 +32,30 @@ export interface ToolIdentity {
32
32
  * distinct from the TARGET's `sourceSha`. Two facts, one call, threaded to both the
33
33
  * report provenance (RunContext) and the run.yaml manifest.
34
34
  *
35
- * **The correctness trap this exists to avoid:** at run time the process cwd is the
36
- * TARGET repo (reconcile runs there), so a bare `git rev-parse HEAD` would re-record the
37
- * TARGET's SHA — the exact bug this ticket fixes. So the SHA is read `git -C <the tool's
38
- * OWN dir>`, derived from `import.meta.url`, never cwd.
35
+ * **TWO TRAPS, AND THIS DOCBLOCK ONLY NAMED THE FIRST FOR ELEVEN WEEKS** (@SCN-RPT-029,
36
+ * 3F-3418). Nothing typechecks a comment, and the sentence below — true, and the whole of
37
+ * what was written here — is what made the second trap read as already-handled.
39
38
  *
40
- * `toolSha` is `git -C <toolDir> rev-parse HEAD` (trimmed), or `null` on any throw — the
41
- * tool installed as a package with no `.git`, git absent, or an empty answer — mirroring
42
- * `resolveSourceSha`'s fail-soft. `toolVersion` is read from the tool's own
43
- * `package.json` (walked up from `toolDir`), or `"unknown"` when none is found — so a run
44
- * stays attributable by version even when no SHA can be read. `toolDir` /
45
- * `packageJsonPath` are injectable for the `@unit` teeth (@SCN-RPT-026).
39
+ * **Trap one, cwd:** at run time the process cwd is the TARGET repo (reconcile runs
40
+ * there), so a bare `git rev-parse HEAD` would re-record the TARGET's SHA. So the SHA is
41
+ * read `git -C <the tool's OWN dir>`, derived from `import.meta.url`, never cwd (3F-1916).
42
+ *
43
+ * **Trap two, which the `-C` guard could not see:** the tool's own dir is ITSELF inside the
44
+ * target. For an installed package that dir is `<consumer>/node_modules/…`, which is inside
45
+ * the consumer's worktree, so `git -C` walks up to the consumer's `.git` and answers with
46
+ * the consumer's HEAD — being `.gitignore`d makes no difference, git does not stop at
47
+ * ignored directories. That is not an absent tool SHA, it is a WRONG one, and nothing on
48
+ * the rendered report distinguishes it from a genuine one. It is also the only case a
49
+ * consumer ever sees: every adopter installs into a git repository. `resolveToolSha`
50
+ * therefore answers a `node_modules` SEGMENT before it asks git at all.
51
+ *
52
+ * `toolSha` is `null` for a tool resolved out of `node_modules`, and otherwise
53
+ * `git -C <toolDir> rev-parse HEAD` (trimmed) or `null` on any throw — no `.git` above the
54
+ * tool, git absent, or an empty answer — mirroring `resolveSourceSha`'s fail-soft.
55
+ * `toolVersion` is read from the tool's own `package.json` (walked up from `toolDir`), or
56
+ * `"unknown"` when none is found — so a run stays attributable by version even when no SHA
57
+ * can be read. `toolDir` / `packageJsonPath` are injectable for the `@unit` teeth
58
+ * (@SCN-RPT-026, @SCN-RPT-029).
46
59
  */
47
60
  export declare function resolveToolIdentity(opts?: {
48
61
  toolDir?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"resolveRunInputs.d.ts","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAiBhG;AAED,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,mGAAmG;IACnG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2FAA2F;IAC3F,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAQ3G;AA2CD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAerE"}
1
+ {"version":3,"file":"resolveRunInputs.d.ts","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAiBhG;AAED,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,mGAAmG;IACnG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2FAA2F;IAC3F,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAQ3G;AAiED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAerE"}
@@ -6,11 +6,11 @@
6
6
  * CLI (cli-balance/cli.ts) calls these once to build the RunContext.
7
7
  *
8
8
  * Scenarios: @SCN-RPT-001 (the run-provenance slice); the --source-sha override;
9
- * @SCN-RPT-016 (target-root derivation).
9
+ * @SCN-RPT-016 (target-root derivation); @SCN-RPT-026 / @SCN-RPT-029 (the tool's own identity).
10
10
  */
11
11
  import { execFileSync } from "node:child_process";
12
12
  import { readFileSync } from "node:fs";
13
- import { dirname, join } from "node:path";
13
+ import { dirname, join, sep } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
15
  /**
16
16
  * Resolve the target's source SHA (project design §4). An explicit non-empty
@@ -44,17 +44,30 @@ export function resolveSourceSha(opts) {
44
44
  * distinct from the TARGET's `sourceSha`. Two facts, one call, threaded to both the
45
45
  * report provenance (RunContext) and the run.yaml manifest.
46
46
  *
47
- * **The correctness trap this exists to avoid:** at run time the process cwd is the
48
- * TARGET repo (reconcile runs there), so a bare `git rev-parse HEAD` would re-record the
49
- * TARGET's SHA — the exact bug this ticket fixes. So the SHA is read `git -C <the tool's
50
- * OWN dir>`, derived from `import.meta.url`, never cwd.
47
+ * **TWO TRAPS, AND THIS DOCBLOCK ONLY NAMED THE FIRST FOR ELEVEN WEEKS** (@SCN-RPT-029,
48
+ * 3F-3418). Nothing typechecks a comment, and the sentence below — true, and the whole of
49
+ * what was written here — is what made the second trap read as already-handled.
51
50
  *
52
- * `toolSha` is `git -C <toolDir> rev-parse HEAD` (trimmed), or `null` on any throw — the
53
- * tool installed as a package with no `.git`, git absent, or an empty answer — mirroring
54
- * `resolveSourceSha`'s fail-soft. `toolVersion` is read from the tool's own
55
- * `package.json` (walked up from `toolDir`), or `"unknown"` when none is found — so a run
56
- * stays attributable by version even when no SHA can be read. `toolDir` /
57
- * `packageJsonPath` are injectable for the `@unit` teeth (@SCN-RPT-026).
51
+ * **Trap one, cwd:** at run time the process cwd is the TARGET repo (reconcile runs
52
+ * there), so a bare `git rev-parse HEAD` would re-record the TARGET's SHA. So the SHA is
53
+ * read `git -C <the tool's OWN dir>`, derived from `import.meta.url`, never cwd (3F-1916).
54
+ *
55
+ * **Trap two, which the `-C` guard could not see:** the tool's own dir is ITSELF inside the
56
+ * target. For an installed package that dir is `<consumer>/node_modules/…`, which is inside
57
+ * the consumer's worktree, so `git -C` walks up to the consumer's `.git` and answers with
58
+ * the consumer's HEAD — being `.gitignore`d makes no difference, git does not stop at
59
+ * ignored directories. That is not an absent tool SHA, it is a WRONG one, and nothing on
60
+ * the rendered report distinguishes it from a genuine one. It is also the only case a
61
+ * consumer ever sees: every adopter installs into a git repository. `resolveToolSha`
62
+ * therefore answers a `node_modules` SEGMENT before it asks git at all.
63
+ *
64
+ * `toolSha` is `null` for a tool resolved out of `node_modules`, and otherwise
65
+ * `git -C <toolDir> rev-parse HEAD` (trimmed) or `null` on any throw — no `.git` above the
66
+ * tool, git absent, or an empty answer — mirroring `resolveSourceSha`'s fail-soft.
67
+ * `toolVersion` is read from the tool's own `package.json` (walked up from `toolDir`), or
68
+ * `"unknown"` when none is found — so a run stays attributable by version even when no SHA
69
+ * can be read. `toolDir` / `packageJsonPath` are injectable for the `@unit` teeth
70
+ * (@SCN-RPT-026, @SCN-RPT-029).
58
71
  */
59
72
  export function resolveToolIdentity(opts = {}) {
60
73
  const toolDir = opts.toolDir !== undefined && opts.toolDir.trim() !== ""
@@ -65,8 +78,31 @@ export function resolveToolIdentity(opts = {}) {
65
78
  toolVersion: resolveToolVersion(opts.packageJsonPath ?? findPackageJson(toolDir)),
66
79
  };
67
80
  }
68
- /** The tool's own git HEAD, read `-C <toolDir>` (never cwd), null on any throw. */
81
+ /**
82
+ * The tool's own git HEAD, read `-C <toolDir>` (never cwd), null on any throw — and null
83
+ * without asking at all for a tool resolved out of `node_modules` (@SCN-RPT-029).
84
+ *
85
+ * A SEGMENT, NEVER A SUBSTRING. A directory honestly named `my_node_modules_backup` is not an
86
+ * install, and a checkout living under a directory literally named `node_modules` reporting null is
87
+ * the pathological trade every tool making this distinction takes.
88
+ *
89
+ * `sep`, NOT A REGEX OVER BOTH SEPARATORS. `[/\\]` would carry a branch no arm on this platform can
90
+ * reach, so a mutant deleting its second half would survive the mutation gate while nothing was
91
+ * worse. `sep` is what `fileURLToPath` produces on each platform, which is the only thing `toolDir`
92
+ * is ever built from.
93
+ *
94
+ * IT ANSWERS BEFORE THE `try`, NOT INSIDE IT. Returning null from a thrown git read and returning
95
+ * null because the tool is an install are the same recorded answer and not the same fact, and only
96
+ * the first of them is allowed to depend on git being present.
97
+ *
98
+ * WHAT IT DOES NOT CLAIM. Under `--preserve-symlinks` Node reports the symlink path rather than the
99
+ * realpath, so a linked development checkout would carry a `node_modules` segment and report null.
100
+ * That is a strictly safer wrong answer than today's, nothing in this repository passes the flag,
101
+ * and no arm covers it — named rather than guarded.
102
+ */
69
103
  function resolveToolSha(toolDir) {
104
+ if (toolDir.split(sep).includes("node_modules"))
105
+ return null;
70
106
  try {
71
107
  const out = execFileSync("git", ["-C", toolDir, "rev-parse", "HEAD"], {
72
108
  encoding: "utf8",
@@ -1 +1 @@
1
- {"version":3,"file":"resolveRunInputs.js","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolveRunInputs.js","sourceRoot":"","sources":["../../src/run-management/resolveRunInputs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-controller",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.20",
4
4
  "description": "Reconcile the behaviour your scenarios name against the evidence that actually ran — the deterministic `balance` CLI.",
5
5
  "keywords": [
6
6
  "reconciliation",
@@ -10,11 +10,6 @@
10
10
  "double-entry",
11
11
  "cli"
12
12
  ],
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/3f-consulting/spec-controller.git",
16
- "directory": "packages/spec-controller"
17
- },
18
13
  "license": "MIT",
19
14
  "type": "module",
20
15
  "engines": {
@@ -30,7 +25,7 @@
30
25
  "@cucumber/gherkin": "^41.0.0",
31
26
  "@cucumber/messages": "^34.0.1",
32
27
  "yaml": "^2.9.0",
33
- "@3f-consulting/spec-controller-core": "0.1.0-alpha.2"
28
+ "@3f-consulting/spec-controller-core": "0.1.0-alpha.20"
34
29
  },
35
30
  "publishConfig": {
36
31
  "access": "public"
@@ -1,46 +0,0 @@
1
- /**
2
- * THE MODULE'S OWN SURFACE — curated symbol by symbol, never a re-export of the tree behind it
3
- * (3F-2804, 3F-3337).
4
- *
5
- * WHAT IS BEHIND THIS BARREL NOW IS TWO READERS, AND THE RATCHET THEY WERE BUILT FOR IS GONE
6
- * (3F-3337). `record.ts` reads a target's banked gate record and hands back the kill floor it
7
- * implies; `report.ts` counts a mutation report's own mutants into a measurement. What left with
8
- * the ratchet is everything that COMPARED the two — the verdicts, the up-only recorder, the
9
- * reconciliation entry and the command that ended on it — because this repository's gate is now a
10
- * per-mutant comparison the runner keeps, and nothing types a mutation count here any more.
11
- *
12
- * ITS TWO CONSUMERS ARE BOTH IN THIS TREE, AND THEY WANT DIFFERENT HALVES. `ingest/
13
- * ingestQualityChecks.ts` wants the RECORD half: the engine's `mutationGate` bar kind lets a target
14
- * author a fitness row naming a gate instead of a figure, which is a published capability decided
15
- * over a target's own record (@SCN-MUT-012, @SCN-MUT-013). `tests/checks/mutationScoreCli.ts` wants
16
- * the REPORT half: `pnpm mutation:score` takes the two counts out of a sweep's report and divides
17
- * them (@SCN-MUT-007, @SCN-MUT-008). Neither wants the other's, which is why both are named here
18
- * rather than the tree behind them being passed on wholesale.
19
- *
20
- * A BARREL THAT RE-EXPORTED EVERY MODULE WOULD BE A CONTRACT NOBODY WROTE. Each module below
21
- * exports what its own siblings need from it, and sibling-visibility is a much wider set than
22
- * consumer-visibility. Passing that set on wholesale would freeze every one of them as something a
23
- * caller may depend on, and the first refactor that moved one would be a breaking change nobody
24
- * meant to make. So this file names what a caller may hold and the omissions are decisions.
25
- *
26
- * THE KILL FLOOR IS THE BAR, AND IT IS NOT A SCORE (3F-2788). `killFloorOf` answers a ledger
27
- * holding a measured row to the figure a gate's own record implies, in mutants — a percentage would
28
- * fold the kill lost and the population grown into one number, which is the distinction a bar on
29
- * this axis exists to keep. A consumer that derived it instead would be the second place knowing
30
- * how an allowance is spent.
31
- *
32
- * THE TYPES ARE SPELLED FOR A CONSUMER'S NAMESPACE RATHER THAN FOR THIS MODULE'S. `GateRecord` is
33
- * unambiguous inside a directory about nothing else; imported into a repository that has gates of
34
- * several kinds it is not, so it crosses this line under the fuller name. The aliasing is
35
- * deliberate and one-directional: the internal spelling stays internal.
36
- *
37
- * AND NO DRIFT GUARD STANDS OVER IT, WHICH IS A DECISION RATHER THAN AN OPEN QUESTION. The sibling
38
- * core package's barrel is reflected and compared against a frozen list in both directions, so a
39
- * symbol quietly added or dropped reds. That is what a PUBLISHED surface is owed, and 3F-2859
40
- * stopped publishing this one: no manifest key resolves here, and no caller outside this repository
41
- * can spell the specifier at all. Freezing the list would make every refactor behind this barrel a
42
- * change to a contract nobody holds.
43
- */
44
- export { floorOf, gateRecordFor, killFloorOf, MalformedRecordError, parseGateRecords, RECORD_FILE, type GateRecord as MutationGateRecord, } from "./record.js";
45
- export { measurementFromReport, readMutationReport, type MutationMeasurement, type MutationReportRead, } from "./report.js";
46
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mutation-ratchet/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EACL,OAAO,EACP,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,KAAK,UAAU,IAAI,kBAAkB,GACtC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC"}
@@ -1,46 +0,0 @@
1
- /**
2
- * THE MODULE'S OWN SURFACE — curated symbol by symbol, never a re-export of the tree behind it
3
- * (3F-2804, 3F-3337).
4
- *
5
- * WHAT IS BEHIND THIS BARREL NOW IS TWO READERS, AND THE RATCHET THEY WERE BUILT FOR IS GONE
6
- * (3F-3337). `record.ts` reads a target's banked gate record and hands back the kill floor it
7
- * implies; `report.ts` counts a mutation report's own mutants into a measurement. What left with
8
- * the ratchet is everything that COMPARED the two — the verdicts, the up-only recorder, the
9
- * reconciliation entry and the command that ended on it — because this repository's gate is now a
10
- * per-mutant comparison the runner keeps, and nothing types a mutation count here any more.
11
- *
12
- * ITS TWO CONSUMERS ARE BOTH IN THIS TREE, AND THEY WANT DIFFERENT HALVES. `ingest/
13
- * ingestQualityChecks.ts` wants the RECORD half: the engine's `mutationGate` bar kind lets a target
14
- * author a fitness row naming a gate instead of a figure, which is a published capability decided
15
- * over a target's own record (@SCN-MUT-012, @SCN-MUT-013). `tests/checks/mutationScoreCli.ts` wants
16
- * the REPORT half: `pnpm mutation:score` takes the two counts out of a sweep's report and divides
17
- * them (@SCN-MUT-007, @SCN-MUT-008). Neither wants the other's, which is why both are named here
18
- * rather than the tree behind them being passed on wholesale.
19
- *
20
- * A BARREL THAT RE-EXPORTED EVERY MODULE WOULD BE A CONTRACT NOBODY WROTE. Each module below
21
- * exports what its own siblings need from it, and sibling-visibility is a much wider set than
22
- * consumer-visibility. Passing that set on wholesale would freeze every one of them as something a
23
- * caller may depend on, and the first refactor that moved one would be a breaking change nobody
24
- * meant to make. So this file names what a caller may hold and the omissions are decisions.
25
- *
26
- * THE KILL FLOOR IS THE BAR, AND IT IS NOT A SCORE (3F-2788). `killFloorOf` answers a ledger
27
- * holding a measured row to the figure a gate's own record implies, in mutants — a percentage would
28
- * fold the kill lost and the population grown into one number, which is the distinction a bar on
29
- * this axis exists to keep. A consumer that derived it instead would be the second place knowing
30
- * how an allowance is spent.
31
- *
32
- * THE TYPES ARE SPELLED FOR A CONSUMER'S NAMESPACE RATHER THAN FOR THIS MODULE'S. `GateRecord` is
33
- * unambiguous inside a directory about nothing else; imported into a repository that has gates of
34
- * several kinds it is not, so it crosses this line under the fuller name. The aliasing is
35
- * deliberate and one-directional: the internal spelling stays internal.
36
- *
37
- * AND NO DRIFT GUARD STANDS OVER IT, WHICH IS A DECISION RATHER THAN AN OPEN QUESTION. The sibling
38
- * core package's barrel is reflected and compared against a frozen list in both directions, so a
39
- * symbol quietly added or dropped reds. That is what a PUBLISHED surface is owed, and 3F-2859
40
- * stopped publishing this one: no manifest key resolves here, and no caller outside this repository
41
- * can spell the specifier at all. Freezing the list would make every refactor behind this barrel a
42
- * change to a contract nobody holds.
43
- */
44
- export { floorOf, gateRecordFor, killFloorOf, MalformedRecordError, parseGateRecords, RECORD_FILE, } from "./record.js";
45
- export { measurementFromReport, readMutationReport, } from "./report.js";
46
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mutation-ratchet/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,OAAO,EACL,OAAO,EACP,aAAa,EACb,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,GAEZ,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GAGnB,MAAM,aAAa,CAAC"}