@3f-consulting/spec-controller-core 0.1.0-alpha.5 → 0.1.0-alpha.50
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 +6 -4
- package/dist/assemble/evidenceReconciliationFromSources.d.ts +5 -40
- package/dist/assemble/evidenceReconciliationFromSources.d.ts.map +1 -1
- package/dist/assemble/evidenceReconciliationFromSources.js +31 -319
- package/dist/assemble/evidenceReconciliationFromSources.js.map +1 -1
- package/dist/assemble/renderInput.d.ts +6 -72
- package/dist/assemble/renderInput.d.ts.map +1 -1
- package/dist/assemble/renderInput.js +3 -45
- package/dist/assemble/renderInput.js.map +1 -1
- package/dist/census/evidenceObligations.d.ts +10 -46
- package/dist/census/evidenceObligations.d.ts.map +1 -1
- package/dist/census/evidenceObligations.js +15 -25
- package/dist/census/evidenceObligations.js.map +1 -1
- package/dist/domain/evidenceOrder.d.ts +3 -0
- package/dist/domain/evidenceOrder.d.ts.map +1 -0
- package/dist/domain/evidenceOrder.js +15 -0
- package/dist/domain/evidenceOrder.js.map +1 -0
- package/dist/domain/evidenceReconciliation.d.ts +16 -386
- package/dist/domain/evidenceReconciliation.d.ts.map +1 -1
- package/dist/domain/evidenceReconciliation.js +79 -375
- package/dist/domain/evidenceReconciliation.js.map +1 -1
- package/dist/domain/featureCode.d.ts +4 -0
- package/dist/domain/featureCode.d.ts.map +1 -0
- package/dist/domain/featureCode.js +12 -0
- package/dist/domain/featureCode.js.map +1 -0
- package/dist/domain/journal.d.ts +7 -392
- package/dist/domain/journal.d.ts.map +1 -1
- package/dist/domain/journal.js +6 -118
- package/dist/domain/journal.js.map +1 -1
- package/dist/domain/ledger.d.ts +4 -328
- package/dist/domain/ledger.d.ts.map +1 -1
- package/dist/domain/ledger.js +11 -317
- package/dist/domain/ledger.js.map +1 -1
- package/dist/domain/outcome.d.ts +3 -0
- package/dist/domain/outcome.d.ts.map +1 -0
- package/dist/domain/outcome.js +2 -0
- package/dist/domain/outcome.js.map +1 -0
- package/dist/domain/posting.d.ts +5 -102
- package/dist/domain/posting.d.ts.map +1 -1
- package/dist/domain/posting.js +3 -55
- package/dist/domain/posting.js.map +1 -1
- package/dist/domain/qualityCheckFault.d.ts +1 -41
- package/dist/domain/qualityCheckFault.d.ts.map +1 -1
- package/dist/domain/qualityCheckFault.js +0 -24
- package/dist/domain/qualityCheckFault.js.map +1 -1
- package/dist/domain/qualityCheckFaultMessages.d.ts +0 -35
- package/dist/domain/qualityCheckFaultMessages.d.ts.map +1 -1
- package/dist/domain/qualityCheckFaultMessages.js +0 -28
- package/dist/domain/qualityCheckFaultMessages.js.map +1 -1
- package/dist/domain/qualityCheckReconciliation.d.ts +5 -278
- package/dist/domain/qualityCheckReconciliation.d.ts.map +1 -1
- package/dist/domain/qualityCheckReconciliation.js +53 -453
- package/dist/domain/qualityCheckReconciliation.js.map +1 -1
- package/dist/domain/qualityCheckReconciliationFault.d.ts +0 -19
- package/dist/domain/qualityCheckReconciliationFault.d.ts.map +1 -1
- package/dist/domain/qualityCheckReconciliationFault.js +0 -23
- package/dist/domain/qualityCheckReconciliationFault.js.map +1 -1
- package/dist/domain/scenarioCodeError.d.ts +16 -0
- package/dist/domain/scenarioCodeError.d.ts.map +1 -0
- package/dist/domain/scenarioCodeError.js +4 -0
- package/dist/domain/scenarioCodeError.js.map +1 -0
- package/dist/domain/scenarioReconciliation.d.ts +0 -205
- package/dist/domain/scenarioReconciliation.d.ts.map +1 -1
- package/dist/domain/scenarioReconciliation.js +1 -98
- package/dist/domain/scenarioReconciliation.js.map +1 -1
- package/dist/domain/scnAllocation.d.ts +27 -0
- package/dist/domain/scnAllocation.d.ts.map +1 -0
- package/dist/domain/scnAllocation.js +33 -0
- package/dist/domain/scnAllocation.js.map +1 -0
- package/dist/domain/verdictCode.d.ts +10 -0
- package/dist/domain/verdictCode.d.ts.map +1 -0
- package/dist/domain/verdictCode.js +16 -0
- package/dist/domain/verdictCode.js.map +1 -0
- package/dist/index.d.ts +12 -38
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -86
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -25
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +3 -93
- package/dist/internal.js.map +1 -1
- package/dist/lib/bareTerm.d.ts +0 -39
- package/dist/lib/bareTerm.d.ts.map +1 -1
- package/dist/lib/bareTerm.js +0 -39
- package/dist/lib/bareTerm.js.map +1 -1
- package/dist/lib/portablePath.d.ts.map +1 -1
- package/dist/lib/portablePath.js +0 -14
- package/dist/lib/portablePath.js.map +1 -1
- package/dist/lib/scnCitation.d.ts +0 -32
- package/dist/lib/scnCitation.d.ts.map +1 -1
- package/dist/lib/scnCitation.js +2 -42
- package/dist/lib/scnCitation.js.map +1 -1
- package/dist/model.d.ts +0 -23
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -23
- package/dist/model.js.map +1 -1
- package/dist/parse/checkScriptsRunInCI.d.ts +3 -151
- package/dist/parse/checkScriptsRunInCI.d.ts.map +1 -1
- package/dist/parse/checkScriptsRunInCI.js +5 -143
- package/dist/parse/checkScriptsRunInCI.js.map +1 -1
- package/dist/parse/ciStepRecord.d.ts +2 -117
- package/dist/parse/ciStepRecord.d.ts.map +1 -1
- package/dist/parse/ciStepRecord.js +12 -218
- package/dist/parse/ciStepRecord.js.map +1 -1
- package/dist/parse/commandRuns.d.ts +0 -39
- package/dist/parse/commandRuns.d.ts.map +1 -1
- package/dist/parse/commandRuns.js +0 -58
- package/dist/parse/commandRuns.js.map +1 -1
- package/dist/parse/cucumber.d.ts +0 -52
- package/dist/parse/cucumber.d.ts.map +1 -1
- package/dist/parse/cucumber.js +37 -143
- package/dist/parse/cucumber.js.map +1 -1
- package/dist/parse/discoveryScope.d.ts +0 -45
- package/dist/parse/discoveryScope.d.ts.map +1 -1
- package/dist/parse/discoveryScope.js +0 -55
- package/dist/parse/discoveryScope.js.map +1 -1
- package/dist/parse/fitnessCitations.d.ts +1 -72
- package/dist/parse/fitnessCitations.d.ts.map +1 -1
- package/dist/parse/fitnessCitations.js +3 -55
- package/dist/parse/fitnessCitations.js.map +1 -1
- package/dist/parse/reconcilerSteps.d.ts +0 -46
- package/dist/parse/reconcilerSteps.d.ts.map +1 -1
- package/dist/parse/reconcilerSteps.js +0 -63
- package/dist/parse/reconcilerSteps.js.map +1 -1
- package/dist/parse/runningStaticChecks.d.ts +2 -118
- package/dist/parse/runningStaticChecks.d.ts.map +1 -1
- package/dist/parse/runningStaticChecks.js +14 -273
- package/dist/parse/runningStaticChecks.js.map +1 -1
- package/dist/parse/scenarioCodeErrors.d.ts +12 -0
- package/dist/parse/scenarioCodeErrors.d.ts.map +1 -0
- package/dist/parse/scenarioCodeErrors.js +88 -0
- package/dist/parse/scenarioCodeErrors.js.map +1 -0
- package/dist/parse/scenarios.d.ts +3 -228
- package/dist/parse/scenarios.d.ts.map +1 -1
- package/dist/parse/scenarios.js +11 -447
- package/dist/parse/scenarios.js.map +1 -1
- package/dist/parse/stepAccounting.d.ts +0 -46
- package/dist/parse/stepAccounting.d.ts.map +1 -1
- package/dist/parse/stepAccounting.js +0 -54
- package/dist/parse/stepAccounting.js.map +1 -1
- package/dist/parse/stepExclusions.d.ts +0 -47
- package/dist/parse/stepExclusions.d.ts.map +1 -1
- package/dist/parse/stepExclusions.js +0 -45
- package/dist/parse/stepExclusions.js.map +1 -1
- package/dist/parse/stepNames.d.ts +0 -27
- package/dist/parse/stepNames.d.ts.map +1 -1
- package/dist/parse/stepNames.js +0 -27
- package/dist/parse/stepNames.js.map +1 -1
- package/dist/parse/targetCorpus.d.ts +1 -78
- package/dist/parse/targetCorpus.d.ts.map +1 -1
- package/dist/parse/targetCorpus.js +4 -46
- package/dist/parse/targetCorpus.js.map +1 -1
- package/dist/parse/targetManifest.d.ts +8 -146
- package/dist/parse/targetManifest.d.ts.map +1 -1
- package/dist/parse/targetManifest.js +47 -198
- package/dist/parse/targetManifest.js.map +1 -1
- package/dist/parse/vitest.d.ts +0 -60
- package/dist/parse/vitest.d.ts.map +1 -1
- package/dist/parse/vitest.js +1 -81
- package/dist/parse/vitest.js.map +1 -1
- package/dist/provenance/provenance.d.ts +2 -110
- package/dist/provenance/provenance.d.ts.map +1 -1
- package/dist/provenance/provenance.js +2 -58
- package/dist/provenance/provenance.js.map +1 -1
- package/dist/render/behaviouralRunners.d.ts +0 -29
- package/dist/render/behaviouralRunners.d.ts.map +1 -1
- package/dist/render/behaviouralRunners.js +0 -64
- package/dist/render/behaviouralRunners.js.map +1 -1
- package/dist/render/configurationNotRead.d.ts +3 -0
- package/dist/render/configurationNotRead.d.ts.map +1 -0
- package/dist/render/configurationNotRead.js +17 -0
- package/dist/render/configurationNotRead.js.map +1 -0
- package/dist/render/discoveryScope.d.ts +0 -37
- package/dist/render/discoveryScope.d.ts.map +1 -1
- package/dist/render/discoveryScope.js +0 -37
- package/dist/render/discoveryScope.js.map +1 -1
- package/dist/render/evidenceGrid.d.ts +1 -35
- package/dist/render/evidenceGrid.d.ts.map +1 -1
- package/dist/render/evidenceGrid.js +18 -100
- package/dist/render/evidenceGrid.js.map +1 -1
- package/dist/render/excludedSteps.d.ts +0 -26
- package/dist/render/excludedSteps.d.ts.map +1 -1
- package/dist/render/excludedSteps.js +0 -29
- package/dist/render/excludedSteps.js.map +1 -1
- package/dist/render/json.d.ts +0 -11
- package/dist/render/json.d.ts.map +1 -1
- package/dist/render/json.js +0 -11
- package/dist/render/json.js.map +1 -1
- package/dist/render/markdown.d.ts +0 -54
- package/dist/render/markdown.d.ts.map +1 -1
- package/dist/render/markdown.js +88 -426
- package/dist/render/markdown.js.map +1 -1
- package/dist/render/provenanceSection.d.ts +0 -22
- package/dist/render/provenanceSection.d.ts.map +1 -1
- package/dist/render/provenanceSection.js +0 -44
- package/dist/render/provenanceSection.js.map +1 -1
- package/dist/render/reconcilerSteps.d.ts +0 -25
- package/dist/render/reconcilerSteps.d.ts.map +1 -1
- package/dist/render/reconcilerSteps.js +0 -26
- package/dist/render/reconcilerSteps.js.map +1 -1
- package/dist/render/runVerdict.d.ts +0 -38
- package/dist/render/runVerdict.d.ts.map +1 -1
- package/dist/render/runVerdict.js +68 -127
- package/dist/render/runVerdict.js.map +1 -1
- package/dist/render/scenarioCodeErrorsSection.d.ts +3 -0
- package/dist/render/scenarioCodeErrorsSection.d.ts.map +1 -0
- package/dist/render/scenarioCodeErrorsSection.js +42 -0
- package/dist/render/scenarioCodeErrorsSection.js.map +1 -0
- package/dist/render/staticChecks.d.ts +0 -20
- package/dist/render/staticChecks.d.ts.map +1 -1
- package/dist/render/staticChecks.js +1 -59
- package/dist/render/staticChecks.js.map +1 -1
- package/dist/render/stepAccounting.d.ts +0 -36
- package/dist/render/stepAccounting.d.ts.map +1 -1
- package/dist/render/stepAccounting.js +0 -44
- package/dist/render/stepAccounting.js.map +1 -1
- package/dist/render/testVolume.d.ts +0 -25
- package/dist/render/testVolume.d.ts.map +1 -1
- package/dist/render/testVolume.js +0 -32
- package/dist/render/testVolume.js.map +1 -1
- package/package.json +4 -1
- package/dist/domain/checkCharacteristics.d.ts +0 -88
- package/dist/domain/checkCharacteristics.d.ts.map +0 -1
- package/dist/domain/checkCharacteristics.js +0 -109
- package/dist/domain/checkCharacteristics.js.map +0 -1
- package/dist/domain/fitnessChecks.d.ts +0 -79
- package/dist/domain/fitnessChecks.d.ts.map +0 -1
- package/dist/domain/fitnessChecks.js +0 -81
- package/dist/domain/fitnessChecks.js.map +0 -1
- package/dist/lib/featureCode.d.ts +0 -21
- package/dist/lib/featureCode.d.ts.map +0 -1
- package/dist/lib/featureCode.js +0 -24
- package/dist/lib/featureCode.js.map +0 -1
- package/dist/parse/corpusCodeFaults.d.ts +0 -76
- package/dist/parse/corpusCodeFaults.d.ts.map +0 -1
- package/dist/parse/corpusCodeFaults.js +0 -121
- package/dist/parse/corpusCodeFaults.js.map +0 -1
- package/dist/parse/corpusFaults.d.ts +0 -124
- package/dist/parse/corpusFaults.d.ts.map +0 -1
- package/dist/parse/corpusFaults.js +0 -72
- package/dist/parse/corpusFaults.js.map +0 -1
- package/dist/parse/corpusGrammarFaults.d.ts +0 -71
- package/dist/parse/corpusGrammarFaults.d.ts.map +0 -1
- package/dist/parse/corpusGrammarFaults.js +0 -292
- package/dist/parse/corpusGrammarFaults.js.map +0 -1
package/dist/parse/cucumber.js
CHANGED
|
@@ -1,61 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `ingest/cucumber` reader — the second named observed-evidence reader.
|
|
3
|
-
* Reads Cucumber-JS's JSON formatter output and normalises each scenario that
|
|
4
|
-
* carries an @SCN tag into an EvidenceObservation, LEVELLED by the scenario's own
|
|
5
|
-
* tier tag (@integration / @e2e / @performance).
|
|
6
|
-
*
|
|
7
|
-
* The level is DERIVED from the cited scenario's own tier tag, NOT from the input
|
|
8
|
-
* source (Cucumber-as-orchestrator-across-levels: the scenario NAMES its tier by tag, cucumber
|
|
9
|
-
* runs whichever). An @e2e scenario proven via cucumber yields an e2e observation. The
|
|
10
|
-
* caller-supplied level (the JS-ecosystem default, integration, set at the CLI edge)
|
|
11
|
-
* survives only as the fallback for an UNTAGGED scenario. The reader classifies FOUR-WAY
|
|
12
|
-
* (@SCN-PND-013, extended by @SCN-LDG-019): any AMBIGUOUS step → a `broken` observation (a broken
|
|
13
|
-
* harness — two step definitions match, so the step cannot run); any failed step → a `failed`
|
|
14
|
-
* observation; all passed → a `passed` observation; otherwise INCONCLUSIVE (undefined/pending/
|
|
15
|
-
* skipped) → the scenario is DROPPED (no observation), so its obligation reconciles missing by
|
|
16
|
-
* absence — pending is never inferred from status.
|
|
17
|
-
*
|
|
18
|
-
* Parent: @SCN-LDG-011 (the tag-derivation headline) over @SCN-LDG-001 (the foundation seam).
|
|
19
|
-
*/
|
|
20
1
|
import { relativizeToRoot } from "../lib/portablePath.js";
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
*
|
|
24
|
-
* IT USED TO BE EXPORTED FOR A SECOND READER OF THIS SAME DOCUMENT — the fitness pass's own
|
|
25
|
-
* cucumber report, read by `convertedFitnessCredits` (@SCN-LNT-021). That pass and that reader went
|
|
26
|
-
* at 3F-3272: the converted checks' credits come off the CI run's own step record now, whose key IS
|
|
27
|
-
* the code, so nothing there has a tag line to read. The export stands because the corpus reader
|
|
28
|
-
* beside it takes the same pattern.
|
|
29
|
-
*/
|
|
30
|
-
export const SCN_TAG = /^@?(SCN-[A-Z0-9]+-\d+)$/;
|
|
31
|
-
/**
|
|
32
|
-
* The non-unit runtime tiers a scenario can NAME by tag. A cucumber observation's
|
|
33
|
-
* level is DERIVED from the cited scenario's own tier tag — the product thesis
|
|
34
|
-
* of Cucumber-as-orchestrator-ACROSS-levels: the scenario names its tier (@integration /
|
|
35
|
-
* @e2e / @performance) and cucumber runs whichever, so an @e2e scenario proven via cucumber
|
|
36
|
-
* yields an e2e observation. `@unit` is deliberately NOT here: unit is the vitest substrate,
|
|
37
|
-
* and a cucumber run genuinely exercises the integrated tiers, not isolation. The caller-supplied
|
|
38
|
-
* `fallbackQualityCheck` survives only for a scenario carrying NO tier tag (the JS-ecosystem
|
|
39
|
-
* default, set at the CLI edge).
|
|
40
|
-
*/
|
|
2
|
+
import { SCN_ID_SOURCE } from "../domain/featureCode.js";
|
|
3
|
+
export const SCN_TAG = new RegExp(`^@?(${SCN_ID_SOURCE})$`);
|
|
41
4
|
const TIER_TAG = /^@?(integration|e2e|performance)$/;
|
|
42
|
-
/**
|
|
43
|
-
* Derive the SET of levels a cucumber observation discharges from the cited scenario's own
|
|
44
|
-
* tier tag(s), falling back to a single caller-supplied level when the scenario carries none.
|
|
45
|
-
*
|
|
46
|
-
* The MULTI-TAG RULE (@SCN-LDG-014, generalising @SCN-LDG-011): a cucumber observation discharges
|
|
47
|
-
* EVERY non-unit runtime obligation its cited scenario raises. So a scenario naming
|
|
48
|
-
* `@integration @e2e` yields TWO levels from a SINGLE cucumber pass (integration + e2e); the caller
|
|
49
|
-
* emits one observation per level. A single-tier scenario yields exactly ONE level (LDG-011/012/013
|
|
50
|
-
* — the single-tier instances of this rule); an untagged scenario yields the single fallback tier.
|
|
51
|
-
* Duplicates are collapsed so a repeated tag never fans out an extra observation.
|
|
52
|
-
*
|
|
53
|
-
* Why discharging both is honest, not double-crediting (Evidence Manifesto §11): §11 complementarity
|
|
54
|
-
* is scoped to `@unit`-vs-the-run (isolation vs the integrated system, DIFFERENT runners) — so `@unit`
|
|
55
|
-
* still needs its own vitest observation. §11 does NOT bite WITHIN the cucumber tiers: one cucumber
|
|
56
|
-
* execution genuinely exercises the integrated components AND the end-to-end journey (the journey
|
|
57
|
-
* CONTAINS the integration), so covering both from the one run is truthful.
|
|
58
|
-
*/
|
|
59
5
|
function deriveLevels(tags, fallbackQualityCheck) {
|
|
60
6
|
const levels = [];
|
|
61
7
|
for (const t of tags) {
|
|
@@ -63,109 +9,57 @@ function deriveLevels(tags, fallbackQualityCheck) {
|
|
|
63
9
|
if (m) {
|
|
64
10
|
const level = m[1];
|
|
65
11
|
if (!levels.includes(level))
|
|
66
|
-
levels.push(level);
|
|
12
|
+
levels.push(level);
|
|
67
13
|
}
|
|
68
14
|
}
|
|
69
15
|
return levels.length > 0 ? levels : [fallbackQualityCheck];
|
|
70
16
|
}
|
|
71
|
-
/**
|
|
72
|
-
* SYNTHESISE the what-broke message of an ambiguous step's `broken` observation (@SCN-LDG-019).
|
|
73
|
-
*
|
|
74
|
-
* Cucumber emits NO `error_message` for an ambiguous step — its result object is exactly
|
|
75
|
-
* `{ "status": "ambiguous", "duration": 0 }` (the "Multiple step definitions match: …" detail is
|
|
76
|
-
* PRETTY-FORMATTER-ONLY, never in the JSON). So the reader cannot quote the runner as the vitest
|
|
77
|
-
* reader does (which passes the collection error through VERBATIM); it must STATE THE DIAGNOSIS
|
|
78
|
-
* itself, from the one thing the report does give: the step's keyword and text.
|
|
79
|
-
*
|
|
80
|
-
* It names WHAT BROKE — this step, matched by two or more step definitions, so it never ran. It
|
|
81
|
-
* prescribes NO CURE: which of the colliding definitions is the wrong one is not the ledger's to
|
|
82
|
-
* say.
|
|
83
|
-
*/
|
|
84
17
|
function ambiguousMessage(step) {
|
|
85
18
|
const text = `${(step.keyword ?? "").trim()} ${step.name ?? ""}`.trim();
|
|
86
19
|
const named = text.length > 0 ? `The step "${text}"` : "A step";
|
|
87
20
|
return `${named} is ambiguous — two or more step definitions match it, so the step never ran.`;
|
|
88
21
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Parse a Cucumber JSON report into observed results, each levelled by DERIVING it from the
|
|
91
|
-
* cited scenario's own tier tag (falling back to `fallbackQualityCheck` for an untagged
|
|
92
|
-
* scenario). One result per scenario: those carrying an @SCN tag cite that scenario; those with
|
|
93
|
-
* NO @SCN tag emit a null-scnId credit (@SCN-LDG-007 — previously DROPPED). A null-scnId credit
|
|
94
|
-
* cites no scenario, so the reconciler folds it into the SUSPENSE row. A scenario is classified
|
|
95
|
-
* THREE-WAY (@SCN-PND-013): passed (all steps passed) / failed (any step failed) / INCONCLUSIVE
|
|
96
|
-
* (otherwise) — an inconclusive scenario emits NOTHING, dropped so it reconciles missing by absence.
|
|
97
|
-
*/
|
|
98
22
|
export function parseCucumberEvidenceObservations(report, fallbackQualityCheck, root) {
|
|
99
23
|
const results = [];
|
|
100
24
|
for (const feature of report) {
|
|
101
|
-
// The feature-file locator (the where-to-fix) — carried on every credit (ruling
|
|
102
|
-
// Q5), made portable relative to the run root (verbatim without root).
|
|
103
25
|
const locator = relativizeToRoot(feature.uri ?? feature.name ?? "(unknown feature)", root);
|
|
104
26
|
for (const scenario of feature.elements ?? []) {
|
|
105
|
-
|
|
106
|
-
const scnTag = tags
|
|
107
|
-
.map((t) => SCN_TAG.exec(t.name ?? ""))
|
|
108
|
-
.find((m) => m !== null);
|
|
109
|
-
const steps = scenario.steps ?? [];
|
|
110
|
-
// FOUR-WAY classification (@SCN-PND-013, extended by @SCN-LDG-019) — pending is NEVER
|
|
111
|
-
// inferred from status. The DROP is what realises inconclusive→missing and the `broken`
|
|
112
|
-
// FLAG is what realises ambiguous→suspense, so `EvidenceStatus` stays binary: no new
|
|
113
|
-
// status, no reconciler change. The drop is WHOLE-SCENARIO — an inconclusive scenario emits
|
|
114
|
-
// no observation at ANY named tier (the `continue` below). The statuses that stay dropped
|
|
115
|
-
// stay honest: `undefined` (no step definition is written — the test genuinely IS absent),
|
|
116
|
-
// `pending` (explicitly deferred), `skipped` (never ran).
|
|
117
|
-
//
|
|
118
|
-
// THE AMBIGUOUS ARM IS ORDERED FIRST (@SCN-LDG-019) because cucumber halts the scenario at
|
|
119
|
-
// the ambiguous step — every step after it reads `skipped`, so the inconclusive drop would
|
|
120
|
-
// otherwise swallow the ambiguity along with them. An ambiguous step is not a stub that
|
|
121
|
-
// proved nothing but a BROKEN HARNESS: two step definitions match one step, so the proof
|
|
122
|
-
// exists and cannot execute. Dropping it as inconclusive sent the reader the WRONG remedy —
|
|
123
|
-
// write a test that already exists, rather than fix the colliding step definitions. It is
|
|
124
|
-
// cucumber's instance of the `broken` outcome vitest's collection failure established
|
|
125
|
-
// (@SCN-LDG-017): evidence that NEVER MATERIALISED.
|
|
126
|
-
//
|
|
127
|
-
// ONE observation for the whole scenario (never one per named tier): the harness broke ONCE,
|
|
128
|
-
// so a multi-tier scenario posts ONE broken item, levelled at its first named tier. Unlike
|
|
129
|
-
// vitest's collection failure (citation-less by construction — a file that fails to collect
|
|
130
|
-
// names no test), this observation CARRIES the scnId: the cucumber scenario DID cite its
|
|
131
|
-
// @SCN; only its step could not run. The reconciler's fail-safe checks `broken` BEFORE
|
|
132
|
-
// `status`, so it can never discharge (or fail) the obligation it cites; it posts to the
|
|
133
|
-
// SUSPENSE row and the obligation reconciles `missing` BY ABSENCE (pinned in
|
|
134
|
-
// reconcile.test.ts [SCN-LDG-019], under BOTH status values).
|
|
135
|
-
const ambiguous = steps.find((s) => s.result?.status === "ambiguous");
|
|
136
|
-
if (ambiguous) {
|
|
137
|
-
results.push({
|
|
138
|
-
qualityCheck: deriveLevels(tags, fallbackQualityCheck)[0],
|
|
139
|
-
scnId: scnTag ? scnTag[1] : null,
|
|
140
|
-
// Structurally required, and the step certainly did not pass; the reconciler's fail-safe
|
|
141
|
-
// checks `broken` BEFORE `status`, so this never reconciles as `failing`.
|
|
142
|
-
status: "failed",
|
|
143
|
-
locator,
|
|
144
|
-
broken: true,
|
|
145
|
-
message: ambiguousMessage(ambiguous),
|
|
146
|
-
});
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
const anyFailed = steps.some((s) => s.result?.status === "failed");
|
|
150
|
-
const allPassed = steps.length > 0 && steps.every((s) => s.result?.status === "passed");
|
|
151
|
-
if (!anyFailed && !allPassed)
|
|
152
|
-
continue; // inconclusive → drop the whole scenario.
|
|
153
|
-
const status = anyFailed ? "failed" : "passed";
|
|
154
|
-
// One observation PER named non-unit tier: a cucumber run of an @integration @e2e
|
|
155
|
-
// scenario discharges BOTH obligations, so it emits an integration AND an e2e observation
|
|
156
|
-
// (the multi-tag ruling's teeth, @SCN-LDG-014). A single-tier or untagged scenario emits
|
|
157
|
-
// exactly one. The levels are DERIVED from the scenario's own tier tags, not the input
|
|
158
|
-
// source; the caller-supplied level is the fallback for an untagged scenario.
|
|
159
|
-
for (const level of deriveLevels(tags, fallbackQualityCheck)) {
|
|
160
|
-
results.push({
|
|
161
|
-
qualityCheck: level,
|
|
162
|
-
scnId: scnTag ? scnTag[1] : null, // no @SCN tag → an uncited credit (SUSPENSE).
|
|
163
|
-
status,
|
|
164
|
-
locator,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
27
|
+
results.push(...scenarioObservations(scenario, locator, fallbackQualityCheck));
|
|
167
28
|
}
|
|
168
29
|
}
|
|
169
30
|
return results;
|
|
170
31
|
}
|
|
32
|
+
function citedScnIdOf(tags) {
|
|
33
|
+
const scnTag = tags
|
|
34
|
+
.map((t) => SCN_TAG.exec(t.name ?? ""))
|
|
35
|
+
.find((m) => m !== null);
|
|
36
|
+
return scnTag ? scnTag[1] : null;
|
|
37
|
+
}
|
|
38
|
+
function scenarioObservations(scenario, locator, fallbackQualityCheck) {
|
|
39
|
+
const tags = scenario.tags ?? [];
|
|
40
|
+
const scnId = citedScnIdOf(tags);
|
|
41
|
+
const steps = scenario.steps ?? [];
|
|
42
|
+
const ambiguous = steps.find((s) => s.result?.status === "ambiguous");
|
|
43
|
+
if (ambiguous) {
|
|
44
|
+
return [{
|
|
45
|
+
qualityCheck: deriveLevels(tags, fallbackQualityCheck)[0],
|
|
46
|
+
scnId,
|
|
47
|
+
status: "failed",
|
|
48
|
+
locator,
|
|
49
|
+
broken: true,
|
|
50
|
+
message: ambiguousMessage(ambiguous),
|
|
51
|
+
}];
|
|
52
|
+
}
|
|
53
|
+
const anyFailed = steps.some((s) => s.result?.status === "failed");
|
|
54
|
+
const allPassed = steps.length > 0 && steps.every((s) => s.result?.status === "passed");
|
|
55
|
+
if (!anyFailed && !allPassed)
|
|
56
|
+
return [];
|
|
57
|
+
const status = anyFailed ? "failed" : "passed";
|
|
58
|
+
return deriveLevels(tags, fallbackQualityCheck).map((level) => ({
|
|
59
|
+
qualityCheck: level,
|
|
60
|
+
scnId,
|
|
61
|
+
status,
|
|
62
|
+
locator,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
171
65
|
//# sourceMappingURL=cucumber.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cucumber.js","sourceRoot":"","sources":["../../src/parse/cucumber.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cucumber.js","sourceRoot":"","sources":["../../src/parse/cucumber.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,48 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE SCOPE DISCOVERY RANGED OVER (@SCN-USG-020, 3F-3343) — one entry per job of every workflow
|
|
3
|
-
* `--ci` resolved: the file, the job, how many steps this run read from it, and how many of those
|
|
4
|
-
* steps are candidate fitness checks.
|
|
5
|
-
*
|
|
6
|
-
* WHY THE REPORT SAYS IT AT ALL, AND WHY IT IS THE ANSWER RATHER THAN A CONSOLATION FOR NOT HAVING
|
|
7
|
-
* ONE. This axis's analysis asked what the tool says when it is pointed somewhere that yields an
|
|
8
|
-
* implausible answer — at a release workflow, or at one job of several. The answer is that it
|
|
9
|
-
* makes NO judgement about plausibility and states its scope instead: a trigger-based or name-based
|
|
10
|
-
* rule for "this looks like a release workflow" is exactly the judgement the ticket puts out of
|
|
11
|
-
* scope, and it is a list of ours, which is the drift the whole inversion exists to remove. A
|
|
12
|
-
* consumer reading the file, the job and the counts knows on sight, and corrects it by narrowing
|
|
13
|
-
* `--ci` (@SCN-USG-008) or by naming the steps that are not checks (@SCN-USG-015).
|
|
14
|
-
*
|
|
15
|
-
* AND IT IS THE ANSWER TO THE QUIETER HALF — THE JOB THE TOOL NEVER LOOKED AT. The census reports
|
|
16
|
-
* how many checks ran and nothing said how many jobs, in how many files, that number came from. A
|
|
17
|
-
* consumer whose second job holds three checks reads exactly what a consumer with three checks in
|
|
18
|
-
* one job reads, and neither figure can be got from the other.
|
|
19
|
-
*
|
|
20
|
-
* BOTH FIGURES PER JOB, because either alone is satisfiable by a reader wrong about the other, and
|
|
21
|
-
* a job that reads its whole pipeline and contributes nothing is precisely the case a reader most
|
|
22
|
-
* needs to see. A job every step of which something took out is reported with none, never dropped.
|
|
23
|
-
*
|
|
24
|
-
* THE CANDIDATE FIGURE IS THE OBSERVER'S OWN RULE, asked through `isCandidateStep`
|
|
25
|
-
* (`parse/runningStaticChecks`) rather than restated here. A census re-deriving membership would
|
|
26
|
-
* be measuring its own arithmetic — it would go on agreeing with the scope section while the books
|
|
27
|
-
* beneath it said something else, which is the one disagreement a reader of this section cannot
|
|
28
|
-
* see. Same walk, too (`ciWorkflowSteps`), so the two readers cannot come to disagree about which
|
|
29
|
-
* steps a workflow even runs.
|
|
30
|
-
*
|
|
31
|
-
* NOT THE ACCOUNTING IDENTITY (@SCN-USG-018). That one asserts the dispositions sum to the steps
|
|
32
|
-
* read, so nothing the reader saw was dropped; this one asserts the provenance — which files and
|
|
33
|
-
* which jobs those steps came from. A reader satisfies either alone: a correct sum over a scope it
|
|
34
|
-
* never names, or a named scope whose numbers do not add up.
|
|
35
|
-
*
|
|
36
|
-
* SORTED, so two runs over one tree cannot differ and a diff of two reports never turns on the
|
|
37
|
-
* order a directory happened to be handed back in — the same reason `ciSourcePathsOf` sorts. The
|
|
38
|
-
* sort is stable, so two jobs no name separates stay in the order their sources were read.
|
|
39
|
-
*
|
|
40
|
-
* NO FILESYSTEM, AND THE NAMES ARE INJECTED, for the reason `stepExclusions` states next door:
|
|
41
|
-
* `ciSources` is an array of anonymous source strings and `ciSourcePaths.ts` is explicit that
|
|
42
|
-
* keeping the core that way is the point. A source this run was given no name for is still a
|
|
43
|
-
* source it READ, so its jobs keep their entries and lose only the half of their name nobody
|
|
44
|
-
* supplied — the direction `reconcilerSteps` takes, and never a dropped row.
|
|
45
|
-
*/
|
|
46
1
|
import { type CiWorkflowStep, type PackageJsonScripts } from "./checkScriptsRunInCI.js";
|
|
47
2
|
import type { JobDiscoveryScope } from "../domain/evidenceReconciliation.js";
|
|
48
3
|
export declare function discoveryScope(ciSources: readonly string[], ciSourceNames: readonly string[], packageJson: PackageJsonScripts, runners: Readonly<Record<string, string | null>>, isExcludedFromDiscovery?: (step: CiWorkflowStep) => boolean): readonly JobDiscoveryScope[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discoveryScope.d.ts","sourceRoot":"","sources":["../../src/parse/discoveryScope.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"discoveryScope.d.ts","sourceRoot":"","sources":["../../src/parse/discoveryScope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEzG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAM7E,wBAAgB,cAAc,CAC5B,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,EAChD,uBAAuB,GAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAqB,GACvE,SAAS,iBAAiB,EAAE,CAiB9B"}
|
|
@@ -1,63 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE SCOPE DISCOVERY RANGED OVER (@SCN-USG-020, 3F-3343) — one entry per job of every workflow
|
|
3
|
-
* `--ci` resolved: the file, the job, how many steps this run read from it, and how many of those
|
|
4
|
-
* steps are candidate fitness checks.
|
|
5
|
-
*
|
|
6
|
-
* WHY THE REPORT SAYS IT AT ALL, AND WHY IT IS THE ANSWER RATHER THAN A CONSOLATION FOR NOT HAVING
|
|
7
|
-
* ONE. This axis's analysis asked what the tool says when it is pointed somewhere that yields an
|
|
8
|
-
* implausible answer — at a release workflow, or at one job of several. The answer is that it
|
|
9
|
-
* makes NO judgement about plausibility and states its scope instead: a trigger-based or name-based
|
|
10
|
-
* rule for "this looks like a release workflow" is exactly the judgement the ticket puts out of
|
|
11
|
-
* scope, and it is a list of ours, which is the drift the whole inversion exists to remove. A
|
|
12
|
-
* consumer reading the file, the job and the counts knows on sight, and corrects it by narrowing
|
|
13
|
-
* `--ci` (@SCN-USG-008) or by naming the steps that are not checks (@SCN-USG-015).
|
|
14
|
-
*
|
|
15
|
-
* AND IT IS THE ANSWER TO THE QUIETER HALF — THE JOB THE TOOL NEVER LOOKED AT. The census reports
|
|
16
|
-
* how many checks ran and nothing said how many jobs, in how many files, that number came from. A
|
|
17
|
-
* consumer whose second job holds three checks reads exactly what a consumer with three checks in
|
|
18
|
-
* one job reads, and neither figure can be got from the other.
|
|
19
|
-
*
|
|
20
|
-
* BOTH FIGURES PER JOB, because either alone is satisfiable by a reader wrong about the other, and
|
|
21
|
-
* a job that reads its whole pipeline and contributes nothing is precisely the case a reader most
|
|
22
|
-
* needs to see. A job every step of which something took out is reported with none, never dropped.
|
|
23
|
-
*
|
|
24
|
-
* THE CANDIDATE FIGURE IS THE OBSERVER'S OWN RULE, asked through `isCandidateStep`
|
|
25
|
-
* (`parse/runningStaticChecks`) rather than restated here. A census re-deriving membership would
|
|
26
|
-
* be measuring its own arithmetic — it would go on agreeing with the scope section while the books
|
|
27
|
-
* beneath it said something else, which is the one disagreement a reader of this section cannot
|
|
28
|
-
* see. Same walk, too (`ciWorkflowSteps`), so the two readers cannot come to disagree about which
|
|
29
|
-
* steps a workflow even runs.
|
|
30
|
-
*
|
|
31
|
-
* NOT THE ACCOUNTING IDENTITY (@SCN-USG-018). That one asserts the dispositions sum to the steps
|
|
32
|
-
* read, so nothing the reader saw was dropped; this one asserts the provenance — which files and
|
|
33
|
-
* which jobs those steps came from. A reader satisfies either alone: a correct sum over a scope it
|
|
34
|
-
* never names, or a named scope whose numbers do not add up.
|
|
35
|
-
*
|
|
36
|
-
* SORTED, so two runs over one tree cannot differ and a diff of two reports never turns on the
|
|
37
|
-
* order a directory happened to be handed back in — the same reason `ciSourcePathsOf` sorts. The
|
|
38
|
-
* sort is stable, so two jobs no name separates stay in the order their sources were read.
|
|
39
|
-
*
|
|
40
|
-
* NO FILESYSTEM, AND THE NAMES ARE INJECTED, for the reason `stepExclusions` states next door:
|
|
41
|
-
* `ciSources` is an array of anonymous source strings and `ciSourcePaths.ts` is explicit that
|
|
42
|
-
* keeping the core that way is the point. A source this run was given no name for is still a
|
|
43
|
-
* source it READ, so its jobs keep their entries and lose only the half of their name nobody
|
|
44
|
-
* supplied — the direction `reconcilerSteps` takes, and never a dropped row.
|
|
45
|
-
*/
|
|
46
1
|
import { ciWorkflowSteps } from "./checkScriptsRunInCI.js";
|
|
47
2
|
import { isCandidateStep } from "./runningStaticChecks.js";
|
|
48
|
-
/**
|
|
49
|
-
* BY SOURCE INDEX AND JOB, never by the source's NAME. Two sources this run was given no name for
|
|
50
|
-
* are two files it read, and keying on the name would fold their same-named jobs into one entry —
|
|
51
|
-
* a job the reader ranged over, gone from the account of what it ranged over.
|
|
52
|
-
*/
|
|
53
3
|
const keyOf = (step) => `${step.sourceIndex}:${step.jobId}`;
|
|
54
4
|
export function discoveryScope(ciSources, ciSourceNames, packageJson, runners, isExcludedFromDiscovery = () => false) {
|
|
55
5
|
const tallies = new Map();
|
|
56
6
|
for (const step of ciWorkflowSteps(ciSources)) {
|
|
57
7
|
const source = ciSourceNames[step.sourceIndex];
|
|
58
8
|
const tally = tallies.get(keyOf(step)) ?? {
|
|
59
|
-
// Spread rather than a `source: undefined` assignment, so an entry for a source nobody named
|
|
60
|
-
// carries no key at all — the shape an absent citation has everywhere else in this engine.
|
|
61
9
|
...(source !== undefined ? { source } : {}),
|
|
62
10
|
job: step.jobId,
|
|
63
11
|
steps: 0,
|
|
@@ -68,9 +16,6 @@ export function discoveryScope(ciSources, ciSourceNames, packageJson, runners, i
|
|
|
68
16
|
tally.candidates += 1;
|
|
69
17
|
tallies.set(keyOf(step), tally);
|
|
70
18
|
}
|
|
71
|
-
// BY FILE AND THEN BY JOB. A source with no name sorts ahead of every named one, which is a
|
|
72
|
-
// settled place rather than a chosen one: it is what an absent name compares as, and the point
|
|
73
|
-
// of the sort is that two runs over one tree agree.
|
|
74
19
|
return [...tallies.values()].sort((a, b) => (a.source ?? "").localeCompare(b.source ?? "") || a.job.localeCompare(b.job));
|
|
75
20
|
}
|
|
76
21
|
//# sourceMappingURL=discoveryScope.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discoveryScope.js","sourceRoot":"","sources":["../../src/parse/discoveryScope.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"discoveryScope.js","sourceRoot":"","sources":["../../src/parse/discoveryScope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgD,MAAM,0BAA0B,CAAC;AACzG,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAK3D,MAAM,KAAK,GAAG,CAAC,IAAoB,EAAU,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;AAEpF,MAAM,UAAU,cAAc,CAC5B,SAA4B,EAC5B,aAAgC,EAChC,WAA+B,EAC/B,OAAgD,EAChD,0BAA6D,GAAG,EAAE,CAAC,KAAK;IAExE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI;YACxC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,GAAG,EAAE,IAAI,CAAC,KAAK;YACf,KAAK,EAAE,CAAC;YACR,UAAU,EAAE,CAAC;SACd,CAAC;QACF,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjB,IAAI,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,CAAC;YAAE,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;QAChG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CACvF,CAAC;AACJ,CAAC"}
|
|
@@ -1,76 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE CITATION SEAM'S SURVIVING ROUTE — a consumer's own CI step states the code of the configured
|
|
3
|
-
* row it answers, and this reads that row back as what the run cites.
|
|
4
|
-
*
|
|
5
|
-
* THE TWO-HOP REGISTRY ROUTE THIS FILE ONCE ALSO HELD IS RETIRED (3F-3161, @SCN-LNT-017 — the last
|
|
6
|
-
* registry-`scn` scenario: a registry entry naming a scenario that carries a different
|
|
7
|
-
* characteristic cited nothing, and no scenario is left needing that resolution at all).
|
|
8
|
-
* The retired registry module (hop 1, script handle → bare check tag) and this module's own
|
|
9
|
-
* `fitnessCitations` / `citationOfScript` (hop 2, bare check tag → the corpus's `@SCN`) went with
|
|
10
|
-
* it. Every check now either states its own row's code on its CI step, or is a converted
|
|
11
|
-
* `@fitness` row read through `domain/fitnessChecks` directly. `citationOfCitedRow` — the `id:`
|
|
12
|
-
* route (@SCN-LNT-031) — is the whole of what is left.
|
|
13
|
-
*
|
|
14
|
-
* NOT A HOP, AND THE DIFFERENCE IS WHERE IT STARTS. The retired hops resolved a runnable script
|
|
15
|
-
* HANDLE into a scenario, because a handle does not know what it is for. An `id:` is not a handle:
|
|
16
|
-
* it is the consumer SAYING which row this check answers — a citation, never a declaration — so
|
|
17
|
-
* there is nothing to resolve. The row keyed by that code carries the characteristic, and both
|
|
18
|
-
* terms come off one configured row rather than one being recovered from the other.
|
|
19
|
-
*
|
|
20
|
-
* IT REFINES, IT DOES NOT MANUFACTURE (@SCN-LNT-031, and 3F-3261's rule kept whole). A code no
|
|
21
|
-
* configured row answers returns `null` rather than a citation half-assembled from the handle that
|
|
22
|
-
* ran: an `id:` names a ROW and never a characteristic, and reaching for the script's name for the
|
|
23
|
-
* missing half is the name-match this axis retired, in a new spelling. A step carrying no code at
|
|
24
|
-
* all is the same answer for the same reason — the target has said nothing about that check, so its
|
|
25
|
-
* run cites nothing and posts to suspense, which is the state a consumer starts in.
|
|
26
|
-
*
|
|
27
|
-
* BARED ON THE WAY IN, because a manifest's `scn` is stored bare and a workflow is hand-authored:
|
|
28
|
-
* the one spelling rule this repository has (`lib/bareTerm`) is what keeps a code written with a
|
|
29
|
-
* sigil or a stray space from being looked up under a key no row is filed at.
|
|
30
|
-
*/
|
|
31
|
-
import type { FitnessCheckIndex } from "../domain/fitnessChecks.js";
|
|
32
|
-
/**
|
|
33
|
-
* WHAT A RUN CITES — both terms the seam resolved, not just the far one.
|
|
34
|
-
*
|
|
35
|
-
* The `@SCN` says WHICH ROW the credit posts to; the bare check tag says WHICH OBLIGATION on that
|
|
36
|
-
* row it answers. Both are needed, because neither is unique on its own: a row may carry more than
|
|
37
|
-
* one bare check tag, so two runs can honestly cite the same `@SCN` (@SCN-LNT-012), and answering
|
|
38
|
-
* by `@SCN` alone hands the first credit found to every fitness obligation the row raises.
|
|
39
|
-
*
|
|
40
|
-
* THE TAG IS THE OBSERVATION'S OWN CHARACTERISTIC, which is why it is carried rather than looked up
|
|
41
|
-
* again downstream. The obligation names the BARE tag its stepless scenario carries (`typecheck`);
|
|
42
|
-
* the run knows only the RUNNABLE HANDLE that invoked it (`lint:complexity`). Those are two
|
|
43
|
-
* vocabularies by design, and comparing them is name-match in a new spelling — it agrees only where
|
|
44
|
-
* the words happen to coincide, which is the single unprefixed check. Resolving the tag HERE, where
|
|
45
|
-
* the registry is already in hand, is what lets the reconciler compare like with like.
|
|
46
|
-
*/
|
|
47
1
|
export interface ScriptCitation {
|
|
48
|
-
/** The BARE check tag this handle runs (`complexity`) — the word an obligation names. */
|
|
49
|
-
readonly checkTag: string;
|
|
50
|
-
/** The `@SCN` of the fitness scenario carrying that check — the row the credit posts to. */
|
|
51
2
|
readonly scnId: string;
|
|
52
3
|
}
|
|
53
|
-
|
|
54
|
-
* THE CONSUMER'S OWN CITATION — the configured row a code written on a CI check step names, read
|
|
55
|
-
* back as what that step's run cites.
|
|
56
|
-
*
|
|
57
|
-
* NOT A HOP, AND THE DIFFERENCE IS WHERE IT STARTS — the same point the file's own docblock makes,
|
|
58
|
-
* repeated here because this function is where it is proved. The retired hops resolved a runnable
|
|
59
|
-
* script HANDLE into a scenario, because a handle does not know what it is for. An `id:` is not a
|
|
60
|
-
* handle: it is the consumer SAYING which row this check answers — a citation, never a declaration
|
|
61
|
-
* — so there is nothing to resolve. The row keyed by that code carries the characteristic, and both
|
|
62
|
-
* terms come off one configured row rather than one being recovered from the other.
|
|
63
|
-
*
|
|
64
|
-
* IT REFINES, IT DOES NOT MANUFACTURE (@SCN-LNT-031, and 3F-3261's rule kept whole). A code no
|
|
65
|
-
* configured row answers returns `null` rather than a citation half-assembled from the handle that
|
|
66
|
-
* ran: an `id:` names a ROW and never a characteristic, and reaching for the script's name for the
|
|
67
|
-
* missing half is the name-match this axis retired, in a new spelling. A step carrying no code at
|
|
68
|
-
* all is the same answer for the same reason — the target has said nothing about that check, so its
|
|
69
|
-
* run cites nothing and posts to suspense, which is the state a consumer starts in.
|
|
70
|
-
*
|
|
71
|
-
* BARED ON THE WAY IN, because a manifest's `scn` is stored bare and a workflow is hand-authored:
|
|
72
|
-
* the one spelling rule this repository has (`lib/bareTerm`) is what keeps a code written with a
|
|
73
|
-
* sigil or a stray space from being looked up under a key no row is filed at.
|
|
74
|
-
*/
|
|
75
|
-
export declare function citationOfCitedRow(citedScn: string | undefined, fitnessChecks: FitnessCheckIndex): ScriptCitation | null;
|
|
4
|
+
export declare function citationOfCitedRow(citedScn: string | undefined): ScriptCitation | null;
|
|
76
5
|
//# sourceMappingURL=fitnessCitations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitnessCitations.d.ts","sourceRoot":"","sources":["../../src/parse/fitnessCitations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fitnessCitations.d.ts","sourceRoot":"","sources":["../../src/parse/fitnessCitations.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CAItF"}
|
|
@@ -1,61 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE CITATION SEAM'S SURVIVING ROUTE — a consumer's own CI step states the code of the configured
|
|
3
|
-
* row it answers, and this reads that row back as what the run cites.
|
|
4
|
-
*
|
|
5
|
-
* THE TWO-HOP REGISTRY ROUTE THIS FILE ONCE ALSO HELD IS RETIRED (3F-3161, @SCN-LNT-017 — the last
|
|
6
|
-
* registry-`scn` scenario: a registry entry naming a scenario that carries a different
|
|
7
|
-
* characteristic cited nothing, and no scenario is left needing that resolution at all).
|
|
8
|
-
* The retired registry module (hop 1, script handle → bare check tag) and this module's own
|
|
9
|
-
* `fitnessCitations` / `citationOfScript` (hop 2, bare check tag → the corpus's `@SCN`) went with
|
|
10
|
-
* it. Every check now either states its own row's code on its CI step, or is a converted
|
|
11
|
-
* `@fitness` row read through `domain/fitnessChecks` directly. `citationOfCitedRow` — the `id:`
|
|
12
|
-
* route (@SCN-LNT-031) — is the whole of what is left.
|
|
13
|
-
*
|
|
14
|
-
* NOT A HOP, AND THE DIFFERENCE IS WHERE IT STARTS. The retired hops resolved a runnable script
|
|
15
|
-
* HANDLE into a scenario, because a handle does not know what it is for. An `id:` is not a handle:
|
|
16
|
-
* it is the consumer SAYING which row this check answers — a citation, never a declaration — so
|
|
17
|
-
* there is nothing to resolve. The row keyed by that code carries the characteristic, and both
|
|
18
|
-
* terms come off one configured row rather than one being recovered from the other.
|
|
19
|
-
*
|
|
20
|
-
* IT REFINES, IT DOES NOT MANUFACTURE (@SCN-LNT-031, and 3F-3261's rule kept whole). A code no
|
|
21
|
-
* configured row answers returns `null` rather than a citation half-assembled from the handle that
|
|
22
|
-
* ran: an `id:` names a ROW and never a characteristic, and reaching for the script's name for the
|
|
23
|
-
* missing half is the name-match this axis retired, in a new spelling. A step carrying no code at
|
|
24
|
-
* all is the same answer for the same reason — the target has said nothing about that check, so its
|
|
25
|
-
* run cites nothing and posts to suspense, which is the state a consumer starts in.
|
|
26
|
-
*
|
|
27
|
-
* BARED ON THE WAY IN, because a manifest's `scn` is stored bare and a workflow is hand-authored:
|
|
28
|
-
* the one spelling rule this repository has (`lib/bareTerm`) is what keeps a code written with a
|
|
29
|
-
* sigil or a stray space from being looked up under a key no row is filed at.
|
|
30
|
-
*/
|
|
31
1
|
import { bareTerm } from "../lib/bareTerm.js";
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* back as what that step's run cites.
|
|
35
|
-
*
|
|
36
|
-
* NOT A HOP, AND THE DIFFERENCE IS WHERE IT STARTS — the same point the file's own docblock makes,
|
|
37
|
-
* repeated here because this function is where it is proved. The retired hops resolved a runnable
|
|
38
|
-
* script HANDLE into a scenario, because a handle does not know what it is for. An `id:` is not a
|
|
39
|
-
* handle: it is the consumer SAYING which row this check answers — a citation, never a declaration
|
|
40
|
-
* — so there is nothing to resolve. The row keyed by that code carries the characteristic, and both
|
|
41
|
-
* terms come off one configured row rather than one being recovered from the other.
|
|
42
|
-
*
|
|
43
|
-
* IT REFINES, IT DOES NOT MANUFACTURE (@SCN-LNT-031, and 3F-3261's rule kept whole). A code no
|
|
44
|
-
* configured row answers returns `null` rather than a citation half-assembled from the handle that
|
|
45
|
-
* ran: an `id:` names a ROW and never a characteristic, and reaching for the script's name for the
|
|
46
|
-
* missing half is the name-match this axis retired, in a new spelling. A step carrying no code at
|
|
47
|
-
* all is the same answer for the same reason — the target has said nothing about that check, so its
|
|
48
|
-
* run cites nothing and posts to suspense, which is the state a consumer starts in.
|
|
49
|
-
*
|
|
50
|
-
* BARED ON THE WAY IN, because a manifest's `scn` is stored bare and a workflow is hand-authored:
|
|
51
|
-
* the one spelling rule this repository has (`lib/bareTerm`) is what keeps a code written with a
|
|
52
|
-
* sigil or a stray space from being looked up under a key no row is filed at.
|
|
53
|
-
*/
|
|
54
|
-
export function citationOfCitedRow(citedScn, fitnessChecks) {
|
|
2
|
+
import { SCN_CODE } from "./scenarios.js";
|
|
3
|
+
export function citationOfCitedRow(citedScn) {
|
|
55
4
|
if (citedScn === undefined)
|
|
56
5
|
return null;
|
|
57
6
|
const scnId = bareTerm(citedScn);
|
|
58
|
-
|
|
59
|
-
return row === undefined ? null : { checkTag: row.characteristic, scnId };
|
|
7
|
+
return SCN_CODE.test(scnId) ? { scnId } : null;
|
|
60
8
|
}
|
|
61
9
|
//# sourceMappingURL=fitnessCitations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitnessCitations.js","sourceRoot":"","sources":["../../src/parse/fitnessCitations.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fitnessCitations.js","sourceRoot":"","sources":["../../src/parse/fitnessCitations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAM1C,MAAM,UAAU,kBAAkB,CAAC,QAA4B;IAC7D,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjC,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC"}
|
|
@@ -1,53 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE RECONCILER'S OWN STEPS (@SCN-USG-014, 3F-3343) — which steps of a target's pipeline are this
|
|
3
|
-
* reconciliation rather than something it reconciles, and how the report says so.
|
|
4
|
-
*
|
|
5
|
-
* THE SECOND EXCLUSION, AND THE ONLY ONE NOBODY CONFIGURES. A behavioural runner is excluded by a
|
|
6
|
-
* rule over what the target named and a non-check by the consumer's own list; this one is excluded
|
|
7
|
-
* BY CONSTRUCTION, because the run that computes the books cannot be a row in them. The
|
|
8
|
-
* distinction is not a nicety: a `notChecks` pair produces the identical report over the identical
|
|
9
|
-
* pipeline, and the two answers part company only at the consumer who has written nothing — whose
|
|
10
|
-
* very first run would otherwise report their own reconciler as an uncited fitness check, and go
|
|
11
|
-
* on doing so until they learned to configure it away.
|
|
12
|
-
*
|
|
13
|
-
* A CITATION ON EITHER IS UNSATISFIABLE, WHICH IS WHAT MAKES IT CONSTRUCTION RATHER THAN JUDGEMENT.
|
|
14
|
-
* The step record is written BEFORE the reconciliation reads it — necessarily, since that record
|
|
15
|
-
* is its input — so no run's record can ever carry the reconciling step's own outcome, and no
|
|
16
|
-
* scenario can ever be shown to have been answered by it. A demand nothing could satisfy is not a
|
|
17
|
-
* check somebody failed to cite. It is not a check.
|
|
18
|
-
*
|
|
19
|
-
* TWO HALVES, RECOGNISED TWO WAYS, AND NEITHER IS A LIST OF NAMES.
|
|
20
|
-
*
|
|
21
|
-
* - THE RUN: a step whose command runs this tool's own reconciling invocation, compared as whole
|
|
22
|
-
* adjacent shell tokens and followed through the manifest scripts a step invokes — the runner
|
|
23
|
-
* rule's own comparison (`parse/commandRuns`), because a pipeline invokes a binary through a
|
|
24
|
-
* script alias far more often than it writes its name. ADJACENT is what keeps the same binary
|
|
25
|
-
* run for another purpose a candidate: this repository's own pipeline runs `spec-controller
|
|
26
|
-
* tags` beside its balance step, and that is an ordinary step of the pipeline being reconciled.
|
|
27
|
-
* - THE RECORD: a step carrying GitHub's own step-record expression, which is the only way that
|
|
28
|
-
* record can be produced. Read off the step's `env:` and its command, wherever the consumer
|
|
29
|
-
* wrote it, and not off its title — a step called `Dump this run's step record` that produces
|
|
30
|
-
* no record is an ordinary step, and one called anything at all that produces the record is
|
|
31
|
-
* the dump.
|
|
32
|
-
*
|
|
33
|
-
* THE INVOCATION IS INJECTED, NEVER ASSUMED. How this product is invoked at a consumer's command
|
|
34
|
-
* line is a fact the application edge holds (`ingest/ingestQualityChecks.ts`), like the script
|
|
35
|
-
* prefixes and the workflow names beside it; the core is handed it as data. A run told no
|
|
36
|
-
* invocation recognises no reconciling step, which is the safe direction — a candidate too many,
|
|
37
|
-
* visible on the report, rather than a step taken off the books by a rule nobody supplied.
|
|
38
|
-
*
|
|
39
|
-
* THE ACCOUNT AND THE SEAM COME OFF ONE RULE. `isReconciler` re-asks the same question of a single
|
|
40
|
-
* step rather than consulting the list this module built, so the account the report prints and the
|
|
41
|
-
* steps discovery skipped cannot come to disagree — a step named on the report as the reconciler
|
|
42
|
-
* while its check sits on the books is a report that contradicts itself in one page.
|
|
43
|
-
*/
|
|
44
1
|
import { type CiWorkflowStep } from "./checkScriptsRunInCI.js";
|
|
45
2
|
import type { ReconcilerStep } from "../domain/evidenceReconciliation.js";
|
|
46
|
-
/** What a run's pipeline yielded of the reconciler — the account, and the one answer per step. */
|
|
47
3
|
export interface ReconcilerSteps {
|
|
48
|
-
/** The steps that are the reconciler, in the order the pipeline runs them. */
|
|
49
4
|
readonly steps: readonly ReconcilerStep[];
|
|
50
|
-
/** Whether this step is the reconciler rather than a step of the pipeline it reconciles. */
|
|
51
5
|
readonly isReconciler: (step: CiWorkflowStep) => boolean;
|
|
52
6
|
}
|
|
53
7
|
export declare function reconcilerSteps(ciSources: readonly string[], ciSourceNames: readonly string[], invocation: string, packageJson: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcilerSteps.d.ts","sourceRoot":"","sources":["../../src/parse/reconcilerSteps.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"reconcilerSteps.d.ts","sourceRoot":"","sources":["../../src/parse/reconcilerSteps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAGhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAE1E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC;CAC1D;AAmBD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAChD,eAAe,CAWjB"}
|