@veraxhq/verax 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +14 -18
  2. package/bin/verax.js +7 -0
  3. package/package.json +3 -3
  4. package/src/cli/commands/baseline.js +104 -0
  5. package/src/cli/commands/default.js +79 -25
  6. package/src/cli/commands/ga.js +243 -0
  7. package/src/cli/commands/gates.js +95 -0
  8. package/src/cli/commands/inspect.js +131 -2
  9. package/src/cli/commands/release-check.js +213 -0
  10. package/src/cli/commands/run.js +246 -35
  11. package/src/cli/commands/security-check.js +211 -0
  12. package/src/cli/commands/truth.js +114 -0
  13. package/src/cli/entry.js +304 -67
  14. package/src/cli/util/angular-component-extractor.js +179 -0
  15. package/src/cli/util/angular-navigation-detector.js +141 -0
  16. package/src/cli/util/angular-network-detector.js +161 -0
  17. package/src/cli/util/angular-state-detector.js +162 -0
  18. package/src/cli/util/ast-interactive-detector.js +546 -0
  19. package/src/cli/util/ast-network-detector.js +603 -0
  20. package/src/cli/util/ast-usestate-detector.js +602 -0
  21. package/src/cli/util/bootstrap-guard.js +86 -0
  22. package/src/cli/util/determinism-runner.js +123 -0
  23. package/src/cli/util/determinism-writer.js +129 -0
  24. package/src/cli/util/env-url.js +4 -0
  25. package/src/cli/util/expectation-extractor.js +369 -73
  26. package/src/cli/util/findings-writer.js +126 -16
  27. package/src/cli/util/learn-writer.js +3 -1
  28. package/src/cli/util/observe-writer.js +3 -1
  29. package/src/cli/util/paths.js +3 -12
  30. package/src/cli/util/project-discovery.js +3 -0
  31. package/src/cli/util/project-writer.js +3 -1
  32. package/src/cli/util/run-resolver.js +64 -0
  33. package/src/cli/util/source-requirement.js +55 -0
  34. package/src/cli/util/summary-writer.js +1 -0
  35. package/src/cli/util/svelte-navigation-detector.js +163 -0
  36. package/src/cli/util/svelte-network-detector.js +80 -0
  37. package/src/cli/util/svelte-sfc-extractor.js +147 -0
  38. package/src/cli/util/svelte-state-detector.js +243 -0
  39. package/src/cli/util/vue-navigation-detector.js +177 -0
  40. package/src/cli/util/vue-sfc-extractor.js +162 -0
  41. package/src/cli/util/vue-state-detector.js +215 -0
  42. package/src/verax/cli/finding-explainer.js +56 -3
  43. package/src/verax/core/artifacts/registry.js +154 -0
  44. package/src/verax/core/artifacts/verifier.js +980 -0
  45. package/src/verax/core/baseline/baseline.enforcer.js +137 -0
  46. package/src/verax/core/baseline/baseline.snapshot.js +231 -0
  47. package/src/verax/core/capabilities/gates.js +499 -0
  48. package/src/verax/core/capabilities/registry.js +475 -0
  49. package/src/verax/core/confidence/confidence-compute.js +137 -0
  50. package/src/verax/core/confidence/confidence-invariants.js +234 -0
  51. package/src/verax/core/confidence/confidence-report-writer.js +112 -0
  52. package/src/verax/core/confidence/confidence-weights.js +44 -0
  53. package/src/verax/core/confidence/confidence.defaults.js +65 -0
  54. package/src/verax/core/confidence/confidence.loader.js +79 -0
  55. package/src/verax/core/confidence/confidence.schema.js +94 -0
  56. package/src/verax/core/confidence-engine-refactor.js +484 -0
  57. package/src/verax/core/confidence-engine.js +486 -0
  58. package/src/verax/core/confidence-engine.js.backup +471 -0
  59. package/src/verax/core/contracts/index.js +29 -0
  60. package/src/verax/core/contracts/types.js +185 -0
  61. package/src/verax/core/contracts/validators.js +381 -0
  62. package/src/verax/core/decision-snapshot.js +30 -3
  63. package/src/verax/core/decisions/decision.trace.js +276 -0
  64. package/src/verax/core/determinism/contract-writer.js +89 -0
  65. package/src/verax/core/determinism/contract.js +139 -0
  66. package/src/verax/core/determinism/diff.js +364 -0
  67. package/src/verax/core/determinism/engine.js +221 -0
  68. package/src/verax/core/determinism/finding-identity.js +148 -0
  69. package/src/verax/core/determinism/normalize.js +438 -0
  70. package/src/verax/core/determinism/report-writer.js +92 -0
  71. package/src/verax/core/determinism/run-fingerprint.js +118 -0
  72. package/src/verax/core/dynamic-route-intelligence.js +528 -0
  73. package/src/verax/core/evidence/evidence-capture-service.js +307 -0
  74. package/src/verax/core/evidence/evidence-intent-ledger.js +165 -0
  75. package/src/verax/core/evidence-builder.js +487 -0
  76. package/src/verax/core/execution-mode-context.js +77 -0
  77. package/src/verax/core/execution-mode-detector.js +190 -0
  78. package/src/verax/core/failures/exit-codes.js +86 -0
  79. package/src/verax/core/failures/failure-summary.js +76 -0
  80. package/src/verax/core/failures/failure.factory.js +225 -0
  81. package/src/verax/core/failures/failure.ledger.js +132 -0
  82. package/src/verax/core/failures/failure.types.js +196 -0
  83. package/src/verax/core/failures/index.js +10 -0
  84. package/src/verax/core/ga/ga-report-writer.js +43 -0
  85. package/src/verax/core/ga/ga.artifact.js +49 -0
  86. package/src/verax/core/ga/ga.contract.js +434 -0
  87. package/src/verax/core/ga/ga.enforcer.js +86 -0
  88. package/src/verax/core/guardrails/guardrails-report-writer.js +109 -0
  89. package/src/verax/core/guardrails/policy.defaults.js +210 -0
  90. package/src/verax/core/guardrails/policy.loader.js +83 -0
  91. package/src/verax/core/guardrails/policy.schema.js +110 -0
  92. package/src/verax/core/guardrails/truth-reconciliation.js +136 -0
  93. package/src/verax/core/guardrails-engine.js +505 -0
  94. package/src/verax/core/observe/run-timeline.js +316 -0
  95. package/src/verax/core/perf/perf.contract.js +186 -0
  96. package/src/verax/core/perf/perf.display.js +65 -0
  97. package/src/verax/core/perf/perf.enforcer.js +91 -0
  98. package/src/verax/core/perf/perf.monitor.js +209 -0
  99. package/src/verax/core/perf/perf.report.js +198 -0
  100. package/src/verax/core/pipeline-tracker.js +238 -0
  101. package/src/verax/core/product-definition.js +127 -0
  102. package/src/verax/core/release/provenance.builder.js +271 -0
  103. package/src/verax/core/release/release-report-writer.js +40 -0
  104. package/src/verax/core/release/release.enforcer.js +159 -0
  105. package/src/verax/core/release/reproducibility.check.js +221 -0
  106. package/src/verax/core/release/sbom.builder.js +283 -0
  107. package/src/verax/core/report/cross-index.js +192 -0
  108. package/src/verax/core/report/human-summary.js +222 -0
  109. package/src/verax/core/route-intelligence.js +419 -0
  110. package/src/verax/core/security/secrets.scan.js +326 -0
  111. package/src/verax/core/security/security-report.js +50 -0
  112. package/src/verax/core/security/security.enforcer.js +124 -0
  113. package/src/verax/core/security/supplychain.defaults.json +38 -0
  114. package/src/verax/core/security/supplychain.policy.js +326 -0
  115. package/src/verax/core/security/vuln.scan.js +265 -0
  116. package/src/verax/core/truth/truth.certificate.js +250 -0
  117. package/src/verax/core/ui-feedback-intelligence.js +515 -0
  118. package/src/verax/detect/confidence-engine.js +628 -40
  119. package/src/verax/detect/confidence-helper.js +33 -0
  120. package/src/verax/detect/detection-engine.js +18 -1
  121. package/src/verax/detect/dynamic-route-findings.js +335 -0
  122. package/src/verax/detect/expectation-chain-detector.js +417 -0
  123. package/src/verax/detect/expectation-model.js +3 -1
  124. package/src/verax/detect/findings-writer.js +141 -5
  125. package/src/verax/detect/index.js +229 -5
  126. package/src/verax/detect/journey-stall-detector.js +558 -0
  127. package/src/verax/detect/route-findings.js +218 -0
  128. package/src/verax/detect/ui-feedback-findings.js +207 -0
  129. package/src/verax/detect/verdict-engine.js +57 -3
  130. package/src/verax/detect/view-switch-correlator.js +242 -0
  131. package/src/verax/index.js +413 -45
  132. package/src/verax/learn/action-contract-extractor.js +682 -64
  133. package/src/verax/learn/route-validator.js +4 -1
  134. package/src/verax/observe/index.js +88 -843
  135. package/src/verax/observe/interaction-runner.js +25 -8
  136. package/src/verax/observe/observe-context.js +205 -0
  137. package/src/verax/observe/observe-helpers.js +191 -0
  138. package/src/verax/observe/observe-runner.js +226 -0
  139. package/src/verax/observe/observers/budget-observer.js +185 -0
  140. package/src/verax/observe/observers/console-observer.js +102 -0
  141. package/src/verax/observe/observers/coverage-observer.js +107 -0
  142. package/src/verax/observe/observers/interaction-observer.js +471 -0
  143. package/src/verax/observe/observers/navigation-observer.js +132 -0
  144. package/src/verax/observe/observers/network-observer.js +87 -0
  145. package/src/verax/observe/observers/safety-observer.js +82 -0
  146. package/src/verax/observe/observers/ui-feedback-observer.js +99 -0
  147. package/src/verax/observe/ui-feedback-detector.js +742 -0
  148. package/src/verax/observe/ui-signal-sensor.js +148 -2
  149. package/src/verax/scan-summary-writer.js +42 -8
  150. package/src/verax/shared/artifact-manager.js +8 -5
  151. package/src/verax/shared/css-spinner-rules.js +204 -0
  152. package/src/verax/shared/view-switch-rules.js +208 -0
@@ -1,11 +1,21 @@
1
1
  import { readFileSync, existsSync } from 'fs';
2
- import { dirname, basename } from 'path';
2
+ import { dirname, basename, join } from 'path';
3
3
  import { expectsNavigation } from './expectation-model.js';
4
4
  import { hasMeaningfulUrlChange, hasVisibleChange, hasDomChange } from './comparison.js';
5
5
  import { writeFindings } from './findings-writer.js';
6
6
  import { getUrlPath } from './evidence-validator.js';
7
7
  import { classifySkipReason, collectSkipReasons } from './skip-classifier.js';
8
8
  import { detectInteractiveFindings } from './interactive-findings.js';
9
+ import { detectRouteFindings } from './route-findings.js';
10
+ import { detectUIFeedbackFindings } from './ui-feedback-findings.js';
11
+ import { detectDynamicRouteFindings } from './dynamic-route-findings.js';
12
+ import { addUnifiedConfidence } from './confidence-helper.js';
13
+ import { applyGuardrails } from '../core/guardrails-engine.js';
14
+ import { finalizeFindingTruth } from '../core/guardrails/truth-reconciliation.js';
15
+ import { writeGuardrailsReport } from '../core/guardrails/guardrails-report-writer.js';
16
+ import { computeFinalConfidence } from '../core/confidence/confidence-compute.js';
17
+ import { enforceConfidenceInvariants } from '../core/confidence/confidence-invariants.js';
18
+ import { writeConfidenceReport } from '../core/confidence/confidence-report-writer.js';
9
19
 
10
20
  /**
11
21
  * @param {string} manifestPath
@@ -221,7 +231,7 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
221
231
 
222
232
  if (expectationType === 'form_submission') {
223
233
  if (normalizedAfter !== normalizedTarget && !hasUrlChange && !hasDomChangeResult) {
224
- findings.push({
234
+ const finding = {
225
235
  type: 'silent_failure',
226
236
  interaction: {
227
237
  type: interaction.type,
@@ -235,7 +245,27 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
235
245
  beforeUrl: beforeUrl,
236
246
  afterUrl: afterUrl
237
247
  }
248
+ };
249
+
250
+ // PHASE 15: Add unified confidence
251
+ const findingWithConfidence = addUnifiedConfidence(finding, {
252
+ expectation: { targetPath: expectedTargetPath, type: expectationType },
253
+ sensors: trace.sensors || {},
254
+ comparisons: {
255
+ urlChanged: hasUrlChange,
256
+ domChanged: hasDomChangeResult,
257
+ },
258
+ evidence: {
259
+ beforeAfter: {
260
+ beforeScreenshot,
261
+ afterScreenshot,
262
+ beforeUrl,
263
+ afterUrl,
264
+ },
265
+ },
238
266
  });
267
+
268
+ findings.push(findingWithConfidence);
239
269
  }
240
270
  } else if (expectationType === 'navigation') {
241
271
  const urlMatchesTarget = normalizedAfter === normalizedTarget;
@@ -261,7 +291,7 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
261
291
  }
262
292
  } else {
263
293
  if (!hasUrlChange && !hasVisibleChangeResult && !hasDomChangeResult) {
264
- findings.push({
294
+ const finding = {
265
295
  type: 'silent_failure',
266
296
  interaction: {
267
297
  type: interaction.type,
@@ -275,7 +305,28 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
275
305
  beforeUrl: beforeUrl,
276
306
  afterUrl: afterUrl
277
307
  }
308
+ };
309
+
310
+ // PHASE 15: Add unified confidence
311
+ const findingWithConfidence = addUnifiedConfidence(finding, {
312
+ expectation: null,
313
+ sensors: trace.sensors || {},
314
+ comparisons: {
315
+ urlChanged: hasUrlChange,
316
+ domChanged: hasDomChangeResult,
317
+ visibleChanged: hasVisibleChangeResult,
318
+ },
319
+ evidence: {
320
+ beforeAfter: {
321
+ beforeScreenshot,
322
+ afterScreenshot,
323
+ beforeUrl,
324
+ afterUrl,
325
+ },
326
+ },
278
327
  });
328
+
329
+ findings.push(findingWithConfidence);
279
330
  }
280
331
  }
281
332
  }
@@ -283,16 +334,187 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
283
334
  // Interactive and accessibility intelligence
284
335
  detectInteractiveFindings(observation.traces, manifest, findings);
285
336
 
286
- // Infer canonical run directory from tracesPath when available
337
+ // PHASE 12: Route intelligence findings
338
+ const routeFindings = detectRouteFindings(observation.traces, manifest, findings);
339
+ findings.push(...routeFindings);
340
+
341
+ // PHASE 13: UI feedback findings
342
+ const uiFeedbackFindings = detectUIFeedbackFindings(observation.traces, manifest, findings);
343
+ findings.push(...uiFeedbackFindings);
344
+
345
+ // PHASE 14: Dynamic route findings
346
+ const dynamicRouteResult = detectDynamicRouteFindings(observation.traces, manifest, findings);
347
+ findings.push(...dynamicRouteResult.findings);
348
+ // Note: skips are handled separately and should be included in skip summary
349
+
350
+ // PHASE 23: Apply guardrails + truth reconciliation (AFTER evidence builder, BEFORE writing artifacts)
351
+ const guardrailsSummary = {
352
+ totalFindingsProcessed: 0,
353
+ preventedConfirmedCount: 0,
354
+ downgradedCount: 0,
355
+ informationalCount: 0,
356
+ };
357
+
358
+ const truthDecisions = {}; // Map of findingIdentity -> truthDecision
359
+
360
+ const findingsWithGuardrails = findings.map(finding => {
361
+ guardrailsSummary.totalFindingsProcessed++;
362
+
363
+ // Capture initial confidence before guardrails
364
+ const initialConfidence = finding.confidence || 0;
365
+ const initialConfidenceLevel = finding.confidenceLevel ||
366
+ (initialConfidence >= 0.8 ? 'HIGH' : initialConfidence >= 0.5 ? 'MEDIUM' : initialConfidence >= 0.2 ? 'LOW' : 'UNPROVEN');
367
+
368
+ // Build context for guardrails
369
+ const context = {
370
+ evidencePackage: finding.evidencePackage,
371
+ signals: finding.evidencePackage?.signals || finding.evidence || {},
372
+ confidenceReasons: finding.confidenceReasons || [],
373
+ promiseType: finding.expectation?.type || finding.promise?.type || null,
374
+ };
375
+
376
+ // Apply guardrails
377
+ const guardrailsResult = applyGuardrails(finding, context);
378
+
379
+ // Finalize truth (reconcile confidence with guardrails outcome)
380
+ const { finalFinding, truthDecision } = finalizeFindingTruth(
381
+ guardrailsResult.finding,
382
+ guardrailsResult,
383
+ {
384
+ initialConfidence,
385
+ initialConfidenceLevel
386
+ }
387
+ );
388
+
389
+ // Store truth decision for report
390
+ const findingIdentity = finalFinding.findingId || finalFinding.id || `finding-${findings.indexOf(finding)}`;
391
+ truthDecisions[findingIdentity] = truthDecision;
392
+
393
+ // Track guardrails impact
394
+ const originalSeverity = finding.severity || 'SUSPECTED';
395
+ const finalSeverity = truthDecision.finalStatus;
396
+
397
+ if (finalSeverity !== originalSeverity && originalSeverity === 'CONFIRMED') {
398
+ guardrailsSummary.preventedConfirmedCount++;
399
+ }
400
+ if (finalSeverity === 'SUSPECTED' && originalSeverity === 'CONFIRMED') {
401
+ guardrailsSummary.downgradedCount++;
402
+ }
403
+ if (finalSeverity === 'INFORMATIONAL') {
404
+ guardrailsSummary.informationalCount++;
405
+ }
406
+
407
+ return finalFinding;
408
+ });
409
+
410
+ // Replace findings with guardrails-applied + truth-reconciled findings
411
+ findings.length = 0;
412
+ findings.push(...findingsWithGuardrails);
413
+
414
+ // PHASE 24: Apply confidence invariants and compute final confidence
415
+ const confidenceData = {}; // Map of findingIdentity -> confidence computation result
416
+
417
+ // Load evidence intent if available
418
+ let evidenceIntentLedger = null;
287
419
  let runDir = null;
288
420
  try {
289
421
  runDir = dirname(tracesPath);
422
+ const evidenceIntentPath = join(runDir, 'evidence.intent.json');
423
+ if (existsSync(evidenceIntentPath)) {
424
+ try {
425
+ const intentContent = readFileSync(evidenceIntentPath, 'utf-8');
426
+ evidenceIntentLedger = JSON.parse(intentContent);
427
+ } catch {
428
+ // Ignore parse errors
429
+ }
430
+ }
290
431
  } catch {
291
432
  // Ignore path parsing errors
292
433
  }
434
+
435
+ const findingsWithConfidence = findings.map(finding => {
436
+ const findingIdentity = finding.findingId || finding.id || `finding-${findings.indexOf(finding)}`;
437
+
438
+ // Get evidence intent entry for this finding
439
+ const evidenceIntentEntry = evidenceIntentLedger?.entries?.find(e => e.findingIdentity === findingIdentity) || null;
440
+
441
+ // Get guardrails outcome
442
+ const guardrailsOutcome = finding.guardrails || truthDecisions[findingIdentity] || null;
443
+
444
+ // Compute final confidence
445
+ const confidenceResult = computeFinalConfidence({
446
+ findingType: finding.type || 'unknown',
447
+ rawSignals: finding.evidencePackage?.signals || finding.evidence || {},
448
+ evidenceIntent: evidenceIntentEntry,
449
+ guardrailsOutcome,
450
+ truthStatus: finding.severity || finding.status || 'SUSPECTED',
451
+ expectation: finding.expectation || null,
452
+ sensors: finding.evidencePackage?.signals || finding.evidence || {},
453
+ comparisons: {},
454
+ evidence: finding.evidence || {},
455
+ options: {
456
+ verificationStatus: null // Will be set by verifier
457
+ }
458
+ });
459
+
460
+ // Store confidence data for report
461
+ confidenceData[findingIdentity] = confidenceResult;
462
+
463
+ // Enforce invariants
464
+ const invariantResult = enforceConfidenceInvariants(finding, {
465
+ expectationProof: confidenceResult.expectationProof,
466
+ verificationStatus: confidenceResult.verificationStatus,
467
+ guardrailsOutcome
468
+ });
469
+
470
+ // Update finding with final confidence
471
+ const finalFinding = {
472
+ ...invariantResult.finding,
473
+ confidence: confidenceResult.confidenceAfter,
474
+ confidenceLevel: confidenceResult.confidenceLevel,
475
+ confidenceReasons: confidenceResult.explanation
476
+ };
477
+
478
+ return finalFinding;
479
+ });
480
+
481
+ // Replace findings with confidence-enforced findings
482
+ findings.length = 0;
483
+ findings.push(...findingsWithConfidence);
484
+
485
+ // Infer canonical run directory from tracesPath when available
486
+ if (!runDir) {
487
+ try {
488
+ runDir = dirname(tracesPath);
489
+ } catch {
490
+ // Ignore path parsing errors
491
+ }
492
+ }
293
493
 
294
494
  const findingsResult = writeFindings(projectDir, observation.url, findings, [], runDir);
295
495
 
496
+ // PHASE 23: Write guardrails report
497
+ let guardrailsReportPath = null;
498
+ if (runDir) {
499
+ try {
500
+ guardrailsReportPath = writeGuardrailsReport(runDir, findings, truthDecisions);
501
+ } catch (error) {
502
+ // Log but don't fail the run
503
+ console.error('Failed to write guardrails report:', error.message);
504
+ }
505
+ }
506
+
507
+ // PHASE 24: Write confidence report
508
+ let confidenceReportPath = null;
509
+ if (runDir) {
510
+ try {
511
+ confidenceReportPath = writeConfidenceReport(runDir, findings, confidenceData);
512
+ } catch (error) {
513
+ // Log but don't fail the run
514
+ console.error('Failed to write confidence report:', error.message);
515
+ }
516
+ }
517
+
296
518
  const skipSummary = collectSkipReasons(skips);
297
519
 
298
520
  const detectTruth = {
@@ -304,6 +526,8 @@ export async function detect(manifestPath, tracesPath, validation = null, _expec
304
526
 
305
527
  return {
306
528
  ...findingsResult,
307
- detectTruth: detectTruth
529
+ detectTruth: detectTruth,
530
+ guardrailsSummary: guardrailsSummary, // PHASE 17: Include guardrails summary
531
+ guardrailsReportPath: guardrailsReportPath // PHASE 23: Include guardrails report path
308
532
  };
309
533
  }