@3f-consulting/spec-controller-core 0.1.0-alpha.6 → 0.1.0-alpha.60
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 +3 -3
- 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/messages.d.ts +191 -0
- package/dist/domain/messages.d.ts.map +1 -0
- package/dist/domain/messages.js +279 -0
- package/dist/domain/messages.js.map +1 -0
- 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/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 +1 -24
- 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 +78 -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 +6 -69
- 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 +3 -39
- 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 +4 -32
- 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 +123 -463
- 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 +10 -53
- 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 +5 -30
- 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 +62 -129
- 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 +45 -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 +4 -61
- 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 +5 -49
- 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 +4 -35
- 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/domain/qualityCheckFaultMessages.d.ts +0 -43
- package/dist/domain/qualityCheckFaultMessages.d.ts.map +0 -1
- package/dist/domain/qualityCheckFaultMessages.js +0 -38
- package/dist/domain/qualityCheckFaultMessages.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,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE `@SCN` SCHEME'S OWN RULES, asked of a target's Gherkin corpus — the rule half of
|
|
3
|
-
* `spec-controller tags`.
|
|
4
|
-
*
|
|
5
|
-
* WHY IT SHIPS AT ALL. The tool hands a consumer the `@SCN` scheme and then made them write
|
|
6
|
-
* the guards that keep it usable; 816 lines of exactly that sat in this repository's own check
|
|
7
|
-
* tree, published nowhere. An adopter got the codes and inherited none of the policing, so
|
|
8
|
-
* nobody's tags were policed but ours. These rules are the kind that CAN ship: every one of
|
|
9
|
-
* them reads a corpus the engine already parses, rather than needing to know what a piece of
|
|
10
|
-
* text IS.
|
|
11
|
-
*
|
|
12
|
-
* WHY IT IS IN CORE AND NOT AT THE CLI EDGE. It is `evidenceReconciliationFromSources`'s shape,
|
|
13
|
-
* taken deliberately rather than by analogy. The published CLI module may reach core only
|
|
14
|
-
* through the ROOT barrel — `./internal` is dropped by `publishConfig.exports` at pack time,
|
|
15
|
-
* which is how an installed `balance --help` once threw ERR_PACKAGE_PATH_NOT_EXPORTED behind
|
|
16
|
-
* thirteen green gates (3F-3086). So the CALLER lives on this side of the boundary and the app
|
|
17
|
-
* hands over bytes; nothing internal is re-exported to buy it.
|
|
18
|
-
*
|
|
19
|
-
* WHAT SEPARATES A FAULT FROM A VERDICT. `balance`'s exit code IS its verdict — balanced, out of
|
|
20
|
-
* balance, pending-under-strict, unsound, nothing-to-reconcile — and a corpus fault is not a
|
|
21
|
-
* reconciliation verdict. It
|
|
22
|
-
* is a statement that the corpus itself is malformed, which is why it is a second command with
|
|
23
|
-
* its own status ladder rather than a fourth meaning bolted onto a status a consumer's CI
|
|
24
|
-
* branches on.
|
|
25
|
-
*
|
|
26
|
-
* NOTHING HERE READS A FILE, AND NOTHING HERE RE-READS ONE. Every input arrives already read,
|
|
27
|
-
* for `evidenceReconciliationFromSources`'s reason: an engine handed a reader is an engine doing
|
|
28
|
-
* I/O wearing a callback, and `lint:boundaries`' `core-imports-io` rule reds over exactly that
|
|
29
|
-
* (@SCN-EPG-001's `io-import` arm until 3F-3437).
|
|
30
|
-
*
|
|
31
|
-
* WHAT IS LEFT IN THIS MODULE, AND WHAT MOVED OUT. The rules themselves live in two siblings —
|
|
32
|
-
* `corpusCodeFaults.ts` (a code binding to a file) and `corpusGrammarFaults.ts` (a tag meaning
|
|
33
|
-
* something) — because the joined module reached the 400-line `max-lines` ceiling, and canon rules
|
|
34
|
-
* that split rather than an exception entry (@SCN-FIT-001). A third sibling held the claim rule
|
|
35
|
-
* (how many checks one scenario claims) until it left with the measured axis (3F-3516). What
|
|
36
|
-
* stays here is the composition and the VOCABULARY: the fault kinds, the shape of a discovered
|
|
37
|
-
* file, and the one entry point any sibling has. Splitting on any other seam would have put a
|
|
38
|
-
* rule's inputs in one module and its finding's wording in another.
|
|
39
|
-
*/
|
|
40
|
-
import type { PackageJsonScripts } from "./checkScriptsRunInCI.js";
|
|
41
|
-
/**
|
|
42
|
-
* A target's manifest as these rules read it — its scripts, and its `specController` block.
|
|
43
|
-
*
|
|
44
|
-
* Spelled here rather than imported for the reason the reconcile composition spells its own:
|
|
45
|
-
* every field of it is `unknown` until a resolver narrows it, so the type is a statement about
|
|
46
|
-
* what a manifest on disk IS rather than a contract owed to anybody.
|
|
47
|
-
*/
|
|
48
|
-
export type TargetManifest = PackageJsonScripts & {
|
|
49
|
-
specController?: {
|
|
50
|
-
deferralTags?: unknown;
|
|
51
|
-
fitnessChecks?: unknown;
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* One way a corpus breaks the `@SCN` scheme's own rules.
|
|
56
|
-
*
|
|
57
|
-
* THREE KINDS, NOT ONE, because they are three faults with three different fixes — the same
|
|
58
|
-
* argument that split the tier-tag check's findings three ways. `duplicate-feature-code` says
|
|
59
|
-
* *give one of these files a code of its own*; `foreign-scenario-code` says *this id names a
|
|
60
|
-
* file it is not written in*; and `unrecognised-tag` says *this word means nothing here*. A
|
|
61
|
-
* fourth, `multiple-check-tags`, left with the measured axis (3F-3516). Collapsing any two would
|
|
62
|
-
* print one fault's remedy at the other's author, which is precisely how a mistyped tier tag
|
|
63
|
-
* stayed invisible for as long as it did.
|
|
64
|
-
*
|
|
65
|
-
* THE UNION IS THE COMMAND'S WHOLE VOCABULARY, and it is stated once here rather than grown a
|
|
66
|
-
* member at a time by whichever rule landed last. That is also why it stayed in this module when
|
|
67
|
-
* the rules left it: the two rule modules each raise a subset of these kinds, and a union
|
|
68
|
-
* assembled from both sides would be a statement about the command that no single file made. The
|
|
69
|
-
* two CODE rules have producers — `duplicate-feature-code` (@SCN-STG-010) and
|
|
70
|
-
* `foreign-scenario-code` (@SCN-STG-011); so does `unrecognised-tag` (@SCN-STG-002, and the
|
|
71
|
-
* clauses that narrow what it reaches at @SCN-STG-003, @SCN-STG-004 and @SCN-STG-005). Every
|
|
72
|
-
* member of the union is raised by a rule with a scenario of its own, which is the state the kinds
|
|
73
|
-
* were written down ahead of.
|
|
74
|
-
*/
|
|
75
|
-
export interface CorpusFault {
|
|
76
|
-
readonly kind: "unrecognised-tag" | "duplicate-feature-code" | "foreign-scenario-code";
|
|
77
|
-
readonly message: string;
|
|
78
|
-
}
|
|
79
|
-
/** One discovered feature file, as the edge read it. */
|
|
80
|
-
export interface CorpusFile {
|
|
81
|
-
/** The feature-file basename without the `.feature` extension. */
|
|
82
|
-
slug: string;
|
|
83
|
-
/**
|
|
84
|
-
* The file's `@<FFF>` header code, or null where it carries none.
|
|
85
|
-
*
|
|
86
|
-
* IT ARRIVES; IT IS NEVER RE-DERIVED HERE. The header is read by exactly one thing — the
|
|
87
|
-
* ingest edge's `extractFeatureCode` — and that is also the reading a reconciliation's
|
|
88
|
-
* *Out-of-balance by feature* cut groups on. A second reading inside this module would be free
|
|
89
|
-
* to disagree with the report about the very field these rules are ABOUT, and the check could
|
|
90
|
-
* then pass clean over a corpus whose report mis-attributes a scenario. So it is a parameter.
|
|
91
|
-
*/
|
|
92
|
-
featureCode: string | null;
|
|
93
|
-
/** The file's raw Gherkin source, read once at the edge. */
|
|
94
|
-
source: string;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Every way this corpus breaks the scheme, in a stable order.
|
|
98
|
-
*
|
|
99
|
-
* THE ONE ENTRY POINT, and the reason the rules' own modules are not on the barrel. A consumer's
|
|
100
|
-
* route to this capability is the CLI; a second route through an imported rule would be a second
|
|
101
|
-
* surface to freeze, and it would let the code rules and the grammar rules be run over two
|
|
102
|
-
* different readings of one corpus.
|
|
103
|
-
*
|
|
104
|
-
* @param input.features the target's discovered feature files — slug, header code and source,
|
|
105
|
-
* read ONCE at the edge so two discoveries can never disagree about which corpus was judged.
|
|
106
|
-
* @param input.packageJson the TARGET's manifest, from which the recognised deferral set is
|
|
107
|
-
* resolved INSIDE this engine — through the same resolver the reconciliation reads it with, so the
|
|
108
|
-
* rules here admit exactly what the reconciliation honours as a skip. READ SINCE 3F-3303, by the
|
|
109
|
-
* grammar rules and only by them: the deferral set (@SCN-PND-021) is resolved from it. The
|
|
110
|
-
* check-tag halves once read from it — the REGISTERED half (@SCN-STG-005) and the MEASURED half
|
|
111
|
-
* — are retired (3F-3161, 3F-3516). The code rules never see it, which is the seam the module
|
|
112
|
-
* split was drawn on.
|
|
113
|
-
* @param input.deferralTags the application layer's STARTER deferral set, which a target's
|
|
114
|
-
* config may only extend. Product policy, single-sourced there and never here — the same
|
|
115
|
-
* argument, and the same parameter, as the reconcile composition's. Read since 3F-3303, and
|
|
116
|
-
* handed onward unresolved: what turns it into the target's recognised set is
|
|
117
|
-
* `resolveDeferralTags`, called once beside the rule that asks the question.
|
|
118
|
-
*/
|
|
119
|
-
export declare function corpusFaults(input: {
|
|
120
|
-
features: readonly CorpusFile[];
|
|
121
|
-
packageJson: TargetManifest;
|
|
122
|
-
deferralTags: readonly string[];
|
|
123
|
-
}): CorpusFault[];
|
|
124
|
-
//# sourceMappingURL=corpusFaults.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"corpusFaults.d.ts","sourceRoot":"","sources":["../../src/parse/corpusFaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG;IAChD,cAAc,CAAC,EAAE;QACf,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,aAAa,CAAC,EAAE,OAAO,CAAC;KACzB,CAAC;CACH,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EACT,kBAAkB,GAClB,wBAAwB,GACxB,uBAAuB,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,UAAU;IACzB,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAClC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IAChC,WAAW,EAAE,cAAc,CAAC;IAC5B,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC,GAAG,WAAW,EAAE,CAMhB"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE `@SCN` SCHEME'S OWN RULES, asked of a target's Gherkin corpus — the rule half of
|
|
3
|
-
* `spec-controller tags`.
|
|
4
|
-
*
|
|
5
|
-
* WHY IT SHIPS AT ALL. The tool hands a consumer the `@SCN` scheme and then made them write
|
|
6
|
-
* the guards that keep it usable; 816 lines of exactly that sat in this repository's own check
|
|
7
|
-
* tree, published nowhere. An adopter got the codes and inherited none of the policing, so
|
|
8
|
-
* nobody's tags were policed but ours. These rules are the kind that CAN ship: every one of
|
|
9
|
-
* them reads a corpus the engine already parses, rather than needing to know what a piece of
|
|
10
|
-
* text IS.
|
|
11
|
-
*
|
|
12
|
-
* WHY IT IS IN CORE AND NOT AT THE CLI EDGE. It is `evidenceReconciliationFromSources`'s shape,
|
|
13
|
-
* taken deliberately rather than by analogy. The published CLI module may reach core only
|
|
14
|
-
* through the ROOT barrel — `./internal` is dropped by `publishConfig.exports` at pack time,
|
|
15
|
-
* which is how an installed `balance --help` once threw ERR_PACKAGE_PATH_NOT_EXPORTED behind
|
|
16
|
-
* thirteen green gates (3F-3086). So the CALLER lives on this side of the boundary and the app
|
|
17
|
-
* hands over bytes; nothing internal is re-exported to buy it.
|
|
18
|
-
*
|
|
19
|
-
* WHAT SEPARATES A FAULT FROM A VERDICT. `balance`'s exit code IS its verdict — balanced, out of
|
|
20
|
-
* balance, pending-under-strict, unsound, nothing-to-reconcile — and a corpus fault is not a
|
|
21
|
-
* reconciliation verdict. It
|
|
22
|
-
* is a statement that the corpus itself is malformed, which is why it is a second command with
|
|
23
|
-
* its own status ladder rather than a fourth meaning bolted onto a status a consumer's CI
|
|
24
|
-
* branches on.
|
|
25
|
-
*
|
|
26
|
-
* NOTHING HERE READS A FILE, AND NOTHING HERE RE-READS ONE. Every input arrives already read,
|
|
27
|
-
* for `evidenceReconciliationFromSources`'s reason: an engine handed a reader is an engine doing
|
|
28
|
-
* I/O wearing a callback, and `lint:boundaries`' `core-imports-io` rule reds over exactly that
|
|
29
|
-
* (@SCN-EPG-001's `io-import` arm until 3F-3437).
|
|
30
|
-
*
|
|
31
|
-
* WHAT IS LEFT IN THIS MODULE, AND WHAT MOVED OUT. The rules themselves live in two siblings —
|
|
32
|
-
* `corpusCodeFaults.ts` (a code binding to a file) and `corpusGrammarFaults.ts` (a tag meaning
|
|
33
|
-
* something) — because the joined module reached the 400-line `max-lines` ceiling, and canon rules
|
|
34
|
-
* that split rather than an exception entry (@SCN-FIT-001). A third sibling held the claim rule
|
|
35
|
-
* (how many checks one scenario claims) until it left with the measured axis (3F-3516). What
|
|
36
|
-
* stays here is the composition and the VOCABULARY: the fault kinds, the shape of a discovered
|
|
37
|
-
* file, and the one entry point any sibling has. Splitting on any other seam would have put a
|
|
38
|
-
* rule's inputs in one module and its finding's wording in another.
|
|
39
|
-
*/
|
|
40
|
-
import { duplicateFeatureCodes, foreignScenarioCodes } from "./corpusCodeFaults.js";
|
|
41
|
-
import { unrecognisedTags } from "./corpusGrammarFaults.js";
|
|
42
|
-
/**
|
|
43
|
-
* Every way this corpus breaks the scheme, in a stable order.
|
|
44
|
-
*
|
|
45
|
-
* THE ONE ENTRY POINT, and the reason the rules' own modules are not on the barrel. A consumer's
|
|
46
|
-
* route to this capability is the CLI; a second route through an imported rule would be a second
|
|
47
|
-
* surface to freeze, and it would let the code rules and the grammar rules be run over two
|
|
48
|
-
* different readings of one corpus.
|
|
49
|
-
*
|
|
50
|
-
* @param input.features the target's discovered feature files — slug, header code and source,
|
|
51
|
-
* read ONCE at the edge so two discoveries can never disagree about which corpus was judged.
|
|
52
|
-
* @param input.packageJson the TARGET's manifest, from which the recognised deferral set is
|
|
53
|
-
* resolved INSIDE this engine — through the same resolver the reconciliation reads it with, so the
|
|
54
|
-
* rules here admit exactly what the reconciliation honours as a skip. READ SINCE 3F-3303, by the
|
|
55
|
-
* grammar rules and only by them: the deferral set (@SCN-PND-021) is resolved from it. The
|
|
56
|
-
* check-tag halves once read from it — the REGISTERED half (@SCN-STG-005) and the MEASURED half
|
|
57
|
-
* — are retired (3F-3161, 3F-3516). The code rules never see it, which is the seam the module
|
|
58
|
-
* split was drawn on.
|
|
59
|
-
* @param input.deferralTags the application layer's STARTER deferral set, which a target's
|
|
60
|
-
* config may only extend. Product policy, single-sourced there and never here — the same
|
|
61
|
-
* argument, and the same parameter, as the reconcile composition's. Read since 3F-3303, and
|
|
62
|
-
* handed onward unresolved: what turns it into the target's recognised set is
|
|
63
|
-
* `resolveDeferralTags`, called once beside the rule that asks the question.
|
|
64
|
-
*/
|
|
65
|
-
export function corpusFaults(input) {
|
|
66
|
-
return [
|
|
67
|
-
...duplicateFeatureCodes(input.features),
|
|
68
|
-
...foreignScenarioCodes(input.features),
|
|
69
|
-
...unrecognisedTags(input.features, input.packageJson, input.deferralTags),
|
|
70
|
-
];
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=corpusFaults.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"corpusFaults.js","sourceRoot":"","sources":["../../src/parse/corpusFaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA+D5D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,YAAY,CAAC,KAI5B;IACC,OAAO;QACL,GAAG,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC;QACxC,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC;QACvC,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC;KAC3E,CAAC;AACJ,CAAC"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE GRAMMAR RULES of `spec-controller tags` — everything about whether a TAG on a scenario
|
|
3
|
-
* means anything. Its sibling holds the other question: `corpusCodeFaults.ts` whether a feature
|
|
4
|
-
* code binds to one feature file. `corpusFaults.ts` composes the two and is the only entry point
|
|
5
|
-
* either of them has.
|
|
6
|
-
*
|
|
7
|
-
* THE SEAM, STATED FROM THIS SIDE. A grammar rule asks *is this word part of the `@SCN` scheme*,
|
|
8
|
-
* and the answer is assembled from places that are not this module's: the engine's own
|
|
9
|
-
* quality-check maps, the `SCN-<FFF>-<NNN>` spelling `featureCodeOf` owns, and the target's own
|
|
10
|
-
* manifest. A code rule needs none of those; it reads the corpus's shape. Two questions, two
|
|
11
|
-
* modules; the split happened when the joined module reached the 400-line `max-lines` ceiling
|
|
12
|
-
* with four more grammar clauses still to land (@SCN-FIT-001, and never an exception entry). The
|
|
13
|
-
* claim rule that once made a third sibling left with the measured axis (3F-3516): once the axis
|
|
14
|
-
* word is the only word that names a check, no scenario can claim two.
|
|
15
|
-
*
|
|
16
|
-
* AND THE TARGET'S HALF IS RESOLVED HERE, NOT HANDED IN RESOLVED. The composition hands this
|
|
17
|
-
* module a manifest rather than an answer, so the read lives beside the rule that uses it — the
|
|
18
|
-
* arrangement the parent's Design settled for the check-tag union and applied here first, because
|
|
19
|
-
* the whole reason the floor and the obligation rule once disagreed about a set was that each
|
|
20
|
-
* assembled its own. The composition passes bytes and policy; what a word MEANS is decided in one
|
|
21
|
-
* place.
|
|
22
|
-
*
|
|
23
|
-
* NOTHING HERE IS RESTATED. The recognised set is the whole subject of this module, and every
|
|
24
|
-
* member of it is DERIVED from the place that already owns it — a list written out here would
|
|
25
|
-
* agree with its source by diligence and then drift, and the check that then reds is the one
|
|
26
|
-
* telling authors which words are legitimate.
|
|
27
|
-
*/
|
|
28
|
-
import type { CorpusFault, CorpusFile, TargetManifest } from "./corpusFaults.js";
|
|
29
|
-
/**
|
|
30
|
-
* A tag on an `@SCN` scenario that means nothing here (@SCN-STG-002, @SCN-STG-003, @SCN-STG-004).
|
|
31
|
-
*
|
|
32
|
-
* ONE VERDICT, AND THE DIAGNOSIS IS SEPARATE FROM IT. Whether a tag is grammar is decided by
|
|
33
|
-
* `isGrammar` alone; what the message then SAYS about it is `unrecognisedTagFault`'s. Keeping the
|
|
34
|
-
* two apart is what lets the group-prefixed reading be as broad as it is (@SCN-STG-004) without
|
|
35
|
-
* ever widening or narrowing what reds.
|
|
36
|
-
*
|
|
37
|
-
* THE TYPO THE REST OF THE MODEL CANNOT SEE, measured rather than argued. `@untit` ALONE
|
|
38
|
-
* reconciles both-missing, so half of this fault a reconciliation does cover. Planted beside a
|
|
39
|
-
* real tier — `@unit @untit` — the only reconciling item is the absent unit Evidence Observation:
|
|
40
|
-
* the typo contributes nothing and is named nowhere, in any cell, at any exit status.
|
|
41
|
-
*
|
|
42
|
-
* PER TAG, NOT PER SCENARIO, because two junk tags are two things to fix and a finding naming one
|
|
43
|
-
* of them leaves the author to re-run the command to discover the other.
|
|
44
|
-
*
|
|
45
|
-
* ONLY `@SCN` SCENARIOS ARE ASKED, which comes free from `parseTaggedScenarios` — it yields
|
|
46
|
-
* nothing for a scenario carrying no id. That is the same scope the tier floor drew and it is
|
|
47
|
-
* drawn for the same reason: a corpus mid-adoption has scenarios the scheme has not reached yet,
|
|
48
|
-
* and policing their tag lines would make adopting the scheme a whole-corpus edit.
|
|
49
|
-
*
|
|
50
|
-
* AND A PARKED SCENARIO IS ASKED TOO (@SCN-STG-003). There is no clause anywhere below that
|
|
51
|
-
* excuses a scenario for carrying a deferral tag, and that absence is the discipline rather than
|
|
52
|
-
* an oversight: parking defers what a scenario OWES, never whether its tags are spelled right.
|
|
53
|
-
* This very set is what lets the walk recognise the parking tag, so excusing the walk on a parked
|
|
54
|
-
* scenario would hide `@wip @untit` — a check whose teeth come off by writing one more tag. The
|
|
55
|
-
* resolve happens once, before the walk, for that reason as much as for the cost.
|
|
56
|
-
*
|
|
57
|
-
* @param features the target's discovered feature files, read once at the edge.
|
|
58
|
-
* @param packageJson the TARGET's manifest, read HERE through the same resolvers the ingest edge
|
|
59
|
-
* reads it with — one reading of `specController.deferralTags` (@SCN-PND-021), so the words this
|
|
60
|
-
* rule calls legitimate are exactly the words the engine beside it honours as a skip.
|
|
61
|
-
* The target's own check registry is retired and read nowhere in this assembly (@SCN-STG-005,
|
|
62
|
-
* 3F-3161). A set handed in already resolved would have been a second answer travelling under the
|
|
63
|
-
* first's name.
|
|
64
|
-
* @param starterDeferralTags the APPLICATION layer's starter set, which a target's config may only
|
|
65
|
-
* extend and never replace. It is a parameter because it is product policy — an evolvable list of
|
|
66
|
-
* strings — and a copy held in core would be a second statement of it. Pass none and this clause
|
|
67
|
-
* recognises nothing it was not given, which is the difference between owning a policy and
|
|
68
|
-
* hard-coding someone else's.
|
|
69
|
-
*/
|
|
70
|
-
export declare function unrecognisedTags(features: readonly CorpusFile[], packageJson: TargetManifest, starterDeferralTags: readonly string[]): CorpusFault[];
|
|
71
|
-
//# sourceMappingURL=corpusGrammarFaults.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"corpusGrammarFaults.d.ts","sourceRoot":"","sources":["../../src/parse/corpusGrammarFaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA2NjF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,UAAU,EAAE,EAC/B,WAAW,EAAE,cAAc,EAC3B,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACrC,WAAW,EAAE,CAqBf"}
|
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE GRAMMAR RULES of `spec-controller tags` — everything about whether a TAG on a scenario
|
|
3
|
-
* means anything. Its sibling holds the other question: `corpusCodeFaults.ts` whether a feature
|
|
4
|
-
* code binds to one feature file. `corpusFaults.ts` composes the two and is the only entry point
|
|
5
|
-
* either of them has.
|
|
6
|
-
*
|
|
7
|
-
* THE SEAM, STATED FROM THIS SIDE. A grammar rule asks *is this word part of the `@SCN` scheme*,
|
|
8
|
-
* and the answer is assembled from places that are not this module's: the engine's own
|
|
9
|
-
* quality-check maps, the `SCN-<FFF>-<NNN>` spelling `featureCodeOf` owns, and the target's own
|
|
10
|
-
* manifest. A code rule needs none of those; it reads the corpus's shape. Two questions, two
|
|
11
|
-
* modules; the split happened when the joined module reached the 400-line `max-lines` ceiling
|
|
12
|
-
* with four more grammar clauses still to land (@SCN-FIT-001, and never an exception entry). The
|
|
13
|
-
* claim rule that once made a third sibling left with the measured axis (3F-3516): once the axis
|
|
14
|
-
* word is the only word that names a check, no scenario can claim two.
|
|
15
|
-
*
|
|
16
|
-
* AND THE TARGET'S HALF IS RESOLVED HERE, NOT HANDED IN RESOLVED. The composition hands this
|
|
17
|
-
* module a manifest rather than an answer, so the read lives beside the rule that uses it — the
|
|
18
|
-
* arrangement the parent's Design settled for the check-tag union and applied here first, because
|
|
19
|
-
* the whole reason the floor and the obligation rule once disagreed about a set was that each
|
|
20
|
-
* assembled its own. The composition passes bytes and policy; what a word MEANS is decided in one
|
|
21
|
-
* place.
|
|
22
|
-
*
|
|
23
|
-
* NOTHING HERE IS RESTATED. The recognised set is the whole subject of this module, and every
|
|
24
|
-
* member of it is DERIVED from the place that already owns it — a list written out here would
|
|
25
|
-
* agree with its source by diligence and then drift, and the check that then reds is the one
|
|
26
|
-
* telling authors which words are legitimate.
|
|
27
|
-
*/
|
|
28
|
-
import { featureCodeOf } from "../lib/featureCode.js";
|
|
29
|
-
import { FITNESS_AXIS_TAG, PENDING_QUALITY_CHECK_TAGS, RUNTIME_QUALITY_CHECK_TAGS, parseTaggedScenarios, } from "./scenarios.js";
|
|
30
|
-
import { resolveDeferralTags } from "./targetManifest.js";
|
|
31
|
-
/**
|
|
32
|
-
* The tier tags an unrecognised tag is measured against, and the set that answers whether a tag
|
|
33
|
-
* NAMES a tier at all.
|
|
34
|
-
*
|
|
35
|
-
* DERIVED, NEVER RESTATED, which is the whole reason this rule could ship. The words live in the
|
|
36
|
-
* engine's own quality-check maps; a list written out here would agree with them by diligence and
|
|
37
|
-
* then drift the first time a tier is added — and the check that then reds is the one telling
|
|
38
|
-
* authors which words are legitimate.
|
|
39
|
-
*
|
|
40
|
-
* BARE `lint` IS ONE OF THEM and is not in either map, because `@lint` is not a runtime tier: it
|
|
41
|
-
* is the style-lint check, a flat peer of `@complexity`, which raises a `lint` obligation without
|
|
42
|
-
* a runtime observation. It is named here rather than pushed into `TAG_TO_QUALITY_CHECK`, where
|
|
43
|
-
* it would start raising runtime obligations for every scenario that carries it.
|
|
44
|
-
*
|
|
45
|
-
* `lintpending` ARRIVES WITH THE PENDING LIST, and that is one word wider than the private check
|
|
46
|
-
* this rule moved out of. That check kept its own four-member tier list, so `@lintpending` was
|
|
47
|
-
* unrecognised there while the engine beside it read the same tag as a deferred `lint`
|
|
48
|
-
* obligation — two readers of one corpus disagreeing about one word, which is precisely the
|
|
49
|
-
* second reading this module exists to end. Taking the engine's own lexicon closes it.
|
|
50
|
-
*/
|
|
51
|
-
const TIER_TAGS = [
|
|
52
|
-
...RUNTIME_QUALITY_CHECK_TAGS,
|
|
53
|
-
"lint",
|
|
54
|
-
...PENDING_QUALITY_CHECK_TAGS,
|
|
55
|
-
];
|
|
56
|
-
/**
|
|
57
|
-
* Every word that NAMES A CHECK on this target (@SCN-STG-005) — the set the grammar admits
|
|
58
|
-
* beside the scheme's own tier tags.
|
|
59
|
-
*
|
|
60
|
-
* ONE ASSEMBLY, AND THAT IS THE WHOLE POINT OF ITS BEING HERE. The tier floor this rule
|
|
61
|
-
* replaced assembled its own copy at a private CLI while the obligation rule assembled another
|
|
62
|
-
* in the engine, and the two coming to disagree about this set cost a slice (3F-3126). Resolving
|
|
63
|
-
* it beside the rule that asks the question means the words this command calls legitimate are
|
|
64
|
-
* the words the engine beside it raises obligations from — there is no second answer to fall
|
|
65
|
-
* behind the first, and no package boundary for one to be resolved on either side of.
|
|
66
|
-
*
|
|
67
|
-
* NO BARE TAG NAMES A CHECK ANY LONGER (3F-3161). The target's own check registry used to be
|
|
68
|
-
* read here as the TARGET's answer for which bare words meant a check; that reading is retired,
|
|
69
|
-
* and a bare check tag is grammar nowhere now, registered or not. The measured tags read off the
|
|
70
|
-
* target's own thresholds left with the measured axis (3F-3516), so the one word this function
|
|
71
|
-
* admits beside the scheme's own tiers is the converted axis word — and it reads no manifest to
|
|
72
|
-
* find it, because the word is the model's. A target still writing a bare check tag is read
|
|
73
|
-
* nowhere by this assembly, which is the whole of what @SCN-STG-005 changed.
|
|
74
|
-
*
|
|
75
|
-
* AND THE AXIS WORD IS NOT THE TARGET'S TO GRANT (3F-3138, 3F-3149). A CONVERTED check carries
|
|
76
|
-
* one word for the whole axis and puts its CHARACTERISTIC on a configured row, so the retired
|
|
77
|
-
* registry names it nowhere and never will. Which words name a CHECK is the target's
|
|
78
|
-
* answer; which axis a scenario is ON is the model's, exactly as `unit` is — so the word is
|
|
79
|
-
* admitted whatever the manifest holds, and a target that has converted nothing does not get to
|
|
80
|
-
* spell it differently. It arrives as `FITNESS_AXIS_TAG`, the one spelling of it, because a
|
|
81
|
-
* literal written out here would be a second answer travelling under the first's name.
|
|
82
|
-
*
|
|
83
|
-
* A CONVERTED SCENARIO NO CONFIGURED ROW NAMES IS ADMITTED, deliberately: that IS a corpus
|
|
84
|
-
* fault, and it is @SCN-LNT-020's, which names the scenario by id and leaves the one remedy
|
|
85
|
-
* there is. Redding it here too would print half of one fault in a second place with the wrong
|
|
86
|
-
* remedy attached — *this word means nothing here*, said to an author whose scenario names the
|
|
87
|
-
* one axis the model has.
|
|
88
|
-
*/
|
|
89
|
-
function checkTagsOf() {
|
|
90
|
-
return [FITNESS_AXIS_TAG];
|
|
91
|
-
}
|
|
92
|
-
/** Levenshtein distance, uncapped — the strings here are tag-length. */
|
|
93
|
-
function editDistance(a, b) {
|
|
94
|
-
let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
95
|
-
for (let i = 1; i <= a.length; i += 1) {
|
|
96
|
-
const current = [i];
|
|
97
|
-
for (let j = 1; j <= b.length; j += 1) {
|
|
98
|
-
const substitution = previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1);
|
|
99
|
-
current[j] = Math.min(current[j - 1] + 1, previous[j] + 1, substitution);
|
|
100
|
-
}
|
|
101
|
-
previous = current;
|
|
102
|
-
}
|
|
103
|
-
return previous[b.length];
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* The tier an unrecognised tag was probably meant to be, or undefined when none is close.
|
|
107
|
-
*
|
|
108
|
-
* A COURTESY, NEVER THE VERDICT. The tag reds whether or not a suggestion is found, so a wrong
|
|
109
|
-
* guess costs a poor message and nothing else. A guess that DECIDED the outcome would make the
|
|
110
|
-
* command only as good as its edit distance.
|
|
111
|
-
*
|
|
112
|
-
* Distance 2 rather than 1 catches the drop-plus-transpose shapes (`@untegration`); wider than
|
|
113
|
-
* that and `@e2e` starts attracting every short tag in the corpus.
|
|
114
|
-
*/
|
|
115
|
-
function nearestTier(bare) {
|
|
116
|
-
let best;
|
|
117
|
-
let bestDistance = 3;
|
|
118
|
-
for (const tier of TIER_TAGS) {
|
|
119
|
-
const distance = editDistance(bare.toLowerCase(), tier);
|
|
120
|
-
if (distance < bestDistance) {
|
|
121
|
-
bestDistance = distance;
|
|
122
|
-
best = tier;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return best;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* The bare tag a group-prefixed tag should have been (@SCN-STG-004), or undefined where the tag
|
|
129
|
-
* carries no value to strip a group from.
|
|
130
|
-
*
|
|
131
|
-
* `fitness=complexity` spells into the tag what the model already holds. There is no
|
|
132
|
-
* `behavioural=unit`, so there is no `fitness=complexity` (canon 2026-08-07, the bare-tags
|
|
133
|
-
* Correction) — and the author's intent survives the mistake intact: drop the group and what is
|
|
134
|
-
* left is the tag they wanted.
|
|
135
|
-
*
|
|
136
|
-
* NO LIST OF GROUP NAMES IS CONSULTED, because there is nothing to list. The words a codebase
|
|
137
|
-
* might reach for are not enumerable, and a list of the ones canon happens to name would green the
|
|
138
|
-
* first group name nobody thought of. So the SHAPE is the whole of the rule: a value means a group
|
|
139
|
-
* was spelled in, whatever the group is called.
|
|
140
|
-
*
|
|
141
|
-
* AND THE RETIRED `lint=<handle>` FORM REACHES IT, served by the same rule rather than carved out.
|
|
142
|
-
* That form raises no Evidence Obligation (@SCN-LNT-007), so admitting it as a tier would let a
|
|
143
|
-
* scenario look tiered while owing nothing — which is the silent slip these rules exist to close,
|
|
144
|
-
* re-opened by the one shape a reader would most expect to be excused. The private check this rule
|
|
145
|
-
* replaced did carve it out, for as long as the form was live; nothing here has to remember to
|
|
146
|
-
* take that clause away again.
|
|
147
|
-
*
|
|
148
|
-
* IT DECIDES NOTHING, WHICH IS WHY IT IS SAFE TO BE THIS BROAD. `isGrammar` has already answered
|
|
149
|
-
* the verdict by the time this is asked; a tag reaching here reds whatever this returns.
|
|
150
|
-
*/
|
|
151
|
-
function groupPrefixedMember(tag) {
|
|
152
|
-
return /^[^=]+=(.+)$/.exec(tag)?.[1];
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Why an unrecognised tag is unrecognised, and what to write instead — the clause following
|
|
156
|
-
* `carries @<tag>,` in the message.
|
|
157
|
-
*
|
|
158
|
-
* TWO SHAPES, ONE VERDICT, TWO MESSAGES. A group-prefixed tag resembles no tier, so edit distance
|
|
159
|
-
* has nothing to offer it (@SCN-STG-004); what it has instead is a legible intent, and the message
|
|
160
|
-
* names the bare tag rather than leaving the author to work out which half of their tag was the
|
|
161
|
-
* mistake. Every other unrecognised tag falls back to the near-miss courtesy, which stays a
|
|
162
|
-
* courtesy and never the verdict (@SCN-STG-002). Collapsing the two would print one fault's remedy
|
|
163
|
-
* at the other's author — the wrong-message failure the fault kinds were split to avoid.
|
|
164
|
-
*/
|
|
165
|
-
function unrecognisedTagFault(tag) {
|
|
166
|
-
const member = groupPrefixedMember(tag);
|
|
167
|
-
if (member !== undefined) {
|
|
168
|
-
return (`which spells a group into the tag — a check is named bare, its group living in the ` +
|
|
169
|
-
`model — so this should have been @${member}`);
|
|
170
|
-
}
|
|
171
|
-
const suggestion = nearestTier(tag);
|
|
172
|
-
return (`which is neither an evidence tier nor a recognised deferral tag` +
|
|
173
|
-
(suggestion === undefined ? "" : ` — did you mean @${suggestion}?`));
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Is this tag part of the `@SCN` scheme's grammar, on a scenario in this file?
|
|
177
|
-
*
|
|
178
|
-
* SIX CLAUSES, AND ONE OF THEM CARRIES THE WHOLE CHECK-TAG SET. What this rule reaches is the
|
|
179
|
-
* scheme's own words, the target's deferral set, and `checkTagsOf`'s one word — the axis word (a
|
|
180
|
-
* bare check tag is grammar nowhere now, 3F-3161, and the measured tags left with the measured
|
|
181
|
-
* axis, 3F-3516). That the set grew and then shrank to one source changed nothing here, which is
|
|
182
|
-
* the point of assembling it there: a clause reading one source at a time would have had to move
|
|
183
|
-
* with it.
|
|
184
|
-
*
|
|
185
|
-
* THE FILE'S HEADER CODE IS GRAMMAR, and that clause is new rather than moved. `@TGT` sits on the
|
|
186
|
-
* `Feature:` line and `parseTaggedScenarios` inherits it onto every scenario beneath, exactly as
|
|
187
|
-
* cucumber does — so without this clause the rule reds every scenario in every coded file:
|
|
188
|
-
* measured over this repository's own corpus, 253 scenario/tag pairs across 28 codes. The private
|
|
189
|
-
* scan this rule replaced never met the case because it read a scenario's own tag block and
|
|
190
|
-
* nothing above it, which is the second reading `parseTaggedScenarios` was extracted to end.
|
|
191
|
-
*
|
|
192
|
-
* A WELL-FORMED `@SCN` ID IS GRAMMAR WHEREVER IT SITS — `featureCodeOf` is the one owner of that
|
|
193
|
-
* spelling, so an id it parses is recognised here without a second regex. An id it CANNOT parse
|
|
194
|
-
* is not this fault: `no-scn-code` raises it, names it, and would print a different remedy.
|
|
195
|
-
*
|
|
196
|
-
* A WORD THAT NAMES A CHECK IS GRAMMAR (@SCN-STG-005), steps or none. A fitness check is named
|
|
197
|
-
* by a BARE tag — a flat peer of the behavioural tiers, not a member of some group — so it
|
|
198
|
-
* matches nothing in `TIER_TAGS` and would otherwise red every fitness scenario in a corpus:
|
|
199
|
-
* measured over this repository's own, ten findings and exit 1 on the commit before this clause
|
|
200
|
-
* landed. The set is `checkTagsOf`'s and is resolved once, before the walk.
|
|
201
|
-
*
|
|
202
|
-
* AND STEPS ARE NOT CONSULTED, WHICH IS STRUCTURAL RATHER THAN REMEMBERED (3F-3126). The tier
|
|
203
|
-
* floor this rule replaced once keyed on steplessness, and a rule keyed on that correlate reds
|
|
204
|
-
* the first converted check for writing exactly the shape the obligation rule asks for. Here
|
|
205
|
-
* there is no clause to remove: the walk reads a scenario's TAGS, so the stepped and the
|
|
206
|
-
* stepless row are one case rather than two that agree.
|
|
207
|
-
*
|
|
208
|
-
* A RECOGNISED DEFERRAL TAG IS GRAMMAR (@SCN-STG-003), and it is the first clause here whose
|
|
209
|
-
* answer is the TARGET'S rather than the scheme's. Reding every tag outside the tier set would red
|
|
210
|
-
* `@skip` — a tag spec-controller itself recognises, honours as a deferral signal, and lets a
|
|
211
|
-
* target extend by config. A check that condemns what the product accepts is not stricter, it is
|
|
212
|
-
* wrong. The set arrives RESOLVED and is never restated, so there is no second list here to fall
|
|
213
|
-
* behind the first; and this module names no community tag of its own, because which words the
|
|
214
|
-
* community recognises is product policy handed in from the application layer.
|
|
215
|
-
*/
|
|
216
|
-
function isGrammar(tag, scenarioId, featureCode, deferralTags, checkTags) {
|
|
217
|
-
if (tag === scenarioId)
|
|
218
|
-
return true;
|
|
219
|
-
if (featureCodeOf(tag) !== null)
|
|
220
|
-
return true;
|
|
221
|
-
if (featureCode !== null && tag === featureCode)
|
|
222
|
-
return true;
|
|
223
|
-
if (deferralTags.includes(tag))
|
|
224
|
-
return true;
|
|
225
|
-
if (checkTags.includes(tag))
|
|
226
|
-
return true;
|
|
227
|
-
return TIER_TAGS.includes(tag);
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* A tag on an `@SCN` scenario that means nothing here (@SCN-STG-002, @SCN-STG-003, @SCN-STG-004).
|
|
231
|
-
*
|
|
232
|
-
* ONE VERDICT, AND THE DIAGNOSIS IS SEPARATE FROM IT. Whether a tag is grammar is decided by
|
|
233
|
-
* `isGrammar` alone; what the message then SAYS about it is `unrecognisedTagFault`'s. Keeping the
|
|
234
|
-
* two apart is what lets the group-prefixed reading be as broad as it is (@SCN-STG-004) without
|
|
235
|
-
* ever widening or narrowing what reds.
|
|
236
|
-
*
|
|
237
|
-
* THE TYPO THE REST OF THE MODEL CANNOT SEE, measured rather than argued. `@untit` ALONE
|
|
238
|
-
* reconciles both-missing, so half of this fault a reconciliation does cover. Planted beside a
|
|
239
|
-
* real tier — `@unit @untit` — the only reconciling item is the absent unit Evidence Observation:
|
|
240
|
-
* the typo contributes nothing and is named nowhere, in any cell, at any exit status.
|
|
241
|
-
*
|
|
242
|
-
* PER TAG, NOT PER SCENARIO, because two junk tags are two things to fix and a finding naming one
|
|
243
|
-
* of them leaves the author to re-run the command to discover the other.
|
|
244
|
-
*
|
|
245
|
-
* ONLY `@SCN` SCENARIOS ARE ASKED, which comes free from `parseTaggedScenarios` — it yields
|
|
246
|
-
* nothing for a scenario carrying no id. That is the same scope the tier floor drew and it is
|
|
247
|
-
* drawn for the same reason: a corpus mid-adoption has scenarios the scheme has not reached yet,
|
|
248
|
-
* and policing their tag lines would make adopting the scheme a whole-corpus edit.
|
|
249
|
-
*
|
|
250
|
-
* AND A PARKED SCENARIO IS ASKED TOO (@SCN-STG-003). There is no clause anywhere below that
|
|
251
|
-
* excuses a scenario for carrying a deferral tag, and that absence is the discipline rather than
|
|
252
|
-
* an oversight: parking defers what a scenario OWES, never whether its tags are spelled right.
|
|
253
|
-
* This very set is what lets the walk recognise the parking tag, so excusing the walk on a parked
|
|
254
|
-
* scenario would hide `@wip @untit` — a check whose teeth come off by writing one more tag. The
|
|
255
|
-
* resolve happens once, before the walk, for that reason as much as for the cost.
|
|
256
|
-
*
|
|
257
|
-
* @param features the target's discovered feature files, read once at the edge.
|
|
258
|
-
* @param packageJson the TARGET's manifest, read HERE through the same resolvers the ingest edge
|
|
259
|
-
* reads it with — one reading of `specController.deferralTags` (@SCN-PND-021), so the words this
|
|
260
|
-
* rule calls legitimate are exactly the words the engine beside it honours as a skip.
|
|
261
|
-
* The target's own check registry is retired and read nowhere in this assembly (@SCN-STG-005,
|
|
262
|
-
* 3F-3161). A set handed in already resolved would have been a second answer travelling under the
|
|
263
|
-
* first's name.
|
|
264
|
-
* @param starterDeferralTags the APPLICATION layer's starter set, which a target's config may only
|
|
265
|
-
* extend and never replace. It is a parameter because it is product policy — an evolvable list of
|
|
266
|
-
* strings — and a copy held in core would be a second statement of it. Pass none and this clause
|
|
267
|
-
* recognises nothing it was not given, which is the difference between owning a policy and
|
|
268
|
-
* hard-coding someone else's.
|
|
269
|
-
*/
|
|
270
|
-
export function unrecognisedTags(features, packageJson, starterDeferralTags) {
|
|
271
|
-
const deferralTags = resolveDeferralTags(packageJson, starterDeferralTags);
|
|
272
|
-
// Both sets are resolved ONCE, before the walk, rather than per tag: the manifest cannot change
|
|
273
|
-
// mid-corpus, and one resolution is what makes "the same set the obligation rule reads" a fact
|
|
274
|
-
// about this run rather than about each tag's turn through it.
|
|
275
|
-
const checkTags = checkTagsOf();
|
|
276
|
-
const faults = [];
|
|
277
|
-
for (const file of features) {
|
|
278
|
-
for (const scenario of parseTaggedScenarios(file.source)) {
|
|
279
|
-
for (const tag of scenario.tags) {
|
|
280
|
-
if (isGrammar(tag, scenario.scnId, file.featureCode, deferralTags, checkTags))
|
|
281
|
-
continue;
|
|
282
|
-
faults.push({
|
|
283
|
-
kind: "unrecognised-tag",
|
|
284
|
-
message: `unrecognised-tag: ${file.slug}.feature scenario @${scenario.scnId} carries @${tag}, ` +
|
|
285
|
-
unrecognisedTagFault(tag),
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return faults;
|
|
291
|
-
}
|
|
292
|
-
//# sourceMappingURL=corpusGrammarFaults.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"corpusGrammarFaults.js","sourceRoot":"","sources":["../../src/parse/corpusGrammarFaults.ts"],"names":[],"mappings":"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"}
|