@3f-consulting/spec-controller-core 0.1.0-alpha.7 → 0.1.0-alpha.71
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 +30 -325
- package/dist/assemble/evidenceReconciliationFromSources.js.map +1 -1
- package/dist/assemble/renderInput.d.ts +7 -73
- 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 +11 -46
- package/dist/census/evidenceObligations.d.ts.map +1 -1
- package/dist/census/evidenceObligations.js +19 -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 +21 -391
- package/dist/domain/evidenceReconciliation.d.ts.map +1 -1
- package/dist/domain/evidenceReconciliation.js +87 -382
- 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 +8 -393
- 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 +8 -328
- package/dist/domain/ledger.d.ts.map +1 -1
- package/dist/domain/ledger.js +23 -326
- package/dist/domain/ledger.js.map +1 -1
- package/dist/domain/messages.d.ts +213 -0
- package/dist/domain/messages.d.ts.map +1 -0
- package/dist/domain/messages.js +313 -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 +8 -105
- package/dist/domain/posting.d.ts.map +1 -1
- package/dist/domain/posting.js +4 -56
- package/dist/domain/posting.js.map +1 -1
- package/dist/domain/qualityCheckFault.d.ts +3 -43
- 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 +7 -280
- package/dist/domain/qualityCheckReconciliation.d.ts.map +1 -1
- package/dist/domain/qualityCheckReconciliation.js +63 -463
- 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 +2 -207
- package/dist/domain/scenarioReconciliation.d.ts.map +1 -1
- package/dist/domain/scenarioReconciliation.js +4 -101
- 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 +14 -40
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -88
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +3 -27
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +3 -94
- 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 +2 -16
- 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 +5 -168
- package/dist/parse/checkScriptsRunInCI.d.ts.map +1 -1
- package/dist/parse/checkScriptsRunInCI.js +11 -171
- package/dist/parse/checkScriptsRunInCI.js.map +1 -1
- package/dist/parse/ciStepRecord.d.ts +4 -118
- package/dist/parse/ciStepRecord.d.ts.map +1 -1
- package/dist/parse/ciStepRecord.js +18 -225
- 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 +6 -67
- package/dist/parse/commandRuns.js.map +1 -1
- package/dist/parse/cucumber.d.ts +0 -53
- package/dist/parse/cucumber.d.ts.map +1 -1
- package/dist/parse/cucumber.js +42 -146
- package/dist/parse/cucumber.js.map +1 -1
- package/dist/parse/discoveryScope.d.ts +1 -46
- package/dist/parse/discoveryScope.d.ts.map +1 -1
- package/dist/parse/discoveryScope.js +2 -57
- 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 +2 -64
- package/dist/parse/reconcilerSteps.js.map +1 -1
- package/dist/parse/runningFitnessFunctions.d.ts +9 -0
- package/dist/parse/runningFitnessFunctions.d.ts.map +1 -0
- package/dist/parse/runningFitnessFunctions.js +57 -0
- package/dist/parse/runningFitnessFunctions.js.map +1 -0
- package/dist/parse/scenarioCodeErrors.d.ts +11 -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 +20 -457
- 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 +1 -55
- 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 +2 -50
- 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 +48 -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 +4 -83
- 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 +21 -103
- 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/fitnessFunctions.d.ts +3 -0
- package/dist/render/fitnessFunctions.d.ts.map +1 -0
- package/dist/render/fitnessFunctions.js +12 -0
- package/dist/render/fitnessFunctions.js.map +1 -0
- 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 +1 -55
- package/dist/render/markdown.d.ts.map +1 -1
- package/dist/render/markdown.js +128 -467
- 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/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
- package/dist/parse/runningStaticChecks.d.ts +0 -125
- package/dist/parse/runningStaticChecks.d.ts.map +0 -1
- package/dist/parse/runningStaticChecks.js +0 -316
- package/dist/parse/runningStaticChecks.js.map +0 -1
- package/dist/render/staticChecks.d.ts +0 -23
- package/dist/render/staticChecks.d.ts.map +0 -1
- package/dist/render/staticChecks.js +0 -69
- package/dist/render/staticChecks.js.map +0 -1
package/dist/domain/ledger.js
CHANGED
|
@@ -1,212 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
* THE LEDGER — the accounts with their posted entries, co-located with its OWN whole-run
|
|
3
|
-
* behaviour: `isBalanced`, `hasPendingItems`, `hasBrokenEvidence` (module, not class). These
|
|
4
|
-
* three pure predicates are the whole-run verdict surface the CLI edge maps to exit codes;
|
|
5
|
-
* they were the reconcile orchestration's exports and now live WITH the concept they fold over.
|
|
6
|
-
*/
|
|
7
|
-
// The row-level static-check cut (3F-2203) — the Ledger-wide lint list is built ON it, so the
|
|
8
|
-
// obligation-side rule is stated once, at the row.
|
|
9
|
-
import { staticCheckReconciliationsOf, isScenario } from "./scenarioReconciliation.js";
|
|
10
|
-
/**
|
|
11
|
-
* The WHOLE-RUN verdict — is the ENTIRE reconciliation balanced? A pure domain
|
|
12
|
-
* derivation over the WHOLE `Ledger`: balanced IFF NO reconciling
|
|
13
|
-
* item exists ANYWHERE, across every Scenario Reconciliation row — scenario,
|
|
14
|
-
* phantom, and suspense alike. Out-of-balance iff ANY row carries a reconciling
|
|
15
|
-
* item: a scenario's out-of-balance items (failing / missing /
|
|
16
|
-
* no-evidence-obligation / both-missing) AND the credit-side suspense/phantom rows (a
|
|
17
|
-
* no-evidence-obligation static-check watermelon, an uncited credit, a phantom scenario).
|
|
18
|
-
*
|
|
19
|
-
* It is deliberately NOT a scan of scenario verdicts alone — that would
|
|
20
|
-
* let a watermelon-only run (every scenario balanced, yet a no-evidence-obligation
|
|
21
|
-
* static check sitting unreconciled in the suspense row) read as balanced, the
|
|
22
|
-
* false pass a CI gate must never give. Every row's `reconcilingItems` is
|
|
23
|
-
* consulted, so the suspense/phantom rows (verdict ALWAYS out-of-balance) count.
|
|
24
|
-
*
|
|
25
|
-
* The CLI edge maps this boolean to the process exit code — balanced → 0,
|
|
26
|
-
* out-of-balance → EXACTLY 1 — an ENUMERATED status, never a count (a count would
|
|
27
|
-
* 8-bit `& 0xFF` wrap → false pass).
|
|
28
|
-
*/
|
|
1
|
+
import { fitnessFunctionReconciliationsOf, isScenario } from "./scenarioReconciliation.js";
|
|
29
2
|
export function isBalanced(reconciliation) {
|
|
30
3
|
return reconciliation.scenarioReconciliations.every((row) => row.reconcilingItems.length === 0);
|
|
31
4
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Does the WHOLE reconciliation carry any Pending Item? A pure domain predicate over the
|
|
34
|
-
* WHOLE `Ledger`, SYMMETRIC with `isBalanced` — together they are the
|
|
35
|
-
* whole-run verdict surface. True iff ANY Scenario Reconciliation row carries a Pending
|
|
36
|
-
* Item (a deferred `<quality-check>pending` obligation partitioned off before reconciliation,
|
|
37
|
-
* @SCN-PND-004). Pending Items are run-neutral by default (@SCN-PND-008); the CLI edge
|
|
38
|
-
* consults this ALONGSIDE `isBalanced` to escalate an otherwise-balanced run to the distinct
|
|
39
|
-
* exit code 3 under `--strict` (@SCN-CLI-011) — an OPT-IN gate on deferred obligations,
|
|
40
|
-
* checked only when `isBalanced` is true (out-of-balance dominates, exit 1).
|
|
41
|
-
*/
|
|
42
5
|
export function hasPendingItems(reconciliation) {
|
|
43
6
|
return reconciliation.scenarioReconciliations.some((row) => row.pendingItems.length > 0);
|
|
44
7
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Does the WHOLE reconciliation carry BROKEN evidence — i.e. is the run UNSOUND? The THIRD
|
|
47
|
-
* whole-run predicate (@SCN-LDG-018), beside `isBalanced` and `hasPendingItems`, and the
|
|
48
|
-
* EXISTENTIAL TWIN of the latter: the same `some(row => some(item => item.outcome === X))` scan.
|
|
49
|
-
*
|
|
50
|
-
* Soundness is a property of the RUN, not of a scenario. If any PROOF NEVER RAN — a vitest suite
|
|
51
|
-
* that failed to collect (@SCN-LDG-017), or a cucumber step matched by two or more definitions
|
|
52
|
-
* (@SCN-LDG-019) — the evidence never fully materialised, so every `missing` in that run is
|
|
53
|
-
* SUSPECT: it may be a broken proof rather than an absent one, and the remedies differ (fix the
|
|
54
|
-
* harness vs write a test). The scenario's own row stays honest at its own resolution (`missing`);
|
|
55
|
-
* the RUN is what is stamped unsound.
|
|
56
|
-
*
|
|
57
|
-
* DERIVED, NEVER STORED — no soundness flag is written onto `Ledger`, the same
|
|
58
|
-
* no-drift reason `isBalanced` and `hasPendingItems` derive. Machine consumers read soundness off
|
|
59
|
-
* `summary.byOutcome.broken > 0` (type-forced into the JSON the moment `broken` joined the
|
|
60
|
-
* `Outcome` union); the markdown renderer prints the HEADLINE word — "unsound" is the render word,
|
|
61
|
-
* never the predicate's name, exactly as "out-of-balance" is for `isBalanced`.
|
|
62
|
-
*
|
|
63
|
-
* Keyed on the `broken` OUTCOME specifically, never on `!isBalanced`: an ordinary out-of-balance
|
|
64
|
-
* run (an honest `missing`, no broken evidence) is perfectly SOUND. The three whole-run
|
|
65
|
-
* predicates are INDEPENDENT — a run may carry Pending Items and be sound; a run may carry broken
|
|
66
|
-
* evidence and no Pending Items. (A broken run is ALWAYS out-of-balance, since the `broken` item
|
|
67
|
-
* sits on the suspense row — which is why the CLI edge must consult THIS predicate BEFORE the
|
|
68
|
-
* balance verdict, @SCN-CLI-012, or its exit code would be unreachable.)
|
|
69
|
-
*/
|
|
70
8
|
export function hasBrokenEvidence(reconciliation) {
|
|
71
9
|
return brokenItemsOf(reconciliation).length > 0;
|
|
72
10
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Does the WHOLE run have NOTHING TO RECONCILE — no accounts at all? The FOURTH whole-run
|
|
75
|
-
* predicate (@SCN-CLI-019), beside `isBalanced` / `hasPendingItems` / `hasBrokenEvidence`, and the
|
|
76
|
-
* one shape the other three cannot speak about.
|
|
77
|
-
*
|
|
78
|
-
* THE FAULT IT EXISTS TO NAME. `isBalanced` is `.every()` over the rows, so on an EMPTY ledger it
|
|
79
|
-
* is VACUOUSLY TRUE; `hasPendingItems` and `hasBrokenEvidence` are `.some()`, so they are
|
|
80
|
-
* vacuously FALSE. A target that declared nothing and produced nothing therefore satisfied every
|
|
81
|
-
* existing predicate in the direction that reads as a pass, and was told "BALANCED … (exit 0)" — a
|
|
82
|
-
* green over silence, from the tool whose whole claim is that silence is not the same as nothing
|
|
83
|
-
* wrong. No combination of the three separates an empty run from a clean one, which is why this is
|
|
84
|
-
* a predicate and not a derivation of one.
|
|
85
|
-
*
|
|
86
|
-
* ITS OWN ENUMERATED STATE, exit 5 (taxonomy: 0 balanced / 1 out-of-balance / 2 usage / 3
|
|
87
|
-
* pending-under-strict / 4 unsound / 5 nothing to reconcile). Not balanced — there are no accounts
|
|
88
|
-
* to agree. Not out-of-balance — nothing disagrees. Not a usage fault — the invocation was valid
|
|
89
|
-
* and `new-client` is a supported adoption state, not a degraded one. Not unsound — no proof
|
|
90
|
-
* failed; none was owed.
|
|
91
|
-
*
|
|
92
|
-
* KEYED ON THE EMPTY LEDGER, NEVER ON THE EMPTY CORPUS, and that is load-bearing rather than
|
|
93
|
-
* pedantic: a target with no corpus but uncited credits HAS a row — its suspense row — and is an
|
|
94
|
-
* ordinary out-of-balance report at exit 1 (@SCN-CLI-020). Keyed on "no corpus" instead, the modal
|
|
95
|
-
* first run's whole report would disappear behind exit 5.
|
|
96
|
-
*
|
|
97
|
-
* DERIVED, NEVER STORED — no emptiness flag is written onto `Ledger`, the same no-drift reason its
|
|
98
|
-
* three siblings derive, and the reason no JSON-schema change is owed: a machine consumer reads
|
|
99
|
-
* the row count off the ledger it already has. The markdown renderer prints the HEADLINE word —
|
|
100
|
-
* "NOTHING TO RECONCILE" is the render word, never the predicate's name, exactly as "unsound" is
|
|
101
|
-
* for `hasBrokenEvidence`.
|
|
102
|
-
*
|
|
103
|
-
* WHERE IT MUST BE ASKED, MEASURED RATHER THAN ARGUED (3F-3344). The ticket predicted this would
|
|
104
|
-
* be @SCN-CLI-012's pre-emption one code further on — ask it after `isBalanced` and the branch
|
|
105
|
-
* goes unreachable. IT IS NOT, and the plant that was supposed to prove it stayed GREEN. An empty
|
|
106
|
-
* ledger is MUTUALLY EXCLUSIVE with all three siblings: with no rows there is no row to carry a
|
|
107
|
-
* broken item, a reconciling item or a Pending Item, so it fires NONE of them and its position
|
|
108
|
-
* AMONG them is unobservable. Moving it below `!isBalanced` in the CLI ladder still exits 5
|
|
109
|
-
* (measured).
|
|
110
|
-
*
|
|
111
|
-
* WHAT IS LOAD-BEARING is its position against the chain's DEFAULT. "Balanced" is not a predicate
|
|
112
|
-
* branch — it is the fall-through — so there is no "after the balanced case" to append a fifth
|
|
113
|
-
* code to, and a chain that reaches its default has already called the run balanced. Appended
|
|
114
|
-
* after the default the branch is dead code and the run exits 0 (measured: the plant that DID red).
|
|
115
|
-
* That is also why the fault survived: a fifth code cannot be ADDED to this chain, it has to
|
|
116
|
-
* DISPLACE the default, and nothing about the other three predicates says so.
|
|
117
|
-
*/
|
|
118
11
|
export function hasNothingToReconcile(reconciliation) {
|
|
119
12
|
return reconciliation.scenarioReconciliations.length === 0;
|
|
120
13
|
}
|
|
121
|
-
/**
|
|
122
|
-
* The BROKEN reconciling items across the WHOLE run (3F-2203) — every proof that never ran, in row
|
|
123
|
-
* order, each carrying its WHERE-to-fix (locator) and WHAT-broke (the runner's message).
|
|
124
|
-
*
|
|
125
|
-
* The QUANTITATIVE twin of `hasBrokenEvidence`, which is now derived FROM it: "is this run
|
|
126
|
-
* unsound?" and "which proofs never ran?" are one question at two resolutions, so they are one
|
|
127
|
-
* scan. The markdown's Run-integrity section listed these by re-deriving the scan itself — a model
|
|
128
|
-
* query living in the renderer, and a second statement of which outcome means broken.
|
|
129
|
-
*
|
|
130
|
-
* The renderer READS this list and takes its length for the count-phrase; asking a list you were
|
|
131
|
-
* given how long it is is projection, not derivation.
|
|
132
|
-
*/
|
|
133
14
|
export function brokenItemsOf(reconciliation) {
|
|
134
15
|
return reconciliation.scenarioReconciliations.flatMap((row) => row.reconcilingItems.filter((item) => item.outcome === "broken"));
|
|
135
16
|
}
|
|
136
|
-
|
|
137
|
-
* The OBLIGATION-SIDE static-check sub-rows across the whole Ledger (3F-2203) — each `lint` Quality
|
|
138
|
-
* Check Reconciliation with the scnId of the row that names it, in row-then-document order.
|
|
139
|
-
*
|
|
140
|
-
* SCENARIO ROWS ONLY. A `lint` obligation is obligation-side, so a phantom or suspense row can carry
|
|
141
|
-
* none; the suspense row's lint CREDIT (a no-evidence-obligation static check, `cites-no-scenario`) is an
|
|
142
|
-
* observation, not an obligation, and must never inflate the obligation-side lint total.
|
|
143
|
-
*
|
|
144
|
-
* ONE COPY, BY CONSTRUCTION. That scenario-rows-only filter plus the lint cut existed TWICE,
|
|
145
|
-
* character-identical — here in `lintTally` and in the markdown's `### Lint evidence obligations`
|
|
146
|
-
* table. They agreed by copy-paste, not construction: either could have grown a clause alone and
|
|
147
|
-
* nothing would have redded. Same anaemia, same cure as `evidenceObligationPairsOf` and
|
|
148
|
-
* the corpus's own fitness obligations; the tally and the table are now two readings of ONE list.
|
|
149
|
-
*/
|
|
150
|
-
export function lintReconciliationsOf(reconciliation) {
|
|
17
|
+
export function fitnessReconciliationsOf(reconciliation) {
|
|
151
18
|
return reconciliation.scenarioReconciliations
|
|
152
19
|
.filter(isScenario)
|
|
153
|
-
.flatMap((row) =>
|
|
20
|
+
.flatMap((row) => fitnessFunctionReconciliationsOf(row).map((r) => ({ scnId: row.scnId, reconciliation: r })));
|
|
154
21
|
}
|
|
155
|
-
|
|
156
|
-
const QUALITY_CHECK_ORDER = ["lint", "unit", "integration", "e2e", "performance"];
|
|
157
|
-
/**
|
|
158
|
-
* Tally the LEDGER-PURE summary totals from the balance — the aggregate the markdown's
|
|
159
|
-
* trial-balance table derives, carried AS DATA so a later render-from-saved-JSON rebuilds it with
|
|
160
|
-
* zero computation (the MATERIALISE ruling). The census pass-throughs (`testVolume`,
|
|
161
|
-
* `staticChecks`) are not Ledger-pure and are merged in by the assembler.
|
|
162
|
-
*/
|
|
22
|
+
const QUALITY_CHECK_ORDER = ["fitness", "unit", "integration", "e2e", "performance"];
|
|
163
23
|
export function ledgerTally(balance) {
|
|
164
24
|
const { scenarioReconciliations, pending } = scenarioReconciliationTally(balance);
|
|
165
25
|
return {
|
|
166
26
|
scenarioReconciliations,
|
|
167
27
|
evidenceObligations: evidenceObligationTotals(balance),
|
|
168
|
-
// The Pending Items tally (@SCN-PND-011) — its OWN summary count, SEPARATE from the
|
|
169
|
-
// scenario verdict counts and the evidence-obligation counts. A Pending Item is deferred,
|
|
170
|
-
// not out-of-balance, so it is never one of the `OUT_OF_BALANCE_OUTCOMES` (never a `byOutcome`
|
|
171
|
-
// leaf of its own, at any leaf count). Always present (a pure balance derive, like `lint`);
|
|
172
|
-
// reads 0 when no scenario raises a pending obligation.
|
|
173
28
|
pending,
|
|
174
|
-
|
|
175
|
-
// (static evidenceObligations balanced / total). Always present (a pure balance derive); `byOutcome`
|
|
176
|
-
// is kind-agnostic and cannot evidenceObservations this static-only cut.
|
|
177
|
-
lint: lintTally(balance),
|
|
29
|
+
fitness: fitnessTally(balance),
|
|
178
30
|
};
|
|
179
31
|
}
|
|
180
|
-
/**
|
|
181
|
-
* The row-level half of `ledgerTally` — the Scenario Reconciliation verdict totals and the
|
|
182
|
-
* Pending Items count, both read off one pass over the rows.
|
|
183
|
-
*/
|
|
184
32
|
function scenarioReconciliationTally(balance) {
|
|
185
|
-
// The headline verdict tally counts EVERY Scenario Reconciliation (@SCN-RMD-001, 3F-1724):
|
|
186
|
-
// the summary is the totals over ALL rows (double-entry-manifesto), and phantom / suspense
|
|
187
|
-
// reconciliations are ALWAYS out-of-balance, so they count into the tally like any other row.
|
|
188
|
-
// `phantom` / `suspense` are kept as SUB-COUNTS — a breakdown OF the total, not a bucket
|
|
189
|
-
// outside it. (The retracted "ruling Q3" tallied scenario rows only, which is what let the
|
|
190
|
-
// tally read 0 out-of-balance on a run `isBalanced` correctly failed → exit 1: 3F-1703.)
|
|
191
33
|
const verdict = { balanced: 0, "out-of-balance": 0 };
|
|
192
34
|
let phantom = 0;
|
|
193
35
|
let suspense = 0;
|
|
194
|
-
// The Pending Items tally (@SCN-PND-011) — the count of Pending Items across the
|
|
195
|
-
// reconciliation, one per deferred `<quality-check>pending` obligation. Counts ITEMS, not
|
|
196
|
-
// scenarios-carrying-pending (a scenario may raise several), mirroring the out-of-balance
|
|
197
|
-
// decomposition, which counts obligations, not scenarios. A Pending Item is a structurally
|
|
198
|
-
// distinct category (never a reconciling item / evidence obligation), so it is tallied
|
|
199
|
-
// SEPARATELY here — never folded into `byOutcome` (the out-of-balance leaves).
|
|
200
36
|
let pending = 0;
|
|
201
37
|
for (const s of balance.scenarioReconciliations) {
|
|
202
|
-
// Pending Items ride every row's `pendingItems` (only scenario rows carry them; a
|
|
203
|
-
// phantom / suspense row has none — as an EMPTY array, never an absent one), so the tally is
|
|
204
|
-
// a plain sum across all rows. `pendingItems` is required on `ScenarioReconciliation`, so
|
|
205
|
-
// there is no absent case to fall back from; `hasPendingItems` above already reads it bare.
|
|
206
38
|
pending += s.pendingItems.length;
|
|
207
|
-
// The kind sub-counts, tallied ALONGSIDE the verdict (never instead of it) — the row still
|
|
208
|
-
// falls through to the verdict tally below, so a phantom / suspense reconciliation counts
|
|
209
|
-
// into `total` and (being always out-of-balance) into `outOfBalance`.
|
|
210
39
|
if (s.kind === "phantom-scenario")
|
|
211
40
|
phantom++;
|
|
212
41
|
if (s.kind === "suspense-scenario")
|
|
@@ -215,25 +44,16 @@ function scenarioReconciliationTally(balance) {
|
|
|
215
44
|
}
|
|
216
45
|
return {
|
|
217
46
|
scenarioReconciliations: {
|
|
218
|
-
// Every row's verdict is tallied, so this IS the count of all Scenario Reconciliations
|
|
219
|
-
// (scenario + phantom + suspense) — the manifesto's "the summary is the totals".
|
|
220
47
|
total: verdict.balanced + verdict["out-of-balance"],
|
|
221
48
|
balanced: verdict.balanced,
|
|
222
49
|
outOfBalance: verdict["out-of-balance"],
|
|
223
|
-
// Sub-counts: a breakdown OF the totals above (scenario = total − phantom − suspense).
|
|
224
50
|
phantom,
|
|
225
51
|
suspense,
|
|
226
52
|
},
|
|
227
53
|
pending,
|
|
228
54
|
};
|
|
229
55
|
}
|
|
230
|
-
/**
|
|
231
|
-
* The obligation-level half of `ledgerTally` — every Quality Check Reconciliation tallied by
|
|
232
|
-
* outcome, with the `missing` ones split by quality-check.
|
|
233
|
-
*/
|
|
234
56
|
function evidenceObligationTotals(balance) {
|
|
235
|
-
// byOutcome tallies EVERY Quality Check Reconciliation across ALL rows (scenario AND
|
|
236
|
-
// phantom), so `cites-unknown-scenario` reflects the real phantom count.
|
|
237
57
|
const byOutcome = {
|
|
238
58
|
satisfied: 0,
|
|
239
59
|
"missing": 0,
|
|
@@ -241,28 +61,16 @@ function evidenceObligationTotals(balance) {
|
|
|
241
61
|
"watermelon": 0,
|
|
242
62
|
"cites-unknown-scenario": 0,
|
|
243
63
|
"cites-no-scenario": 0,
|
|
244
|
-
// The debit twin of cites-no-scenario (@SCN-LDG-021) — a scenario with no @SCN code to link.
|
|
245
64
|
"no-scn-code": 0,
|
|
246
|
-
|
|
247
|
-
// (@SCN-LDG-017), or a cucumber step matched by two or more definitions (@SCN-LDG-019). A
|
|
248
|
-
// machine consumer reads run-soundness off this count: `byOutcome.broken > 0` ⇒ any `missing`
|
|
249
|
-
// in the run may be a BROKEN proof rather than an absent one.
|
|
65
|
+
"duplicate-scn-code": 0,
|
|
250
66
|
"broken": 0,
|
|
251
|
-
// The no-evidence-obligation reconciling item (@SCN-LDG-008) — a credit citing a real
|
|
252
|
-
// scenario at a quality-check it never named. Shown here so a reader sees it break out of
|
|
253
|
-
// the reconciliation-matched-attributed count (ruling Q1).
|
|
254
67
|
"no-evidence-obligation": 0,
|
|
255
|
-
// The both-missing reconciling item (@SCN-LDG-009) — the NEITHER-side outcome:
|
|
256
|
-
// a scenario reconciling to zero rows on both sides. `byOutcome` is now 8-valued.
|
|
257
68
|
"both-missing": 0,
|
|
258
69
|
};
|
|
259
70
|
const missing = new Map();
|
|
260
71
|
for (const s of balance.scenarioReconciliations) {
|
|
261
72
|
for (const o of s.qualityCheckReconciliations) {
|
|
262
73
|
byOutcome[o.outcome]++;
|
|
263
|
-
// The subject IS the flat quality-check — `lint` or a runtime quality-check. The
|
|
264
|
-
// both-missing item carries no quality-check (it is not a `missing` evidence obligation), so the
|
|
265
|
-
// guard both narrows the type and keeps it out of the missing split.
|
|
266
74
|
if (o.outcome === "missing" && o.qualityCheck) {
|
|
267
75
|
missing.set(o.qualityCheck, (missing.get(o.qualityCheck) ?? 0) + 1);
|
|
268
76
|
}
|
|
@@ -276,60 +84,14 @@ function evidenceObligationTotals(balance) {
|
|
|
276
84
|
missingByQualityCheck: QUALITY_CHECK_ORDER.filter((s) => (missing.get(s) ?? 0) > 0).map((subject) => ({ subject, count: missing.get(subject) })),
|
|
277
85
|
};
|
|
278
86
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
* satisfied (`balanced`), out of the total raised. Byte-for-byte the markdown's
|
|
282
|
-
* `countStaticEvidenceObligations` (`src/render/markdown.ts`), so slice 2 can read `satisfied` / `total`
|
|
283
|
-
* with zero byte change. `summary.byOutcome` counts ALL kinds, so the static-only total is derived
|
|
284
|
-
* here explicitly.
|
|
285
|
-
*/
|
|
286
|
-
export function lintTally(balance) {
|
|
287
|
-
// TWO READINGS OF ONE LIST (3F-2203) — the obligation-side lint sub-rows come from
|
|
288
|
-
// `lintReconciliationsOf`, the same list the markdown's lint table renders. The
|
|
289
|
-
// scenario-rows-only cut lives there, once, so the tally and the table cannot disagree.
|
|
290
|
-
const lint = lintReconciliationsOf(balance);
|
|
87
|
+
export function fitnessTally(balance) {
|
|
88
|
+
const fitness = fitnessReconciliationsOf(balance);
|
|
291
89
|
return {
|
|
292
|
-
satisfied:
|
|
293
|
-
total:
|
|
90
|
+
satisfied: fitness.filter(({ reconciliation }) => reconciliation.outcome === "satisfied").length,
|
|
91
|
+
total: fitness.length,
|
|
294
92
|
};
|
|
295
93
|
}
|
|
296
|
-
// ---------------------------------------------------------------------------
|
|
297
|
-
// THE RUNTIME-OBSERVATION TALLY (3F-2102, Read @SCN-RMD-003) — the credit-side
|
|
298
|
-
// headline the report's `### Test volume` cut derives, a FOLD OVER THE LEDGER co-located here
|
|
299
|
-
// beside `ledgerTally` for the same reason: "the summary is the totals" — the Ledger counts its
|
|
300
|
-
// OWN posted credits because it IS the balance. This RETIRES the runtime evidence-observation
|
|
301
|
-
// census (`census/evidenceObservations.ts`): "census" and "collection of evidence observations"
|
|
302
|
-
// are not manifesto concepts, so the counting folds onto the Ledger rather than living in a
|
|
303
|
-
// parallel store. Only the AGGREGATE headlines survive (the raw per-quality-check totals and the
|
|
304
|
-
// per-scenario-kind counts) — the per-`(scnId, quality-check)` `attributed[]` list did not, being
|
|
305
|
-
// a re-representation of the Ledger's own posted credits (retire, don't relocate).
|
|
306
|
-
// ---------------------------------------------------------------------------
|
|
307
|
-
/** The canonical runtime quality-check order, in reading order. */
|
|
308
94
|
export const RUNTIME_QUALITY_CHECKS = ["unit", "integration", "e2e", "performance"];
|
|
309
|
-
/**
|
|
310
|
-
* Tally the runtime evidence observations from the Ledger — a FOLD OVER THE POSTED CREDITS
|
|
311
|
-
* (@SCN-RMD-003), the credit-side twin of `ledgerTally`'s debit-side fold. It walks the POSTED
|
|
312
|
-
* CREDITS on each Scenario Reconciliation row (@SCN-LDG-022) and reads each credit's account off
|
|
313
|
-
* THE ROW IT POSTED TO — a scenario row ⇒ `onScenario`, a phantom row ⇒ `onPhantomScenario`,
|
|
314
|
-
* the suspense row ⇒ `onSuspenseScenario` — summing the raw per-quality-check total in lockstep.
|
|
315
|
-
*
|
|
316
|
-
* It RE-DERIVES NOTHING and it does NOT classify: the reconciler already decided which account
|
|
317
|
-
* every credit posts to (the account IS the citation, @SCN-LDG-022), so asking the row is asking
|
|
318
|
-
* that decision. There is ONE place that decides what a credit is, so this tally can never disagree
|
|
319
|
-
* with the verdict — the views (Test volume, the per-quality-check table) are projections of the
|
|
320
|
-
* same rows, not a parallel opinion kept in step.
|
|
321
|
-
*
|
|
322
|
-
* Static check (`lint`) credits are SKIPPED, ON THE CHECK and never on the absence of a citation
|
|
323
|
-
* (@SCN-RPT-023). A fitness credit now CITES its own scenario and posts to an ordinary
|
|
324
|
-
* scenario row, so to a naive walk it is indistinguishable from a runtime credit by the account it
|
|
325
|
-
* landed on; the `qualityCheck` is the only thing that tells them apart. Counting one would fold
|
|
326
|
-
* the static axis into the Test volume, which must not see it at all.
|
|
327
|
-
*
|
|
328
|
-
* The per-scenario-kind counts feed `summary.testVolume` directly (`onScenario` counts credits
|
|
329
|
-
* citing a scenario, INCLUDING no-evidence-obligation — so the 3-termed identity
|
|
330
|
-
* `total = onScenario + onPhantomScenario + onSuspenseScenario` holds); `rawByRuntimeQualityCheck`
|
|
331
|
-
* is the re-homed per-quality-check headline the by-level table renders.
|
|
332
|
-
*/
|
|
333
95
|
export function runtimeObservationTally(ledger) {
|
|
334
96
|
const rawByRuntimeQualityCheck = {
|
|
335
97
|
unit: 0,
|
|
@@ -340,15 +102,11 @@ export function runtimeObservationTally(ledger) {
|
|
|
340
102
|
let onScenario = 0;
|
|
341
103
|
let onPhantomScenario = 0;
|
|
342
104
|
let onSuspenseScenario = 0;
|
|
343
|
-
// THE FOLD (@SCN-RMD-003). Walk the POSTED CREDITS and read each credit's ACCOUNT off the row it
|
|
344
|
-
// posted to — the reconciler's own ruling, never re-classified here.
|
|
345
105
|
for (const row of ledger.scenarioReconciliations) {
|
|
346
|
-
for (const
|
|
347
|
-
|
|
348
|
-
// runtime observation, so it is not counted (see the docstring).
|
|
349
|
-
if (obs.qualityCheck === "lint")
|
|
106
|
+
for (const observation of row.evidenceObservations) {
|
|
107
|
+
if (observation.qualityCheck === "fitness")
|
|
350
108
|
continue;
|
|
351
|
-
rawByRuntimeQualityCheck[
|
|
109
|
+
rawByRuntimeQualityCheck[observation.qualityCheck]++;
|
|
352
110
|
if (row.kind === "phantom-scenario")
|
|
353
111
|
onPhantomScenario++;
|
|
354
112
|
else if (row.kind === "suspense-scenario")
|
|
@@ -357,86 +115,25 @@ export function runtimeObservationTally(ledger) {
|
|
|
357
115
|
onScenario++;
|
|
358
116
|
}
|
|
359
117
|
}
|
|
360
|
-
// THE COMPLETENESS IDENTITY — `Σ raw = onScenario + onPhantomScenario + onSuspenseScenario` —
|
|
361
|
-
// holds BY CONSTRUCTION: the single walk above increments a per-quality-check counter and exactly
|
|
362
|
-
// one per-scenario-kind counter in the SAME iteration, so the two sides cannot diverge. It is
|
|
363
|
-
// COMPLETENESS ONLY: invariant under a misfile BETWEEN its own terms, so it catches a credit
|
|
364
|
-
// VANISHING, never a credit in the wrong account (the `@SCN`s and the rows are that).
|
|
365
|
-
//
|
|
366
|
-
// THE RUNTIME `throw` THAT STOOD HERE IS GONE (3F-2231). It could not fire — both sides move
|
|
367
|
-
// together in one loop — so it was dead code asserting an invariant the structure already
|
|
368
|
-
// guarantees, which is precisely the scar-tissue shape `why-ddd-for-spec-controller.md` names as
|
|
369
|
-
// the anemic tell ("kept honest by hand-written identity assertions"); the goal is that summing
|
|
370
|
-
// the wrong rows "stops being POSSIBLE, not merely asserted-against". The invariant is not
|
|
371
|
-
// unguarded by its removal: `runtimeObservationTally.test.ts` pins it over a spanning corpus,
|
|
372
|
-
// which is where an invariant belongs. If this fold is ever split into two walks the identity
|
|
373
|
-
// becomes a real risk again — and that test, not a throw in a pure function, is what will red.
|
|
374
118
|
const total = RUNTIME_QUALITY_CHECKS.reduce((n, qc) => n + rawByRuntimeQualityCheck[qc], 0);
|
|
375
119
|
return { rawByRuntimeQualityCheck, total, onScenario, onPhantomScenario, onSuspenseScenario };
|
|
376
120
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
* Scenario Reconciliation row (@SCN-LDG-022), reads each credit off THE ROW IT POSTED TO, and — like
|
|
381
|
-
* its runtime sibling — RE-DERIVES NOTHING: the reconciler already decided which account every credit
|
|
382
|
-
* posts to, so this can never disagree with the verdict.
|
|
383
|
-
*
|
|
384
|
-
* `uncitedStaticCheckCount` is the count of RUNNING lint credits on the SUSPENSE row — the
|
|
385
|
-
* no-evidence-obligation static checks the reconciler folded there (a static check running with no
|
|
386
|
-
* scenario citing it, `cites-no-scenario` on the credit side). THE RUNNING QUALIFIER IS APPLIED
|
|
387
|
-
* HERE RATHER THAN ASSUMED (@SCN-LNT-033): the uncited count is the running count's suspense-row
|
|
388
|
-
* subset, so the two take one membership rule. A severed check nobody cites RAN, and is in both
|
|
389
|
-
* (3F-3280). A BROKEN credit reaches the same row by a different route (@SCN-LNT-026) and is
|
|
390
|
-
* excluded: it is a check a scenario DID name, which did not run.
|
|
391
|
-
*
|
|
392
|
-
* `runningStaticCheckCount` is the count of lint credits that RAN, across ALL rows. One care-move
|
|
393
|
-
* the runtime axis does not need (see the block comment above):
|
|
394
|
-
* - FILTER TO WHAT RAN (`exists`): a missing (absent) or broken check STILL posts (posting is not
|
|
395
|
-
* classifying), but it did not run, so it is excluded — as the retired census's running-only
|
|
396
|
-
* `continue` excluded it. A severed check (wired, and the job's verdict does not depend on it)
|
|
397
|
-
* ran and is counted; its row reads the watermelon (3F-3280, ruled 2026-09-17).
|
|
398
|
-
*
|
|
399
|
-
* The named (implicit) count is `runningStaticCheckCount − uncitedStaticCheckCount`, and it cannot
|
|
400
|
-
* go below nil: the uncited count is drawn from inside the running one.
|
|
401
|
-
*/
|
|
402
|
-
export function staticObservationTally(ledger) {
|
|
403
|
-
// The static-check credits that RAN, across ALL rows. Only checks that ran (`exists`) are
|
|
404
|
-
// counted — a missing or broken check, which posts but did not run, is filtered out (the
|
|
405
|
-
// census's running-only `continue`). A severed check ran, so it counts (3F-3280).
|
|
406
|
-
let runningStaticCheckCount = 0;
|
|
407
|
-
// The uncited static checks — the RUNNING lint credits the reconciler folded onto the SUSPENSE
|
|
408
|
-
// row (a no-evidence-obligation running check, `cites-no-scenario`). Not a plain count of that
|
|
409
|
-
// row's lint credits: a broken credit lands there too and did not run (@SCN-LNT-026), so this
|
|
410
|
-
// count takes the running count's rule rather than a rule of its own (@SCN-LNT-033).
|
|
411
|
-
let uncitedStaticCheckCount = 0;
|
|
121
|
+
export function fitnessFunctionTally(ledger) {
|
|
122
|
+
let runningFitnessFunctionCount = 0;
|
|
123
|
+
let uncitedFitnessFunctionCount = 0;
|
|
412
124
|
for (const row of ledger.scenarioReconciliations) {
|
|
413
|
-
for (const
|
|
414
|
-
|
|
415
|
-
// credit (the uncited/broken ones the suspense row also holds) is not a static observation.
|
|
416
|
-
if (obs.qualityCheck !== "lint")
|
|
125
|
+
for (const observation of row.evidenceObservations) {
|
|
126
|
+
if (observation.qualityCheck !== "fitness")
|
|
417
127
|
continue;
|
|
418
|
-
|
|
419
|
-
// the uncited count does not name: the check DID have a scenario naming it, and it did not
|
|
420
|
-
// run. Counting it as uncited would report a check nobody named, sending the reader to write
|
|
421
|
-
// an obligation that is already written — the misdirection the `broken` outcome exists to
|
|
422
|
-
// avoid. It is not a running static check either, and `exists` reads false so the clause
|
|
423
|
-
// below already says so; this one is what keeps the sentence true rather than incidental.
|
|
424
|
-
if (obs.broken === true)
|
|
128
|
+
if (observation.broken === true)
|
|
425
129
|
continue;
|
|
426
|
-
|
|
427
|
-
// running count's suspense-row SUBSET, so the two cannot be given different rules by a later
|
|
428
|
-
// edit to one of them, and the figure a reader takes from the pair — `running − uncited`,
|
|
429
|
-
// the named count neither of them prints — cannot go below nil. Two sibling `if`s reading
|
|
430
|
-
// the same credit under different conditions is exactly the arrangement that let a severed
|
|
431
|
-
// uncited check leave one count and stay in the other. The rule is `exists` alone: a check
|
|
432
|
-
// whose red its job survives RAN, and the census counts what ran (3F-3280).
|
|
433
|
-
if (!obs.exists)
|
|
130
|
+
if (!observation.exists)
|
|
434
131
|
continue;
|
|
435
|
-
|
|
132
|
+
runningFitnessFunctionCount++;
|
|
436
133
|
if (row.kind === "suspense-scenario")
|
|
437
|
-
|
|
134
|
+
uncitedFitnessFunctionCount++;
|
|
438
135
|
}
|
|
439
136
|
}
|
|
440
|
-
return {
|
|
137
|
+
return { runningFitnessFunctionCount, uncitedFitnessFunctionCount };
|
|
441
138
|
}
|
|
442
139
|
//# sourceMappingURL=ledger.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/domain/ledger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../src/domain/ledger.ts"],"names":[],"mappings":"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"}
|