@3f-consulting/spec-controller-core 0.1.0-alpha.5 → 0.1.0-alpha.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +29 -324
- 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
|
@@ -1,227 +1,76 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The TARGET's `specController.*` configuration, read into the rows and mints the
|
|
3
|
-
* reconciler takes — the `resolve*` family, moved here from the app's ingest edge (3F-3087).
|
|
4
|
-
*
|
|
5
|
-
* WHY THEY LIVE IN THE ENGINE. Every one of them is a pure function of a manifest object
|
|
6
|
-
* somebody else already read off disk, and every one of them is the ONE reading of the key it
|
|
7
|
-
* names — `fitnessChecksOf` and `bareTerm` are both core's, so the reader and the
|
|
8
|
-
* thing it reads through belonged on the same side of the package boundary. Sitting at the app
|
|
9
|
-
* edge they were the reason a PUBLISHED module imported core's unpublished `/internal` subpath,
|
|
10
|
-
* which is the fault 3F-3086 repairs; nothing about reading a parsed manifest ever needed the
|
|
11
|
-
* edge that produced it.
|
|
12
|
-
*
|
|
13
|
-
* WHAT THE EDGE STILL OWES THEM, AND WHY IT IS A PARAMETER. One of these readings depends on
|
|
14
|
-
* something the engine must not know: the deferral-tag STARTER SET is product policy the
|
|
15
|
-
* application layer single-sources (`DEFAULT_DEFERRAL_TAGS`). It arrives as an argument, as data,
|
|
16
|
-
* so the engine keeps knowing nothing about files (`lint:boundaries`' `core-imports-io` rule,
|
|
17
|
-
* which was @SCN-EPG-001's `io-import` arm until 3F-3437; and 3F-2841's pattern: a project-owned
|
|
18
|
-
* term arrives as an input).
|
|
19
|
-
*
|
|
20
|
-
* DEFENSIVE THROUGHOUT, AND THAT IS THE FAMILY'S STANCE RATHER THAN LOCAL CHOICES PER RESOLVER.
|
|
21
|
-
* Config is data from outside: a missing, non-object or array-shaped value resolves EMPTY, and a
|
|
22
|
-
* malformed entry is dropped by the reading function it is handed to rather than thrown. A check
|
|
23
|
-
* that throws on a typo produces no verdict at all.
|
|
24
|
-
*/
|
|
25
1
|
import { bareTerm } from "../lib/bareTerm.js";
|
|
26
|
-
import { fitnessChecksOf } from "../domain/fitnessChecks.js";
|
|
27
|
-
// THE FOUR CANON TIERS, read from the ledger's own enumeration rather than restated here
|
|
28
|
-
// (@SCN-USG-019). A second list of the same four would agree by coincidence, and this axis's
|
|
29
|
-
// whole argument is that a list of names is the drift.
|
|
30
2
|
import { RUNTIME_QUALITY_CHECKS } from "../domain/ledger.js";
|
|
31
|
-
/** Whether a value read out of a manifest is a block of named fields, rather than a list or scalar. */
|
|
32
3
|
function isBlock(value) {
|
|
33
4
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34
5
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*
|
|
39
|
-
* IT IS THE CONSUMER'S OWN LIST, and that is the whole reason it may exist at all. Not everything
|
|
40
|
-
* that is not a behavioural runner is a fitness check — a checkout, a dependency install, a deploy
|
|
41
|
-
* — and this axis's standing rule is that a list of check NAMES is the drift. A list of the
|
|
42
|
-
* consumer's own STEPS is the opposite thing: it is about their pipeline, it is written once, and
|
|
43
|
-
* nothing in this tree has an opinion about what is on it.
|
|
44
|
-
*
|
|
45
|
-
* The seventh of this family's `specController.*` resolvers, and defensive like the six above it:
|
|
46
|
-
* a missing or non-array value resolves EMPTY and a non-string entry is dropped rather than
|
|
47
|
-
* thrown. Deduplicated, as the configured-static-check list beside it is, so a target that wrote
|
|
48
|
-
* one line twice is reported one line — the account below is per ENTRY, and the same entry twice
|
|
49
|
-
* is one thing the consumer said.
|
|
50
|
-
*
|
|
51
|
-
* WHAT AN ENTRY MEANS IS NOT DECIDED HERE. This reader takes the list off the manifest; matching it
|
|
52
|
-
* against a pipeline, and saying which entries matched nothing, is `parse/stepExclusions`.
|
|
53
|
-
*/
|
|
6
|
+
const isTier = (key) => RUNTIME_QUALITY_CHECKS.includes(key);
|
|
7
|
+
const isRunner = (value) => typeof value === "string" || value === null;
|
|
8
|
+
const isListEntry = (value) => typeof value === "string";
|
|
54
9
|
export function resolveNotChecks(packageJson) {
|
|
55
10
|
const configured = packageJson.specController?.notChecks;
|
|
56
11
|
if (!Array.isArray(configured))
|
|
57
12
|
return [];
|
|
58
|
-
return [...new Set(configured.filter(
|
|
13
|
+
return [...new Set(configured.filter(isListEntry))];
|
|
59
14
|
}
|
|
60
|
-
|
|
61
|
-
* Resolve the recognised deferral-tag set for the target (@SCN-PND-021) — the app's single-sourced
|
|
62
|
-
* starter set EXTENDED by the target `package.json`'s `specController.deferralTags`. Config
|
|
63
|
-
* EXTENDS, never replaces: a project cannot un-recognise a built-in (`@wip` always defers).
|
|
64
|
-
* Configured tags are bare names, `@`-stripped, consistent with the starter set; non-string /
|
|
65
|
-
* non-array config is ignored defensively. `parseScenarios` then takes the union as its injected
|
|
66
|
-
* `deferralTags` param.
|
|
67
|
-
*
|
|
68
|
-
* THE STARTER SET ARRIVES AS AN ARGUMENT AND IS NOT THE ENGINE'S TO HOLD (3F-3087). Which
|
|
69
|
-
* community tags defer is product policy — an evolvable list of strings the application layer
|
|
70
|
-
* single-sources as `DEFAULT_DEFERRAL_TAGS` — and a core-held copy would be a second statement of
|
|
71
|
-
* it. So the union is computed here, where the config read is, and the policy is handed in.
|
|
72
|
-
*/
|
|
73
|
-
export function resolveDeferralTags(packageJson,
|
|
74
|
-
/** The application layer's starter set — the built-ins a target's config may only extend. */
|
|
75
|
-
starterTags) {
|
|
15
|
+
export function resolveDeferralTags(packageJson, starterTags) {
|
|
76
16
|
const configured = packageJson.specController?.deferralTags;
|
|
77
17
|
const extras = Array.isArray(configured)
|
|
78
18
|
? configured
|
|
79
|
-
.filter(
|
|
80
|
-
// Through the ONE reading of what a term bare is (@SCN-TRM-001). This port had no trim at
|
|
81
|
-
// all, so `"@wip "` failed as well as `" @wip"`, and a term that is nothing but
|
|
82
|
-
// whitespace and a sigil is dropped here as an empty one already is.
|
|
19
|
+
.filter(isListEntry)
|
|
83
20
|
.map(bareTerm)
|
|
84
21
|
.filter((tag) => tag !== "")
|
|
85
22
|
: [];
|
|
86
|
-
// Union: the starter set FIRST (extends, never replaces — a project cannot un-recognise a
|
|
87
|
-
// built-in), then the configured extras; de-duplicated to keep the set clean.
|
|
88
23
|
return [...new Set([...starterTags, ...extras])];
|
|
89
24
|
}
|
|
90
|
-
/**
|
|
91
|
-
* The TARGET's CONFIGURED FITNESS ROWS (@SCN-LNT-018) — `specController.fitnessChecks`, read as
|
|
92
|
-
* `@SCN → the characteristic that scenario asserts` through the engine's own `fitnessChecksOf`.
|
|
93
|
-
*
|
|
94
|
-
* THE DEBIT SIDE OF A CONVERTED CHECK. A converted scenario carries `@fitness` and nothing about
|
|
95
|
-
* its subject, so the characteristic it owes comes from here — and from the row whose `scn` is that
|
|
96
|
-
* scenario's own, which is what removes the registry hop an unconverted static check needs.
|
|
97
|
-
*
|
|
98
|
-
* IT IS THE TARGET'S, for the reason the check registry and the ceilings are (@SCN-LNT-005): a
|
|
99
|
-
* characteristic means what the target says it means, and a row resolved from this tool's own
|
|
100
|
-
* manifest would put an obligation on a target's books under a word it never wrote.
|
|
101
|
-
*
|
|
102
|
-
* The fifth of this family's `specController.*` resolvers, and defensive like the four above it: a
|
|
103
|
-
* missing or wrongly-shaped config resolves EMPTY, and a malformed row is dropped by
|
|
104
|
-
* `fitnessChecksOf` rather than thrown. There is no starter set: a target that has converted
|
|
105
|
-
* nothing owes nothing on this route, which is what keeps the reading inert on an unswept corpus.
|
|
106
|
-
*/
|
|
107
|
-
export function resolveFitnessChecks(packageJson) {
|
|
108
|
-
return fitnessChecksOf(packageJson.specController?.fitnessChecks);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* The TARGET's BEHAVIOURAL RUNNERS (@SCN-USG-011, 3F-3343) — `specController.runners`, read as
|
|
112
|
-
* `tier → the name of the binary that tier's suite runs under`.
|
|
113
|
-
*
|
|
114
|
-
* THE SMALL CLOSED THING, NAMED, so the open one can be inferred. The set of names a quality check
|
|
115
|
-
* might go by is unbounded and belongs to the consumer; the set of behavioural runners is one per
|
|
116
|
-
* tier tag and the tiers are canon. Naming the closed set and deriving the rest is the move the
|
|
117
|
-
* `@fitness` collapse already made one level in (3F-3139), and it cannot go stale by omission.
|
|
118
|
-
*
|
|
119
|
-
* IT IS THE TARGET'S, for the reason the check registry and the ceilings are (@SCN-LNT-005): which
|
|
120
|
-
* command runs a repository's unit suite is a fact about that repository, and a runner resolved
|
|
121
|
-
* from this tool's own manifest would answer for a pipeline this run never looked at.
|
|
122
|
-
*
|
|
123
|
-
* The sixth of this family's `specController.*` resolvers, and defensive like the five above it: a
|
|
124
|
-
* missing, non-object or array-shaped config resolves EMPTY, and an entry whose value is neither a
|
|
125
|
-
* runner's NAME nor `null` is dropped rather than thrown. A manifest naming no runners is not an
|
|
126
|
-
* error — it is a `new-client`, which is the state this axis is sold on.
|
|
127
|
-
*
|
|
128
|
-
* A NULL IS KEPT, AND IT IS THE THIRD STATE (@SCN-USG-016, 3F-3343). `"performance": null` is
|
|
129
|
-
* something the target SAID — we have no performance suite — and a tier the block omits is
|
|
130
|
-
* something it never said. Dropping the null folds the first into the second and loses a fact we
|
|
131
|
-
* were given, in the one direction nothing downstream can recover: after the fold, silence and a
|
|
132
|
-
* stated absence are indistinguishable. Nothing else in this reader's contract moves — a null
|
|
133
|
-
* recognises no step, exactly as a missing key recognises none — so the ONLY place the two can be
|
|
134
|
-
* told apart is this return value and the report rendered off it.
|
|
135
|
-
*
|
|
136
|
-
* THE KEY SET IS CLOSED, AND THE PARTITION IS THIS READER'S (@SCN-USG-019, 3F-3343). The block is
|
|
137
|
-
* keyed by TIER and the tiers are canon, which is exactly what makes the whole inversion possible:
|
|
138
|
-
* the closed set is named because it is enumerable, and the open one is inferred from what is left.
|
|
139
|
-
* A key outside the four is therefore not a runner for anything, and both obvious answers to it are
|
|
140
|
-
* wrong. HONOURING it is the smuggling the closure forbids — `"lint": "eslint"` is a consumer taking
|
|
141
|
-
* their own checks out of discovery one key at a time, and it reinstates the silence this axis
|
|
142
|
-
* exists to remove. DROPPING it silently is the same class of fault one layer along: the consumer
|
|
143
|
-
* wrote something, believes it took effect, and has no line anywhere to correct it from. So the key
|
|
144
|
-
* is partitioned out of the runners AND handed back to be named, and the run is not aborted over it.
|
|
145
|
-
*
|
|
146
|
-
* THE FOUR TIERS ARE READ, NEVER RESTATED. `RUNTIME_QUALITY_CHECKS` is the ledger's own enumeration
|
|
147
|
-
* of the runtime tiers; a second copy here would agree with it by coincidence, and a list of names
|
|
148
|
-
* is the drift this ticket is about.
|
|
149
|
-
*
|
|
150
|
-
* THE PARTITION IS ON THE KEY AND THE DEFENSIVE DROP IS ON THE VALUE, and the two are different
|
|
151
|
-
* questions kept apart. A canon tier whose value is neither a runner's NAME nor `null` is malformed
|
|
152
|
-
* config and is dropped, which is this family's stance about data from outside. A key that is not a
|
|
153
|
-
* tier at all is not malformed — there is no tier for any value of it to name a runner for — so its
|
|
154
|
-
* value is beside the point and the key is the fact worth reporting, whatever it was set to.
|
|
155
|
-
*/
|
|
156
25
|
export function resolveRunners(packageJson) {
|
|
157
26
|
const configured = packageJson.specController?.runners;
|
|
158
27
|
if (!isBlock(configured))
|
|
159
28
|
return { tiers: {}, unrecognisedKeys: [] };
|
|
160
|
-
const isTier = (key) => RUNTIME_QUALITY_CHECKS.includes(key);
|
|
161
29
|
return {
|
|
162
|
-
tiers: Object.fromEntries(Object.entries(configured).filter((entry) => isTier(entry[0]) && (
|
|
30
|
+
tiers: Object.fromEntries(Object.entries(configured).filter((entry) => isTier(entry[0]) && isRunner(entry[1]))),
|
|
163
31
|
unrecognisedKeys: Object.keys(configured).filter((key) => !isTier(key)),
|
|
164
32
|
};
|
|
165
33
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
* does what they think, with nothing on the report to correct it from — the same fault as a
|
|
175
|
-
* dropped step, reached from the retirement side rather than the discovery side.
|
|
176
|
-
*
|
|
177
|
-
* APPEND-ONLY, the family's own append-only key set (RUNTIME_QUALITY_CHECKS beside it). A key
|
|
178
|
-
* retires once and is never re-read; the set only grows as this reader retires more of them
|
|
179
|
-
* (`checkRegistry` first, 3F-3398; `staticChecks` second, 3F-3399 — the tiebreak
|
|
180
|
-
* `parse/runningStaticChecks.ts`'s `handleOf` used to settle among several invoked scripts,
|
|
181
|
-
* 3F-3396 deleted; `thresholds` third, 3F-3517 — the ceilings the measured axis held a scenario
|
|
182
|
-
* to, 3F-3516 deleted).
|
|
183
|
-
*
|
|
184
|
-
* DEFENSIVE LIKE THE READERS ABOVE IT: a missing or non-object `specController` names no
|
|
185
|
-
* retired key, never throws.
|
|
186
|
-
*/
|
|
187
|
-
const RETIRED_SPEC_CONTROLLER_KEYS = ["checkRegistry", "staticChecks", "thresholds"];
|
|
188
|
-
/**
|
|
189
|
-
* THE BAR A CONFIGURED ROW STILL CARRIES (@SCN-LNT-035) — the row-level keys this reader has
|
|
190
|
-
* retired, append-only like the top-level set above. Nothing reads a row's bar since 3F-3510: a
|
|
191
|
-
* row is credited by its own step's outcome, so a bar left on it holds the check to nothing. A
|
|
192
|
-
* `mutationGate` is a value of `atLeast`, so the key it sits under is what names it.
|
|
193
|
-
*
|
|
194
|
-
* NAMED WITH ITS ROW, `fitnessChecks[<@SCN>].<key>`, because a row-level key alone says nothing a
|
|
195
|
-
* consumer could find it by. A row stating no usable `@SCN` names no bar: the row reader drops it
|
|
196
|
-
* whole, and there is no handle to name its bar by.
|
|
197
|
-
*/
|
|
198
|
-
const RETIRED_ROW_KEYS = ["atLeast", "atMost"];
|
|
199
|
-
function retiredRowKeysOf(rows) {
|
|
200
|
-
if (!Array.isArray(rows))
|
|
201
|
-
return [];
|
|
202
|
-
return rows.flatMap((row) => {
|
|
203
|
-
if (!isBlock(row) || typeof row["scn"] !== "string")
|
|
204
|
-
return [];
|
|
205
|
-
const scnId = bareTerm(row["scn"]);
|
|
206
|
-
if (scnId === "")
|
|
207
|
-
return [];
|
|
208
|
-
return Object.keys(row)
|
|
209
|
-
.filter((key) => RETIRED_ROW_KEYS.includes(key))
|
|
210
|
-
.map((key) => `fitnessChecks[${scnId}].${key}`);
|
|
211
|
-
});
|
|
34
|
+
function kindOf(value) {
|
|
35
|
+
if (value === null)
|
|
36
|
+
return "null";
|
|
37
|
+
if (Array.isArray(value))
|
|
38
|
+
return "a list";
|
|
39
|
+
if (typeof value === "object")
|
|
40
|
+
return "an object";
|
|
41
|
+
return `a ${typeof value}`;
|
|
212
42
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!
|
|
220
|
-
return [];
|
|
221
|
-
return
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
43
|
+
const wrongKind = (entry, value, reads) => ({
|
|
44
|
+
entry,
|
|
45
|
+
is: kindOf(value),
|
|
46
|
+
reads,
|
|
47
|
+
});
|
|
48
|
+
function wrongKindsInList(value, at) {
|
|
49
|
+
if (!Array.isArray(value))
|
|
50
|
+
return [wrongKind(at, value, "a list")];
|
|
51
|
+
return value.flatMap((entry, i) => (isListEntry(entry) ? [] : [wrongKind(`${at}[${i}]`, entry, "a string")]));
|
|
52
|
+
}
|
|
53
|
+
function wrongKindsInRunners(value, at) {
|
|
54
|
+
if (!isBlock(value))
|
|
55
|
+
return [wrongKind(at, value, "an object")];
|
|
56
|
+
return Object.entries(value)
|
|
57
|
+
.filter(([key, runner]) => isTier(key) && !isRunner(runner))
|
|
58
|
+
.map(([key, runner]) => wrongKind(`${at}.${key}`, runner, "a string or null"));
|
|
59
|
+
}
|
|
60
|
+
const BLOCK_READS = {
|
|
61
|
+
runners: wrongKindsInRunners,
|
|
62
|
+
notChecks: wrongKindsInList,
|
|
63
|
+
deferralTags: wrongKindsInList,
|
|
64
|
+
};
|
|
65
|
+
export function configurationNotRead(packageJson) {
|
|
66
|
+
const block = packageJson.specController;
|
|
67
|
+
if (block === undefined)
|
|
68
|
+
return { wrongKinds: [], unknownKeys: [] };
|
|
69
|
+
if (!isBlock(block))
|
|
70
|
+
return { wrongKinds: [wrongKind("specController", block, "an object")], unknownKeys: [] };
|
|
71
|
+
return {
|
|
72
|
+
unknownKeys: Object.keys(block).filter((key) => !Object.hasOwn(BLOCK_READS, key)),
|
|
73
|
+
wrongKinds: Object.entries(block).flatMap(([key, value]) => Object.hasOwn(BLOCK_READS, key) ? BLOCK_READS[key](value, `specController.${key}`) : []),
|
|
74
|
+
};
|
|
226
75
|
}
|
|
227
76
|
//# sourceMappingURL=targetManifest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targetManifest.js","sourceRoot":"","sources":["../../src/parse/targetManifest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"targetManifest.js","sourceRoot":"","sources":["../../src/parse/targetManifest.ts"],"names":[],"mappings":"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"}
|
package/dist/parse/vitest.d.ts
CHANGED
|
@@ -1,50 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `ingest/vitest` reader — one of the two named observed-evidence readers
|
|
3
|
-
* (the embryonic adapters, deliberately not a registry in v1). Reads Vitest's
|
|
4
|
-
* JSON reporter output and normalises each assertion that cites an @SCN id into
|
|
5
|
-
* an EvidenceObservation at the `unit` level.
|
|
6
|
-
*
|
|
7
|
-
* The level is supplied by the CALLER, not inferred: the caller states the level this Vitest
|
|
8
|
-
* source yields, and the reader stamps it — no Vitest⇒unit assumption baked into the parser. The
|
|
9
|
-
* JS-ecosystem default (unit) is set at the CLI edge.
|
|
10
|
-
*
|
|
11
|
-
* The @SCN id is the bracketed `[SCN-<FFF>-<NNN>]` token carried in the test's
|
|
12
|
-
* `describe`/`it` name (the bidirectional-link rule). The bracket is what makes it a
|
|
13
|
-
* citation and not a mention: this module's regex used to match any SCN-shaped token
|
|
14
|
-
* anywhere in the name, so fixture data and prose cross-references cited scenarios nobody
|
|
15
|
-
* meant to cite (@SCN-LDG-033, 3F-2368). The form now lives in `lib/scnCitation.ts`,
|
|
16
|
-
* shared with the scn-subissue gate's cite scan so one answer serves both readers.
|
|
17
|
-
*
|
|
18
|
-
* Vitest surfaces the assertion's OWN name as `assertionResults[].title` and its
|
|
19
|
-
* ANCESTOR PATH (describe → it) as `fullName`;
|
|
20
|
-
* the citation belongs to the assertion, so the reader reads the leaf's title FIRST and
|
|
21
|
-
* falls back to the ancestor path only when the leaf does not self-cite — most-specific-
|
|
22
|
-
* citation-wins (@SCN-LDG-016).
|
|
23
|
-
*
|
|
24
|
-
* The reader classifies THREE-WAY (@SCN-PND-015), uniform with the cucumber reader
|
|
25
|
-
* (@SCN-PND-013): a `passed` assertion → a `passed` observation (satisfied); a `failed`
|
|
26
|
-
* assertion → a `failed` observation (failing); an INCONCLUSIVE vitest status (`skipped`/`todo`,
|
|
27
|
-
* and any status ∉ {passed, failed}) → the assertion is DROPPED (no observation), so its
|
|
28
|
-
* obligation reconciles missing by absence — pending is never inferred from status. A skipped/todo
|
|
29
|
-
* unit test is a GAP, not a failure.
|
|
30
|
-
*
|
|
31
|
-
* Parent: @SCN-LDG-001 (the foundation seam; balanced path).
|
|
32
|
-
*/
|
|
33
1
|
import type { RuntimeQualityCheck, EvidenceObservation } from "../model.js";
|
|
34
|
-
/** The minimal shape of Vitest's JSON reporter output this reader depends on. */
|
|
35
2
|
export interface VitestJsonReport {
|
|
36
3
|
testResults?: Array<{
|
|
37
|
-
/** The test-file path — the locator for the evidenceObservations reconciliation. */
|
|
38
4
|
name?: string;
|
|
39
|
-
/**
|
|
40
|
-
* The FILE-level status (@SCN-LDG-017) — previously read and discarded. A file that failed to
|
|
41
|
-
* COLLECT reports `"failed"` here WITH a `message` and ZERO `assertionResults`: it errored
|
|
42
|
-
* before naming a test. That pair (failed + zero assertions) is the collection-failure
|
|
43
|
-
* signature the reader now emits as a `broken` observation. (A file whose tests merely FAILED
|
|
44
|
-
* also reports `"failed"` here — but it carries assertions, so it is not broken.)
|
|
45
|
-
*/
|
|
46
5
|
status?: string;
|
|
47
|
-
/** The FILE-level error message a collection failure reports (@SCN-LDG-017). */
|
|
48
6
|
message?: string;
|
|
49
7
|
assertionResults?: Array<{
|
|
50
8
|
fullName?: string;
|
|
@@ -53,23 +11,5 @@ export interface VitestJsonReport {
|
|
|
53
11
|
}>;
|
|
54
12
|
}>;
|
|
55
13
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Parse a Vitest JSON report into observed results at the CALLER-SUPPLIED level. One result per
|
|
58
|
-
* EMITTED assertion: those carrying an @SCN id cite that scenario; those with NO id emit a
|
|
59
|
-
* null-scnId credit (@SCN-LDG-007 — previously DROPPED). A null-scnId credit cites no scenario,
|
|
60
|
-
* so the reconciler folds it into the SUSPENSE row. Every result carries its test-file locator.
|
|
61
|
-
*
|
|
62
|
-
* THREE-WAY classification (@SCN-PND-015), uniform with the cucumber reader (@SCN-PND-013) —
|
|
63
|
-
* pending is NEVER inferred from status:
|
|
64
|
-
* - `passed` → a `passed` observation → satisfied.
|
|
65
|
-
* - `failed` → a `failed` observation → failing.
|
|
66
|
-
* - otherwise (`skipped`/`todo`, and any status ∉ {passed, failed}) → INCONCLUSIVE: an assertion
|
|
67
|
-
* that RAN but proved nothing. Emit NOTHING — the evidence obligation then finds no matching
|
|
68
|
-
* observation and reconciles missing BY ABSENCE.
|
|
69
|
-
* Treating any non-pass-non-fail status as inconclusive keeps the reader robust to vitest's status
|
|
70
|
-
* spelling (`skipped`/`todo`/`pending`). `EvidenceStatus` stays binary (no new status, no reconciler
|
|
71
|
-
* change): the DROP is what realises inconclusive→missing. The uncited (null-scnId) SUSPENSE credit
|
|
72
|
-
* is preserved for genuine passed/failed results — only inconclusive assertions are dropped.
|
|
73
|
-
*/
|
|
74
14
|
export declare function parseVitestEvidenceObservations(report: VitestJsonReport, qualityCheck: RuntimeQualityCheck, root?: string): EvidenceObservation[];
|
|
75
15
|
//# sourceMappingURL=vitest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/parse/vitest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"vitest.d.ts","sourceRoot":"","sources":["../../src/parse/vitest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAI5E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gBAAgB,CAAC,EAAE,KAAK,CAAC;YACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB,CAAC,CAAC;KACJ,CAAC,CAAC;CACJ;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,gBAAgB,EACxB,YAAY,EAAE,mBAAmB,EACjC,IAAI,CAAC,EAAE,MAAM,GACZ,mBAAmB,EAAE,CA8BvB"}
|
package/dist/parse/vitest.js
CHANGED
|
@@ -1,81 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `ingest/vitest` reader — one of the two named observed-evidence readers
|
|
3
|
-
* (the embryonic adapters, deliberately not a registry in v1). Reads Vitest's
|
|
4
|
-
* JSON reporter output and normalises each assertion that cites an @SCN id into
|
|
5
|
-
* an EvidenceObservation at the `unit` level.
|
|
6
|
-
*
|
|
7
|
-
* The level is supplied by the CALLER, not inferred: the caller states the level this Vitest
|
|
8
|
-
* source yields, and the reader stamps it — no Vitest⇒unit assumption baked into the parser. The
|
|
9
|
-
* JS-ecosystem default (unit) is set at the CLI edge.
|
|
10
|
-
*
|
|
11
|
-
* The @SCN id is the bracketed `[SCN-<FFF>-<NNN>]` token carried in the test's
|
|
12
|
-
* `describe`/`it` name (the bidirectional-link rule). The bracket is what makes it a
|
|
13
|
-
* citation and not a mention: this module's regex used to match any SCN-shaped token
|
|
14
|
-
* anywhere in the name, so fixture data and prose cross-references cited scenarios nobody
|
|
15
|
-
* meant to cite (@SCN-LDG-033, 3F-2368). The form now lives in `lib/scnCitation.ts`,
|
|
16
|
-
* shared with the scn-subissue gate's cite scan so one answer serves both readers.
|
|
17
|
-
*
|
|
18
|
-
* Vitest surfaces the assertion's OWN name as `assertionResults[].title` and its
|
|
19
|
-
* ANCESTOR PATH (describe → it) as `fullName`;
|
|
20
|
-
* the citation belongs to the assertion, so the reader reads the leaf's title FIRST and
|
|
21
|
-
* falls back to the ancestor path only when the leaf does not self-cite — most-specific-
|
|
22
|
-
* citation-wins (@SCN-LDG-016).
|
|
23
|
-
*
|
|
24
|
-
* The reader classifies THREE-WAY (@SCN-PND-015), uniform with the cucumber reader
|
|
25
|
-
* (@SCN-PND-013): a `passed` assertion → a `passed` observation (satisfied); a `failed`
|
|
26
|
-
* assertion → a `failed` observation (failing); an INCONCLUSIVE vitest status (`skipped`/`todo`,
|
|
27
|
-
* and any status ∉ {passed, failed}) → the assertion is DROPPED (no observation), so its
|
|
28
|
-
* obligation reconciles missing by absence — pending is never inferred from status. A skipped/todo
|
|
29
|
-
* unit test is a GAP, not a failure.
|
|
30
|
-
*
|
|
31
|
-
* Parent: @SCN-LDG-001 (the foundation seam; balanced path).
|
|
32
|
-
*/
|
|
33
1
|
import { relativizeToRoot } from "../lib/portablePath.js";
|
|
34
2
|
import { parseScnCitation } from "../lib/scnCitation.js";
|
|
35
|
-
/**
|
|
36
|
-
* Parse a Vitest JSON report into observed results at the CALLER-SUPPLIED level. One result per
|
|
37
|
-
* EMITTED assertion: those carrying an @SCN id cite that scenario; those with NO id emit a
|
|
38
|
-
* null-scnId credit (@SCN-LDG-007 — previously DROPPED). A null-scnId credit cites no scenario,
|
|
39
|
-
* so the reconciler folds it into the SUSPENSE row. Every result carries its test-file locator.
|
|
40
|
-
*
|
|
41
|
-
* THREE-WAY classification (@SCN-PND-015), uniform with the cucumber reader (@SCN-PND-013) —
|
|
42
|
-
* pending is NEVER inferred from status:
|
|
43
|
-
* - `passed` → a `passed` observation → satisfied.
|
|
44
|
-
* - `failed` → a `failed` observation → failing.
|
|
45
|
-
* - otherwise (`skipped`/`todo`, and any status ∉ {passed, failed}) → INCONCLUSIVE: an assertion
|
|
46
|
-
* that RAN but proved nothing. Emit NOTHING — the evidence obligation then finds no matching
|
|
47
|
-
* observation and reconciles missing BY ABSENCE.
|
|
48
|
-
* Treating any non-pass-non-fail status as inconclusive keeps the reader robust to vitest's status
|
|
49
|
-
* spelling (`skipped`/`todo`/`pending`). `EvidenceStatus` stays binary (no new status, no reconciler
|
|
50
|
-
* change): the DROP is what realises inconclusive→missing. The uncited (null-scnId) SUSPENSE credit
|
|
51
|
-
* is preserved for genuine passed/failed results — only inconclusive assertions are dropped.
|
|
52
|
-
*/
|
|
53
3
|
export function parseVitestEvidenceObservations(report, qualityCheck, root) {
|
|
54
4
|
const results = [];
|
|
55
5
|
for (const file of report.testResults ?? []) {
|
|
56
|
-
// The test-file locator (the where-to-fix) — carried on every credit (ruling
|
|
57
|
-
// Q5), made portable relative to the run root (verbatim when no root given).
|
|
58
6
|
const locator = relativizeToRoot(file.name ?? "(unknown vitest file)", root);
|
|
59
|
-
// BROKEN, NOT ABSENT (@SCN-LDG-017) — the COLLECTION FAILURE. A file that failed to collect
|
|
60
|
-
// reports `status: "failed"` WITH a message and ZERO assertionResults: it errored before it
|
|
61
|
-
// named a test. Walking `assertionResults[]` alone saw nothing to emit, so the scenario whose
|
|
62
|
-
// proof lived here reconciled `missing` — indistinguishable from an unwritten test, and the
|
|
63
|
-
// wrong remedy (write a test vs fix the harness). Emit ONE observation carrying the collection
|
|
64
|
-
// failure: `broken: true`, the file locator (WHERE to fix), and the runner's message (WHAT
|
|
65
|
-
// broke). It cites NO scenario (`scnId: null`) — a suite that named no test cites no @SCN — so
|
|
66
|
-
// the reconciler posts it to the SUSPENSE row.
|
|
67
|
-
//
|
|
68
|
-
// The signature is the PAIR (failed + zero assertions), never file status alone: an ordinary
|
|
69
|
-
// red run also reports `status: "failed"` at file level, but its assertions ARE named and
|
|
70
|
-
// attributable, and already land as `failing` on the scenarios they cite (the boundary). A
|
|
71
|
-
// green file with zero assertions is likewise not broken — nothing errored.
|
|
72
7
|
const assertions = file.assertionResults ?? [];
|
|
73
8
|
if (file.status === "failed" && assertions.length === 0) {
|
|
74
9
|
results.push({
|
|
75
10
|
qualityCheck,
|
|
76
11
|
scnId: null,
|
|
77
|
-
// `status` is structurally required and the runner did report `failed`; the FAIL-SAFE in
|
|
78
|
-
// the reconciler checks `broken` BEFORE `status`, so this never reconciles as `failing`.
|
|
79
12
|
status: "failed",
|
|
80
13
|
locator,
|
|
81
14
|
broken: true,
|
|
@@ -85,25 +18,12 @@ export function parseVitestEvidenceObservations(report, qualityCheck, root) {
|
|
|
85
18
|
}
|
|
86
19
|
for (const assertion of assertions) {
|
|
87
20
|
const status = assertion.status;
|
|
88
|
-
// THREE-WAY (@SCN-PND-015): drop any inconclusive assertion (status ∉ {passed, failed}) —
|
|
89
|
-
// skipped/todo/pending/undefined proved nothing, so the obligation reconciles missing by
|
|
90
|
-
// absence. Only genuine passed/failed emit (the guard narrows `status` to EvidenceStatus).
|
|
91
21
|
if (status !== "passed" && status !== "failed")
|
|
92
22
|
continue;
|
|
93
|
-
// MOST-SPECIFIC-CITATION-WINS (@SCN-LDG-016): the citation belongs to the ASSERTION, and
|
|
94
|
-
// the assertion's OWN name is `title`; `fullName` is the ancestor PATH (outermost describe
|
|
95
|
-
// → innermost it). So read the leaf's own title FIRST and fall back to the ancestor path
|
|
96
|
-
// only when the leaf does not self-cite. This preserves the "describe carries the bracket,
|
|
97
|
-
// plain `it`s beneath" style (a bare leaf falls through to the describe's citation) while
|
|
98
|
-
// letting a self-citing leaf OVERRIDE its ancestor. The retired first-match-on-
|
|
99
|
-
// `fullName + " " + title` did the opposite: a grouping describe's citation SHADOWED a
|
|
100
|
-
// self-citing child, so the leaf's scenario reconciled missing while the ancestor took a
|
|
101
|
-
// spurious SECOND credit. Semantic, not positional — last-match on the concatenation would
|
|
102
|
-
// misfire when a leaf's prose names a second scenario after its own.
|
|
103
23
|
const scnId = parseScnCitation(assertion.title ?? "") ?? parseScnCitation(assertion.fullName ?? "");
|
|
104
24
|
results.push({
|
|
105
25
|
qualityCheck,
|
|
106
|
-
scnId,
|
|
26
|
+
scnId,
|
|
107
27
|
status,
|
|
108
28
|
locator,
|
|
109
29
|
});
|
package/dist/parse/vitest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/parse/vitest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/parse/vitest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAezD,MAAM,UAAU,+BAA+B,CAC7C,MAAwB,EACxB,YAAiC,EACjC,IAAa;IAEb,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,IAAI,uBAAuB,EAAE,IAAI,CAAC,CAAC;QAC7E,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY;gBACZ,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,QAAQ;gBAChB,OAAO;gBACP,MAAM,EAAE,IAAI;gBACZ,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACjE,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;YAChC,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,QAAQ;gBAAE,SAAS;YACzD,MAAM,KAAK,GACT,gBAAgB,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,gBAAgB,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;YACxF,OAAO,CAAC,IAAI,CAAC;gBACX,YAAY;gBACZ,KAAK;gBACL,MAAM;gBACN,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|