@veraxhq/verax 0.2.1 → 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.
- package/README.md +10 -6
- package/bin/verax.js +11 -11
- package/package.json +29 -8
- package/src/cli/commands/baseline.js +103 -0
- package/src/cli/commands/default.js +51 -6
- package/src/cli/commands/doctor.js +29 -0
- package/src/cli/commands/ga.js +246 -0
- package/src/cli/commands/gates.js +95 -0
- package/src/cli/commands/inspect.js +4 -2
- package/src/cli/commands/release-check.js +215 -0
- package/src/cli/commands/run.js +45 -6
- package/src/cli/commands/security-check.js +212 -0
- package/src/cli/commands/truth.js +113 -0
- package/src/cli/entry.js +30 -20
- 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 +544 -0
- package/src/cli/util/ast-network-detector.js +603 -0
- package/src/cli/util/ast-promise-extractor.js +581 -0
- package/src/cli/util/ast-usestate-detector.js +602 -0
- package/src/cli/util/atomic-write.js +12 -1
- package/src/cli/util/bootstrap-guard.js +86 -0
- package/src/cli/util/console-reporter.js +72 -0
- package/src/cli/util/detection-engine.js +105 -41
- package/src/cli/util/determinism-runner.js +124 -0
- package/src/cli/util/determinism-writer.js +129 -0
- package/src/cli/util/digest-engine.js +359 -0
- package/src/cli/util/dom-diff.js +226 -0
- package/src/cli/util/evidence-engine.js +287 -0
- package/src/cli/util/expectation-extractor.js +151 -5
- package/src/cli/util/findings-writer.js +3 -0
- package/src/cli/util/framework-detector.js +572 -0
- package/src/cli/util/idgen.js +1 -1
- package/src/cli/util/interaction-planner.js +529 -0
- package/src/cli/util/learn-writer.js +2 -0
- package/src/cli/util/ledger-writer.js +110 -0
- package/src/cli/util/monorepo-resolver.js +162 -0
- package/src/cli/util/observation-engine.js +127 -278
- package/src/cli/util/observe-writer.js +2 -0
- package/src/cli/util/project-discovery.js +284 -0
- package/src/cli/util/project-writer.js +2 -0
- package/src/cli/util/run-id.js +23 -27
- package/src/cli/util/run-resolver.js +64 -0
- package/src/cli/util/run-result.js +778 -0
- package/src/cli/util/selector-resolver.js +235 -0
- package/src/cli/util/source-requirement.js +55 -0
- package/src/cli/util/summary-writer.js +2 -0
- 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 +146 -0
- package/src/cli/util/svelte-state-detector.js +242 -0
- package/src/cli/util/trust-activation-integration.js +496 -0
- package/src/cli/util/trust-activation-wrapper.js +85 -0
- package/src/cli/util/trust-integration-hooks.js +164 -0
- package/src/cli/util/types.js +153 -0
- package/src/cli/util/url-validation.js +40 -0
- package/src/cli/util/vue-navigation-detector.js +178 -0
- package/src/cli/util/vue-sfc-extractor.js +161 -0
- package/src/cli/util/vue-state-detector.js +215 -0
- package/src/types/fs-augment.d.ts +23 -0
- package/src/types/global.d.ts +137 -0
- package/src/types/internal-types.d.ts +35 -0
- package/src/verax/cli/init.js +4 -18
- package/src/verax/core/action-classifier.js +4 -3
- package/src/verax/core/artifacts/registry.js +139 -0
- package/src/verax/core/artifacts/verifier.js +990 -0
- package/src/verax/core/baseline/baseline.enforcer.js +137 -0
- package/src/verax/core/baseline/baseline.snapshot.js +233 -0
- package/src/verax/core/capabilities/gates.js +505 -0
- package/src/verax/core/capabilities/registry.js +475 -0
- package/src/verax/core/confidence/confidence-compute.js +144 -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 +80 -0
- package/src/verax/core/confidence/confidence.schema.js +94 -0
- package/src/verax/core/confidence-engine-refactor.js +489 -0
- package/src/verax/core/confidence-engine.js +625 -0
- package/src/verax/core/contracts/index.js +29 -0
- package/src/verax/core/contracts/types.js +186 -0
- package/src/verax/core/contracts/validators.js +456 -0
- package/src/verax/core/decisions/decision.trace.js +278 -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 +405 -0
- package/src/verax/core/determinism/engine.js +222 -0
- package/src/verax/core/determinism/finding-identity.js +149 -0
- package/src/verax/core/determinism/normalize.js +466 -0
- package/src/verax/core/determinism/report-writer.js +93 -0
- package/src/verax/core/determinism/run-fingerprint.js +123 -0
- package/src/verax/core/dynamic-route-intelligence.js +529 -0
- package/src/verax/core/evidence/evidence-capture-service.js +308 -0
- package/src/verax/core/evidence/evidence-intent-ledger.js +166 -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 +192 -0
- package/src/verax/core/failures/exit-codes.js +88 -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 +133 -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 +435 -0
- package/src/verax/core/ga/ga.enforcer.js +87 -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 +84 -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 +1 -0
- package/src/verax/core/integrity/budget.js +138 -0
- package/src/verax/core/integrity/determinism.js +342 -0
- package/src/verax/core/integrity/integrity.js +208 -0
- package/src/verax/core/integrity/poisoning.js +108 -0
- package/src/verax/core/integrity/transaction.js +140 -0
- package/src/verax/core/observe/run-timeline.js +318 -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 +200 -0
- package/src/verax/core/pipeline-tracker.js +243 -0
- package/src/verax/core/product-definition.js +127 -0
- package/src/verax/core/release/provenance.builder.js +130 -0
- package/src/verax/core/release/release-report-writer.js +40 -0
- package/src/verax/core/release/release.enforcer.js +164 -0
- package/src/verax/core/release/reproducibility.check.js +222 -0
- package/src/verax/core/release/sbom.builder.js +292 -0
- package/src/verax/core/replay-validator.js +2 -0
- package/src/verax/core/replay.js +4 -0
- package/src/verax/core/report/cross-index.js +195 -0
- package/src/verax/core/report/human-summary.js +362 -0
- package/src/verax/core/route-intelligence.js +420 -0
- package/src/verax/core/run-id.js +6 -3
- package/src/verax/core/run-manifest.js +4 -3
- package/src/verax/core/security/secrets.scan.js +329 -0
- package/src/verax/core/security/security-report.js +50 -0
- package/src/verax/core/security/security.enforcer.js +128 -0
- package/src/verax/core/security/supplychain.defaults.json +38 -0
- package/src/verax/core/security/supplychain.policy.js +334 -0
- package/src/verax/core/security/vuln.scan.js +265 -0
- package/src/verax/core/truth/truth.certificate.js +252 -0
- package/src/verax/core/ui-feedback-intelligence.js +481 -0
- package/src/verax/detect/conditional-ui-silent-failure.js +84 -0
- package/src/verax/detect/confidence-engine.js +62 -34
- package/src/verax/detect/confidence-helper.js +34 -0
- package/src/verax/detect/dynamic-route-findings.js +338 -0
- package/src/verax/detect/expectation-chain-detector.js +417 -0
- package/src/verax/detect/expectation-model.js +2 -2
- package/src/verax/detect/failure-cause-inference.js +293 -0
- package/src/verax/detect/findings-writer.js +131 -35
- package/src/verax/detect/flow-detector.js +2 -2
- package/src/verax/detect/form-silent-failure.js +98 -0
- package/src/verax/detect/index.js +46 -5
- package/src/verax/detect/invariants-enforcer.js +147 -0
- package/src/verax/detect/journey-stall-detector.js +558 -0
- package/src/verax/detect/navigation-silent-failure.js +82 -0
- package/src/verax/detect/problem-aggregator.js +361 -0
- package/src/verax/detect/route-findings.js +219 -0
- package/src/verax/detect/summary-writer.js +477 -0
- package/src/verax/detect/test-failure-cause-inference.js +314 -0
- package/src/verax/detect/ui-feedback-findings.js +207 -0
- package/src/verax/detect/view-switch-correlator.js +242 -0
- package/src/verax/flow/flow-engine.js +2 -1
- package/src/verax/flow/flow-spec.js +0 -6
- package/src/verax/index.js +4 -0
- package/src/verax/intel/ts-program.js +1 -0
- package/src/verax/intel/vue-navigation-extractor.js +3 -0
- package/src/verax/learn/action-contract-extractor.js +3 -0
- package/src/verax/learn/ast-contract-extractor.js +1 -1
- package/src/verax/learn/flow-extractor.js +1 -0
- package/src/verax/learn/project-detector.js +5 -0
- package/src/verax/learn/react-router-extractor.js +2 -0
- package/src/verax/learn/source-instrumenter.js +1 -0
- package/src/verax/learn/state-extractor.js +2 -1
- package/src/verax/learn/static-extractor.js +1 -0
- package/src/verax/observe/coverage-gaps.js +132 -0
- package/src/verax/observe/expectation-handler.js +126 -0
- package/src/verax/observe/incremental-skip.js +46 -0
- package/src/verax/observe/index.js +51 -155
- package/src/verax/observe/interaction-executor.js +192 -0
- package/src/verax/observe/interaction-runner.js +782 -513
- package/src/verax/observe/network-firewall.js +86 -0
- package/src/verax/observe/observation-builder.js +169 -0
- package/src/verax/observe/observe-context.js +205 -0
- package/src/verax/observe/observe-helpers.js +192 -0
- package/src/verax/observe/observe-runner.js +230 -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/page-traversal.js +138 -0
- package/src/verax/observe/snapshot-ops.js +94 -0
- package/src/verax/observe/ui-feedback-detector.js +742 -0
- package/src/verax/scan-summary-writer.js +2 -0
- package/src/verax/shared/artifact-manager.js +25 -5
- package/src/verax/shared/caching.js +1 -0
- package/src/verax/shared/css-spinner-rules.js +204 -0
- package/src/verax/shared/expectation-tracker.js +1 -0
- package/src/verax/shared/view-switch-rules.js +208 -0
- package/src/verax/shared/zip-artifacts.js +6 -0
- package/src/verax/shared/config-loader.js +0 -169
- /package/src/verax/shared/{expectation-proof.js → expectation-validation.js} +0 -0
|
@@ -33,6 +33,7 @@ export async function discoverProject(srcPath) {
|
|
|
33
33
|
let packageJson = null;
|
|
34
34
|
if (packageJsonPath && existsSync(packageJsonPath)) {
|
|
35
35
|
try {
|
|
36
|
+
// @ts-expect-error - readFileSync with encoding returns string
|
|
36
37
|
packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
37
38
|
} catch (error) {
|
|
38
39
|
packageJson = null;
|
|
@@ -64,6 +65,44 @@ export async function discoverProject(srcPath) {
|
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
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
|
+
|
|
67
106
|
/**
|
|
68
107
|
* Find the nearest package.json by walking up directories
|
|
69
108
|
*/
|
|
@@ -295,3 +334,248 @@ export function extractPortFromScript(script) {
|
|
|
295
334
|
|
|
296
335
|
return null;
|
|
297
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
|
+
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { atomicWriteJson } from './atomic-write.js';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
+
import { ARTIFACT_REGISTRY } from '../../verax/core/artifacts/registry.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Write project profile artifact
|
|
@@ -8,6 +9,7 @@ export function writeProjectJson(runPaths, projectProfile) {
|
|
|
8
9
|
const projectJsonPath = resolve(runPaths.baseDir, 'project.json');
|
|
9
10
|
|
|
10
11
|
const projectJson = {
|
|
12
|
+
contractVersion: ARTIFACT_REGISTRY.project.contractVersion,
|
|
11
13
|
framework: projectProfile.framework,
|
|
12
14
|
router: projectProfile.router,
|
|
13
15
|
sourceRoot: projectProfile.sourceRoot,
|
package/src/cli/util/run-id.js
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { generateRunId as generateDeterministicRunId } from '../../verax/core/run-id.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHASE 21.6.1 — Run Resolver
|
|
3
|
+
*
|
|
4
|
+
* Pure filesystem logic to resolve run IDs.
|
|
5
|
+
* No side effects, no execution dependencies.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readdirSync, statSync, existsSync } from 'fs';
|
|
9
|
+
import { resolve } from 'path';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Find the latest run ID from .verax/runs/
|
|
13
|
+
*
|
|
14
|
+
* @param {string} projectDir - Project directory
|
|
15
|
+
* @returns {string|null} Latest run ID or null if no runs found
|
|
16
|
+
*/
|
|
17
|
+
export function findLatestRunId(projectDir) {
|
|
18
|
+
const runsDir = resolve(projectDir, '.verax', 'runs');
|
|
19
|
+
|
|
20
|
+
if (!existsSync(runsDir)) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const runs = readdirSync(runsDir, { withFileTypes: true })
|
|
26
|
+
.filter(dirent => dirent.isDirectory())
|
|
27
|
+
.map(dirent => {
|
|
28
|
+
const runPath = resolve(runsDir, dirent.name);
|
|
29
|
+
try {
|
|
30
|
+
const stats = statSync(runPath);
|
|
31
|
+
return {
|
|
32
|
+
name: dirent.name,
|
|
33
|
+
mtimeMs: stats.mtimeMs
|
|
34
|
+
};
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
.filter(run => run !== null);
|
|
40
|
+
|
|
41
|
+
if (runs.length === 0) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Sort by modification time (descending) and return latest
|
|
46
|
+
runs.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
47
|
+
return runs[0].name;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validate that a run ID exists
|
|
55
|
+
*
|
|
56
|
+
* @param {string} projectDir - Project directory
|
|
57
|
+
* @param {string} runId - Run ID to validate
|
|
58
|
+
* @returns {boolean} Whether run exists
|
|
59
|
+
*/
|
|
60
|
+
export function validateRunId(projectDir, runId) {
|
|
61
|
+
const runDir = resolve(projectDir, '.verax', 'runs', runId);
|
|
62
|
+
return existsSync(runDir);
|
|
63
|
+
}
|
|
64
|
+
|