@veraxhq/verax 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -18
- package/bin/verax.js +7 -0
- package/package.json +15 -5
- package/src/cli/commands/baseline.js +104 -0
- package/src/cli/commands/default.js +323 -111
- package/src/cli/commands/doctor.js +36 -4
- package/src/cli/commands/ga.js +243 -0
- package/src/cli/commands/gates.js +95 -0
- package/src/cli/commands/inspect.js +131 -2
- package/src/cli/commands/release-check.js +213 -0
- package/src/cli/commands/run.js +498 -103
- package/src/cli/commands/security-check.js +211 -0
- package/src/cli/commands/truth.js +114 -0
- package/src/cli/entry.js +305 -68
- package/src/cli/util/angular-component-extractor.js +179 -0
- package/src/cli/util/angular-navigation-detector.js +141 -0
- package/src/cli/util/angular-network-detector.js +161 -0
- package/src/cli/util/angular-state-detector.js +162 -0
- package/src/cli/util/ast-interactive-detector.js +546 -0
- package/src/cli/util/ast-network-detector.js +603 -0
- package/src/cli/util/ast-usestate-detector.js +602 -0
- package/src/cli/util/bootstrap-guard.js +86 -0
- package/src/cli/util/detection-engine.js +4 -3
- package/src/cli/util/determinism-runner.js +123 -0
- package/src/cli/util/determinism-writer.js +129 -0
- package/src/cli/util/env-url.js +4 -0
- package/src/cli/util/events.js +76 -0
- package/src/cli/util/expectation-extractor.js +380 -74
- package/src/cli/util/findings-writer.js +126 -15
- package/src/cli/util/learn-writer.js +3 -1
- package/src/cli/util/observation-engine.js +69 -23
- package/src/cli/util/observe-writer.js +3 -1
- package/src/cli/util/paths.js +6 -14
- package/src/cli/util/project-discovery.js +23 -0
- package/src/cli/util/project-writer.js +3 -1
- package/src/cli/util/redact.js +2 -2
- package/src/cli/util/run-resolver.js +64 -0
- package/src/cli/util/runtime-budget.js +147 -0
- package/src/cli/util/source-requirement.js +55 -0
- package/src/cli/util/summary-writer.js +13 -1
- package/src/cli/util/svelte-navigation-detector.js +163 -0
- package/src/cli/util/svelte-network-detector.js +80 -0
- package/src/cli/util/svelte-sfc-extractor.js +147 -0
- package/src/cli/util/svelte-state-detector.js +243 -0
- package/src/cli/util/vue-navigation-detector.js +177 -0
- package/src/cli/util/vue-sfc-extractor.js +162 -0
- package/src/cli/util/vue-state-detector.js +215 -0
- package/src/types/global.d.ts +28 -0
- package/src/types/ts-ast.d.ts +24 -0
- package/src/verax/cli/doctor.js +2 -2
- package/src/verax/cli/finding-explainer.js +56 -3
- package/src/verax/cli/init.js +1 -1
- package/src/verax/cli/url-safety.js +12 -2
- package/src/verax/cli/wizard.js +13 -2
- package/src/verax/core/artifacts/registry.js +154 -0
- package/src/verax/core/artifacts/verifier.js +980 -0
- package/src/verax/core/baseline/baseline.enforcer.js +137 -0
- package/src/verax/core/baseline/baseline.snapshot.js +231 -0
- package/src/verax/core/budget-engine.js +1 -1
- package/src/verax/core/capabilities/gates.js +499 -0
- package/src/verax/core/capabilities/registry.js +475 -0
- package/src/verax/core/confidence/confidence-compute.js +137 -0
- package/src/verax/core/confidence/confidence-invariants.js +234 -0
- package/src/verax/core/confidence/confidence-report-writer.js +112 -0
- package/src/verax/core/confidence/confidence-weights.js +44 -0
- package/src/verax/core/confidence/confidence.defaults.js +65 -0
- package/src/verax/core/confidence/confidence.loader.js +79 -0
- package/src/verax/core/confidence/confidence.schema.js +94 -0
- package/src/verax/core/confidence-engine-refactor.js +484 -0
- package/src/verax/core/confidence-engine.js +486 -0
- package/src/verax/core/confidence-engine.js.backup +471 -0
- package/src/verax/core/contracts/index.js +29 -0
- package/src/verax/core/contracts/types.js +185 -0
- package/src/verax/core/contracts/validators.js +381 -0
- package/src/verax/core/decision-snapshot.js +31 -4
- package/src/verax/core/decisions/decision.trace.js +276 -0
- package/src/verax/core/determinism/contract-writer.js +89 -0
- package/src/verax/core/determinism/contract.js +139 -0
- package/src/verax/core/determinism/diff.js +364 -0
- package/src/verax/core/determinism/engine.js +221 -0
- package/src/verax/core/determinism/finding-identity.js +148 -0
- package/src/verax/core/determinism/normalize.js +438 -0
- package/src/verax/core/determinism/report-writer.js +92 -0
- package/src/verax/core/determinism/run-fingerprint.js +118 -0
- package/src/verax/core/determinism-model.js +35 -6
- package/src/verax/core/dynamic-route-intelligence.js +528 -0
- package/src/verax/core/evidence/evidence-capture-service.js +307 -0
- package/src/verax/core/evidence/evidence-intent-ledger.js +165 -0
- package/src/verax/core/evidence-builder.js +487 -0
- package/src/verax/core/execution-mode-context.js +77 -0
- package/src/verax/core/execution-mode-detector.js +190 -0
- package/src/verax/core/failures/exit-codes.js +86 -0
- package/src/verax/core/failures/failure-summary.js +76 -0
- package/src/verax/core/failures/failure.factory.js +225 -0
- package/src/verax/core/failures/failure.ledger.js +132 -0
- package/src/verax/core/failures/failure.types.js +196 -0
- package/src/verax/core/failures/index.js +10 -0
- package/src/verax/core/ga/ga-report-writer.js +43 -0
- package/src/verax/core/ga/ga.artifact.js +49 -0
- package/src/verax/core/ga/ga.contract.js +434 -0
- package/src/verax/core/ga/ga.enforcer.js +86 -0
- package/src/verax/core/guardrails/guardrails-report-writer.js +109 -0
- package/src/verax/core/guardrails/policy.defaults.js +210 -0
- package/src/verax/core/guardrails/policy.loader.js +83 -0
- package/src/verax/core/guardrails/policy.schema.js +110 -0
- package/src/verax/core/guardrails/truth-reconciliation.js +136 -0
- package/src/verax/core/guardrails-engine.js +505 -0
- package/src/verax/core/incremental-store.js +15 -7
- package/src/verax/core/observe/run-timeline.js +316 -0
- package/src/verax/core/perf/perf.contract.js +186 -0
- package/src/verax/core/perf/perf.display.js +65 -0
- package/src/verax/core/perf/perf.enforcer.js +91 -0
- package/src/verax/core/perf/perf.monitor.js +209 -0
- package/src/verax/core/perf/perf.report.js +198 -0
- package/src/verax/core/pipeline-tracker.js +238 -0
- package/src/verax/core/product-definition.js +127 -0
- package/src/verax/core/release/provenance.builder.js +271 -0
- package/src/verax/core/release/release-report-writer.js +40 -0
- package/src/verax/core/release/release.enforcer.js +159 -0
- package/src/verax/core/release/reproducibility.check.js +221 -0
- package/src/verax/core/release/sbom.builder.js +283 -0
- package/src/verax/core/replay-validator.js +4 -4
- package/src/verax/core/replay.js +1 -1
- package/src/verax/core/report/cross-index.js +192 -0
- package/src/verax/core/report/human-summary.js +222 -0
- package/src/verax/core/route-intelligence.js +419 -0
- package/src/verax/core/security/secrets.scan.js +326 -0
- package/src/verax/core/security/security-report.js +50 -0
- package/src/verax/core/security/security.enforcer.js +124 -0
- package/src/verax/core/security/supplychain.defaults.json +38 -0
- package/src/verax/core/security/supplychain.policy.js +326 -0
- package/src/verax/core/security/vuln.scan.js +265 -0
- package/src/verax/core/silence-impact.js +1 -1
- package/src/verax/core/silence-model.js +9 -7
- package/src/verax/core/truth/truth.certificate.js +250 -0
- package/src/verax/core/ui-feedback-intelligence.js +515 -0
- package/src/verax/detect/comparison.js +8 -3
- package/src/verax/detect/confidence-engine.js +645 -57
- package/src/verax/detect/confidence-helper.js +33 -0
- package/src/verax/detect/detection-engine.js +19 -2
- package/src/verax/detect/dynamic-route-findings.js +335 -0
- package/src/verax/detect/evidence-index.js +15 -65
- package/src/verax/detect/expectation-chain-detector.js +417 -0
- package/src/verax/detect/expectation-model.js +56 -3
- package/src/verax/detect/explanation-helpers.js +1 -1
- package/src/verax/detect/finding-detector.js +2 -2
- package/src/verax/detect/findings-writer.js +149 -20
- package/src/verax/detect/flow-detector.js +4 -4
- package/src/verax/detect/index.js +265 -15
- package/src/verax/detect/interactive-findings.js +3 -4
- package/src/verax/detect/journey-stall-detector.js +558 -0
- package/src/verax/detect/route-findings.js +218 -0
- package/src/verax/detect/signal-mapper.js +2 -2
- package/src/verax/detect/skip-classifier.js +4 -4
- package/src/verax/detect/ui-feedback-findings.js +207 -0
- package/src/verax/detect/verdict-engine.js +61 -9
- package/src/verax/detect/view-switch-correlator.js +242 -0
- package/src/verax/flow/flow-engine.js +3 -2
- package/src/verax/flow/flow-spec.js +1 -2
- package/src/verax/index.js +413 -33
- package/src/verax/intel/effect-detector.js +1 -1
- package/src/verax/intel/index.js +2 -2
- package/src/verax/intel/route-extractor.js +3 -3
- package/src/verax/intel/vue-navigation-extractor.js +81 -18
- package/src/verax/intel/vue-router-extractor.js +4 -2
- package/src/verax/learn/action-contract-extractor.js +684 -66
- package/src/verax/learn/ast-contract-extractor.js +53 -1
- package/src/verax/learn/index.js +36 -2
- package/src/verax/learn/manifest-writer.js +28 -14
- package/src/verax/learn/route-extractor.js +1 -1
- package/src/verax/learn/route-validator.js +12 -8
- package/src/verax/learn/state-extractor.js +1 -1
- package/src/verax/learn/static-extractor-navigation.js +1 -1
- package/src/verax/learn/static-extractor-validation.js +2 -2
- package/src/verax/learn/static-extractor.js +8 -7
- package/src/verax/learn/ts-contract-resolver.js +14 -12
- package/src/verax/observe/browser.js +22 -3
- package/src/verax/observe/console-sensor.js +2 -2
- package/src/verax/observe/expectation-executor.js +2 -1
- package/src/verax/observe/focus-sensor.js +1 -1
- package/src/verax/observe/human-driver.js +29 -10
- package/src/verax/observe/index.js +92 -844
- package/src/verax/observe/interaction-discovery.js +27 -15
- package/src/verax/observe/interaction-runner.js +31 -14
- package/src/verax/observe/loading-sensor.js +6 -0
- package/src/verax/observe/navigation-sensor.js +1 -1
- package/src/verax/observe/observe-context.js +205 -0
- package/src/verax/observe/observe-helpers.js +191 -0
- package/src/verax/observe/observe-runner.js +226 -0
- package/src/verax/observe/observers/budget-observer.js +185 -0
- package/src/verax/observe/observers/console-observer.js +102 -0
- package/src/verax/observe/observers/coverage-observer.js +107 -0
- package/src/verax/observe/observers/interaction-observer.js +471 -0
- package/src/verax/observe/observers/navigation-observer.js +132 -0
- package/src/verax/observe/observers/network-observer.js +87 -0
- package/src/verax/observe/observers/safety-observer.js +82 -0
- package/src/verax/observe/observers/ui-feedback-observer.js +99 -0
- package/src/verax/observe/settle.js +1 -0
- package/src/verax/observe/state-sensor.js +8 -4
- package/src/verax/observe/state-ui-sensor.js +7 -1
- package/src/verax/observe/traces-writer.js +27 -16
- package/src/verax/observe/ui-feedback-detector.js +742 -0
- package/src/verax/observe/ui-signal-sensor.js +155 -2
- package/src/verax/scan-summary-writer.js +46 -9
- package/src/verax/shared/artifact-manager.js +9 -6
- package/src/verax/shared/budget-profiles.js +2 -2
- package/src/verax/shared/caching.js +1 -1
- package/src/verax/shared/config-loader.js +1 -2
- package/src/verax/shared/css-spinner-rules.js +204 -0
- package/src/verax/shared/dynamic-route-utils.js +12 -6
- package/src/verax/shared/retry-policy.js +1 -6
- package/src/verax/shared/root-artifacts.js +1 -1
- package/src/verax/shared/view-switch-rules.js +208 -0
- package/src/verax/shared/zip-artifacts.js +1 -0
- package/src/verax/validate/context-validator.js +1 -1
- package/src/verax/observe/index.js.backup +0 -1
- package/src/verax/validate/context-validator.js.bak +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHASE 20 — Vue State Promise Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects ref/reactive mutations that are UI-bound:
|
|
5
|
+
* - ref declarations: const count = ref(0);
|
|
6
|
+
* - reactive: const state = reactive({ x: 1 });
|
|
7
|
+
* - Only emit if identifiers are used in template bindings
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { parse } from '@babel/parser';
|
|
11
|
+
import _traverse from '@babel/traverse';
|
|
12
|
+
|
|
13
|
+
const traverse = _traverse.default || _traverse;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* PHASE 20: Detect Vue state promises
|
|
17
|
+
*
|
|
18
|
+
* @param {string} scriptContent - Script block content
|
|
19
|
+
* @param {string} filePath - File path
|
|
20
|
+
* @param {string} relPath - Relative path
|
|
21
|
+
* @param {Object} scriptBlock - Script block metadata
|
|
22
|
+
* @param {Object} templateBindings - Template bindings
|
|
23
|
+
* @returns {Array} State promises
|
|
24
|
+
*/
|
|
25
|
+
export function detectVueStatePromises(scriptContent, filePath, relPath, scriptBlock, templateBindings) {
|
|
26
|
+
const promises = [];
|
|
27
|
+
const templateVars = new Set(templateBindings.bindings || []);
|
|
28
|
+
|
|
29
|
+
if (templateVars.size === 0) {
|
|
30
|
+
return promises; // No template bindings, skip
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const ast = parse(scriptContent, {
|
|
35
|
+
sourceType: 'module',
|
|
36
|
+
plugins: [
|
|
37
|
+
'typescript',
|
|
38
|
+
'classProperties',
|
|
39
|
+
'optionalChaining',
|
|
40
|
+
'nullishCoalescingOperator',
|
|
41
|
+
'dynamicImport',
|
|
42
|
+
'topLevelAwait',
|
|
43
|
+
'objectRestSpread',
|
|
44
|
+
],
|
|
45
|
+
errorRecovery: true,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const lines = scriptContent.split('\n');
|
|
49
|
+
const refDeclarations = new Map(); // varName -> { loc, astSource }
|
|
50
|
+
const reactiveDeclarations = new Map();
|
|
51
|
+
|
|
52
|
+
traverse(ast, {
|
|
53
|
+
// Detect ref() declarations
|
|
54
|
+
VariableDeclarator(path) {
|
|
55
|
+
const node = path.node;
|
|
56
|
+
const init = node.init;
|
|
57
|
+
|
|
58
|
+
if (init && init.type === 'CallExpression') {
|
|
59
|
+
const callee = init.callee;
|
|
60
|
+
|
|
61
|
+
// ref(0) or ref({})
|
|
62
|
+
if (callee.type === 'Identifier' && callee.name === 'ref') {
|
|
63
|
+
const varName = node.id.name;
|
|
64
|
+
if (templateVars.has(varName)) {
|
|
65
|
+
const loc = node.loc;
|
|
66
|
+
const line = loc ? loc.start.line : 1;
|
|
67
|
+
const astSource = lines.slice(line - 1, loc ? loc.end.line : line)
|
|
68
|
+
.join('\n')
|
|
69
|
+
.substring(0, 200);
|
|
70
|
+
|
|
71
|
+
refDeclarations.set(varName, {
|
|
72
|
+
loc,
|
|
73
|
+
astSource,
|
|
74
|
+
line,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// reactive({})
|
|
80
|
+
if (callee.type === 'Identifier' && callee.name === 'reactive') {
|
|
81
|
+
const varName = node.id.name;
|
|
82
|
+
if (templateVars.has(varName)) {
|
|
83
|
+
const loc = node.loc;
|
|
84
|
+
const line = loc ? loc.start.line : 1;
|
|
85
|
+
const astSource = lines.slice(line - 1, loc ? loc.end.line : line)
|
|
86
|
+
.join('\n')
|
|
87
|
+
.substring(0, 200);
|
|
88
|
+
|
|
89
|
+
reactiveDeclarations.set(varName, {
|
|
90
|
+
loc,
|
|
91
|
+
astSource,
|
|
92
|
+
line,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
// Detect mutations: count.value = ... or state.x = ...
|
|
100
|
+
AssignmentExpression(path) {
|
|
101
|
+
const node = path.node;
|
|
102
|
+
const left = node.left;
|
|
103
|
+
|
|
104
|
+
// count.value = ...
|
|
105
|
+
if (left.type === 'MemberExpression' &&
|
|
106
|
+
left.property.name === 'value' &&
|
|
107
|
+
left.object.type === 'Identifier') {
|
|
108
|
+
const varName = left.object.name;
|
|
109
|
+
|
|
110
|
+
if (refDeclarations.has(varName) && templateVars.has(varName)) {
|
|
111
|
+
const decl = refDeclarations.get(varName);
|
|
112
|
+
const loc = node.loc;
|
|
113
|
+
const line = loc ? loc.start.line : 1;
|
|
114
|
+
const column = loc ? loc.start.column : 0;
|
|
115
|
+
|
|
116
|
+
const astSource = lines.slice(line - 1, loc ? loc.end.line : line)
|
|
117
|
+
.join('\n')
|
|
118
|
+
.substring(0, 200);
|
|
119
|
+
|
|
120
|
+
const context = buildContext(path);
|
|
121
|
+
|
|
122
|
+
promises.push({
|
|
123
|
+
type: 'state',
|
|
124
|
+
promise: {
|
|
125
|
+
kind: 'state-change',
|
|
126
|
+
value: `${varName}.value`,
|
|
127
|
+
stateVar: varName,
|
|
128
|
+
},
|
|
129
|
+
source: {
|
|
130
|
+
file: relPath,
|
|
131
|
+
line,
|
|
132
|
+
column,
|
|
133
|
+
context,
|
|
134
|
+
astSource,
|
|
135
|
+
},
|
|
136
|
+
confidence: 0.9,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// state.x = ...
|
|
142
|
+
if (left.type === 'MemberExpression' &&
|
|
143
|
+
left.object.type === 'Identifier') {
|
|
144
|
+
const varName = left.object.name;
|
|
145
|
+
|
|
146
|
+
if (reactiveDeclarations.has(varName) && templateVars.has(varName)) {
|
|
147
|
+
const loc = node.loc;
|
|
148
|
+
const line = loc ? loc.start.line : 1;
|
|
149
|
+
const column = loc ? loc.start.column : 0;
|
|
150
|
+
|
|
151
|
+
const astSource = lines.slice(line - 1, loc ? loc.end.line : line)
|
|
152
|
+
.join('\n')
|
|
153
|
+
.substring(0, 200);
|
|
154
|
+
|
|
155
|
+
const context = buildContext(path);
|
|
156
|
+
const propName = left.property.name || '<property>';
|
|
157
|
+
|
|
158
|
+
promises.push({
|
|
159
|
+
type: 'state',
|
|
160
|
+
promise: {
|
|
161
|
+
kind: 'state-change',
|
|
162
|
+
value: `${varName}.${propName}`,
|
|
163
|
+
stateVar: varName,
|
|
164
|
+
},
|
|
165
|
+
source: {
|
|
166
|
+
file: relPath,
|
|
167
|
+
line,
|
|
168
|
+
column,
|
|
169
|
+
context,
|
|
170
|
+
astSource,
|
|
171
|
+
},
|
|
172
|
+
confidence: 0.9,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
} catch (error) {
|
|
179
|
+
// Parse error - skip
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return promises;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Build context chain from AST path
|
|
187
|
+
*/
|
|
188
|
+
function buildContext(path) {
|
|
189
|
+
const context = [];
|
|
190
|
+
let current = path;
|
|
191
|
+
|
|
192
|
+
while (current) {
|
|
193
|
+
if (current.isFunctionDeclaration()) {
|
|
194
|
+
context.push({
|
|
195
|
+
type: 'function',
|
|
196
|
+
name: current.node.id?.name || '<anonymous>',
|
|
197
|
+
});
|
|
198
|
+
} else if (current.isArrowFunctionExpression()) {
|
|
199
|
+
context.push({
|
|
200
|
+
type: 'arrow-function',
|
|
201
|
+
name: '<arrow>',
|
|
202
|
+
});
|
|
203
|
+
} else if (current.isMethodDefinition()) {
|
|
204
|
+
context.push({
|
|
205
|
+
type: 'method',
|
|
206
|
+
name: current.node.key?.name || '<method>',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
current = current.parentPath;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return context.reverse().map(c => `${c.type}:${c.name}`).join(' > ');
|
|
214
|
+
}
|
|
215
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global type declarations for VERAX
|
|
3
|
+
* These extend built-in types to support runtime-injected properties
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Extend Window interface for browser-injected properties
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
__veraxNavTracking?: any;
|
|
10
|
+
next?: any;
|
|
11
|
+
__REDUX_STORE__?: any;
|
|
12
|
+
store?: any;
|
|
13
|
+
__REDUX_DEVTOOLS_EXTENSION__?: any;
|
|
14
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__?: any;
|
|
15
|
+
__VERAX_STATE_SENSOR__?: any;
|
|
16
|
+
__unhandledRejections?: any[];
|
|
17
|
+
__ZUSTAND_STORE__?: any;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Playwright Page type (imported from playwright)
|
|
22
|
+
import type { Page as PlaywrightPage } from 'playwright';
|
|
23
|
+
|
|
24
|
+
// Re-export for use in JS files
|
|
25
|
+
export type Page = PlaywrightPage;
|
|
26
|
+
|
|
27
|
+
export {};
|
|
28
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript AST Node type extensions
|
|
3
|
+
* These extend the base Node type to include properties used by VERAX
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type * as ts from 'typescript';
|
|
7
|
+
|
|
8
|
+
declare module 'typescript' {
|
|
9
|
+
interface Node {
|
|
10
|
+
attributes?: ts.NodeArray<ts.JSDocAttribute>;
|
|
11
|
+
tagName?: ts.Identifier;
|
|
12
|
+
body?: ts.Node;
|
|
13
|
+
arguments?: ts.NodeArray<ts.Expression>;
|
|
14
|
+
initializer?: ts.Expression;
|
|
15
|
+
expression?: ts.Expression;
|
|
16
|
+
children?: ts.NodeArray<ts.Node>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
namespace ts {
|
|
20
|
+
// Add isFalseKeyword if it doesn't exist (it might be in a different version)
|
|
21
|
+
function isFalseKeyword(node: ts.Node): node is ts.FalseKeyword;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
package/src/verax/cli/doctor.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Checks environment, dependencies, and project setup.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { mkdirSync, writeFileSync, unlinkSync } from 'fs';
|
|
8
8
|
import { resolve } from 'path';
|
|
9
9
|
import { chromium } from 'playwright';
|
|
10
10
|
import { get } from 'http';
|
|
@@ -182,7 +182,7 @@ async function checkUrlReachability(url) {
|
|
|
182
182
|
* @returns {Promise<Object>} Doctor results
|
|
183
183
|
*/
|
|
184
184
|
export async function runDoctor(options = {}) {
|
|
185
|
-
const { projectRoot = process.cwd(), url = null, json = false } = options;
|
|
185
|
+
const { projectRoot = process.cwd(), url = null, json: _json = false } = options;
|
|
186
186
|
|
|
187
187
|
const checks = [];
|
|
188
188
|
let overallStatus = 'ok';
|
|
@@ -14,11 +14,22 @@
|
|
|
14
14
|
export function formatFinding(finding, expectation = null) {
|
|
15
15
|
const lines = [];
|
|
16
16
|
|
|
17
|
-
// Finding type and confidence
|
|
18
|
-
const confidenceLevel = finding.confidence?.level || '
|
|
19
|
-
const confidenceScore = finding.confidence
|
|
17
|
+
// PHASE 15: Finding type and unified confidence
|
|
18
|
+
const confidenceLevel = finding.confidenceLevel || finding.confidence?.level || 'UNPROVEN';
|
|
19
|
+
const confidenceScore = finding.confidence !== undefined
|
|
20
|
+
? (finding.confidence <= 1 ? Math.round(finding.confidence * 100) : finding.confidence)
|
|
21
|
+
: (finding.confidence?.score || 0);
|
|
22
|
+
const confidenceReasons = finding.confidenceReasons || [];
|
|
23
|
+
|
|
20
24
|
lines.push(` [${confidenceLevel} (${confidenceScore}%)] ${finding.type || 'unknown'}`);
|
|
21
25
|
|
|
26
|
+
// PHASE 15: Show top confidence reasons
|
|
27
|
+
if (confidenceReasons.length > 0) {
|
|
28
|
+
const topReasons = confidenceReasons.slice(0, 3);
|
|
29
|
+
const reasonText = topReasons.join(', ');
|
|
30
|
+
lines.push(` └─ Confidence: ${reasonText}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
// Expectation (what was promised)
|
|
23
34
|
if (expectation) {
|
|
24
35
|
let expectationDesc = '';
|
|
@@ -84,6 +95,48 @@ export function formatFinding(finding, expectation = null) {
|
|
|
84
95
|
lines.push(` └─ Source: ${expectation.source.file}${sourceLine}`);
|
|
85
96
|
}
|
|
86
97
|
|
|
98
|
+
// PHASE 16: Show evidence completeness
|
|
99
|
+
if (finding.evidencePackage) {
|
|
100
|
+
if (finding.evidencePackage.isComplete) {
|
|
101
|
+
lines.push(` └─ Evidence: Complete`);
|
|
102
|
+
} else {
|
|
103
|
+
lines.push(` └─ Evidence: Incomplete (missing: ${finding.evidencePackage.missingEvidence.join(', ')})`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// PHASE 16: Show downgrade reason if evidence was incomplete
|
|
108
|
+
if (finding.evidenceCompleteness?.downgraded) {
|
|
109
|
+
lines.push(` └─ Downgraded: ${finding.evidenceCompleteness.downgradeReason}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// PHASE 17/23: Show guardrails applied and reconciliation
|
|
113
|
+
if (finding.guardrails) {
|
|
114
|
+
const guardrails = finding.guardrails;
|
|
115
|
+
if (guardrails.appliedRules && guardrails.appliedRules.length > 0) {
|
|
116
|
+
const ruleCodes = guardrails.appliedRules.map(r => r.code || r.ruleId).filter(Boolean);
|
|
117
|
+
if (ruleCodes.length > 0) {
|
|
118
|
+
lines.push(` └─ Final status due to guardrails: ${ruleCodes.join(', ')}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (guardrails.contradictions && guardrails.contradictions.length > 0) {
|
|
122
|
+
lines.push(` └─ Contradiction: ${guardrails.contradictions[0].message}`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// PHASE 23: Show confidence reconciliation if present
|
|
126
|
+
if (guardrails.reconciliation) {
|
|
127
|
+
const recon = guardrails.reconciliation;
|
|
128
|
+
if (recon.confidenceBefore !== recon.confidenceAfter) {
|
|
129
|
+
const beforePercent = Math.round(recon.confidenceBefore * 100);
|
|
130
|
+
const afterPercent = Math.round(recon.confidenceAfter * 100);
|
|
131
|
+
lines.push(` └─ Confidence: ${beforePercent}% → ${afterPercent}% (${recon.confidenceLevelBefore} → ${recon.confidenceLevelAfter})`);
|
|
132
|
+
}
|
|
133
|
+
if (recon.reconciliationReasons && recon.reconciliationReasons.length > 0) {
|
|
134
|
+
const topReasons = recon.reconciliationReasons.slice(0, 2);
|
|
135
|
+
lines.push(` └─ Reconciliation: ${topReasons.join(', ')}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
87
140
|
return lines.join('\n');
|
|
88
141
|
}
|
|
89
142
|
|
package/src/verax/cli/init.js
CHANGED
|
@@ -68,11 +68,21 @@ export function checkUrlSafety(url) {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* @typedef {Object} ReadlineInterface
|
|
73
|
+
* @property {function(string): Promise<string>} question - Prompt user with question
|
|
74
|
+
* @property {function(): void} close - Close the readline interface
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @typedef {Object} ConfirmExternalUrlOptions
|
|
79
|
+
* @property {ReadlineInterface} [readlineInterface] - Readline interface (injectable)
|
|
80
|
+
*/
|
|
81
|
+
|
|
71
82
|
/**
|
|
72
83
|
* Prompt for external URL confirmation
|
|
73
84
|
* @param {string} hostname - Hostname to confirm
|
|
74
|
-
* @param {
|
|
75
|
-
* @param {Function} options.readlineInterface - Readline interface (injectable)
|
|
85
|
+
* @param {ConfirmExternalUrlOptions} [options={}] - Options
|
|
76
86
|
* @returns {Promise<boolean>} True if confirmed
|
|
77
87
|
*/
|
|
78
88
|
export async function confirmExternalUrl(hostname, options = {}) {
|
package/src/verax/cli/wizard.js
CHANGED
|
@@ -4,8 +4,15 @@
|
|
|
4
4
|
* Guides users through VERAX configuration with friendly prompts.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} ReadlineInterface
|
|
9
|
+
* @property {function(string): Promise<string>} question - Prompt user with question
|
|
10
|
+
* @property {function(): void} close - Close the readline interface
|
|
11
|
+
*/
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
14
|
* Create a readline interface (can be injected for testing)
|
|
15
|
+
* @returns {Promise<ReadlineInterface>}
|
|
9
16
|
*/
|
|
10
17
|
async function createReadlineInterface(input = process.stdin, output = process.stdout) {
|
|
11
18
|
const readline = await import('readline/promises');
|
|
@@ -16,10 +23,14 @@ async function createReadlineInterface(input = process.stdin, output = process.s
|
|
|
16
23
|
});
|
|
17
24
|
}
|
|
18
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {Object} WizardOptions
|
|
28
|
+
* @property {ReadlineInterface} [readlineInterface] - Readline interface (injectable for testing)
|
|
29
|
+
*/
|
|
30
|
+
|
|
19
31
|
/**
|
|
20
32
|
* Run interactive wizard
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {Function} options.readlineInterface - Readline interface (injectable for testing)
|
|
33
|
+
* @param {WizardOptions} [options={}] - Options for wizard
|
|
23
34
|
* @returns {Promise<Object>} Wizard results
|
|
24
35
|
*/
|
|
25
36
|
export async function runWizard(options = {}) {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
|
|
3
|
+
export const ARTIFACT_REGISTRY = {
|
|
4
|
+
runStatus: {
|
|
5
|
+
key: 'runStatus',
|
|
6
|
+
filename: 'run.status.json',
|
|
7
|
+
stage: 'init',
|
|
8
|
+
contractVersion: 1,
|
|
9
|
+
type: 'file'
|
|
10
|
+
},
|
|
11
|
+
runMeta: {
|
|
12
|
+
key: 'runMeta',
|
|
13
|
+
filename: 'run.meta.json',
|
|
14
|
+
stage: 'init',
|
|
15
|
+
contractVersion: 1,
|
|
16
|
+
type: 'file'
|
|
17
|
+
},
|
|
18
|
+
summary: {
|
|
19
|
+
key: 'summary',
|
|
20
|
+
filename: 'summary.json',
|
|
21
|
+
stage: 'finalize',
|
|
22
|
+
contractVersion: 1,
|
|
23
|
+
type: 'file'
|
|
24
|
+
},
|
|
25
|
+
findings: {
|
|
26
|
+
key: 'findings',
|
|
27
|
+
filename: 'findings.json',
|
|
28
|
+
stage: 'detect',
|
|
29
|
+
contractVersion: 1,
|
|
30
|
+
type: 'file'
|
|
31
|
+
},
|
|
32
|
+
learn: {
|
|
33
|
+
key: 'learn',
|
|
34
|
+
filename: 'learn.json',
|
|
35
|
+
stage: 'learn',
|
|
36
|
+
contractVersion: 1,
|
|
37
|
+
type: 'file'
|
|
38
|
+
},
|
|
39
|
+
observe: {
|
|
40
|
+
key: 'observe',
|
|
41
|
+
filename: 'observe.json',
|
|
42
|
+
stage: 'observe',
|
|
43
|
+
contractVersion: 1,
|
|
44
|
+
type: 'file'
|
|
45
|
+
},
|
|
46
|
+
project: {
|
|
47
|
+
key: 'project',
|
|
48
|
+
filename: 'project.json',
|
|
49
|
+
stage: 'init',
|
|
50
|
+
contractVersion: 1,
|
|
51
|
+
type: 'file'
|
|
52
|
+
},
|
|
53
|
+
traces: {
|
|
54
|
+
key: 'traces',
|
|
55
|
+
filename: 'traces.jsonl',
|
|
56
|
+
stage: 'finalize',
|
|
57
|
+
contractVersion: 1,
|
|
58
|
+
type: 'file'
|
|
59
|
+
},
|
|
60
|
+
evidence: {
|
|
61
|
+
key: 'evidence',
|
|
62
|
+
filename: 'evidence',
|
|
63
|
+
stage: 'observe',
|
|
64
|
+
contractVersion: 1,
|
|
65
|
+
type: 'directory'
|
|
66
|
+
},
|
|
67
|
+
scanSummary: {
|
|
68
|
+
key: 'scanSummary',
|
|
69
|
+
filename: 'scan-summary.json',
|
|
70
|
+
stage: 'finalize',
|
|
71
|
+
contractVersion: 1,
|
|
72
|
+
type: 'file'
|
|
73
|
+
},
|
|
74
|
+
determinismReport: {
|
|
75
|
+
key: 'determinismReport',
|
|
76
|
+
filename: 'determinism.report.json',
|
|
77
|
+
stage: 'finalize',
|
|
78
|
+
contractVersion: 1,
|
|
79
|
+
type: 'file'
|
|
80
|
+
},
|
|
81
|
+
evidenceIntent: {
|
|
82
|
+
key: 'evidenceIntent',
|
|
83
|
+
filename: 'evidence.intent.json',
|
|
84
|
+
stage: 'detect',
|
|
85
|
+
contractVersion: 1,
|
|
86
|
+
type: 'file'
|
|
87
|
+
},
|
|
88
|
+
guardrailsReport: {
|
|
89
|
+
key: 'guardrailsReport',
|
|
90
|
+
filename: 'guardrails.report.json',
|
|
91
|
+
stage: 'detect',
|
|
92
|
+
contractVersion: 1,
|
|
93
|
+
type: 'file'
|
|
94
|
+
},
|
|
95
|
+
confidenceReport: {
|
|
96
|
+
key: 'confidenceReport',
|
|
97
|
+
filename: 'confidence.report.json',
|
|
98
|
+
stage: 'detect',
|
|
99
|
+
contractVersion: 1,
|
|
100
|
+
type: 'file'
|
|
101
|
+
},
|
|
102
|
+
determinismContract: {
|
|
103
|
+
key: 'determinismContract',
|
|
104
|
+
filename: 'determinism.contract.json',
|
|
105
|
+
stage: 'observe',
|
|
106
|
+
contractVersion: 1,
|
|
107
|
+
type: 'file'
|
|
108
|
+
},
|
|
109
|
+
determinismReport: {
|
|
110
|
+
key: 'determinismReport',
|
|
111
|
+
filename: 'determinism.report.json',
|
|
112
|
+
stage: 'verify',
|
|
113
|
+
contractVersion: 1,
|
|
114
|
+
type: 'file'
|
|
115
|
+
},
|
|
116
|
+
runMeta: {
|
|
117
|
+
key: 'runMeta',
|
|
118
|
+
filename: 'run.meta.json',
|
|
119
|
+
stage: 'learn',
|
|
120
|
+
contractVersion: 1,
|
|
121
|
+
type: 'file'
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export function getArtifactVersions() {
|
|
126
|
+
const versions = {};
|
|
127
|
+
for (const [key, def] of Object.entries(ARTIFACT_REGISTRY)) {
|
|
128
|
+
versions[key] = def.contractVersion;
|
|
129
|
+
}
|
|
130
|
+
return versions;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function buildRunArtifactPaths(baseDir) {
|
|
134
|
+
return {
|
|
135
|
+
baseDir,
|
|
136
|
+
runStatusJson: join(baseDir, ARTIFACT_REGISTRY.runStatus.filename),
|
|
137
|
+
runMetaJson: join(baseDir, ARTIFACT_REGISTRY.runMeta.filename),
|
|
138
|
+
summaryJson: join(baseDir, ARTIFACT_REGISTRY.summary.filename),
|
|
139
|
+
findingsJson: join(baseDir, ARTIFACT_REGISTRY.findings.filename),
|
|
140
|
+
tracesJsonl: join(baseDir, ARTIFACT_REGISTRY.traces.filename),
|
|
141
|
+
evidenceDir: join(baseDir, ARTIFACT_REGISTRY.evidence.filename),
|
|
142
|
+
learnJson: join(baseDir, ARTIFACT_REGISTRY.learn.filename),
|
|
143
|
+
observeJson: join(baseDir, ARTIFACT_REGISTRY.observe.filename),
|
|
144
|
+
projectJson: join(baseDir, ARTIFACT_REGISTRY.project.filename),
|
|
145
|
+
scanSummaryJson: join(baseDir, ARTIFACT_REGISTRY.scanSummary.filename),
|
|
146
|
+
evidenceIntentJson: join(baseDir, ARTIFACT_REGISTRY.evidenceIntent.filename),
|
|
147
|
+
guardrailsReportJson: join(baseDir, ARTIFACT_REGISTRY.guardrailsReport.filename),
|
|
148
|
+
confidenceReportJson: join(baseDir, ARTIFACT_REGISTRY.confidenceReport.filename),
|
|
149
|
+
determinismContractJson: join(baseDir, ARTIFACT_REGISTRY.determinismContract.filename),
|
|
150
|
+
determinismReportJson: join(baseDir, ARTIFACT_REGISTRY.determinismReport.filename),
|
|
151
|
+
runMetaJson: join(baseDir, ARTIFACT_REGISTRY.runMeta.filename),
|
|
152
|
+
artifactVersions: getArtifactVersions()
|
|
153
|
+
};
|
|
154
|
+
}
|