@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
@@ -1,41 +1,13 @@
1
- import { resolve, dirname, basename } from 'path';
1
+ import { resolve } from 'path';
2
2
  import { existsSync, readFileSync, readdirSync } from 'fs';
3
3
  import { DataError } from '../util/errors.js';
4
- import { displayPerformanceInInspect } from '../../verax/core/perf/perf.display.js';
5
- import { loadRunTimeline } from '../../verax/core/observe/run-timeline.js';
6
- import { loadDecisionTrace } from '../../verax/core/decisions/decision.trace.js';
7
- import { loadCrossIndex } from '../../verax/core/report/cross-index.js';
8
- import { generateHumanSummary, formatHumanSummary } from '../../verax/core/report/human-summary.js';
9
-
10
- /**
11
- * Extract runId from runPath
12
- */
13
- function extractRunId(runPath) {
14
- const fullPath = resolve(runPath);
15
- const runDirBasename = basename(fullPath);
16
- const parentDir = basename(dirname(fullPath));
17
-
18
- // Check if path is .verax/runs/<runId>
19
- if (parentDir === 'runs') {
20
- return runDirBasename;
21
- }
22
-
23
- return runDirBasename;
24
- }
25
4
 
26
5
  /**
27
6
  * `verax inspect` command
28
7
  * Read an existing run folder and display summary
29
8
  */
30
9
  export async function inspectCommand(runPath, options = {}) {
31
- const {
32
- json = false,
33
- timeline = false,
34
- decisions = false,
35
- failures = false,
36
- performance = false,
37
- evidence = false
38
- } = options;
10
+ const { json = false } = options;
39
11
 
40
12
  const fullPath = resolve(runPath);
41
13
 
@@ -65,13 +37,15 @@ export async function inspectCommand(runPath, options = {}) {
65
37
  let summary, findings;
66
38
 
67
39
  try {
68
- summary = JSON.parse(readFileSync(`${fullPath}/summary.json`, 'utf8'));
40
+ // @ts-expect-error - readFileSync with encoding returns string
41
+ summary = JSON.parse(readFileSync(`${fullPath}/summary.json`, 'utf-8'));
69
42
  } catch (error) {
70
43
  throw new DataError(`Failed to parse summary.json: ${error.message}`);
71
44
  }
72
45
 
73
46
  try {
74
- findings = JSON.parse(readFileSync(`${fullPath}/findings.json`, 'utf8'));
47
+ // @ts-expect-error - readFileSync with encoding returns string
48
+ findings = JSON.parse(readFileSync(`${fullPath}/findings.json`, 'utf-8'));
75
49
  } catch (error) {
76
50
  throw new DataError(`Failed to parse findings.json: ${error.message}`);
77
51
  }
@@ -130,108 +104,7 @@ export async function inspectCommand(runPath, options = {}) {
130
104
  console.log(`Evidence: not found`);
131
105
  }
132
106
 
133
- // PHASE 21.9: Display performance metrics
134
- const runId = output.runId;
135
- const projectDir = resolve(process.cwd());
136
-
137
- // PHASE 21.10: Handle specific flags
138
- if (timeline) {
139
- const timelineData = loadRunTimeline(projectDir, runId);
140
- if (timelineData) {
141
- if (json) {
142
- console.log(JSON.stringify(timelineData, null, 2));
143
- } else {
144
- console.log('\n=== Timeline ===\n');
145
- for (const event of timelineData.events) {
146
- console.log(`${event.timestamp || 'N/A'} [${event.phase}] ${event.event}`);
147
- if (event.data) {
148
- console.log(` ${JSON.stringify(event.data)}`);
149
- }
150
- }
151
- console.log('');
152
- }
153
- return output;
154
- }
155
- }
156
-
157
- if (decisions) {
158
- const decisionTrace = loadDecisionTrace(projectDir, runId);
159
- if (decisionTrace) {
160
- if (json) {
161
- console.log(JSON.stringify(decisionTrace, null, 2));
162
- } else {
163
- console.log('\n=== Decision Trace ===\n');
164
- for (const trace of decisionTrace.findings) {
165
- console.log(`Finding: ${trace.findingId}`);
166
- console.log(` Status: ${trace.status.value}`);
167
- console.log(` Confidence: ${trace.confidence.level || 'UNKNOWN'}`);
168
- console.log(` Why detected: ${trace.detection.why.map(w => w.reason).join('; ')}`);
169
- console.log(` Why status: ${trace.status.why.map(w => w.reason).join('; ')}`);
170
- console.log('');
171
- }
172
- }
173
- return output;
174
- }
175
- }
176
-
177
- if (failures) {
178
- const failureLedgerPath = resolve(fullPath, 'failure.ledger.json');
179
- if (existsSync(failureLedgerPath)) {
180
- const failureLedger = JSON.parse(readFileSync(failureLedgerPath, 'utf-8'));
181
- if (json) {
182
- console.log(JSON.stringify(failureLedger, null, 2));
183
- } else {
184
- console.log('\n=== Failures ===\n');
185
- console.log(`Total: ${failureLedger.summary?.total || 0}`);
186
- if (failureLedger.failures) {
187
- for (const failure of failureLedger.failures) {
188
- console.log(`[${failure.severity || 'UNKNOWN'}] ${failure.code}: ${failure.message}`);
189
- }
190
- }
191
- console.log('');
192
- }
193
- return output;
194
- }
195
- }
196
-
197
- if (performance) {
198
- displayPerformanceInInspect(projectDir, runId);
199
107
  console.log('');
200
- return output;
201
- }
202
-
203
- if (evidence) {
204
- const crossIndex = loadCrossIndex(projectDir, runId);
205
- if (crossIndex) {
206
- if (json) {
207
- console.log(JSON.stringify(crossIndex, null, 2));
208
- } else {
209
- console.log('\n=== Evidence Cross-Index ===\n');
210
- for (const [findingId, entry] of Object.entries(crossIndex.findings)) {
211
- console.log(`Finding: ${findingId}`);
212
- console.log(` Evidence files: ${entry.evidence.files.length}`);
213
- console.log(` Evidence complete: ${entry.evidence.isComplete}`);
214
- console.log(` Confidence: ${entry.confidence.level || 'UNKNOWN'}`);
215
- console.log(` Guardrails: ${entry.guardrails.applied.length} rule(s) applied`);
216
- console.log('');
217
- }
218
- }
219
- return output;
220
- }
221
- }
222
-
223
- // Default: show summary + human summary
224
- displayPerformanceInInspect(projectDir, runId);
225
-
226
- // PHASE 21.10: Display human summary
227
- const humanSummary = await generateHumanSummary(projectDir, runId);
228
- if (humanSummary && !json) {
229
- console.log(formatHumanSummary(humanSummary));
230
- } else if (humanSummary && json) {
231
- output.humanSummary = humanSummary;
232
- }
233
-
234
- console.log('');
235
108
  }
236
109
 
237
110
  return output;
@@ -53,6 +53,7 @@ export async function releaseCheckCommand(options = {}) {
53
53
  const provenancePath = resolve(projectDir, 'release', 'release.provenance.json');
54
54
  if (existsSync(provenancePath)) {
55
55
  status.provenance.exists = true;
56
+ // @ts-expect-error - readFileSync with encoding returns string
56
57
  const provenance = JSON.parse(readFileSync(provenancePath, 'utf-8'));
57
58
 
58
59
  // Validate provenance structure
@@ -85,6 +86,7 @@ export async function releaseCheckCommand(options = {}) {
85
86
  const sbomPath = resolve(projectDir, 'release', 'sbom.json');
86
87
  if (existsSync(sbomPath)) {
87
88
  status.sbom.exists = true;
89
+ // @ts-expect-error - readFileSync with encoding returns string
88
90
  const sbom = JSON.parse(readFileSync(sbomPath, 'utf-8'));
89
91
 
90
92
  // Validate SBOM structure
@@ -17,9 +17,8 @@ import { detectFindings } from '../util/detection-engine.js';
17
17
  import { writeFindingsJson } from '../util/findings-writer.js';
18
18
  import { writeSummaryJson } from '../util/summary-writer.js';
19
19
  import { computeRuntimeBudget, withTimeout } from '../util/runtime-budget.js';
20
- import { assertHasLocalSource } from '../util/source-requirement.js';
21
- import { runWithDeterminism } from '../util/determinism-runner.js';
22
- import { runDeterminismCheck } from '../../verax/core/determinism/engine.js';
20
+ import { saveDigest } from '../util/digest-engine.js';
21
+ import { ARTIFACT_REGISTRY, getArtifactVersions } from '../../verax/core/artifacts/registry.js';
23
22
 
24
23
  const __filename = fileURLToPath(import.meta.url);
25
24
  const __dirname = dirname(__filename);
@@ -27,10 +26,11 @@ const __dirname = dirname(__filename);
27
26
  function getVersion() {
28
27
  try {
29
28
  const pkgPath = resolve(__dirname, '../../../package.json');
30
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
29
+ // @ts-expect-error - readFileSync with encoding returns string
30
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
31
31
  return pkg.version;
32
32
  } catch {
33
- return '0.3.0';
33
+ return '0.2.0';
34
34
  }
35
35
  }
36
36
 
@@ -39,68 +39,17 @@ function getVersion() {
39
39
  * Strict, non-interactive CLI mode with explicit flags
40
40
  */
41
41
  export async function runCommand(options) {
42
- return await runCommandInternal(options);
43
- }
44
-
45
- /**
46
- * Internal run command implementation
47
- */
48
- async function runCommandInternal(options) {
49
42
  const {
50
43
  url,
51
- fixture,
52
44
  src = '.',
53
45
  out = '.verax',
54
46
  json = false,
55
47
  verbose = false,
56
- determinism = false,
57
- determinismRuns = 2,
58
48
  } = options;
59
49
 
60
- // PHASE 25: Support fixture mode for determinism
61
- let resolvedUrl = url;
62
- let fixtureId = null;
63
-
64
- if (fixture && !url) {
65
- // Extract URL from fixture
66
- const { resolve } = await import('path');
67
- const { existsSync, readFileSync } = await import('fs');
68
- const { fileURLToPath } = await import('url');
69
- const { dirname } = await import('path');
70
- const __filename = fileURLToPath(import.meta.url);
71
- const __dirname = dirname(__filename);
72
-
73
- const fixturePath = resolve(__dirname, '..', '..', '..', 'test', 'fixtures', 'realistic', fixture);
74
- if (existsSync(fixturePath)) {
75
- // Try to read package.json or index.html to extract URL
76
- const packagePath = resolve(fixturePath, 'package.json');
77
- const indexPath = resolve(fixturePath, 'index.html');
78
-
79
- if (existsSync(packagePath)) {
80
- try {
81
- const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));
82
- if (pkg.verax && pkg.verax.url) {
83
- resolvedUrl = pkg.verax.url;
84
- fixtureId = fixture;
85
- }
86
- } catch {
87
- // Ignore parse errors
88
- }
89
- }
90
-
91
- // If no URL found, use default localhost URL for fixture
92
- if (!resolvedUrl) {
93
- resolvedUrl = `http://localhost:5173`; // Default Vite dev server
94
- fixtureId = fixture;
95
- }
96
- } else {
97
- throw new DataError(`Fixture not found: ${fixture}`);
98
- }
99
- }
100
-
101
50
  // Validate required arguments
102
- if (!resolvedUrl) {
103
- throw new UsageError('Missing required argument: --url <url> or --fixture <fixture>');
51
+ if (!url) {
52
+ throw new UsageError('Missing required argument: --url <url>');
104
53
  }
105
54
 
106
55
  const projectRoot = resolve(process.cwd());
@@ -110,9 +59,6 @@ async function runCommandInternal(options) {
110
59
  if (!existsSync(srcPath)) {
111
60
  throw new DataError(`Source directory not found: ${srcPath}`);
112
61
  }
113
-
114
- // Enforce local source availability (no URL-only scans)
115
- assertHasLocalSource(srcPath);
116
62
 
117
63
  // Create event emitter
118
64
  const events = new RunEventEmitter();
@@ -150,7 +96,7 @@ async function runCommandInternal(options) {
150
96
  const failedAt = new Date().toISOString();
151
97
  atomicWriteJson(paths.runStatusJson, {
152
98
  contractVersion: 1,
153
- artifactVersions: paths.artifactVersions,
99
+ artifactVersions: getArtifactVersions(),
154
100
  status: 'FAILED',
155
101
  runId,
156
102
  startedAt,
@@ -159,8 +105,7 @@ async function runCommandInternal(options) {
159
105
  });
160
106
 
161
107
  atomicWriteJson(paths.runMetaJson, {
162
- contractVersion: 1,
163
- artifactVersions: paths.artifactVersions,
108
+ contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
164
109
  veraxVersion: getVersion(),
165
110
  nodeVersion: process.version,
166
111
  platform: process.platform,
@@ -181,7 +126,7 @@ async function runCommandInternal(options) {
181
126
  startedAt,
182
127
  completedAt: failedAt,
183
128
  command: 'run',
184
- url: resolvedUrl,
129
+ url,
185
130
  notes: `Run timed out: ${reason}`,
186
131
  }, {
187
132
  expectationsTotal: 0,
@@ -206,73 +151,9 @@ async function runCommandInternal(options) {
206
151
  });
207
152
  };
208
153
 
209
- // PHASE 25: If determinism mode, wrap execution
210
- if (determinism) {
211
- const scanFn = async (runConfig) => {
212
- // Execute a single scan run
213
- const singleRunId = generateRunId();
214
- const singlePaths = getRunPaths(projectRoot, out, singleRunId);
215
- ensureRunDirectories(singlePaths);
216
-
217
- // Execute scan (reuse existing logic but with single run)
218
- // This is a simplified version - in production, you'd extract the scan logic
219
- const { scan } = await import('../../verax/index.js');
220
- const scanResult = await scan(
221
- projectRoot,
222
- resolvedUrl,
223
- null, // manifestPath
224
- null, // scanBudgetOverride
225
- {}, // safetyFlags
226
- singleRunId
227
- );
228
-
229
- return {
230
- runId: singleRunId,
231
- artifactPaths: {
232
- findings: singlePaths.findingsJson,
233
- runStatus: singlePaths.runStatusJson,
234
- summary: singlePaths.summaryJson,
235
- learn: singlePaths.learnJson,
236
- observe: singlePaths.observeJson,
237
- runDir: singlePaths.baseDir
238
- }
239
- };
240
- };
241
-
242
- const determinismResult = await runWithDeterminism(scanFn, {
243
- runs: determinismRuns,
244
- out,
245
- url: resolvedUrl,
246
- fixture: fixtureId,
247
- src,
248
- verbose,
249
- json
250
- });
251
-
252
- // PHASE 25: Output determinism report path
253
- if (!json) {
254
- console.log(`\nDeterminism check complete.`);
255
- console.log(`Verdict: ${determinismResult.verdict}`);
256
- console.log(`Report: ${determinismResult.reportPath}`);
257
- } else {
258
- console.log(JSON.stringify({
259
- type: 'determinism:complete',
260
- verdict: determinismResult.verdict,
261
- reportPath: determinismResult.reportPath,
262
- summary: determinismResult.summary
263
- }));
264
- }
265
-
266
- return {
267
- success: determinismResult.verdict === 'DETERMINISTIC' || determinismResult.verdict === 'NON_DETERMINISTIC_EXPECTED',
268
- verdict: determinismResult.verdict,
269
- reportPath: determinismResult.reportPath
270
- };
271
- }
272
-
273
154
  try {
274
155
  // Generate run ID
275
- runId = generateRunId();
156
+ runId = generateRunId(url);
276
157
  if (verbose && !json) console.log(`Run ID: ${runId}`);
277
158
 
278
159
  paths = getRunPaths(projectRoot, out, runId);
@@ -323,7 +204,7 @@ async function runCommandInternal(options) {
323
204
 
324
205
  atomicWriteJson(paths.runStatusJson, {
325
206
  contractVersion: 1,
326
- artifactVersions: paths.artifactVersions,
207
+ artifactVersions: getArtifactVersions(),
327
208
  status: 'RUNNING',
328
209
  runId,
329
210
  startedAt,
@@ -331,16 +212,14 @@ async function runCommandInternal(options) {
331
212
 
332
213
  // Write metadata
333
214
  atomicWriteJson(paths.runMetaJson, {
334
- contractVersion: 1,
335
- artifactVersions: paths.artifactVersions,
215
+ contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
336
216
  veraxVersion: getVersion(),
337
217
  nodeVersion: process.version,
338
218
  platform: process.platform,
339
219
  cwd: projectRoot,
340
220
  command: 'run',
341
- args: { url: resolvedUrl, fixture: fixtureId, src, out },
342
- url: resolvedUrl,
343
- fixtureId: fixtureId,
221
+ args: { url, src, out },
222
+ url,
344
223
  src: srcPath,
345
224
  startedAt,
346
225
  completedAt: null,
@@ -421,7 +300,8 @@ async function runCommandInternal(options) {
421
300
  paths.evidenceDir,
422
301
  (progress) => {
423
302
  events.emit(progress.event, progress);
424
- }
303
+ },
304
+ {}
425
305
  ),
426
306
  'Observe'
427
307
  );
@@ -532,6 +412,32 @@ async function runCommandInternal(options) {
532
412
 
533
413
  const completedAt = new Date().toISOString();
534
414
 
415
+ // Write completed status
416
+ atomicWriteJson(paths.runStatusJson, {
417
+ contractVersion: 1,
418
+ artifactVersions: getArtifactVersions(),
419
+ status: 'COMPLETE',
420
+ runId,
421
+ startedAt,
422
+ completedAt,
423
+ });
424
+
425
+ // Update metadata with completion time
426
+ atomicWriteJson(paths.runMetaJson, {
427
+ contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
428
+ veraxVersion: getVersion(),
429
+ nodeVersion: process.version,
430
+ platform: process.platform,
431
+ cwd: projectRoot,
432
+ command: 'run',
433
+ args: { url, src, out },
434
+ url,
435
+ src: srcPath,
436
+ startedAt,
437
+ completedAt,
438
+ error: null,
439
+ });
440
+
535
441
  const runDurationMs = completedAt && startedAt ? (Date.parse(completedAt) - Date.parse(startedAt)) : 0;
536
442
  const metrics = {
537
443
  learnMs: observeData?.timings?.learnMs || 0,
@@ -546,9 +452,6 @@ async function runCommandInternal(options) {
546
452
  UNKNOWN: 0,
547
453
  };
548
454
 
549
- // Write detect results (or empty if detection failed)
550
- const findingsResult = writeFindingsJson(paths.baseDir, detectData);
551
-
552
455
  // Write summary with stable digest
553
456
  writeSummaryJson(paths.summaryJson, {
554
457
  runId,
@@ -572,6 +475,9 @@ async function runCommandInternal(options) {
572
475
  ...findingsCounts,
573
476
  });
574
477
 
478
+ // Write detect results (or empty if detection failed)
479
+ writeFindingsJson(paths.baseDir, detectData);
480
+
575
481
  // Write traces (include all events including heartbeats)
576
482
  const allEvents = events.getEvents();
577
483
  const tracesContent = allEvents
@@ -587,78 +493,12 @@ async function runCommandInternal(options) {
587
493
 
588
494
  // Write observe results
589
495
  writeObserveJson(paths.baseDir, observeData);
590
-
591
- // PHASE 6: Verify artifacts after all writers finish
592
- const { verifyRun } = await import('../../verax/core/artifacts/verifier.js');
593
- const verification = verifyRun(paths.baseDir, paths.artifactVersions);
594
-
595
- // Determine final status based on verification
596
- let finalStatus = 'COMPLETE';
597
- if (!verification.ok) {
598
- finalStatus = 'INVALID';
599
- } else if (verification.warnings.length > 0) {
600
- finalStatus = 'VALID_WITH_WARNINGS';
601
- }
602
496
 
603
- // PHASE 21.2: Compute determinism summary for run.status.json
604
- let determinismSummary = null;
605
- try {
606
- const decisionsPath = resolve(paths.baseDir, 'decisions.json');
607
- if (existsSync(decisionsPath)) {
608
- const decisions = JSON.parse(readFileSync(decisionsPath, 'utf-8'));
609
- const { DecisionRecorder } = await import('../../verax/core/determinism-model.js');
610
- const recorder = DecisionRecorder.fromExport(decisions);
611
- const { computeDeterminismVerdict } = await import('../../verax/core/determinism/contract.js');
612
- const verdict = computeDeterminismVerdict(recorder);
613
-
614
- determinismSummary = {
615
- verdict: verdict.verdict, // DETERMINISTIC or NON_DETERMINISTIC
616
- message: verdict.message,
617
- adaptiveEventsCount: verdict.adaptiveEvents.length
618
- };
619
- }
620
- } catch (error) {
621
- // Ignore errors - determinism summary is optional
497
+ // H5: Write deterministic digest for reproducibility proof
498
+ if (observeData && observeData.digest) {
499
+ saveDigest(resolve(paths.baseDir, 'run.digest.json'), observeData.digest);
622
500
  }
623
501
 
624
- // Write completed status with contract + enforcement snapshot + verification + determinism
625
- atomicWriteJson(paths.runStatusJson, {
626
- contractVersion: 1,
627
- artifactVersions: paths.artifactVersions,
628
- status: finalStatus,
629
- runId,
630
- startedAt,
631
- completedAt,
632
- enforcement: findingsResult?.payload?.enforcement || null,
633
- verification: {
634
- ok: verification.ok,
635
- status: finalStatus,
636
- errorsCount: verification.errors.length,
637
- warningsCount: verification.warnings.length,
638
- verifiedAt: verification.verifiedAt
639
- },
640
- // PHASE 21.2: Determinism summary
641
- determinismSummary: determinismSummary
642
- });
643
-
644
- // Update metadata with completion time
645
- atomicWriteJson(paths.runMetaJson, {
646
- contractVersion: 1,
647
- artifactVersions: paths.artifactVersions,
648
- veraxVersion: getVersion(),
649
- nodeVersion: process.version,
650
- platform: process.platform,
651
- cwd: projectRoot,
652
- command: 'run',
653
- args: { url: resolvedUrl, fixture: fixtureId, src, out },
654
- url: resolvedUrl,
655
- fixtureId: fixtureId,
656
- src: srcPath,
657
- startedAt,
658
- completedAt,
659
- error: null,
660
- });
661
-
662
502
  events.emit('phase:completed', {
663
503
  phase: 'Finalize Artifacts',
664
504
  message: 'Run artifacts written',
@@ -686,37 +526,27 @@ async function runCommandInternal(options) {
686
526
 
687
527
  // Print summary if not JSON mode
688
528
  if (!json) {
689
- console.log('\nRun complete.');
690
- console.log(`Run ID: ${runId}`);
691
- console.log(`Artifacts: ${paths.baseDir}`);
692
-
693
- // PHASE 21.2: Display determinism truth
694
- if (determinismSummary) {
695
- console.log('');
696
- if (determinismSummary.verdict === 'DETERMINISTIC') {
697
- console.log('Deterministic: YES');
698
- } else {
699
- console.log(`Deterministic: NO (${determinismSummary.message})`);
700
- if (determinismSummary.adaptiveEventsCount > 0) {
701
- console.log(` Adaptive events detected: ${determinismSummary.adaptiveEventsCount}`);
702
- }
703
- }
704
- }
705
-
706
- // PHASE 6: Display verification results
707
- const { formatVerificationOutput } = await import('../../verax/core/artifacts/verifier.js');
708
- const verificationOutput = formatVerificationOutput(verification, verbose);
529
+ const relativePath = paths.baseDir.replace(/\\/g, '/').split('/').slice(-1)[0];
530
+ console.log('');
531
+ console.log('VERAX — Silent Failure Detection');
532
+ console.log('');
533
+ console.log(`✔ URL: ${url}`);
534
+ console.log('');
535
+ console.log('Learn phase:');
536
+ console.log(` → Extracted ${expectations.length} promises`);
537
+ console.log('');
538
+ console.log('Observe phase:');
539
+ console.log(` Executed ${observeData.stats?.attempted || 0} interactions`);
540
+ console.log(` → Observed: ${observeData.stats?.observed || 0}/${observeData.stats?.attempted || 0}`);
541
+ console.log('');
542
+ console.log('Detect phase:');
543
+ console.log(` → Silent failures: ${detectData.stats?.silentFailures || 0}`);
544
+ console.log(` → Unproven: ${detectData.stats?.unproven || 0}`);
545
+ console.log(` → Coverage gaps: ${detectData.stats?.coverageGaps || 0}`);
546
+ console.log('');
547
+ console.log('Artifacts written to:');
548
+ console.log(` .verax/runs/${relativePath}/`);
709
549
  console.log('');
710
- console.log(verificationOutput);
711
-
712
- // PHASE 21.9: Display performance metrics
713
- const { loadPerformanceReport } = await import('../../verax/core/perf/perf.report.js');
714
- const { formatPerformanceMetrics } = await import('../../verax/core/perf/perf.display.js');
715
- const perfReport = loadPerformanceReport(projectRoot, runId);
716
- if (perfReport) {
717
- console.log('');
718
- console.log(formatPerformanceMetrics(perfReport));
719
- }
720
550
  }
721
551
 
722
552
  return { runId, paths, success: true };
@@ -735,7 +565,7 @@ async function runCommandInternal(options) {
735
565
  const failedAt = new Date().toISOString();
736
566
  atomicWriteJson(paths.runStatusJson, {
737
567
  contractVersion: 1,
738
- artifactVersions: paths.artifactVersions,
568
+ artifactVersions: getArtifactVersions(),
739
569
  status: 'FAILED',
740
570
  runId,
741
571
  startedAt,
@@ -745,16 +575,14 @@ async function runCommandInternal(options) {
745
575
 
746
576
  // Update metadata
747
577
  atomicWriteJson(paths.runMetaJson, {
748
- contractVersion: 1,
749
- artifactVersions: paths.artifactVersions,
578
+ contractVersion: ARTIFACT_REGISTRY.runMeta.contractVersion,
750
579
  veraxVersion: getVersion(),
751
580
  nodeVersion: process.version,
752
581
  platform: process.platform,
753
582
  cwd: projectRoot,
754
583
  command: 'run',
755
- args: { url: resolvedUrl || url, fixture: fixtureId, src, out },
756
- url: resolvedUrl || url,
757
- fixtureId: fixtureId,
584
+ args: { url, src, out },
585
+ url,
758
586
  src: srcPath,
759
587
  startedAt,
760
588
  completedAt: failedAt,
@@ -769,7 +597,7 @@ async function runCommandInternal(options) {
769
597
  startedAt,
770
598
  completedAt: failedAt,
771
599
  command: 'run',
772
- url: resolvedUrl || url,
600
+ url,
773
601
  notes: `Run failed: ${error.message}`,
774
602
  }, {
775
603
  expectationsTotal: 0,
@@ -10,7 +10,7 @@ import { scanVulnerabilities, writeVulnReport } from '../../verax/core/security/
10
10
  import { evaluateSupplyChainPolicy, writeSupplyChainReport } from '../../verax/core/security/supplychain.policy.js';
11
11
  import { writeSecurityReport } from '../../verax/core/security/security-report.js';
12
12
  import { resolve } from 'path';
13
- import { mkdirSync, existsSync } from 'fs';
13
+ import { mkdirSync as _mkdirSync, existsSync } from 'fs';
14
14
 
15
15
  /**
16
16
  * Security check command
@@ -116,6 +116,7 @@ export async function securityCheckCommand(options = {}) {
116
116
  const secretsPath = resolve(projectDir, 'release', 'security.secrets.report.json');
117
117
  if (existsSync(secretsPath)) {
118
118
  const { readFileSync } = await import('fs');
119
+ // @ts-expect-error - readFileSync with encoding returns string
119
120
  secretsReport = JSON.parse(readFileSync(secretsPath, 'utf-8'));
120
121
  }
121
122
  } catch {
@@ -4,7 +4,6 @@
4
4
  * `verax truth` - Shows truth certificate summary
5
5
  */
6
6
 
7
- import { resolve } from 'path';
8
7
  import { findLatestRunId } from '../util/run-resolver.js';
9
8
  import { generateTruthCertificate, loadTruthCertificate } from '../../verax/core/truth/truth.certificate.js';
10
9