@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,6 +1,5 @@
1
1
  import { join, isAbsolute } from 'path';
2
2
  import { mkdirSync } from 'fs';
3
- import { buildRunArtifactPaths } from '../../verax/core/artifacts/registry.js';
4
3
 
5
4
  /**
6
5
  * Build run artifact paths
@@ -8,8 +7,18 @@ import { buildRunArtifactPaths } from '../../verax/core/artifacts/registry.js';
8
7
  export function getRunPaths(projectRoot, outDir, runId) {
9
8
  const outBase = isAbsolute(outDir) ? outDir : join(projectRoot, outDir);
10
9
  const baseDir = join(outBase, 'runs', runId);
11
-
12
- return buildRunArtifactPaths(baseDir);
10
+
11
+ return {
12
+ baseDir,
13
+ runStatusJson: join(baseDir, 'run.status.json'),
14
+ runMetaJson: join(baseDir, 'run.meta.json'),
15
+ summaryJson: join(baseDir, 'summary.json'),
16
+ findingsJson: join(baseDir, 'findings.json'),
17
+ tracesJsonl: join(baseDir, 'traces.jsonl'),
18
+ evidenceDir: join(baseDir, 'evidence'),
19
+ learnJson: join(baseDir, 'learn.json'),
20
+ observeJson: join(baseDir, 'observe.json'),
21
+ };
13
22
  }
14
23
 
15
24
  /**
@@ -1,6 +1,5 @@
1
1
  import { existsSync, readFileSync, readdirSync } from 'fs';
2
2
  import { resolve, dirname } from 'path';
3
- import { assertExecutionBootstrapAllowed } from './bootstrap-guard.js';
4
3
 
5
4
  /**
6
5
  * Project Discovery Module
@@ -22,8 +21,6 @@ import { assertExecutionBootstrapAllowed } from './bootstrap-guard.js';
22
21
  * @returns {Promise<ProjectProfile>}
23
22
  */
24
23
  export async function discoverProject(srcPath) {
25
- // PHASE 21.6.1: Runtime guard - crash if called during inspection
26
- assertExecutionBootstrapAllowed('discoverProject');
27
24
  const projectRoot = resolve(srcPath);
28
25
 
29
26
  // Find the nearest package.json
@@ -36,6 +33,7 @@ export async function discoverProject(srcPath) {
36
33
  let packageJson = null;
37
34
  if (packageJsonPath && existsSync(packageJsonPath)) {
38
35
  try {
36
+ // @ts-expect-error - readFileSync with encoding returns string
39
37
  packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
40
38
  } catch (error) {
41
39
  packageJson = null;
@@ -67,6 +65,44 @@ export async function discoverProject(srcPath) {
67
65
  };
68
66
  }
69
67
 
68
+ /**
69
+ * Synchronous project profile resolver used by zero-config helpers
70
+ */
71
+ export function getProjectProfile(projectPath) {
72
+ const projectRoot = resolve(projectPath);
73
+ const packageJsonPath = findPackageJson(projectRoot);
74
+ const projectDir = packageJsonPath ? dirname(packageJsonPath) : projectRoot;
75
+
76
+ let packageJson = null;
77
+ if (packageJsonPath && existsSync(packageJsonPath)) {
78
+ try {
79
+ // @ts-expect-error - readFileSync with encoding returns string
80
+ packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
81
+ } catch {
82
+ packageJson = null;
83
+ }
84
+ }
85
+
86
+ const framework = detectFramework(projectDir, packageJson);
87
+ const router = detectRouter(framework, projectDir);
88
+ const packageManager = detectPackageManager(projectDir);
89
+ const scripts = {
90
+ dev: packageJson?.scripts?.dev || null,
91
+ build: packageJson?.scripts?.build || null,
92
+ start: packageJson?.scripts?.start || null,
93
+ };
94
+
95
+ return {
96
+ framework,
97
+ router,
98
+ sourceRoot: projectDir,
99
+ packageManager,
100
+ scripts,
101
+ detectedAt: new Date().toISOString(),
102
+ packageJsonPath,
103
+ };
104
+ }
105
+
70
106
  /**
71
107
  * Find the nearest package.json by walking up directories
72
108
  */
@@ -298,3 +334,248 @@ export function extractPortFromScript(script) {
298
334
 
299
335
  return null;
300
336
  }
337
+
338
+ /**
339
+ * Detect if running in CI environment (H5: Zero-Config)
340
+ */
341
+ export function isCI() {
342
+ return !!(
343
+ process.env.CI ||
344
+ process.env.CONTINUOUS_INTEGRATION ||
345
+ process.env.GITHUB_ACTIONS ||
346
+ process.env.GITLAB_CI ||
347
+ process.env.CIRCLECI ||
348
+ process.env.TRAVIS ||
349
+ process.env.BUILDKITE
350
+ );
351
+ }
352
+
353
+ /**
354
+ * Check if a port is accessible via HTTP (H5: Zero-Config)
355
+ */
356
+ export async function isPortAccessible(port, host = 'localhost', timeout = 3000) {
357
+ return new Promise(resolve => {
358
+ const _startTime = Date.now();
359
+ const timeoutId = setTimeout(() => {
360
+ resolve(false);
361
+ }, timeout);
362
+
363
+ try {
364
+ const http = require('http');
365
+ const req = http.get(
366
+ {
367
+ hostname: host,
368
+ port,
369
+ path: '/',
370
+ timeout: 1000,
371
+ },
372
+ () => {
373
+ clearTimeout(timeoutId);
374
+ resolve(true);
375
+ }
376
+ );
377
+
378
+ req.on('error', () => {
379
+ clearTimeout(timeoutId);
380
+ resolve(false);
381
+ });
382
+
383
+ req.on('timeout', () => {
384
+ clearTimeout(timeoutId);
385
+ req.destroy();
386
+ resolve(false);
387
+ });
388
+ } catch (e) {
389
+ clearTimeout(timeoutId);
390
+ resolve(false);
391
+ }
392
+ });
393
+ }
394
+
395
+ /**
396
+ * Infer URL from existing framework detection (H5: Zero-Config)
397
+ */
398
+ export async function inferURL(projectPath, profile, preferredPort = null) {
399
+ const result = {
400
+ url: null,
401
+ port: preferredPort || 3000,
402
+ discovered: false,
403
+ };
404
+
405
+ // Extract port from scripts if available
406
+ const profile2 = profile || getProjectProfile(projectPath);
407
+ if (profile2?.scripts?.dev && !preferredPort) {
408
+ const portFromScript = extractPortFromScript(profile2.scripts.dev);
409
+ if (portFromScript) {
410
+ result.port = portFromScript;
411
+ }
412
+ }
413
+
414
+ // Try preferred port
415
+ if (await isPortAccessible(result.port, 'localhost', 1000)) {
416
+ result.url = `http://localhost:${result.port}`;
417
+ result.discovered = true;
418
+ return result;
419
+ }
420
+
421
+ // Try common ports
422
+ const commonPorts = [3000, 5173, 4200, 8080, 8000];
423
+ for (const port of commonPorts) {
424
+ if (await isPortAccessible(port, 'localhost', 1000)) {
425
+ result.url = `http://localhost:${port}`;
426
+ result.port = port;
427
+ result.discovered = true;
428
+ return result;
429
+ }
430
+ }
431
+
432
+ // No port found
433
+ return result;
434
+ }
435
+
436
+ /**
437
+ * Full zero-config setup (H5: Zero-Config)
438
+ * Returns: { url, discovery }
439
+ */
440
+ export async function setupZeroConfig(projectPath, providedURL = null) {
441
+ const discovery = {
442
+ method: null,
443
+ framework: null,
444
+ serverAutoStarted: false,
445
+ details: {},
446
+ };
447
+
448
+ // If URL provided, use it immediately
449
+ if (providedURL) {
450
+ discovery.method = 'provided';
451
+ return {
452
+ url: providedURL,
453
+ discovery,
454
+ };
455
+ }
456
+
457
+ // Detect framework
458
+ const profile = getProjectProfile(projectPath);
459
+ discovery.framework = profile?.framework || 'unknown';
460
+
461
+ // Try to infer URL from existing ports
462
+ const inference = await inferURL(projectPath, profile);
463
+
464
+ if (inference.discovered) {
465
+ discovery.method = 'inferred';
466
+ discovery.details = {
467
+ port: inference.port,
468
+ framework: profile?.framework,
469
+ };
470
+ return {
471
+ url: inference.url,
472
+ discovery,
473
+ };
474
+ }
475
+
476
+ // Server not running and auto-start is disabled in CI
477
+ if (isCI()) {
478
+ throw new Error(
479
+ `No running server detected on port ${inference.port}. ` +
480
+ 'In CI environment, use --url to specify server URL.'
481
+ );
482
+ }
483
+
484
+ // H5: Auto-start dev server (max 30s startup)
485
+ try {
486
+ const started = await autoStartDevServer(projectPath, profile, inference.port);
487
+ if (started.success) {
488
+ discovery.method = 'auto-started';
489
+ discovery.serverAutoStarted = true;
490
+ discovery.details = {
491
+ port: started.port,
492
+ framework: profile?.framework,
493
+ startupTime: started.startupTime,
494
+ };
495
+ return {
496
+ url: `http://localhost:${started.port}`,
497
+ discovery,
498
+ };
499
+ }
500
+ } catch (e) {
501
+ // Fall through to error
502
+ }
503
+
504
+ // Could not start server
505
+ throw new Error(
506
+ `No running server detected on port ${inference.port}. ` +
507
+ 'Start your dev server or use --url to specify the server URL.'
508
+ );
509
+ }
510
+
511
+ /**
512
+ * H5: Auto-start development server
513
+ * Supports: Next.js, Vite, CRA, Vue, Svelte, Angular
514
+ * Max 30 second startup with automatic port detection
515
+ */
516
+ export async function autoStartDevServer(projectPath, profile = null, preferredPort = 3000) {
517
+ const prof = profile || getProjectProfile(projectPath);
518
+
519
+ if (!prof?.scripts?.dev) {
520
+ return { success: false, reason: 'no-dev-script' };
521
+ }
522
+
523
+ // Extract port from dev script
524
+ const port = extractPortFromScript(prof.scripts.dev) || preferredPort;
525
+
526
+ // Check if port is already accessible (server already running)
527
+ if (await isPortAccessible(port, 'localhost', 1000)) {
528
+ return { success: true, port, startupTime: 0 };
529
+ }
530
+
531
+ // Import required modules for spawning process
532
+ const { spawn } = await import('child_process');
533
+ const startTime = Date.now();
534
+ const MAX_STARTUP_TIME = 30 * 1000; // 30 seconds
535
+
536
+ return new Promise((resolve) => {
537
+ let resolved = false;
538
+
539
+ const process = spawn('npm', ['run', 'dev'], {
540
+ cwd: projectPath,
541
+ stdio: 'ignore',
542
+ detached: true,
543
+ });
544
+
545
+ // Detach the process so it doesn't keep this process alive
546
+ process.unref();
547
+
548
+ // Poll for port accessibility
549
+ const pollInterval = setInterval(async () => {
550
+ const elapsed = Date.now() - startTime;
551
+
552
+ if (elapsed > MAX_STARTUP_TIME) {
553
+ clearInterval(pollInterval);
554
+ if (!resolved) {
555
+ resolved = true;
556
+ resolve({ success: false, reason: 'startup-timeout', elapsed });
557
+ }
558
+ return;
559
+ }
560
+
561
+ if (await isPortAccessible(port, 'localhost', 1000)) {
562
+ clearInterval(pollInterval);
563
+ if (!resolved) {
564
+ resolved = true;
565
+ const startupTime = Date.now() - startTime;
566
+ resolve({ success: true, port, startupTime });
567
+ }
568
+ }
569
+ }, 500); // Check every 500ms
570
+
571
+ // Timeout safety
572
+ setTimeout(() => {
573
+ clearInterval(pollInterval);
574
+ if (!resolved) {
575
+ resolved = true;
576
+ resolve({ success: false, reason: 'startup-timeout', elapsed: MAX_STARTUP_TIME });
577
+ }
578
+ }, MAX_STARTUP_TIME + 1000);
579
+ });
580
+ }
581
+
@@ -6,10 +6,10 @@ import { ARTIFACT_REGISTRY } from '../../verax/core/artifacts/registry.js';
6
6
  * Write project profile artifact
7
7
  */
8
8
  export function writeProjectJson(runPaths, projectProfile) {
9
- const projectJsonPath = resolve(runPaths.baseDir, ARTIFACT_REGISTRY.project.filename);
9
+ const projectJsonPath = resolve(runPaths.baseDir, 'project.json');
10
10
 
11
11
  const projectJson = {
12
- contractVersion: 1,
12
+ contractVersion: ARTIFACT_REGISTRY.project.contractVersion,
13
13
  framework: projectProfile.framework,
14
14
  router: projectProfile.router,
15
15
  sourceRoot: projectProfile.sourceRoot,
@@ -1,30 +1,26 @@
1
- import crypto from 'crypto';
1
+ import { generateRunId as generateDeterministicRunId } from '../../verax/core/run-id.js';
2
2
 
3
- /**
4
- * Generate a run ID in format: <ISO_TIMESTAMP_UTC>_<6-8 char short hash>
5
- * Example: 2026-01-11T00-59-12Z_4f2a9c
6
- */
7
- export function generateRunId() {
8
- // Create ISO timestamp with colons replaced by dashes for filesystem compatibility
9
- const now = new Date();
10
- const isoString = now.toISOString();
11
- // Format: 2026-01-11T00:59:12.123Z -> 2026-01-11T00-59-12Z
12
- const timestamp = isoString.replace(/:/g, '-').replace(/\.\d+Z/, 'Z');
13
-
14
- // Generate a short hash (6-8 chars)
15
- const hash = crypto
16
- .randomBytes(4)
17
- .toString('hex')
18
- .substring(0, 6);
19
-
20
- return `${timestamp}_${hash}`;
21
- }
3
+ const ZERO_BUDGET = Object.freeze({
4
+ maxScanDurationMs: 0,
5
+ maxInteractionsPerPage: 0,
6
+ maxUniqueUrls: 0,
7
+ interactionTimeoutMs: 0,
8
+ navigationTimeoutMs: 0,
9
+ });
22
10
 
23
- /**
24
- * Validate a run ID format
25
- */
26
- export function isValidRunId(runId) {
27
- // Pattern: YYYY-MM-DDTHH-MM-SSZ_hexchars
28
- const pattern = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z_[a-f0-9]{6,8}$/;
29
- return pattern.test(runId);
11
+ // Deterministic run ID wrapper to align CLI with core generator (no time/randomness)
12
+ export function generateRunId(url = 'about:blank') {
13
+ let baseOrigin = 'about:blank';
14
+ try {
15
+ baseOrigin = new URL(url).origin;
16
+ } catch {
17
+ baseOrigin = url;
18
+ }
19
+ return generateDeterministicRunId({
20
+ url,
21
+ safetyFlags: {},
22
+ baseOrigin,
23
+ scanBudget: ZERO_BUDGET,
24
+ manifestPath: null,
25
+ });
30
26
  }