@vibecheckai/cli 3.5.0 → 3.5.2
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/bin/registry.js +214 -237
- package/bin/runners/cli-utils.js +33 -2
- package/bin/runners/context/analyzer.js +52 -1
- package/bin/runners/context/generators/cursor.js +2 -49
- package/bin/runners/context/git-context.js +3 -1
- package/bin/runners/context/team-conventions.js +33 -7
- package/bin/runners/lib/analysis-core.js +25 -5
- package/bin/runners/lib/analyzers.js +431 -481
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/doctor/modules/security.js +3 -1
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +18 -218
- package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
- package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
- package/bin/runners/lib/engines/mock-data-engine.js +10 -53
- package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
- package/bin/runners/lib/engines/type-aware-engine.js +39 -263
- package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/entitlements-v2.js +73 -97
- package/bin/runners/lib/error-handler.js +44 -3
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +7 -1
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/html-proof-report.js +700 -350
- package/bin/runners/lib/missions/plan.js +6 -46
- package/bin/runners/lib/missions/templates.js +0 -232
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/route-detection.js +137 -68
- package/bin/runners/lib/scan-output.js +91 -76
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/validator.js +27 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/ship-output-enterprise.js +23 -23
- package/bin/runners/lib/ship-output.js +75 -31
- package/bin/runners/lib/terminal-ui.js +6 -113
- package/bin/runners/lib/truth.js +351 -10
- package/bin/runners/lib/unified-cli-output.js +430 -603
- package/bin/runners/lib/unified-output.js +13 -9
- package/bin/runners/runAIAgent.js +10 -5
- package/bin/runners/runAgent.js +0 -3
- package/bin/runners/runAllowlist.js +389 -0
- package/bin/runners/runApprove.js +0 -33
- package/bin/runners/runAuth.js +73 -45
- package/bin/runners/runCheckpoint.js +51 -11
- package/bin/runners/runClassify.js +85 -21
- package/bin/runners/runContext.js +0 -3
- package/bin/runners/runDoctor.js +41 -28
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.js +0 -3
- package/bin/runners/runFirewallHook.js +0 -3
- package/bin/runners/runFix.js +66 -76
- package/bin/runners/runGuard.js +18 -411
- package/bin/runners/runInit.js +113 -30
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runMcp.js +19 -25
- package/bin/runners/runPolish.js +64 -240
- package/bin/runners/runPromptFirewall.js +12 -5
- package/bin/runners/runProve.js +57 -22
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +59 -68
- package/bin/runners/runReport.js +38 -33
- package/bin/runners/runRuntime.js +8 -5
- package/bin/runners/runScan.js +1413 -190
- package/bin/runners/runShip.js +113 -719
- package/bin/runners/runTruth.js +0 -3
- package/bin/runners/runValidate.js +13 -9
- package/bin/runners/runWatch.js +23 -14
- package/bin/scan.js +6 -1
- package/bin/vibecheck.js +204 -185
- package/mcp-server/deprecation-middleware.js +282 -0
- package/mcp-server/handlers/index.ts +15 -0
- package/mcp-server/handlers/tool-handler.ts +554 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +210 -238
- package/mcp-server/lib/cache-wrapper.cjs +383 -0
- package/mcp-server/lib/error-envelope.js +138 -0
- package/mcp-server/lib/executor.ts +499 -0
- package/mcp-server/lib/index.ts +19 -0
- package/mcp-server/lib/rate-limiter.js +166 -0
- package/mcp-server/lib/sandbox.test.ts +519 -0
- package/mcp-server/lib/sandbox.ts +395 -0
- package/mcp-server/lib/types.ts +267 -0
- package/mcp-server/package.json +12 -3
- package/mcp-server/registry/tool-registry.js +794 -0
- package/mcp-server/registry/tools.json +605 -0
- package/mcp-server/registry.test.ts +334 -0
- package/mcp-server/tests/tier-gating.test.js +297 -0
- package/mcp-server/tier-auth.js +378 -45
- package/mcp-server/tools-v3.js +353 -442
- package/mcp-server/tsconfig.json +37 -0
- package/mcp-server/vibecheck-2.0-tools.js +14 -1
- package/package.json +1 -1
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
- package/bin/runners/lib/audit-logger.js +0 -532
- package/bin/runners/lib/authority/authorities/architecture.js +0 -364
- package/bin/runners/lib/authority/authorities/compliance.js +0 -341
- package/bin/runners/lib/authority/authorities/human.js +0 -343
- package/bin/runners/lib/authority/authorities/quality.js +0 -420
- package/bin/runners/lib/authority/authorities/security.js +0 -228
- package/bin/runners/lib/authority/index.js +0 -293
- package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
- package/bin/runners/lib/cli-charts.js +0 -368
- package/bin/runners/lib/cli-config-display.js +0 -405
- package/bin/runners/lib/cli-demo.js +0 -275
- package/bin/runners/lib/cli-errors.js +0 -438
- package/bin/runners/lib/cli-help-formatter.js +0 -439
- package/bin/runners/lib/cli-interactive-menu.js +0 -509
- package/bin/runners/lib/cli-prompts.js +0 -441
- package/bin/runners/lib/cli-scan-cards.js +0 -362
- package/bin/runners/lib/compliance-reporter.js +0 -710
- package/bin/runners/lib/conductor/index.js +0 -671
- package/bin/runners/lib/easy/README.md +0 -123
- package/bin/runners/lib/easy/index.js +0 -140
- package/bin/runners/lib/easy/interactive-wizard.js +0 -788
- package/bin/runners/lib/easy/one-click-firewall.js +0 -564
- package/bin/runners/lib/easy/zero-config-reality.js +0 -714
- package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
- package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
- package/bin/runners/lib/engines/confidence-scoring.js +0 -276
- package/bin/runners/lib/engines/context-detection.js +0 -264
- package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
- package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
- package/bin/runners/lib/engines/env-variables-engine.js +0 -458
- package/bin/runners/lib/engines/error-handling-engine.js +0 -437
- package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
- package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
- package/bin/runners/lib/engines/framework-detection.js +0 -508
- package/bin/runners/lib/engines/import-order-engine.js +0 -429
- package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
- package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
- package/bin/runners/lib/engines/orchestrator.js +0 -334
- package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
- package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
- package/bin/runners/lib/enhanced-features/index.js +0 -305
- package/bin/runners/lib/enhanced-output.js +0 -631
- package/bin/runners/lib/enterprise.js +0 -300
- package/bin/runners/lib/firewall/command-validator.js +0 -351
- package/bin/runners/lib/firewall/config.js +0 -341
- package/bin/runners/lib/firewall/content-validator.js +0 -519
- package/bin/runners/lib/firewall/index.js +0 -101
- package/bin/runners/lib/firewall/path-validator.js +0 -256
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
- package/bin/runners/lib/mcp-utils.js +0 -425
- package/bin/runners/lib/output/index.js +0 -1022
- package/bin/runners/lib/policy-engine.js +0 -652
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
- package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
- package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
- package/bin/runners/lib/polish/autofix/index.js +0 -200
- package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
- package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
- package/bin/runners/lib/polish/backend-checks.js +0 -148
- package/bin/runners/lib/polish/documentation-checks.js +0 -111
- package/bin/runners/lib/polish/frontend-checks.js +0 -168
- package/bin/runners/lib/polish/index.js +0 -71
- package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
- package/bin/runners/lib/polish/library-detection.js +0 -175
- package/bin/runners/lib/polish/performance-checks.js +0 -100
- package/bin/runners/lib/polish/security-checks.js +0 -148
- package/bin/runners/lib/polish/utils.js +0 -203
- package/bin/runners/lib/prompt-builder.js +0 -540
- package/bin/runners/lib/proof-certificate.js +0 -634
- package/bin/runners/lib/reality/accessibility-audit.js +0 -946
- package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
- package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
- package/bin/runners/lib/reality/performance-tracker.js +0 -1077
- package/bin/runners/lib/reality/scenario-generator.js +0 -1404
- package/bin/runners/lib/reality/visual-regression.js +0 -852
- package/bin/runners/lib/reality-profiler.js +0 -717
- package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
- package/bin/runners/lib/review/ai-code-review.js +0 -832
- package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
- package/bin/runners/lib/sbom-generator.js +0 -641
- package/bin/runners/lib/scan-output-enhanced.js +0 -512
- package/bin/runners/lib/security/owasp-scanner.js +0 -939
- package/bin/runners/lib/validators/contract-validator.js +0 -283
- package/bin/runners/lib/validators/dead-export-detector.js +0 -279
- package/bin/runners/lib/validators/dep-audit.js +0 -245
- package/bin/runners/lib/validators/env-validator.js +0 -319
- package/bin/runners/lib/validators/index.js +0 -120
- package/bin/runners/lib/validators/license-checker.js +0 -252
- package/bin/runners/lib/validators/route-validator.js +0 -290
- package/bin/runners/runAuthority.js +0 -528
- package/bin/runners/runConductor.js +0 -772
- package/bin/runners/runContainer.js +0 -366
- package/bin/runners/runEasy.js +0 -410
- package/bin/runners/runIaC.js +0 -372
- package/bin/runners/runVibe.js +0 -791
- package/mcp-server/tools.js +0 -495
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://vibecheck.dev/schemas/report-artifact.schema.json",
|
|
4
|
+
"x-schemaVersion": "1.0.0",
|
|
5
|
+
"title": "Vibecheck Report Artifact",
|
|
6
|
+
"description": "Generic report artifact from analysis operations",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": [
|
|
9
|
+
"type",
|
|
10
|
+
"timestamp",
|
|
11
|
+
"data"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"type": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": [
|
|
17
|
+
"scan_result",
|
|
18
|
+
"fix_plan",
|
|
19
|
+
"fix_result",
|
|
20
|
+
"status_report",
|
|
21
|
+
"context_rules",
|
|
22
|
+
"reality_report",
|
|
23
|
+
"evidence_pack"
|
|
24
|
+
],
|
|
25
|
+
"description": "Type of report artifact"
|
|
26
|
+
},
|
|
27
|
+
"timestamp": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"format": "date-time",
|
|
30
|
+
"description": "ISO 8601 timestamp of generation"
|
|
31
|
+
},
|
|
32
|
+
"vibecheck_version": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+",
|
|
35
|
+
"description": "Vibecheck version that generated this artifact"
|
|
36
|
+
},
|
|
37
|
+
"data": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"description": "Artifact-specific data payload"
|
|
40
|
+
},
|
|
41
|
+
"findings": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": {
|
|
44
|
+
"$ref": "finding-v3.schema.json"
|
|
45
|
+
},
|
|
46
|
+
"description": "Associated findings (if applicable)"
|
|
47
|
+
},
|
|
48
|
+
"summary": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"properties": {
|
|
51
|
+
"total_files_scanned": {
|
|
52
|
+
"type": "integer",
|
|
53
|
+
"minimum": 0
|
|
54
|
+
},
|
|
55
|
+
"total_findings": {
|
|
56
|
+
"type": "integer",
|
|
57
|
+
"minimum": 0
|
|
58
|
+
},
|
|
59
|
+
"duration_ms": {
|
|
60
|
+
"type": "integer",
|
|
61
|
+
"minimum": 0
|
|
62
|
+
},
|
|
63
|
+
"counts_by_severity": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"properties": {
|
|
66
|
+
"BLOCK": { "type": "integer", "minimum": 0 },
|
|
67
|
+
"WARN": { "type": "integer", "minimum": 0 },
|
|
68
|
+
"INFO": { "type": "integer", "minimum": 0 }
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"counts_by_category": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"additionalProperties": {
|
|
74
|
+
"type": "integer",
|
|
75
|
+
"minimum": 0
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"metadata": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {
|
|
83
|
+
"project_path": {
|
|
84
|
+
"type": "string"
|
|
85
|
+
},
|
|
86
|
+
"project_fingerprint": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"pattern": "^sha256:[a-f0-9]{64}$"
|
|
89
|
+
},
|
|
90
|
+
"git_commit": {
|
|
91
|
+
"type": ["string", "null"]
|
|
92
|
+
},
|
|
93
|
+
"git_branch": {
|
|
94
|
+
"type": ["string", "null"]
|
|
95
|
+
},
|
|
96
|
+
"ci_build_id": {
|
|
97
|
+
"type": ["string", "null"]
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"artifacts": {
|
|
102
|
+
"type": "array",
|
|
103
|
+
"items": {
|
|
104
|
+
"type": "object",
|
|
105
|
+
"required": ["name", "path"],
|
|
106
|
+
"properties": {
|
|
107
|
+
"name": { "type": "string" },
|
|
108
|
+
"path": { "type": "string" },
|
|
109
|
+
"type": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"enum": ["html", "json", "sarif", "md", "png", "mp4"]
|
|
112
|
+
},
|
|
113
|
+
"size_bytes": { "type": "integer", "minimum": 0 }
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"description": "Generated artifact files"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"additionalProperties": false
|
|
120
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://vibecheck.dev/schemas/run-request.schema.json",
|
|
4
|
+
"x-schemaVersion": "1.0.0",
|
|
5
|
+
"title": "Vibecheck Run Request",
|
|
6
|
+
"description": "Input schema for all vibecheck tool invocations",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": ["tool"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"tool": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Tool name to invoke",
|
|
13
|
+
"minLength": 1
|
|
14
|
+
},
|
|
15
|
+
"projectPath": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Path to project root",
|
|
18
|
+
"default": "."
|
|
19
|
+
},
|
|
20
|
+
"options": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"description": "Tool-specific options",
|
|
23
|
+
"properties": {
|
|
24
|
+
"profile": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["quick", "standard", "full", "paranoid"],
|
|
27
|
+
"default": "standard"
|
|
28
|
+
},
|
|
29
|
+
"format": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"enum": ["json", "text", "html", "sarif", "md"],
|
|
32
|
+
"default": "json"
|
|
33
|
+
},
|
|
34
|
+
"strict": {
|
|
35
|
+
"type": "boolean",
|
|
36
|
+
"default": false
|
|
37
|
+
},
|
|
38
|
+
"ci": {
|
|
39
|
+
"type": "boolean",
|
|
40
|
+
"default": false
|
|
41
|
+
},
|
|
42
|
+
"verbose": {
|
|
43
|
+
"type": "boolean",
|
|
44
|
+
"default": false
|
|
45
|
+
},
|
|
46
|
+
"timeout": {
|
|
47
|
+
"type": "integer",
|
|
48
|
+
"minimum": 1000,
|
|
49
|
+
"maximum": 600000,
|
|
50
|
+
"default": 30000
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"additionalProperties": true
|
|
54
|
+
},
|
|
55
|
+
"context": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"description": "Execution context",
|
|
58
|
+
"properties": {
|
|
59
|
+
"apiKey": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "API key for authenticated requests"
|
|
62
|
+
},
|
|
63
|
+
"sessionId": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Session ID for tracking"
|
|
66
|
+
},
|
|
67
|
+
"correlationId": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Correlation ID for distributed tracing"
|
|
70
|
+
},
|
|
71
|
+
"userAgent": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "Client user agent"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"filters": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"description": "Filtering options",
|
|
80
|
+
"properties": {
|
|
81
|
+
"include": {
|
|
82
|
+
"type": "array",
|
|
83
|
+
"items": { "type": "string" },
|
|
84
|
+
"description": "Glob patterns to include"
|
|
85
|
+
},
|
|
86
|
+
"exclude": {
|
|
87
|
+
"type": "array",
|
|
88
|
+
"items": { "type": "string" },
|
|
89
|
+
"description": "Glob patterns to exclude"
|
|
90
|
+
},
|
|
91
|
+
"categories": {
|
|
92
|
+
"type": "array",
|
|
93
|
+
"items": { "type": "string" },
|
|
94
|
+
"description": "Categories to check"
|
|
95
|
+
},
|
|
96
|
+
"severity": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"enum": ["BLOCK", "WARN", "INFO"]
|
|
101
|
+
},
|
|
102
|
+
"description": "Severity levels to include"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"additionalProperties": false
|
|
108
|
+
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Validates artifacts against JSON schemas and provides
|
|
5
5
|
* consistent finding/evidence generation.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This module now delegates to ajv-validator.js when AJV is available.
|
|
8
|
+
* The minimal implementation is kept as a fallback for environments without AJV.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
11
|
"use strict";
|
|
@@ -11,6 +14,30 @@ const fs = require("fs");
|
|
|
11
14
|
const path = require("path");
|
|
12
15
|
const crypto = require("crypto");
|
|
13
16
|
|
|
17
|
+
// Try to use the AJV-based validator if available
|
|
18
|
+
let ajvValidator = null;
|
|
19
|
+
try {
|
|
20
|
+
// Check if AJV is installed before requiring
|
|
21
|
+
require.resolve("ajv");
|
|
22
|
+
require.resolve("ajv-formats");
|
|
23
|
+
ajvValidator = require("./ajv-validator.js");
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// AJV not available, will use minimal validator
|
|
26
|
+
if (process.env.NODE_ENV === "production") {
|
|
27
|
+
console.warn("Warning: AJV not available, using minimal schema validator");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// If AJV validator is available, export it directly
|
|
32
|
+
if (ajvValidator) {
|
|
33
|
+
module.exports = ajvValidator;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// =============================================================================
|
|
38
|
+
// MINIMAL VALIDATOR FALLBACK (when AJV is not available)
|
|
39
|
+
// =============================================================================
|
|
40
|
+
|
|
14
41
|
// Schema cache
|
|
15
42
|
const schemaCache = new Map();
|
|
16
43
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://vibecheck.dev/schemas/verdict.schema.json",
|
|
4
|
+
"x-schemaVersion": "1.0.0",
|
|
5
|
+
"title": "Vibecheck Verdict",
|
|
6
|
+
"description": "Final verdict from ship/checkpoint operations",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": [
|
|
9
|
+
"status",
|
|
10
|
+
"score",
|
|
11
|
+
"blockers_count",
|
|
12
|
+
"next_steps",
|
|
13
|
+
"groups"
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"status": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": ["SHIP", "WARN", "BLOCK"],
|
|
19
|
+
"description": "Final verdict status"
|
|
20
|
+
},
|
|
21
|
+
"score": {
|
|
22
|
+
"type": "integer",
|
|
23
|
+
"minimum": 0,
|
|
24
|
+
"maximum": 100,
|
|
25
|
+
"description": "Overall health score (0-100)"
|
|
26
|
+
},
|
|
27
|
+
"blockers_count": {
|
|
28
|
+
"type": "integer",
|
|
29
|
+
"minimum": 0,
|
|
30
|
+
"description": "Number of blocking issues"
|
|
31
|
+
},
|
|
32
|
+
"warnings_count": {
|
|
33
|
+
"type": "integer",
|
|
34
|
+
"minimum": 0,
|
|
35
|
+
"description": "Number of warning issues"
|
|
36
|
+
},
|
|
37
|
+
"info_count": {
|
|
38
|
+
"type": "integer",
|
|
39
|
+
"minimum": 0,
|
|
40
|
+
"description": "Number of informational issues"
|
|
41
|
+
},
|
|
42
|
+
"next_steps": {
|
|
43
|
+
"type": "array",
|
|
44
|
+
"items": {
|
|
45
|
+
"type": "string"
|
|
46
|
+
},
|
|
47
|
+
"description": "Recommended next steps to address issues"
|
|
48
|
+
},
|
|
49
|
+
"groups": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": {
|
|
52
|
+
"$ref": "#/$defs/findingGroup"
|
|
53
|
+
},
|
|
54
|
+
"description": "Findings grouped by category"
|
|
55
|
+
},
|
|
56
|
+
"timestamp": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"format": "date-time",
|
|
59
|
+
"description": "ISO 8601 timestamp of verdict generation"
|
|
60
|
+
},
|
|
61
|
+
"duration_ms": {
|
|
62
|
+
"type": "integer",
|
|
63
|
+
"minimum": 0,
|
|
64
|
+
"description": "Analysis duration in milliseconds"
|
|
65
|
+
},
|
|
66
|
+
"vibecheck_version": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+",
|
|
69
|
+
"description": "Vibecheck version that generated this verdict"
|
|
70
|
+
},
|
|
71
|
+
"project_fingerprint": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"pattern": "^sha256:[a-f0-9]{64}$",
|
|
74
|
+
"description": "Hash of project state at analysis time"
|
|
75
|
+
},
|
|
76
|
+
"policy": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"properties": {
|
|
79
|
+
"fail_on_warn": {
|
|
80
|
+
"type": "boolean",
|
|
81
|
+
"default": false,
|
|
82
|
+
"description": "Whether warnings should cause BLOCK status"
|
|
83
|
+
},
|
|
84
|
+
"strictness": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"enum": ["chill", "standard", "strict", "paranoid"],
|
|
87
|
+
"default": "standard"
|
|
88
|
+
},
|
|
89
|
+
"required_score": {
|
|
90
|
+
"type": "integer",
|
|
91
|
+
"minimum": 0,
|
|
92
|
+
"maximum": 100,
|
|
93
|
+
"description": "Minimum score required to SHIP"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"ci_mode": {
|
|
98
|
+
"type": "boolean",
|
|
99
|
+
"default": false,
|
|
100
|
+
"description": "Whether this was run in CI mode"
|
|
101
|
+
},
|
|
102
|
+
"exit_code": {
|
|
103
|
+
"type": "integer",
|
|
104
|
+
"enum": [0, 1, 2],
|
|
105
|
+
"description": "Suggested exit code (0=SHIP, 1=WARN, 2=BLOCK)"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"$defs": {
|
|
109
|
+
"findingGroup": {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"required": ["category", "count", "severity_breakdown"],
|
|
112
|
+
"properties": {
|
|
113
|
+
"category": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"description": "Category name"
|
|
116
|
+
},
|
|
117
|
+
"count": {
|
|
118
|
+
"type": "integer",
|
|
119
|
+
"minimum": 0,
|
|
120
|
+
"description": "Total findings in this category"
|
|
121
|
+
},
|
|
122
|
+
"severity_breakdown": {
|
|
123
|
+
"type": "object",
|
|
124
|
+
"properties": {
|
|
125
|
+
"BLOCK": { "type": "integer", "minimum": 0 },
|
|
126
|
+
"WARN": { "type": "integer", "minimum": 0 },
|
|
127
|
+
"INFO": { "type": "integer", "minimum": 0 }
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"top_findings": {
|
|
131
|
+
"type": "array",
|
|
132
|
+
"items": { "type": "string" },
|
|
133
|
+
"maxItems": 5,
|
|
134
|
+
"description": "IDs of top findings in this category"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"additionalProperties": false
|
|
140
|
+
}
|
|
@@ -190,39 +190,39 @@ function formatShipOutput(result) {
|
|
|
190
190
|
lines.push(BOX.vertical + tBot + BOX.vertical);
|
|
191
191
|
lines.push(BOX.vertical + ' '.repeat(WIDTH - 2) + BOX.vertical);
|
|
192
192
|
|
|
193
|
-
// 6.
|
|
193
|
+
// 6. AUTO-FIX SECTION
|
|
194
194
|
lines.push(BOX.teeRight + BOX.horizontal.repeat(WIDTH - 2) + BOX.teeLeft);
|
|
195
|
-
lines.push(BOX.vertical + padCenter('
|
|
195
|
+
lines.push(BOX.vertical + padCenter('⚡ AUTO-FIX AVAILABLE', WIDTH - 2) + BOX.vertical);
|
|
196
196
|
lines.push(BOX.vertical + padCenter('────────────────────────────────────────────────────────────────────', WIDTH - 2) + BOX.vertical);
|
|
197
|
-
lines.push(BOX.vertical + padCenter('The specific lines of code causing these breaks are deeper in the', WIDTH - 2) + BOX.vertical);
|
|
198
|
-
lines.push(BOX.vertical + padCenter('dependency graph. Starter/Pro context is required to trace them.', WIDTH - 2) + BOX.vertical);
|
|
199
197
|
lines.push(BOX.vertical + ' '.repeat(WIDTH - 2) + BOX.vertical);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const bar = '░'.repeat(60);
|
|
203
|
-
lines.push(BOX.vertical + padCenter(bar, WIDTH - 2) + BOX.vertical);
|
|
204
|
-
|
|
205
|
-
const redacted = [
|
|
206
|
-
'░░ [REDACTED] 🔒 Schema definition mismatch in node_modules/@api...',
|
|
207
|
-
'░░ [REDACTED] 🔒 Environment leakage detected in webpack.config...',
|
|
208
|
-
'░░ [REDACTED] 🔒 Route /checkout defined in backend but not exp...'
|
|
209
|
-
];
|
|
210
|
-
|
|
211
|
-
redacted.forEach(r => {
|
|
212
|
-
lines.push(BOX.vertical + padCenter(r, WIDTH - 2) + BOX.vertical);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
lines.push(BOX.vertical + padCenter(bar, WIDTH - 2) + BOX.vertical);
|
|
198
|
+
lines.push(BOX.vertical + padCenter('Run `vibecheck ship --fix` to apply automatic fixes', WIDTH - 2) + BOX.vertical);
|
|
199
|
+
lines.push(BOX.vertical + padCenter('Run `vibecheck fix` to generate AI-powered fix missions', WIDTH - 2) + BOX.vertical);
|
|
216
200
|
lines.push(BOX.vertical + ' '.repeat(WIDTH - 2) + BOX.vertical);
|
|
217
|
-
|
|
218
|
-
lines.push(BOX.vertical + padCenter('👉 RESOLUTION:', WIDTH - 2) + BOX.vertical);
|
|
219
|
-
lines.push(BOX.vertical + padCenter('Run `vibecheck upgrade starter` to reveal root causes.', WIDTH - 2) + BOX.vertical);
|
|
220
201
|
}
|
|
221
202
|
|
|
222
203
|
// 7. BOTTOM FRAME
|
|
223
204
|
lines.push(BOX.vertical + ' '.repeat(WIDTH - 2) + BOX.vertical);
|
|
224
205
|
lines.push(BOX.bottomLeft + BOX.horizontal.repeat(WIDTH - 2) + BOX.bottomRight);
|
|
225
206
|
|
|
207
|
+
// DASHBOARD LINK (outside frame)
|
|
208
|
+
const runId = result.runId;
|
|
209
|
+
if (runId) {
|
|
210
|
+
lines.push('');
|
|
211
|
+
lines.push(` 🔗 Dashboard: https://app.vibecheckai.dev/runs/${runId}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// NEXT BEST ACTION (outside frame)
|
|
215
|
+
try {
|
|
216
|
+
const { formatNextActionOneLine, getNextActionForCommand } = require('./next-action');
|
|
217
|
+
const tier = result.tier || 'free';
|
|
218
|
+
const findings = [...(result.blockers || []), ...(result.warnings || [])];
|
|
219
|
+
const nextAction = getNextActionForCommand('ship', { verdict, runId, findings }, tier);
|
|
220
|
+
lines.push('');
|
|
221
|
+
lines.push(` ${formatNextActionOneLine(nextAction)}`);
|
|
222
|
+
} catch (e) {
|
|
223
|
+
// Next action module might not be available, skip gracefully
|
|
224
|
+
}
|
|
225
|
+
|
|
226
226
|
return lines.join('\n');
|
|
227
227
|
}
|
|
228
228
|
|
|
@@ -210,17 +210,45 @@ function renderRouteTruthMap(truthpack) {
|
|
|
210
210
|
lines.push(renderSection('ROUTE TRUTH MAP', shipIcons.map));
|
|
211
211
|
lines.push('');
|
|
212
212
|
|
|
213
|
-
const serverRoutes = truthpack.routes?.server
|
|
213
|
+
const serverRoutes = truthpack.routes?.server || [];
|
|
214
|
+
const serverRouteCount = serverRoutes.length;
|
|
214
215
|
const clientRefs = truthpack.routes?.clientRefs?.length || 0;
|
|
215
216
|
const envVars = truthpack.env?.vars?.length || 0;
|
|
216
217
|
const envDeclared = truthpack.env?.declared?.length || 0;
|
|
217
218
|
|
|
219
|
+
// Framework detection output
|
|
220
|
+
const frameworkCounts = {};
|
|
221
|
+
for (const route of serverRoutes) {
|
|
222
|
+
const fw = route.framework || 'unknown';
|
|
223
|
+
frameworkCounts[fw] = (frameworkCounts[fw] || 0) + 1;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Also include project-level detected frameworks
|
|
227
|
+
const detectedFrameworks = truthpack.project?.frameworks || [];
|
|
228
|
+
for (const fw of detectedFrameworks) {
|
|
229
|
+
if (!frameworkCounts[fw]) frameworkCounts[fw] = 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Sort by count descending
|
|
233
|
+
const sortedFrameworks = Object.entries(frameworkCounts)
|
|
234
|
+
.filter(([fw]) => fw !== 'unknown')
|
|
235
|
+
.sort((a, b) => b[1] - a[1]);
|
|
236
|
+
|
|
237
|
+
if (sortedFrameworks.length > 0) {
|
|
238
|
+
const fwDisplay = sortedFrameworks
|
|
239
|
+
.slice(0, 5)
|
|
240
|
+
.map(([fw, count]) => `${fw} (${count})`)
|
|
241
|
+
.join(', ');
|
|
242
|
+
lines.push(` ${ansi.bold}Frameworks:${ansi.reset} ${colors.accent}${fwDisplay}${ansi.reset}`);
|
|
243
|
+
lines.push('');
|
|
244
|
+
}
|
|
245
|
+
|
|
218
246
|
// Routes coverage
|
|
219
|
-
const routeCoverage =
|
|
247
|
+
const routeCoverage = serverRouteCount > 0 ? Math.round((clientRefs / serverRouteCount) * 100) : 100;
|
|
220
248
|
const routeColor = routeCoverage >= 80 ? colors.success : routeCoverage >= 50 ? colors.warning : colors.error;
|
|
221
249
|
|
|
222
250
|
lines.push(` ${shipIcons.route} ${ansi.bold}Routes${ansi.reset}`);
|
|
223
|
-
lines.push(` Server: ${colors.accent}${
|
|
251
|
+
lines.push(` Server: ${colors.accent}${serverRouteCount}${ansi.reset} defined`);
|
|
224
252
|
lines.push(` Client: ${colors.accent}${clientRefs}${ansi.reset} references`);
|
|
225
253
|
lines.push(` Coverage: ${renderProgressBar(routeCoverage, 20, routeColor)} ${routeColor}${routeCoverage}%${ansi.reset}`);
|
|
226
254
|
lines.push('');
|
|
@@ -243,19 +271,28 @@ function renderRouteTruthMap(truthpack) {
|
|
|
243
271
|
|
|
244
272
|
function getCategoryIcon(category) {
|
|
245
273
|
const iconMap = {
|
|
274
|
+
// AI Hallucination Categories (primary)
|
|
246
275
|
'MissingRoute': shipIcons.route,
|
|
247
|
-
'EnvContract': shipIcons.env,
|
|
248
|
-
'EnvGap': shipIcons.env,
|
|
249
276
|
'FakeSuccess': shipIcons.ghost,
|
|
250
277
|
'GhostAuth': shipIcons.auth,
|
|
278
|
+
'EnvContract': shipIcons.env,
|
|
279
|
+
'EnvGap': shipIcons.env,
|
|
280
|
+
'DeadUI': shipIcons.dead,
|
|
281
|
+
'OwnerModeBypass': shipIcons.lock,
|
|
282
|
+
'OptimisticNoRollback': '↩️',
|
|
283
|
+
'SilentCatch': '🔇',
|
|
284
|
+
'MethodMismatch': '🔀',
|
|
285
|
+
// Billing/Monetization
|
|
286
|
+
'Billing': shipIcons.money,
|
|
251
287
|
'StripeWebhook': shipIcons.money,
|
|
252
288
|
'PaidSurface': shipIcons.money,
|
|
253
|
-
'
|
|
254
|
-
|
|
255
|
-
'ContractDrift': icons.warning,
|
|
289
|
+
'Entitlements': '💳',
|
|
290
|
+
// Security
|
|
256
291
|
'Security': shipIcons.shield,
|
|
257
292
|
'Auth': shipIcons.lock,
|
|
258
293
|
'SECRET': shipIcons.key,
|
|
294
|
+
// Quality
|
|
295
|
+
'ContractDrift': icons.warning,
|
|
259
296
|
'ROUTE': shipIcons.route,
|
|
260
297
|
'BILLING': shipIcons.money,
|
|
261
298
|
'MOCK': shipIcons.ghost,
|
|
@@ -322,9 +359,6 @@ function renderBlockerDetails(findings, maxShow = 8, options = {}) {
|
|
|
322
359
|
|
|
323
360
|
if (blockers.length === 0) return '';
|
|
324
361
|
|
|
325
|
-
// Fix hints are PRO only (2-tier model)
|
|
326
|
-
const canShowFixHints = tier === 'pro' || tier === 'compliance' || tier === 'starter'; // starter=legacy compatibility
|
|
327
|
-
|
|
328
362
|
const lines = [];
|
|
329
363
|
lines.push(renderSection(`BLOCKERS (${blockers.length})`, '🚨'));
|
|
330
364
|
lines.push('');
|
|
@@ -364,16 +398,11 @@ function renderBlockerDetails(findings, maxShow = 8, options = {}) {
|
|
|
364
398
|
lines.push(` ${colors.accent}${shipIcons.doc} ${fileDisplay}${ansi.reset}`);
|
|
365
399
|
}
|
|
366
400
|
|
|
367
|
-
// Fix hint -
|
|
368
|
-
if (
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
lines.push(` ${colors.success}→ ${truncate(blocker.fix, 50)}${ansi.reset}`);
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
// Show locked fix hint for FREE tier
|
|
376
|
-
lines.push(` ${ansi.dim}🔒 Fix hints available with PRO ($69/mo)${ansi.reset}`);
|
|
401
|
+
// Fix hint - shown to ALL tiers (FREE gets full details, PRO gets auto-fix capability)
|
|
402
|
+
if (blocker.fixHints && blocker.fixHints.length > 0) {
|
|
403
|
+
lines.push(` ${colors.success}→ ${truncate(blocker.fixHints[0], 50)}${ansi.reset}`);
|
|
404
|
+
} else if (blocker.fix) {
|
|
405
|
+
lines.push(` ${colors.success}→ ${truncate(blocker.fix, 50)}${ansi.reset}`);
|
|
377
406
|
}
|
|
378
407
|
|
|
379
408
|
lines.push('');
|
|
@@ -384,13 +413,11 @@ function renderBlockerDetails(findings, maxShow = 8, options = {}) {
|
|
|
384
413
|
lines.push('');
|
|
385
414
|
}
|
|
386
415
|
|
|
387
|
-
// Show upsell for fix
|
|
388
|
-
if (
|
|
416
|
+
// Show PRO upsell for auto-fix capability (not viewing fix hints)
|
|
417
|
+
if (blockers.length > 0) {
|
|
389
418
|
lines.push(` ${ansi.dim}─────────────────────────────────────────${ansi.reset}`);
|
|
390
|
-
lines.push(` ${colors.accent}
|
|
391
|
-
lines.push(` ${ansi.dim}
|
|
392
|
-
lines.push(` ${ansi.dim}AI mission prompts for every issue.${ansi.reset}`);
|
|
393
|
-
lines.push(` ${colors.accent}Upgrade to PRO ($69/mo)${ansi.reset} ${ansi.dim}→ vibecheckai.dev/pricing${ansi.reset}`);
|
|
419
|
+
lines.push(` ${colors.accent}⚡${ansi.reset} ${ansi.bold}Auto-fix available${ansi.reset}`);
|
|
420
|
+
lines.push(` ${ansi.dim}Run${ansi.reset} ${colors.accent}vibecheck ship --fix${ansi.reset} ${ansi.dim}to apply fixes automatically${ansi.reset}`);
|
|
394
421
|
lines.push('');
|
|
395
422
|
}
|
|
396
423
|
|
|
@@ -591,13 +618,30 @@ function renderReportLinks(outputDir, hasFix = false) {
|
|
|
591
618
|
|
|
592
619
|
// Categories that indicate common AI hallucination patterns
|
|
593
620
|
const AI_HALLUCINATION_CATEGORIES = {
|
|
621
|
+
// Route & API Issues (highest weight - these break apps)
|
|
594
622
|
'MissingRoute': { weight: 25, label: 'Invented endpoints', desc: 'AI created API routes that don\'t exist' },
|
|
623
|
+
'MethodMismatch': { weight: 20, label: 'Wrong HTTP method', desc: 'GET request to POST-only endpoint or vice versa' },
|
|
624
|
+
|
|
625
|
+
// Success/Error Handling Issues
|
|
595
626
|
'FakeSuccess': { weight: 20, label: 'Fake success UI', desc: 'Shows success without verifying the operation' },
|
|
596
|
-
'
|
|
627
|
+
'OptimisticNoRollback': { weight: 18, label: 'No rollback', desc: 'Optimistic update without failure rollback' },
|
|
628
|
+
'SilentCatch': { weight: 15, label: 'Silent failure', desc: 'Catch block swallows errors without handling' },
|
|
629
|
+
|
|
630
|
+
// Auth & Security Issues
|
|
631
|
+
'GhostAuth': { weight: 15, label: 'Missing auth', desc: 'Sensitive endpoints without server-side protection' },
|
|
632
|
+
'OwnerModeBypass': { weight: 15, label: 'Backdoor access', desc: 'Production security bypasses left in code' },
|
|
633
|
+
|
|
634
|
+
// Environment & Config Issues
|
|
597
635
|
'EnvGap': { weight: 10, label: 'Undefined env vars', desc: 'Uses environment variables that don\'t exist' },
|
|
598
|
-
'
|
|
599
|
-
|
|
600
|
-
|
|
636
|
+
'EnvContract': { weight: 10, label: 'Env contract', desc: 'Environment variable contract violations' },
|
|
637
|
+
|
|
638
|
+
// UI & UX Issues
|
|
639
|
+
'DeadUI': { weight: 10, label: 'Dead UI elements', desc: 'Buttons/forms/links that do nothing or go nowhere' },
|
|
640
|
+
|
|
641
|
+
// Billing & Monetization Issues
|
|
642
|
+
'PaidSurface': { weight: 5, label: 'Billing bypass', desc: 'Paid features accessible without enforcement' },
|
|
643
|
+
'Billing': { weight: 8, label: 'Billing issue', desc: 'Payment/webhook handling problems' },
|
|
644
|
+
'Entitlements': { weight: 8, label: 'Entitlement gap', desc: 'Feature access without entitlement check' },
|
|
601
645
|
};
|
|
602
646
|
|
|
603
647
|
function calculateAIHallucinationScore(findings) {
|