@veraxhq/verax 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +14 -18
  2. package/bin/verax.js +7 -0
  3. package/package.json +15 -5
  4. package/src/cli/commands/baseline.js +104 -0
  5. package/src/cli/commands/default.js +323 -111
  6. package/src/cli/commands/doctor.js +36 -4
  7. package/src/cli/commands/ga.js +243 -0
  8. package/src/cli/commands/gates.js +95 -0
  9. package/src/cli/commands/inspect.js +131 -2
  10. package/src/cli/commands/release-check.js +213 -0
  11. package/src/cli/commands/run.js +498 -103
  12. package/src/cli/commands/security-check.js +211 -0
  13. package/src/cli/commands/truth.js +114 -0
  14. package/src/cli/entry.js +305 -68
  15. package/src/cli/util/angular-component-extractor.js +179 -0
  16. package/src/cli/util/angular-navigation-detector.js +141 -0
  17. package/src/cli/util/angular-network-detector.js +161 -0
  18. package/src/cli/util/angular-state-detector.js +162 -0
  19. package/src/cli/util/ast-interactive-detector.js +546 -0
  20. package/src/cli/util/ast-network-detector.js +603 -0
  21. package/src/cli/util/ast-usestate-detector.js +602 -0
  22. package/src/cli/util/bootstrap-guard.js +86 -0
  23. package/src/cli/util/detection-engine.js +4 -3
  24. package/src/cli/util/determinism-runner.js +123 -0
  25. package/src/cli/util/determinism-writer.js +129 -0
  26. package/src/cli/util/env-url.js +4 -0
  27. package/src/cli/util/events.js +76 -0
  28. package/src/cli/util/expectation-extractor.js +380 -74
  29. package/src/cli/util/findings-writer.js +126 -15
  30. package/src/cli/util/learn-writer.js +3 -1
  31. package/src/cli/util/observation-engine.js +69 -23
  32. package/src/cli/util/observe-writer.js +3 -1
  33. package/src/cli/util/paths.js +6 -14
  34. package/src/cli/util/project-discovery.js +23 -0
  35. package/src/cli/util/project-writer.js +3 -1
  36. package/src/cli/util/redact.js +2 -2
  37. package/src/cli/util/run-resolver.js +64 -0
  38. package/src/cli/util/runtime-budget.js +147 -0
  39. package/src/cli/util/source-requirement.js +55 -0
  40. package/src/cli/util/summary-writer.js +13 -1
  41. package/src/cli/util/svelte-navigation-detector.js +163 -0
  42. package/src/cli/util/svelte-network-detector.js +80 -0
  43. package/src/cli/util/svelte-sfc-extractor.js +147 -0
  44. package/src/cli/util/svelte-state-detector.js +243 -0
  45. package/src/cli/util/vue-navigation-detector.js +177 -0
  46. package/src/cli/util/vue-sfc-extractor.js +162 -0
  47. package/src/cli/util/vue-state-detector.js +215 -0
  48. package/src/types/global.d.ts +28 -0
  49. package/src/types/ts-ast.d.ts +24 -0
  50. package/src/verax/cli/doctor.js +2 -2
  51. package/src/verax/cli/finding-explainer.js +56 -3
  52. package/src/verax/cli/init.js +1 -1
  53. package/src/verax/cli/url-safety.js +12 -2
  54. package/src/verax/cli/wizard.js +13 -2
  55. package/src/verax/core/artifacts/registry.js +154 -0
  56. package/src/verax/core/artifacts/verifier.js +980 -0
  57. package/src/verax/core/baseline/baseline.enforcer.js +137 -0
  58. package/src/verax/core/baseline/baseline.snapshot.js +231 -0
  59. package/src/verax/core/budget-engine.js +1 -1
  60. package/src/verax/core/capabilities/gates.js +499 -0
  61. package/src/verax/core/capabilities/registry.js +475 -0
  62. package/src/verax/core/confidence/confidence-compute.js +137 -0
  63. package/src/verax/core/confidence/confidence-invariants.js +234 -0
  64. package/src/verax/core/confidence/confidence-report-writer.js +112 -0
  65. package/src/verax/core/confidence/confidence-weights.js +44 -0
  66. package/src/verax/core/confidence/confidence.defaults.js +65 -0
  67. package/src/verax/core/confidence/confidence.loader.js +79 -0
  68. package/src/verax/core/confidence/confidence.schema.js +94 -0
  69. package/src/verax/core/confidence-engine-refactor.js +484 -0
  70. package/src/verax/core/confidence-engine.js +486 -0
  71. package/src/verax/core/confidence-engine.js.backup +471 -0
  72. package/src/verax/core/contracts/index.js +29 -0
  73. package/src/verax/core/contracts/types.js +185 -0
  74. package/src/verax/core/contracts/validators.js +381 -0
  75. package/src/verax/core/decision-snapshot.js +31 -4
  76. package/src/verax/core/decisions/decision.trace.js +276 -0
  77. package/src/verax/core/determinism/contract-writer.js +89 -0
  78. package/src/verax/core/determinism/contract.js +139 -0
  79. package/src/verax/core/determinism/diff.js +364 -0
  80. package/src/verax/core/determinism/engine.js +221 -0
  81. package/src/verax/core/determinism/finding-identity.js +148 -0
  82. package/src/verax/core/determinism/normalize.js +438 -0
  83. package/src/verax/core/determinism/report-writer.js +92 -0
  84. package/src/verax/core/determinism/run-fingerprint.js +118 -0
  85. package/src/verax/core/determinism-model.js +35 -6
  86. package/src/verax/core/dynamic-route-intelligence.js +528 -0
  87. package/src/verax/core/evidence/evidence-capture-service.js +307 -0
  88. package/src/verax/core/evidence/evidence-intent-ledger.js +165 -0
  89. package/src/verax/core/evidence-builder.js +487 -0
  90. package/src/verax/core/execution-mode-context.js +77 -0
  91. package/src/verax/core/execution-mode-detector.js +190 -0
  92. package/src/verax/core/failures/exit-codes.js +86 -0
  93. package/src/verax/core/failures/failure-summary.js +76 -0
  94. package/src/verax/core/failures/failure.factory.js +225 -0
  95. package/src/verax/core/failures/failure.ledger.js +132 -0
  96. package/src/verax/core/failures/failure.types.js +196 -0
  97. package/src/verax/core/failures/index.js +10 -0
  98. package/src/verax/core/ga/ga-report-writer.js +43 -0
  99. package/src/verax/core/ga/ga.artifact.js +49 -0
  100. package/src/verax/core/ga/ga.contract.js +434 -0
  101. package/src/verax/core/ga/ga.enforcer.js +86 -0
  102. package/src/verax/core/guardrails/guardrails-report-writer.js +109 -0
  103. package/src/verax/core/guardrails/policy.defaults.js +210 -0
  104. package/src/verax/core/guardrails/policy.loader.js +83 -0
  105. package/src/verax/core/guardrails/policy.schema.js +110 -0
  106. package/src/verax/core/guardrails/truth-reconciliation.js +136 -0
  107. package/src/verax/core/guardrails-engine.js +505 -0
  108. package/src/verax/core/incremental-store.js +15 -7
  109. package/src/verax/core/observe/run-timeline.js +316 -0
  110. package/src/verax/core/perf/perf.contract.js +186 -0
  111. package/src/verax/core/perf/perf.display.js +65 -0
  112. package/src/verax/core/perf/perf.enforcer.js +91 -0
  113. package/src/verax/core/perf/perf.monitor.js +209 -0
  114. package/src/verax/core/perf/perf.report.js +198 -0
  115. package/src/verax/core/pipeline-tracker.js +238 -0
  116. package/src/verax/core/product-definition.js +127 -0
  117. package/src/verax/core/release/provenance.builder.js +271 -0
  118. package/src/verax/core/release/release-report-writer.js +40 -0
  119. package/src/verax/core/release/release.enforcer.js +159 -0
  120. package/src/verax/core/release/reproducibility.check.js +221 -0
  121. package/src/verax/core/release/sbom.builder.js +283 -0
  122. package/src/verax/core/replay-validator.js +4 -4
  123. package/src/verax/core/replay.js +1 -1
  124. package/src/verax/core/report/cross-index.js +192 -0
  125. package/src/verax/core/report/human-summary.js +222 -0
  126. package/src/verax/core/route-intelligence.js +419 -0
  127. package/src/verax/core/security/secrets.scan.js +326 -0
  128. package/src/verax/core/security/security-report.js +50 -0
  129. package/src/verax/core/security/security.enforcer.js +124 -0
  130. package/src/verax/core/security/supplychain.defaults.json +38 -0
  131. package/src/verax/core/security/supplychain.policy.js +326 -0
  132. package/src/verax/core/security/vuln.scan.js +265 -0
  133. package/src/verax/core/silence-impact.js +1 -1
  134. package/src/verax/core/silence-model.js +9 -7
  135. package/src/verax/core/truth/truth.certificate.js +250 -0
  136. package/src/verax/core/ui-feedback-intelligence.js +515 -0
  137. package/src/verax/detect/comparison.js +8 -3
  138. package/src/verax/detect/confidence-engine.js +645 -57
  139. package/src/verax/detect/confidence-helper.js +33 -0
  140. package/src/verax/detect/detection-engine.js +19 -2
  141. package/src/verax/detect/dynamic-route-findings.js +335 -0
  142. package/src/verax/detect/evidence-index.js +15 -65
  143. package/src/verax/detect/expectation-chain-detector.js +417 -0
  144. package/src/verax/detect/expectation-model.js +56 -3
  145. package/src/verax/detect/explanation-helpers.js +1 -1
  146. package/src/verax/detect/finding-detector.js +2 -2
  147. package/src/verax/detect/findings-writer.js +149 -20
  148. package/src/verax/detect/flow-detector.js +4 -4
  149. package/src/verax/detect/index.js +265 -15
  150. package/src/verax/detect/interactive-findings.js +3 -4
  151. package/src/verax/detect/journey-stall-detector.js +558 -0
  152. package/src/verax/detect/route-findings.js +218 -0
  153. package/src/verax/detect/signal-mapper.js +2 -2
  154. package/src/verax/detect/skip-classifier.js +4 -4
  155. package/src/verax/detect/ui-feedback-findings.js +207 -0
  156. package/src/verax/detect/verdict-engine.js +61 -9
  157. package/src/verax/detect/view-switch-correlator.js +242 -0
  158. package/src/verax/flow/flow-engine.js +3 -2
  159. package/src/verax/flow/flow-spec.js +1 -2
  160. package/src/verax/index.js +413 -33
  161. package/src/verax/intel/effect-detector.js +1 -1
  162. package/src/verax/intel/index.js +2 -2
  163. package/src/verax/intel/route-extractor.js +3 -3
  164. package/src/verax/intel/vue-navigation-extractor.js +81 -18
  165. package/src/verax/intel/vue-router-extractor.js +4 -2
  166. package/src/verax/learn/action-contract-extractor.js +684 -66
  167. package/src/verax/learn/ast-contract-extractor.js +53 -1
  168. package/src/verax/learn/index.js +36 -2
  169. package/src/verax/learn/manifest-writer.js +28 -14
  170. package/src/verax/learn/route-extractor.js +1 -1
  171. package/src/verax/learn/route-validator.js +12 -8
  172. package/src/verax/learn/state-extractor.js +1 -1
  173. package/src/verax/learn/static-extractor-navigation.js +1 -1
  174. package/src/verax/learn/static-extractor-validation.js +2 -2
  175. package/src/verax/learn/static-extractor.js +8 -7
  176. package/src/verax/learn/ts-contract-resolver.js +14 -12
  177. package/src/verax/observe/browser.js +22 -3
  178. package/src/verax/observe/console-sensor.js +2 -2
  179. package/src/verax/observe/expectation-executor.js +2 -1
  180. package/src/verax/observe/focus-sensor.js +1 -1
  181. package/src/verax/observe/human-driver.js +29 -10
  182. package/src/verax/observe/index.js +92 -844
  183. package/src/verax/observe/interaction-discovery.js +27 -15
  184. package/src/verax/observe/interaction-runner.js +31 -14
  185. package/src/verax/observe/loading-sensor.js +6 -0
  186. package/src/verax/observe/navigation-sensor.js +1 -1
  187. package/src/verax/observe/observe-context.js +205 -0
  188. package/src/verax/observe/observe-helpers.js +191 -0
  189. package/src/verax/observe/observe-runner.js +226 -0
  190. package/src/verax/observe/observers/budget-observer.js +185 -0
  191. package/src/verax/observe/observers/console-observer.js +102 -0
  192. package/src/verax/observe/observers/coverage-observer.js +107 -0
  193. package/src/verax/observe/observers/interaction-observer.js +471 -0
  194. package/src/verax/observe/observers/navigation-observer.js +132 -0
  195. package/src/verax/observe/observers/network-observer.js +87 -0
  196. package/src/verax/observe/observers/safety-observer.js +82 -0
  197. package/src/verax/observe/observers/ui-feedback-observer.js +99 -0
  198. package/src/verax/observe/settle.js +1 -0
  199. package/src/verax/observe/state-sensor.js +8 -4
  200. package/src/verax/observe/state-ui-sensor.js +7 -1
  201. package/src/verax/observe/traces-writer.js +27 -16
  202. package/src/verax/observe/ui-feedback-detector.js +742 -0
  203. package/src/verax/observe/ui-signal-sensor.js +155 -2
  204. package/src/verax/scan-summary-writer.js +46 -9
  205. package/src/verax/shared/artifact-manager.js +9 -6
  206. package/src/verax/shared/budget-profiles.js +2 -2
  207. package/src/verax/shared/caching.js +1 -1
  208. package/src/verax/shared/config-loader.js +1 -2
  209. package/src/verax/shared/css-spinner-rules.js +204 -0
  210. package/src/verax/shared/dynamic-route-utils.js +12 -6
  211. package/src/verax/shared/retry-policy.js +1 -6
  212. package/src/verax/shared/root-artifacts.js +1 -1
  213. package/src/verax/shared/view-switch-rules.js +208 -0
  214. package/src/verax/shared/zip-artifacts.js +1 -0
  215. package/src/verax/validate/context-validator.js +1 -1
  216. package/src/verax/observe/index.js.backup +0 -1
  217. package/src/verax/validate/context-validator.js.bak +0 -0
@@ -0,0 +1,137 @@
1
+ /**
2
+ * PHASE 21.11 — Baseline Enforcer
3
+ *
4
+ * Enforces baseline integrity. Detects drift and blocks changes after GA.
5
+ */
6
+
7
+ import { loadBaselineSnapshot, buildBaselineSnapshot } from './baseline.snapshot.js';
8
+ import { FAILURE_CODE, createInternalFailure } from '../failures/index.js';
9
+
10
+ /**
11
+ * Compare two baseline snapshots
12
+ *
13
+ * @param {Object} current - Current baseline
14
+ * @param {Object} frozen - Frozen baseline (from GA)
15
+ * @returns {Object} Comparison result
16
+ */
17
+ export function compareBaselines(current, frozen) {
18
+ if (!frozen) {
19
+ return {
20
+ drifted: false,
21
+ message: 'No frozen baseline found (pre-GA)',
22
+ differences: []
23
+ };
24
+ }
25
+
26
+ if (!frozen.frozen) {
27
+ return {
28
+ drifted: false,
29
+ message: 'Baseline not frozen (pre-GA)',
30
+ differences: []
31
+ };
32
+ }
33
+
34
+ const differences = [];
35
+
36
+ // Compare baseline hash
37
+ if (current.baselineHash !== frozen.baselineHash) {
38
+ differences.push({
39
+ type: 'BASELINE_HASH_MISMATCH',
40
+ message: 'Baseline hash changed',
41
+ current: current.baselineHash,
42
+ frozen: frozen.baselineHash
43
+ });
44
+ }
45
+
46
+ // Compare individual hashes
47
+ for (const [key, frozenHash] of Object.entries(frozen.hashes || {})) {
48
+ const currentHash = current.hashes?.[key];
49
+ if (currentHash && currentHash !== frozenHash) {
50
+ differences.push({
51
+ type: 'HASH_MISMATCH',
52
+ component: key,
53
+ message: `${key} hash changed`,
54
+ current: currentHash,
55
+ frozen: frozenHash
56
+ });
57
+ }
58
+ }
59
+
60
+ return {
61
+ drifted: differences.length > 0,
62
+ message: differences.length > 0
63
+ ? `Baseline drift detected: ${differences.length} difference(s)`
64
+ : 'No baseline drift',
65
+ differences
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Enforce baseline integrity
71
+ *
72
+ * @param {string} projectDir - Project directory
73
+ * @param {Object} failureLedger - Failure ledger instance
74
+ * @returns {Object} Enforcement result
75
+ */
76
+ export function enforceBaseline(projectDir, failureLedger) {
77
+ const frozen = loadBaselineSnapshot(projectDir);
78
+
79
+ // If no frozen baseline, allow (pre-GA)
80
+ if (!frozen || !frozen.frozen) {
81
+ return {
82
+ blocked: false,
83
+ message: 'No frozen baseline (pre-GA)',
84
+ drifted: false
85
+ };
86
+ }
87
+
88
+ // Build current baseline
89
+ const current = buildBaselineSnapshot(projectDir);
90
+
91
+ // Compare
92
+ const comparison = compareBaselines(current, frozen);
93
+
94
+ if (comparison.drifted) {
95
+ // Record BLOCKING failure
96
+ const failure = createInternalFailure(
97
+ FAILURE_CODE.BASELINE_DRIFT,
98
+ `BASELINE_DRIFT: ${comparison.message}. Changes to core contracts/policies after GA require MAJOR version bump and baseline regeneration.`,
99
+ 'baseline',
100
+ {
101
+ differences: comparison.differences,
102
+ frozenCommit: frozen.gitCommit,
103
+ currentCommit: current.gitCommit,
104
+ frozenVersion: frozen.veraxVersion,
105
+ currentVersion: current.veraxVersion
106
+ },
107
+ false // Not recoverable
108
+ );
109
+
110
+ failureLedger.record(failure);
111
+
112
+ return {
113
+ blocked: true,
114
+ message: comparison.message,
115
+ drifted: true,
116
+ differences: comparison.differences
117
+ };
118
+ }
119
+
120
+ return {
121
+ blocked: false,
122
+ message: 'Baseline integrity maintained',
123
+ drifted: false
124
+ };
125
+ }
126
+
127
+ /**
128
+ * Check if baseline is frozen
129
+ *
130
+ * @param {string} projectDir - Project directory
131
+ * @returns {boolean} True if frozen
132
+ */
133
+ export function isBaselineFrozen(projectDir) {
134
+ const snapshot = loadBaselineSnapshot(projectDir);
135
+ return snapshot?.frozen === true;
136
+ }
137
+
@@ -0,0 +1,231 @@
1
+ /**
2
+ * PHASE 21.11 — Immutable Baseline Snapshot
3
+ *
4
+ * Creates a snapshot of all core contracts, policies, and criteria.
5
+ * Any drift from this baseline after GA is BLOCKING.
6
+ */
7
+
8
+ import { readFileSync, existsSync, writeFileSync } from 'fs';
9
+ import { resolve } from 'path';
10
+ import { createHash } from 'crypto';
11
+ import { VERAX_PRODUCT_DEFINITION } from '../product-definition.js';
12
+
13
+ /**
14
+ * Compute SHA256 hash of content
15
+ */
16
+ function hashContent(content) {
17
+ return createHash('sha256').update(content).digest('hex');
18
+ }
19
+
20
+ /**
21
+ * Load and hash a file
22
+ */
23
+ function hashFile(filePath) {
24
+ if (!existsSync(filePath)) {
25
+ return null;
26
+ }
27
+ try {
28
+ const content = readFileSync(filePath, 'utf-8');
29
+ return hashContent(content);
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Get git commit hash
37
+ */
38
+ function getGitCommit() {
39
+ try {
40
+ const { execSync } = require('child_process');
41
+ return execSync('git rev-parse HEAD', { encoding: 'utf-8' }).trim();
42
+ } catch {
43
+ return 'unknown';
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Check if git repo is dirty
49
+ */
50
+ function isGitDirty() {
51
+ try {
52
+ const { execSync } = require('child_process');
53
+ const status = execSync('git status --porcelain', { encoding: 'utf-8' });
54
+ return status.trim().length > 0;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Get VERAX version
62
+ */
63
+ function getVeraxVersion() {
64
+ try {
65
+ const packageJson = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf-8'));
66
+ return packageJson.version || 'unknown';
67
+ } catch {
68
+ return 'unknown';
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Build baseline snapshot
74
+ *
75
+ * @param {string} projectDir - Project directory
76
+ * @returns {Object} Baseline snapshot
77
+ */
78
+ export function buildBaselineSnapshot(projectDir) {
79
+ const coreDir = resolve(projectDir, 'src', 'verax', 'core');
80
+
81
+ // Core contracts
82
+ const evidenceLaw = hashContent(JSON.stringify(VERAX_PRODUCT_DEFINITION.evidenceLaw));
83
+ const productDefinition = hashFile(resolve(coreDir, 'product-definition.js'));
84
+
85
+ // Confidence defaults
86
+ const confidenceEngine = hashFile(resolve(coreDir, 'confidence-engine.js'));
87
+ const confidenceDefaults = hashFile(resolve(coreDir, 'confidence-engine-refactor.js'));
88
+
89
+ // Guardrails defaults
90
+ const guardrailsDefaults = hashFile(resolve(coreDir, 'guardrails', 'defaults.json'));
91
+ const guardrailsContract = hashFile(resolve(coreDir, 'guardrails', 'contract.js'));
92
+
93
+ // GA criteria
94
+ const gaContract = hashFile(resolve(coreDir, 'ga', 'ga.contract.js'));
95
+
96
+ // Performance budgets
97
+ const perfContract = hashFile(resolve(coreDir, 'perf', 'perf.contract.js'));
98
+ const perfProfiles = hashFile(resolve(projectDir, 'src', 'verax', 'shared', 'budget-profiles.js'));
99
+
100
+ // Security policies
101
+ const supplychainPolicy = hashFile(resolve(coreDir, 'security', 'supplychain.policy.js'));
102
+ const supplychainDefaults = hashFile(resolve(coreDir, 'security', 'supplychain.defaults.json'));
103
+
104
+ // Failure taxonomy
105
+ const failureTypes = hashFile(resolve(coreDir, 'failures', 'failure.types.js'));
106
+ const failureLedger = hashFile(resolve(coreDir, 'failures', 'failure.ledger.js'));
107
+
108
+ // Contracts
109
+ const contractsIndex = hashFile(resolve(coreDir, 'contracts', 'index.js'));
110
+ const contractsValidators = hashFile(resolve(coreDir, 'contracts', 'validators.js'));
111
+ const contractsTypes = hashFile(resolve(coreDir, 'contracts', 'types.js'));
112
+
113
+ // Determinism
114
+ const determinismContract = hashFile(resolve(coreDir, 'determinism', 'contract.js'));
115
+
116
+ // Evidence builder
117
+ const evidenceBuilder = hashFile(resolve(coreDir, 'evidence-builder.js'));
118
+
119
+ const snapshot = {
120
+ version: 1,
121
+ timestamp: new Date().toISOString(),
122
+ veraxVersion: getVeraxVersion(),
123
+ gitCommit: getGitCommit(),
124
+ gitDirty: isGitDirty(),
125
+
126
+ hashes: {
127
+ // Core contracts
128
+ evidenceLaw,
129
+ productDefinition,
130
+
131
+ // Confidence
132
+ confidenceEngine,
133
+ confidenceDefaults,
134
+
135
+ // Guardrails
136
+ guardrailsDefaults,
137
+ guardrailsContract,
138
+
139
+ // GA
140
+ gaContract,
141
+
142
+ // Performance
143
+ perfContract,
144
+ perfProfiles,
145
+
146
+ // Security
147
+ supplychainPolicy,
148
+ supplychainDefaults,
149
+
150
+ // Failures
151
+ failureTypes,
152
+ failureLedger,
153
+
154
+ // Contracts
155
+ contractsIndex,
156
+ contractsValidators,
157
+ contractsTypes,
158
+
159
+ // Determinism
160
+ determinismContract,
161
+
162
+ // Evidence
163
+ evidenceBuilder
164
+ },
165
+
166
+ // Combined hash for quick comparison
167
+ baselineHash: hashContent(JSON.stringify({
168
+ evidenceLaw,
169
+ productDefinition,
170
+ confidenceEngine,
171
+ confidenceDefaults,
172
+ guardrailsDefaults,
173
+ guardrailsContract,
174
+ gaContract,
175
+ perfContract,
176
+ perfProfiles,
177
+ supplychainPolicy,
178
+ supplychainDefaults,
179
+ failureTypes,
180
+ failureLedger,
181
+ contractsIndex,
182
+ contractsValidators,
183
+ contractsTypes,
184
+ determinismContract,
185
+ evidenceBuilder
186
+ }))
187
+ };
188
+
189
+ return snapshot;
190
+ }
191
+
192
+ /**
193
+ * Write baseline snapshot to file
194
+ *
195
+ * @param {string} projectDir - Project directory
196
+ * @param {Object} snapshot - Baseline snapshot
197
+ * @param {boolean} gaStatus - GA status
198
+ * @returns {string} Path to written file
199
+ */
200
+ export function writeBaselineSnapshot(projectDir, snapshot, gaStatus = false) {
201
+ const snapshotWithGA = {
202
+ ...snapshot,
203
+ gaStatus: gaStatus ? 'GA-READY' : 'PRE-GA',
204
+ frozen: gaStatus // After GA, baseline is frozen
205
+ };
206
+
207
+ const outputPath = resolve(projectDir, 'baseline.snapshot.json');
208
+ writeFileSync(outputPath, JSON.stringify(snapshotWithGA, null, 2), 'utf-8');
209
+ return outputPath;
210
+ }
211
+
212
+ /**
213
+ * Load baseline snapshot from file
214
+ *
215
+ * @param {string} projectDir - Project directory
216
+ * @returns {Object|null} Baseline snapshot or null
217
+ */
218
+ export function loadBaselineSnapshot(projectDir) {
219
+ const snapshotPath = resolve(projectDir, 'baseline.snapshot.json');
220
+
221
+ if (!existsSync(snapshotPath)) {
222
+ return null;
223
+ }
224
+
225
+ try {
226
+ return JSON.parse(readFileSync(snapshotPath, 'utf-8'));
227
+ } catch {
228
+ return null;
229
+ }
230
+ }
231
+
@@ -131,7 +131,7 @@ export function computeRouteBudget(manifest, currentUrl, baseBudget) {
131
131
  const routes = manifest.routes || [];
132
132
  const expectations = manifest.staticExpectations || [];
133
133
  const totalRoutes = routes.length;
134
- const totalExpectations = expectations.length;
134
+ // const totalExpectations = expectations.length; // Reserved for future use
135
135
 
136
136
  // Count expectations per route
137
137
  const routeExpectationCount = new Map();