@veraxhq/verax 0.3.0 → 0.4.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 (191) hide show
  1. package/README.md +28 -20
  2. package/bin/verax.js +11 -18
  3. package/package.json +28 -7
  4. package/src/cli/commands/baseline.js +1 -2
  5. package/src/cli/commands/default.js +72 -81
  6. package/src/cli/commands/doctor.js +29 -0
  7. package/src/cli/commands/ga.js +3 -0
  8. package/src/cli/commands/gates.js +1 -1
  9. package/src/cli/commands/inspect.js +6 -133
  10. package/src/cli/commands/release-check.js +2 -0
  11. package/src/cli/commands/run.js +74 -246
  12. package/src/cli/commands/security-check.js +2 -1
  13. package/src/cli/commands/truth.js +0 -1
  14. package/src/cli/entry.js +82 -309
  15. package/src/cli/util/angular-component-extractor.js +2 -2
  16. package/src/cli/util/angular-navigation-detector.js +2 -2
  17. package/src/cli/util/ast-interactive-detector.js +4 -6
  18. package/src/cli/util/ast-network-detector.js +3 -3
  19. package/src/cli/util/ast-promise-extractor.js +581 -0
  20. package/src/cli/util/ast-usestate-detector.js +3 -3
  21. package/src/cli/util/atomic-write.js +12 -1
  22. package/src/cli/util/console-reporter.js +72 -0
  23. package/src/cli/util/detection-engine.js +105 -41
  24. package/src/cli/util/determinism-runner.js +2 -1
  25. package/src/cli/util/determinism-writer.js +1 -1
  26. package/src/cli/util/digest-engine.js +359 -0
  27. package/src/cli/util/dom-diff.js +226 -0
  28. package/src/cli/util/env-url.js +0 -4
  29. package/src/cli/util/evidence-engine.js +287 -0
  30. package/src/cli/util/expectation-extractor.js +217 -367
  31. package/src/cli/util/findings-writer.js +19 -126
  32. package/src/cli/util/framework-detector.js +572 -0
  33. package/src/cli/util/idgen.js +1 -1
  34. package/src/cli/util/interaction-planner.js +529 -0
  35. package/src/cli/util/learn-writer.js +2 -2
  36. package/src/cli/util/ledger-writer.js +110 -0
  37. package/src/cli/util/monorepo-resolver.js +162 -0
  38. package/src/cli/util/observation-engine.js +127 -278
  39. package/src/cli/util/observe-writer.js +2 -2
  40. package/src/cli/util/paths.js +12 -3
  41. package/src/cli/util/project-discovery.js +284 -3
  42. package/src/cli/util/project-writer.js +2 -2
  43. package/src/cli/util/run-id.js +23 -27
  44. package/src/cli/util/run-result.js +778 -0
  45. package/src/cli/util/selector-resolver.js +235 -0
  46. package/src/cli/util/summary-writer.js +2 -1
  47. package/src/cli/util/svelte-navigation-detector.js +3 -3
  48. package/src/cli/util/svelte-sfc-extractor.js +0 -1
  49. package/src/cli/util/svelte-state-detector.js +1 -2
  50. package/src/cli/util/trust-activation-integration.js +496 -0
  51. package/src/cli/util/trust-activation-wrapper.js +85 -0
  52. package/src/cli/util/trust-integration-hooks.js +164 -0
  53. package/src/cli/util/types.js +153 -0
  54. package/src/cli/util/url-validation.js +40 -0
  55. package/src/cli/util/vue-navigation-detector.js +4 -3
  56. package/src/cli/util/vue-sfc-extractor.js +1 -2
  57. package/src/cli/util/vue-state-detector.js +1 -1
  58. package/src/types/fs-augment.d.ts +23 -0
  59. package/src/types/global.d.ts +137 -0
  60. package/src/types/internal-types.d.ts +35 -0
  61. package/src/verax/cli/finding-explainer.js +3 -56
  62. package/src/verax/cli/init.js +4 -18
  63. package/src/verax/core/action-classifier.js +4 -3
  64. package/src/verax/core/artifacts/registry.js +0 -15
  65. package/src/verax/core/artifacts/verifier.js +18 -8
  66. package/src/verax/core/baseline/baseline.snapshot.js +2 -0
  67. package/src/verax/core/capabilities/gates.js +7 -1
  68. package/src/verax/core/confidence/confidence-compute.js +14 -7
  69. package/src/verax/core/confidence/confidence.loader.js +1 -0
  70. package/src/verax/core/confidence-engine-refactor.js +8 -3
  71. package/src/verax/core/confidence-engine.js +162 -23
  72. package/src/verax/core/contracts/types.js +1 -0
  73. package/src/verax/core/contracts/validators.js +79 -4
  74. package/src/verax/core/decision-snapshot.js +3 -30
  75. package/src/verax/core/decisions/decision.trace.js +2 -0
  76. package/src/verax/core/determinism/contract-writer.js +2 -2
  77. package/src/verax/core/determinism/contract.js +1 -1
  78. package/src/verax/core/determinism/diff.js +42 -1
  79. package/src/verax/core/determinism/engine.js +7 -6
  80. package/src/verax/core/determinism/finding-identity.js +3 -2
  81. package/src/verax/core/determinism/normalize.js +32 -4
  82. package/src/verax/core/determinism/report-writer.js +1 -0
  83. package/src/verax/core/determinism/run-fingerprint.js +7 -2
  84. package/src/verax/core/dynamic-route-intelligence.js +8 -7
  85. package/src/verax/core/evidence/evidence-capture-service.js +1 -0
  86. package/src/verax/core/evidence/evidence-intent-ledger.js +2 -1
  87. package/src/verax/core/evidence-builder.js +2 -2
  88. package/src/verax/core/execution-mode-context.js +1 -1
  89. package/src/verax/core/execution-mode-detector.js +5 -3
  90. package/src/verax/core/failures/exit-codes.js +39 -37
  91. package/src/verax/core/failures/failure-summary.js +1 -1
  92. package/src/verax/core/failures/failure.factory.js +3 -3
  93. package/src/verax/core/failures/failure.ledger.js +3 -2
  94. package/src/verax/core/ga/ga.artifact.js +1 -1
  95. package/src/verax/core/ga/ga.contract.js +3 -2
  96. package/src/verax/core/ga/ga.enforcer.js +1 -0
  97. package/src/verax/core/guardrails/policy.loader.js +1 -0
  98. package/src/verax/core/guardrails/truth-reconciliation.js +1 -1
  99. package/src/verax/core/guardrails-engine.js +2 -2
  100. package/src/verax/core/incremental-store.js +1 -0
  101. package/src/verax/core/integrity/budget.js +138 -0
  102. package/src/verax/core/integrity/determinism.js +342 -0
  103. package/src/verax/core/integrity/integrity.js +208 -0
  104. package/src/verax/core/integrity/poisoning.js +108 -0
  105. package/src/verax/core/integrity/transaction.js +140 -0
  106. package/src/verax/core/observe/run-timeline.js +2 -0
  107. package/src/verax/core/perf/perf.report.js +2 -0
  108. package/src/verax/core/pipeline-tracker.js +5 -0
  109. package/src/verax/core/release/provenance.builder.js +73 -214
  110. package/src/verax/core/release/release.enforcer.js +14 -9
  111. package/src/verax/core/release/reproducibility.check.js +1 -0
  112. package/src/verax/core/release/sbom.builder.js +32 -23
  113. package/src/verax/core/replay-validator.js +2 -0
  114. package/src/verax/core/replay.js +4 -0
  115. package/src/verax/core/report/cross-index.js +6 -3
  116. package/src/verax/core/report/human-summary.js +141 -1
  117. package/src/verax/core/route-intelligence.js +4 -3
  118. package/src/verax/core/run-id.js +6 -3
  119. package/src/verax/core/run-manifest.js +4 -3
  120. package/src/verax/core/security/secrets.scan.js +10 -7
  121. package/src/verax/core/security/security.enforcer.js +4 -0
  122. package/src/verax/core/security/supplychain.policy.js +9 -1
  123. package/src/verax/core/security/vuln.scan.js +2 -2
  124. package/src/verax/core/truth/truth.certificate.js +3 -1
  125. package/src/verax/core/ui-feedback-intelligence.js +12 -46
  126. package/src/verax/detect/conditional-ui-silent-failure.js +84 -0
  127. package/src/verax/detect/confidence-engine.js +100 -660
  128. package/src/verax/detect/confidence-helper.js +1 -0
  129. package/src/verax/detect/detection-engine.js +1 -18
  130. package/src/verax/detect/dynamic-route-findings.js +17 -14
  131. package/src/verax/detect/expectation-chain-detector.js +1 -1
  132. package/src/verax/detect/expectation-model.js +3 -5
  133. package/src/verax/detect/failure-cause-inference.js +293 -0
  134. package/src/verax/detect/findings-writer.js +126 -166
  135. package/src/verax/detect/flow-detector.js +2 -2
  136. package/src/verax/detect/form-silent-failure.js +98 -0
  137. package/src/verax/detect/index.js +51 -234
  138. package/src/verax/detect/invariants-enforcer.js +147 -0
  139. package/src/verax/detect/journey-stall-detector.js +4 -4
  140. package/src/verax/detect/navigation-silent-failure.js +82 -0
  141. package/src/verax/detect/problem-aggregator.js +361 -0
  142. package/src/verax/detect/route-findings.js +7 -6
  143. package/src/verax/detect/summary-writer.js +477 -0
  144. package/src/verax/detect/test-failure-cause-inference.js +314 -0
  145. package/src/verax/detect/ui-feedback-findings.js +18 -18
  146. package/src/verax/detect/verdict-engine.js +3 -57
  147. package/src/verax/detect/view-switch-correlator.js +2 -2
  148. package/src/verax/flow/flow-engine.js +2 -1
  149. package/src/verax/flow/flow-spec.js +0 -6
  150. package/src/verax/index.js +48 -412
  151. package/src/verax/intel/ts-program.js +1 -0
  152. package/src/verax/intel/vue-navigation-extractor.js +3 -0
  153. package/src/verax/learn/action-contract-extractor.js +67 -682
  154. package/src/verax/learn/ast-contract-extractor.js +1 -1
  155. package/src/verax/learn/flow-extractor.js +1 -0
  156. package/src/verax/learn/project-detector.js +5 -0
  157. package/src/verax/learn/react-router-extractor.js +2 -0
  158. package/src/verax/learn/route-validator.js +1 -4
  159. package/src/verax/learn/source-instrumenter.js +1 -0
  160. package/src/verax/learn/state-extractor.js +2 -1
  161. package/src/verax/learn/static-extractor.js +1 -0
  162. package/src/verax/observe/coverage-gaps.js +132 -0
  163. package/src/verax/observe/expectation-handler.js +126 -0
  164. package/src/verax/observe/incremental-skip.js +46 -0
  165. package/src/verax/observe/index.js +735 -84
  166. package/src/verax/observe/interaction-executor.js +192 -0
  167. package/src/verax/observe/interaction-runner.js +782 -530
  168. package/src/verax/observe/network-firewall.js +86 -0
  169. package/src/verax/observe/observation-builder.js +169 -0
  170. package/src/verax/observe/observe-context.js +1 -1
  171. package/src/verax/observe/observe-helpers.js +2 -1
  172. package/src/verax/observe/observe-runner.js +28 -24
  173. package/src/verax/observe/observers/budget-observer.js +3 -3
  174. package/src/verax/observe/observers/console-observer.js +4 -4
  175. package/src/verax/observe/observers/coverage-observer.js +4 -4
  176. package/src/verax/observe/observers/interaction-observer.js +3 -3
  177. package/src/verax/observe/observers/navigation-observer.js +4 -4
  178. package/src/verax/observe/observers/network-observer.js +4 -4
  179. package/src/verax/observe/observers/safety-observer.js +1 -1
  180. package/src/verax/observe/observers/ui-feedback-observer.js +4 -4
  181. package/src/verax/observe/page-traversal.js +138 -0
  182. package/src/verax/observe/snapshot-ops.js +94 -0
  183. package/src/verax/observe/ui-signal-sensor.js +2 -148
  184. package/src/verax/scan-summary-writer.js +10 -42
  185. package/src/verax/shared/artifact-manager.js +30 -13
  186. package/src/verax/shared/caching.js +1 -0
  187. package/src/verax/shared/expectation-tracker.js +1 -0
  188. package/src/verax/shared/zip-artifacts.js +6 -0
  189. package/src/verax/core/confidence-engine.js.backup +0 -471
  190. package/src/verax/shared/config-loader.js +0 -169
  191. /package/src/verax/shared/{expectation-proof.js → expectation-validation.js} +0 -0
@@ -9,93 +9,40 @@ import SilenceTracker from './core/silence-model.js';
9
9
  import { generateRunId, getRunArtifactDir, getArtifactPath } from './core/run-id.js';
10
10
  import { createRunManifest, updateRunManifestHashes } from './core/run-manifest.js';
11
11
  import { computeArtifactHashes } from './core/run-id.js';
12
- import { FailureLedger } from './core/failures/failure.ledger.js';
13
- import { errorToFailure, createIOFailure, createInternalFailure } from './core/failures/failure.factory.js';
14
- import { FAILURE_CODE, EXECUTION_PHASE } from './core/failures/failure.types.js';
15
- import { createPerformanceMonitor } from './core/perf/perf.monitor.js';
16
- import { generatePerformanceReport, writePerformanceReport } from './core/perf/perf.report.js';
17
- import { recordPerformanceViolations } from './core/perf/perf.enforcer.js';
18
- import { PipelineTracker, PIPELINE_STAGES } from './core/pipeline-tracker.js';
19
- import { verifyRun } from './core/artifacts/verifier.js';
20
- import { getArtifactVersions } from './core/artifacts/registry.js';
21
12
 
22
13
  export async function scan(projectDir, url, manifestPath = null, scanBudgetOverride = null, safetyFlags = {}) {
23
- // PHASE 21.5: Initialize failure ledger (runId will be set after learn)
24
- const scanBudget = scanBudgetOverride || createScanBudgetWithProfile();
25
- const failureLedger = new FailureLedger(null, projectDir);
26
-
27
- // PHASE 21.9: Initialize performance monitor
28
- const perfMonitor = createPerformanceMonitor();
29
- perfMonitor.startPhase('LEARN');
30
-
31
- // ARCHITECTURAL HARDENING: Initialize pipeline tracker early (before runId is known)
32
- // We'll set runId on the tracker once it's generated
33
- let pipelineTracker = null;
14
+ // VISION ENFORCEMENT: Zero-configuration mode (config files ignored unless explicit --use-config flag)
15
+ // VERAX adapts to the project, never requires project to adapt to VERAX
34
16
 
35
17
  // If manifestPath is provided, read it first before learn() overwrites it
36
18
  let loadedManifest = null;
37
19
  if (manifestPath) {
38
20
  const { readFileSync } = await import('fs');
39
21
  try {
22
+ // @ts-expect-error - readFileSync with encoding returns string
40
23
  const manifestContent = JSON.parse(readFileSync(manifestPath, 'utf-8'));
41
24
  loadedManifest = manifestContent;
42
25
  } catch (e) {
43
- // PHASE 21.5: Record I/O failure
44
- const failure = createIOFailure(
45
- FAILURE_CODE.IO_READ_FAILED,
46
- `Failed to read manifest: ${e.message}`,
47
- 'scan',
48
- { manifestPath, error: e.message },
49
- true // Recoverable - will fall through to learn
50
- );
51
- failureLedger.record(failure);
26
+ // Fall through to learn if we can't read the manifest
52
27
  }
53
28
  }
54
29
 
55
- // ARCHITECTURAL HARDENING: Track LEARN stage
56
- // Note: We can't track LEARN yet because we don't have runId, but we'll track it retroactively
57
- const learnStartTime = Date.now();
58
30
  const learnedManifest = await learn(projectDir);
59
- const learnEndTime = Date.now();
60
- perfMonitor.endPhase('LEARN');
61
31
 
62
- // ARCHITECTURAL HARDENING: Explicit manifest merging with deterministic precedence
63
- // Rule: Loaded manifest routes take precedence, but learned manifest provides truth and project type
32
+ // Merge: prefer loaded manifest for routes, but use learned for project type and truth
64
33
  let manifest;
65
34
  if (loadedManifest) {
66
- // Explicit merge: loaded manifest routes override learned, but learned provides truth
67
35
  manifest = {
68
36
  ...learnedManifest,
69
- // Routes from loaded manifest (if present) override learned routes
70
- publicRoutes: loadedManifest.publicRoutes || learnedManifest.publicRoutes || [],
71
- routes: loadedManifest.routes || learnedManifest.routes || [],
72
- internalRoutes: loadedManifest.internalRoutes || learnedManifest.internalRoutes || [],
73
- staticExpectations: loadedManifest.staticExpectations || learnedManifest.staticExpectations || [],
74
- // Project type: prefer loaded, fallback to learned
75
37
  projectType: loadedManifest.projectType || learnedManifest.projectType,
76
- // Always preserve learned truth (this is the source of truth)
77
- learnTruth: learnedManifest.learnTruth || {},
78
- // Track manifest source for auditability
79
- manifestSource: 'merged',
80
- manifestPath: manifestPath,
81
- mergeMetadata: {
82
- loadedManifestProvided: true,
83
- learnedManifestProvided: true,
84
- routesSource: loadedManifest.routes ? 'loaded' : 'learned',
85
- projectTypeSource: loadedManifest.projectType ? 'loaded' : 'learned'
86
- }
38
+ publicRoutes: loadedManifest.publicRoutes || learnedManifest.publicRoutes,
39
+ routes: loadedManifest.routes || learnedManifest.routes,
40
+ internalRoutes: loadedManifest.internalRoutes || learnedManifest.internalRoutes,
41
+ staticExpectations: loadedManifest.staticExpectations || learnedManifest.staticExpectations,
42
+ manifestPath: manifestPath
87
43
  };
88
44
  } else {
89
- manifest = {
90
- ...learnedManifest,
91
- manifestSource: 'learned',
92
- mergeMetadata: {
93
- loadedManifestProvided: false,
94
- learnedManifestProvided: true,
95
- routesSource: 'learned',
96
- projectTypeSource: 'learned'
97
- }
98
- };
45
+ manifest = learnedManifest;
99
46
  }
100
47
 
101
48
  if (!url) {
@@ -110,8 +57,18 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
110
57
  manifestPath: manifest.manifestPath
111
58
  };
112
59
 
113
- // ARCHITECTURAL HARDENING: validateRoutes now always returns explicit validation object
114
- const validation = await validateRoutes(manifestForValidation, url);
60
+ let validation = await validateRoutes(manifestForValidation, url);
61
+
62
+ if (!validation) {
63
+ // validateRoutes might return null if routes cannot be validated
64
+ validation = {
65
+ routesValidated: 0,
66
+ routesReachable: 0,
67
+ routesUnreachable: 0,
68
+ details: [],
69
+ warnings: []
70
+ };
71
+ }
115
72
  if (validation.warnings && validation.warnings.length > 0) {
116
73
  if (!manifest.learnTruth.warnings) {
117
74
  manifest.learnTruth.warnings = [];
@@ -119,6 +76,9 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
119
76
  manifest.learnTruth.warnings.push(...validation.warnings);
120
77
  }
121
78
 
79
+ // Use budget profile if no override provided
80
+ const scanBudget = scanBudgetOverride || createScanBudgetWithProfile();
81
+
122
82
  // PHASE 5: Generate deterministic runId and create run manifest
123
83
  const { getBaseOrigin } = await import('./observe/domain-boundary.js');
124
84
  const baseOrigin = getBaseOrigin(url);
@@ -130,41 +90,6 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
130
90
  manifestPath
131
91
  });
132
92
 
133
- // PHASE 21.5: Set runId in failure ledger
134
- failureLedger.runId = runId;
135
-
136
- // ARCHITECTURAL HARDENING: Initialize pipeline tracker now that we have runId
137
- // PHASE 25: Pass runFingerprint params to PipelineTracker
138
- const runFingerprintParams = url ? {
139
- url,
140
- projectDir,
141
- manifestPath: null,
142
- fixtureId: null
143
- } : null;
144
- pipelineTracker = new PipelineTracker(projectDir, runId, runFingerprintParams);
145
-
146
- // Record LEARN stage retroactively (it completed before we had runId)
147
- try {
148
- pipelineTracker.stages[PIPELINE_STAGES.LEARN] = {
149
- name: PIPELINE_STAGES.LEARN,
150
- startedAt: new Date(learnStartTime).toISOString(),
151
- completedAt: new Date(learnEndTime).toISOString(),
152
- durationMs: learnEndTime - learnStartTime,
153
- status: 'COMPLETE'
154
- };
155
- pipelineTracker.completedStages.push(PIPELINE_STAGES.LEARN);
156
- pipelineTracker._writeMeta();
157
- } catch (error) {
158
- const failure = createInternalFailure(
159
- FAILURE_CODE.INTERNAL_UNEXPECTED_ERROR,
160
- `Failed to record LEARN stage: ${error.message}`,
161
- 'scan',
162
- { error: error.message },
163
- error.stack
164
- );
165
- failureLedger.record(failure);
166
- }
167
-
168
93
  // Create run manifest at start of execution
169
94
  const runManifest = createRunManifest(projectDir, runId, {
170
95
  url,
@@ -176,61 +101,15 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
176
101
  });
177
102
 
178
103
  const usedManifestPath = manifestPath || manifest.manifestPath;
179
-
180
- // ARCHITECTURAL HARDENING: Track OBSERVE stage
181
- pipelineTracker.startStage(PIPELINE_STAGES.OBSERVE);
182
- perfMonitor.startPhase('OBSERVE');
183
- let observation;
184
- try {
185
- observation = await observe(url, usedManifestPath, scanBudget, safetyFlags, projectDir, runId);
186
- perfMonitor.endPhase('OBSERVE');
187
- pipelineTracker.completeStage(PIPELINE_STAGES.OBSERVE, {
188
- pagesVisited: observation.observeTruth?.pagesVisited || 0,
189
- interactionsExecuted: observation.observeTruth?.interactionsExecuted || 0
190
- });
191
- } catch (error) {
192
- perfMonitor.endPhase('OBSERVE');
193
- pipelineTracker.failStage(PIPELINE_STAGES.OBSERVE, error);
194
- const failure = errorToFailure(
195
- error,
196
- FAILURE_CODE.OBSERVE_EXECUTION_FAILED,
197
- 'OBSERVE',
198
- EXECUTION_PHASE.OBSERVE,
199
- 'observe',
200
- { manifestPath: usedManifestPath }
201
- );
202
- failureLedger.record(failure);
203
- throw error;
204
- }
205
-
206
- // Update performance monitor with observed metrics
207
- if (observation.observeTruth) {
208
- const pagesVisited = observation.observeTruth.pagesVisited || 0;
209
- const interactionsExecuted = observation.observeTruth.interactionsExecuted || observation.observeTruth.candidatesSelected || 0;
210
-
211
- for (let i = 0; i < pagesVisited; i++) {
212
- perfMonitor.incrementPages();
213
- }
214
- for (let i = 0; i < interactionsExecuted; i++) {
215
- perfMonitor.incrementInteractions();
216
- }
217
- }
104
+ const observation = await observe(url, usedManifestPath, scanBudget, safetyFlags, projectDir, runId);
218
105
 
219
106
  // Write a copy of the manifest into canonical run directory for replay integrity
220
107
  try {
221
108
  const { writeFileSync } = await import('fs');
222
109
  const manifestCopyPath = getArtifactPath(projectDir, runId, 'manifest.json');
223
110
  writeFileSync(manifestCopyPath, JSON.stringify(manifest, null, 2));
224
- } catch (error) {
225
- // PHASE 21.5: Record I/O failure (WARNING - recoverable)
226
- const failure = createIOFailure(
227
- FAILURE_CODE.IO_WRITE_FAILED,
228
- `Failed to write manifest copy: ${error.message}`,
229
- 'scan',
230
- { manifestPath, error: error.message },
231
- true
232
- );
233
- failureLedger.record(failure);
111
+ } catch {
112
+ // Ignore write errors
234
113
  }
235
114
 
236
115
  // Create silence tracker from observation silences
@@ -239,69 +118,27 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
239
118
  silenceTracker.recordBatch(observation.silences.entries);
240
119
  }
241
120
 
242
- // ARCHITECTURAL HARDENING: Track DETECT stage
243
- pipelineTracker.startStage(PIPELINE_STAGES.DETECT);
244
- perfMonitor.startPhase('DETECT');
245
- let findings;
246
- try {
247
- findings = await detect(usedManifestPath, observation.tracesPath, validation, observation.expectationCoverageGaps || [], silenceTracker);
248
- perfMonitor.endPhase('DETECT');
249
- pipelineTracker.completeStage(PIPELINE_STAGES.DETECT, {
250
- findingsCount: findings.findings?.length || 0,
251
- coverageGapsCount: findings.coverageGaps?.length || 0
252
- });
253
- } catch (error) {
254
- perfMonitor.endPhase('DETECT');
255
- pipelineTracker.failStage(PIPELINE_STAGES.DETECT, error);
256
- const failure = errorToFailure(
257
- error,
258
- FAILURE_CODE.DETECT_FINDING_PROCESSING_FAILED,
259
- 'DETECT',
260
- EXECUTION_PHASE.DETECT,
261
- 'detect',
262
- { manifestPath: usedManifestPath }
263
- );
264
- failureLedger.record(failure);
265
- throw error; // Re-throw BLOCKING failures
266
- }
121
+ const findings = await detect(usedManifestPath, observation.tracesPath, validation, observation.expectationCoverageGaps || [], silenceTracker);
267
122
 
268
123
  const learnTruthWithValidation = {
269
124
  ...manifest.learnTruth,
270
125
  validation: validation
271
126
  };
272
127
 
273
- // ARCHITECTURAL HARDENING: Track WRITE stage
274
- pipelineTracker.startStage(PIPELINE_STAGES.WRITE);
275
128
  const runDir = getRunArtifactDir(projectDir, runId);
276
- let scanSummary;
277
- try {
278
- scanSummary = await writeScanSummary(
279
- projectDir,
280
- url,
281
- manifest.projectType,
282
- learnTruthWithValidation,
283
- observation.observeTruth,
284
- findings.detectTruth,
285
- manifest.manifestPath,
286
- observation.tracesPath,
287
- findings.findingsPath,
288
- runDir,
289
- findings.findings // PHASE 7: Pass findings array for decision snapshot
290
- );
291
- pipelineTracker.completeStage(PIPELINE_STAGES.WRITE);
292
- } catch (error) {
293
- pipelineTracker.failStage(PIPELINE_STAGES.WRITE, error);
294
- const failure = errorToFailure(
295
- error,
296
- FAILURE_CODE.IO_WRITE_FAILED,
297
- 'WRITE',
298
- EXECUTION_PHASE.WRITE,
299
- 'writeScanSummary',
300
- { runDir }
301
- );
302
- failureLedger.record(failure);
303
- throw error;
304
- }
129
+ const scanSummary = writeScanSummary(
130
+ projectDir,
131
+ url,
132
+ manifest.projectType,
133
+ learnTruthWithValidation,
134
+ observation.observeTruth,
135
+ findings.detectTruth,
136
+ manifest.manifestPath,
137
+ observation.tracesPath,
138
+ findings.findingsPath,
139
+ runDir,
140
+ findings.findings // PHASE 7: Pass findings array for decision snapshot
141
+ );
305
142
 
306
143
  // Compute observation summary from scan results (not a verdict)
307
144
  // Pass observation object (which includes traces) to observation engine
@@ -330,204 +167,9 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
330
167
  );
331
168
  observationSummary.evidenceIndexPath = evidenceIndexPath;
332
169
 
333
- // PHASE 21.4: Write policy artifacts
334
- try {
335
- const { writeFileSync } = await import('fs');
336
- const { loadGuardrailsPolicy, getPolicyReport: getGuardrailsPolicyReport } = await import('./core/guardrails/policy.loader.js');
337
- const { loadConfidencePolicy, getPolicyReport: getConfidencePolicyReport } = await import('./core/confidence/confidence.loader.js');
338
-
339
- const guardrailsPolicy = loadGuardrailsPolicy();
340
- const confidencePolicy = loadConfidencePolicy();
341
-
342
- const guardrailsPolicyPath = getArtifactPath(projectDir, failureLedger.runId, 'guardrails.policy.json');
343
- const confidencePolicyPath = getArtifactPath(projectDir, failureLedger.runId, 'confidence.policy.json');
344
-
345
- writeFileSync(guardrailsPolicyPath, JSON.stringify({
346
- ...getGuardrailsPolicyReport(guardrailsPolicy),
347
- rules: guardrailsPolicy.rules.map(r => ({
348
- id: r.id,
349
- category: r.category,
350
- action: r.action,
351
- mandatory: r.mandatory
352
- }))
353
- }, null, 2));
354
-
355
- writeFileSync(confidencePolicyPath, JSON.stringify(getConfidencePolicyReport(confidencePolicy), null, 2));
356
- } catch (error) {
357
- // PHASE 21.5: Record I/O failure (WARNING - recoverable)
358
- const failure = createIOFailure(
359
- FAILURE_CODE.IO_WRITE_FAILED,
360
- `Failed to write policy artifacts: ${error.message}`,
361
- 'scan',
362
- { error: error.message },
363
- true
364
- );
365
- failureLedger.record(failure);
366
- }
367
-
368
-
369
- // ARCHITECTURAL HARDENING: Write failure ledger with fallback to run.status.json
370
- let ledgerPath;
371
- try {
372
- ledgerPath = failureLedger.write();
373
- } catch (error) {
374
- // If ledger write fails, write fallback entry to run.status.json
375
- const failure = createInternalFailure(
376
- FAILURE_CODE.INTERNAL_UNEXPECTED_ERROR,
377
- `Failed to write failure ledger: ${error.message}`,
378
- 'scan',
379
- { error: error.message },
380
- error.stack
381
- );
382
- failureLedger.record(failure);
383
-
384
- // Write fallback failure entry to run.status.json
385
- try {
386
- const { writeFileSync, readFileSync } = await import('fs');
387
- const runStatusPath = getArtifactPath(projectDir, runId, 'run.status.json');
388
- let runStatus = { status: 'FAILED', failures: [] };
389
- try {
390
- const existing = readFileSync(runStatusPath, 'utf-8');
391
- runStatus = JSON.parse(existing);
392
- } catch {
393
- // File doesn't exist or is invalid, use defaults
394
- }
395
- runStatus.failures = runStatus.failures || [];
396
- runStatus.failures.push({
397
- code: FAILURE_CODE.INTERNAL_UNEXPECTED_ERROR,
398
- message: `Failed to write failure ledger: ${error.message}`,
399
- timestamp: new Date().toISOString(),
400
- recoverable: false
401
- });
402
- runStatus.ledgerWriteFailed = true;
403
- runStatus.ledgerWriteError = error.message;
404
- writeFileSync(runStatusPath, JSON.stringify(runStatus, null, 2) + '\n', 'utf-8');
405
- } catch (fallbackError) {
406
- // Even fallback write failed - log only
407
- console.error('CRITICAL: Failed to write failure ledger and fallback:', error.message, fallbackError.message);
408
- }
409
- }
410
-
411
- // PHASE 21.9: Generate and write performance report
412
- try {
413
- perfMonitor.stop();
414
- const monitorReport = perfMonitor.getFinalReport();
415
- const profileName = process.env.VERAX_BUDGET_PROFILE || 'STANDARD';
416
- const perfReport = generatePerformanceReport(projectDir, runId, monitorReport, profileName);
417
- writePerformanceReport(projectDir, runId, perfReport);
418
-
419
- // Record performance violations in failure ledger
420
- recordPerformanceViolations(projectDir, runId, failureLedger);
421
- } catch (error) {
422
- // Record performance report failure (WARNING - recoverable)
423
- const failure = createIOFailure(
424
- FAILURE_CODE.IO_WRITE_FAILED,
425
- `Failed to write performance report: ${error.message}`,
426
- 'scan',
427
- { error: error.message },
428
- true
429
- );
430
- failureLedger.record(failure);
431
- }
432
-
433
- // ARCHITECTURAL HARDENING: Track VERIFY stage
434
- pipelineTracker.startStage(PIPELINE_STAGES.VERIFY);
435
- let verification = null;
436
- try {
437
- const artifactVersions = getArtifactVersions();
438
- verification = verifyRun(runDir, artifactVersions);
439
- pipelineTracker.completeStage(PIPELINE_STAGES.VERIFY, {
440
- ok: verification.ok,
441
- errorsCount: verification.errors.length,
442
- warningsCount: verification.warnings.length
443
- });
444
- } catch (error) {
445
- pipelineTracker.failStage(PIPELINE_STAGES.VERIFY, error);
446
- const failure = errorToFailure(
447
- error,
448
- FAILURE_CODE.VERIFICATION_FAILED,
449
- 'VERIFY',
450
- EXECUTION_PHASE.VERIFY,
451
- 'verifyRun',
452
- { runDir }
453
- );
454
- failureLedger.record(failure);
455
- // Verification failure is not blocking, but we record it
456
- verification = {
457
- ok: false,
458
- errors: [error.message],
459
- warnings: [],
460
- verifiedAt: new Date().toISOString()
461
- };
462
- }
463
-
464
- // ARCHITECTURAL HARDENING: Track VERDICT stage (only after verification completes)
465
- pipelineTracker.startStage(PIPELINE_STAGES.VERDICT);
466
- try {
467
- // PHASE 5: Compute artifact hashes and update run manifest
468
- const artifactHashes = computeArtifactHashes(projectDir, runId);
469
- updateRunManifestHashes(projectDir, runId, artifactHashes);
470
-
471
- // Verdict computation (determinism and evidence law checks)
472
- let determinismVerdict = null;
473
- let evidenceLawViolated = false;
474
- try {
475
- const decisionsPath = getArtifactPath(projectDir, runId, 'decisions.json');
476
- const { readFileSync, existsSync } = await import('fs');
477
- if (existsSync(decisionsPath)) {
478
- const decisions = JSON.parse(readFileSync(decisionsPath, 'utf-8'));
479
- const { DecisionRecorder } = await import('./core/determinism-model.js');
480
- const recorder = DecisionRecorder.fromExport(decisions);
481
- const { computeDeterminismVerdict } = await import('./core/determinism/contract.js');
482
- const verdict = computeDeterminismVerdict(recorder);
483
- determinismVerdict = verdict.verdict;
484
- }
485
-
486
- // Check for Evidence Law violations (incomplete evidence with CONFIRMED findings)
487
- if (findings.findings) {
488
- for (const finding of findings.findings) {
489
- if ((finding.severity === 'CONFIRMED' || finding.status === 'CONFIRMED') &&
490
- finding.evidencePackage && !finding.evidencePackage.isComplete) {
491
- evidenceLawViolated = true;
492
- break;
493
- }
494
- }
495
- }
496
- } catch (error) {
497
- // Record failure but don't block
498
- const failure = createInternalFailure(
499
- FAILURE_CODE.INTERNAL_UNEXPECTED_ERROR,
500
- `Failed to compute determinism verdict: ${error.message}`,
501
- 'scan',
502
- { error: error.message },
503
- error.stack
504
- );
505
- failureLedger.record(failure);
506
- }
507
-
508
- pipelineTracker.completeStage(PIPELINE_STAGES.VERDICT, {
509
- determinismVerdict,
510
- evidenceLawViolated,
511
- verificationOk: verification?.ok || false
512
- });
513
- } catch (error) {
514
- pipelineTracker.failStage(PIPELINE_STAGES.VERDICT, error);
515
- const failure = errorToFailure(
516
- error,
517
- FAILURE_CODE.VERDICT_COMPUTATION_FAILED,
518
- 'VERDICT',
519
- EXECUTION_PHASE.VERDICT,
520
- 'computeVerdict',
521
- {}
522
- );
523
- failureLedger.record(failure);
524
- throw error;
525
- }
526
-
527
- // Extract verdict data from pipeline tracker
528
- const verdictStage = pipelineTracker.getStage(PIPELINE_STAGES.VERDICT);
529
- const determinismVerdict = verdictStage?.determinismVerdict || null;
530
- const evidenceLawViolated = verdictStage?.evidenceLawViolated || false;
170
+ // PHASE 5: Compute artifact hashes and update run manifest
171
+ const artifactHashes = computeArtifactHashes(projectDir, runId);
172
+ updateRunManifestHashes(projectDir, runId, artifactHashes);
531
173
 
532
174
  return {
533
175
  manifest,
@@ -537,14 +179,8 @@ export async function scan(projectDir, url, manifestPath = null, scanBudgetOverr
537
179
  validation,
538
180
  coverageGaps: findings.coverageGaps || [],
539
181
  observationSummary,
540
- runId: failureLedger.runId,
541
- runManifest,
542
- failureLedger: failureLedger.export(),
543
- ledgerPath,
544
- determinismVerdict,
545
- evidenceLawViolated,
546
- verification,
547
- pipelineStages: pipelineTracker.getAllStages()
182
+ runId,
183
+ runManifest
548
184
  };
549
185
  }
550
186
 
@@ -245,6 +245,7 @@ export function parseFile(filePath, isJsx = false) {
245
245
 
246
246
  return ts.createSourceFile(
247
247
  filePath,
248
+ // @ts-expect-error - readFileSync with encoding returns string
248
249
  content,
249
250
  ts.ScriptTarget.ES2020,
250
251
  true,
@@ -85,6 +85,7 @@ function extractFromFile(filePath, projectRoot, _program) {
85
85
  // to handle template literals and complex navigation calls
86
86
  try {
87
87
  const content = readFileSync(filePath, 'utf-8');
88
+ // @ts-expect-error - readFileSync with encoding returns string
88
89
  const scriptMatch = content.match(/<script[^>]*>([\s\S]*?)<\/script>/);
89
90
  if (scriptMatch) {
90
91
  const scriptContent = scriptMatch[1];
@@ -162,6 +163,7 @@ function extractFromVueSFC(filePath, projectRoot) {
162
163
  const content = readFileSync(filePath, 'utf-8');
163
164
 
164
165
  // Extract template section
166
+ // @ts-expect-error - readFileSync with encoding returns string
165
167
  const templateMatch = content.match(/<template[^>]*>([\s\S]*?)<\/template>/);
166
168
  if (templateMatch) {
167
169
  const templateContent = templateMatch[1];
@@ -263,6 +265,7 @@ function extractFromVueSFC(filePath, projectRoot) {
263
265
  }
264
266
 
265
267
  // Extract script section for router.push/replace
268
+ // @ts-expect-error - readFileSync with encoding returns string
266
269
  const scriptMatch = content.match(/<script[^>]*>([\s\S]*?)<\/script>/);
267
270
  if (scriptMatch) {
268
271
  const scriptContent = scriptMatch[1];