vibecheck-ai 2.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/bin/.generated +25 -0
  2. package/bin/_deprecations.js +463 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/dev/run-v2-torture.js +30 -0
  6. package/bin/registry.js +656 -0
  7. package/bin/runners/CLI_REFACTOR_SUMMARY.md +229 -0
  8. package/bin/runners/ENHANCEMENT_GUIDE.md +121 -0
  9. package/bin/runners/REPORT_AUDIT.md +64 -0
  10. package/bin/runners/cli-utils.js +1070 -0
  11. package/bin/runners/context/ai-task-decomposer.js +337 -0
  12. package/bin/runners/context/analyzer.js +513 -0
  13. package/bin/runners/context/api-contracts.js +427 -0
  14. package/bin/runners/context/context-diff.js +342 -0
  15. package/bin/runners/context/context-pruner.js +291 -0
  16. package/bin/runners/context/dependency-graph.js +414 -0
  17. package/bin/runners/context/generators/claude.js +107 -0
  18. package/bin/runners/context/generators/codex.js +108 -0
  19. package/bin/runners/context/generators/copilot.js +119 -0
  20. package/bin/runners/context/generators/cursor-enhanced.js +2525 -0
  21. package/bin/runners/context/generators/cursor.js +514 -0
  22. package/bin/runners/context/generators/mcp.js +169 -0
  23. package/bin/runners/context/generators/windsurf.js +180 -0
  24. package/bin/runners/context/git-context.js +304 -0
  25. package/bin/runners/context/index.js +1110 -0
  26. package/bin/runners/context/insights.js +173 -0
  27. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  28. package/bin/runners/context/mcp-server/index.js +1176 -0
  29. package/bin/runners/context/mcp-server/package.json +24 -0
  30. package/bin/runners/context/memory.js +200 -0
  31. package/bin/runners/context/monorepo.js +215 -0
  32. package/bin/runners/context/multi-repo-federation.js +404 -0
  33. package/bin/runners/context/patterns.js +253 -0
  34. package/bin/runners/context/proof-context.js +1264 -0
  35. package/bin/runners/context/security-scanner.js +541 -0
  36. package/bin/runners/context/semantic-search.js +350 -0
  37. package/bin/runners/context/shared.js +264 -0
  38. package/bin/runners/context/team-conventions.js +336 -0
  39. package/bin/runners/lib/__tests__/entitlements-v2.test.js +295 -0
  40. package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +474 -0
  41. package/bin/runners/lib/agent-firewall/change-packet/builder.js +488 -0
  42. package/bin/runners/lib/agent-firewall/change-packet/schema.json +228 -0
  43. package/bin/runners/lib/agent-firewall/change-packet/store.js +200 -0
  44. package/bin/runners/lib/agent-firewall/claims/claim-types.js +21 -0
  45. package/bin/runners/lib/agent-firewall/claims/extractor.js +303 -0
  46. package/bin/runners/lib/agent-firewall/claims/patterns.js +24 -0
  47. package/bin/runners/lib/agent-firewall/critic/index.js +151 -0
  48. package/bin/runners/lib/agent-firewall/critic/judge.js +432 -0
  49. package/bin/runners/lib/agent-firewall/critic/prompts.js +305 -0
  50. package/bin/runners/lib/agent-firewall/enforcement/gateway.js +1059 -0
  51. package/bin/runners/lib/agent-firewall/enforcement/index.js +98 -0
  52. package/bin/runners/lib/agent-firewall/enforcement/mode.js +318 -0
  53. package/bin/runners/lib/agent-firewall/enforcement/orchestrator.js +484 -0
  54. package/bin/runners/lib/agent-firewall/enforcement/proof-artifact.js +418 -0
  55. package/bin/runners/lib/agent-firewall/enforcement/schemas/change-event.schema.json +173 -0
  56. package/bin/runners/lib/agent-firewall/enforcement/schemas/intent.schema.json +181 -0
  57. package/bin/runners/lib/agent-firewall/enforcement/schemas/verdict.schema.json +222 -0
  58. package/bin/runners/lib/agent-firewall/enforcement/verdict-v2.js +333 -0
  59. package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +88 -0
  60. package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +75 -0
  61. package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +127 -0
  62. package/bin/runners/lib/agent-firewall/evidence/resolver.js +102 -0
  63. package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +213 -0
  64. package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +145 -0
  65. package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +19 -0
  66. package/bin/runners/lib/agent-firewall/fs-hook/installer.js +87 -0
  67. package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +184 -0
  68. package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +163 -0
  69. package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +107 -0
  70. package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +68 -0
  71. package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +66 -0
  72. package/bin/runners/lib/agent-firewall/index.js +200 -0
  73. package/bin/runners/lib/agent-firewall/integration/index.js +20 -0
  74. package/bin/runners/lib/agent-firewall/integration/ship-gate.js +437 -0
  75. package/bin/runners/lib/agent-firewall/intent/alignment-engine.js +634 -0
  76. package/bin/runners/lib/agent-firewall/intent/auto-detect.js +426 -0
  77. package/bin/runners/lib/agent-firewall/intent/index.js +102 -0
  78. package/bin/runners/lib/agent-firewall/intent/schema.js +352 -0
  79. package/bin/runners/lib/agent-firewall/intent/store.js +283 -0
  80. package/bin/runners/lib/agent-firewall/interception/fs-interceptor.js +502 -0
  81. package/bin/runners/lib/agent-firewall/interception/index.js +23 -0
  82. package/bin/runners/lib/agent-firewall/interceptor/base.js +308 -0
  83. package/bin/runners/lib/agent-firewall/interceptor/cursor.js +35 -0
  84. package/bin/runners/lib/agent-firewall/interceptor/vscode.js +35 -0
  85. package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +34 -0
  86. package/bin/runners/lib/agent-firewall/lawbook/distributor.js +465 -0
  87. package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +604 -0
  88. package/bin/runners/lib/agent-firewall/lawbook/index.js +304 -0
  89. package/bin/runners/lib/agent-firewall/lawbook/registry.js +514 -0
  90. package/bin/runners/lib/agent-firewall/lawbook/schema.js +420 -0
  91. package/bin/runners/lib/agent-firewall/logger.js +141 -0
  92. package/bin/runners/lib/agent-firewall/policy/default-policy.json +90 -0
  93. package/bin/runners/lib/agent-firewall/policy/engine.js +103 -0
  94. package/bin/runners/lib/agent-firewall/policy/loader.js +451 -0
  95. package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +50 -0
  96. package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +50 -0
  97. package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +79 -0
  98. package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +227 -0
  99. package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +191 -0
  100. package/bin/runners/lib/agent-firewall/policy/rules/scope.js +93 -0
  101. package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +57 -0
  102. package/bin/runners/lib/agent-firewall/policy/schema.json +183 -0
  103. package/bin/runners/lib/agent-firewall/policy/verdict.js +54 -0
  104. package/bin/runners/lib/agent-firewall/proposal/extractor.js +394 -0
  105. package/bin/runners/lib/agent-firewall/proposal/index.js +212 -0
  106. package/bin/runners/lib/agent-firewall/proposal/schema.js +251 -0
  107. package/bin/runners/lib/agent-firewall/proposal/validator.js +386 -0
  108. package/bin/runners/lib/agent-firewall/reality/index.js +332 -0
  109. package/bin/runners/lib/agent-firewall/reality/state.js +625 -0
  110. package/bin/runners/lib/agent-firewall/reality/watcher.js +322 -0
  111. package/bin/runners/lib/agent-firewall/risk/index.js +173 -0
  112. package/bin/runners/lib/agent-firewall/risk/scorer.js +328 -0
  113. package/bin/runners/lib/agent-firewall/risk/thresholds.js +322 -0
  114. package/bin/runners/lib/agent-firewall/risk/vectors.js +421 -0
  115. package/bin/runners/lib/agent-firewall/session/collector.js +451 -0
  116. package/bin/runners/lib/agent-firewall/session/index.js +26 -0
  117. package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +472 -0
  118. package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +346 -0
  119. package/bin/runners/lib/agent-firewall/simulator/index.js +181 -0
  120. package/bin/runners/lib/agent-firewall/simulator/route-validator.js +380 -0
  121. package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +661 -0
  122. package/bin/runners/lib/agent-firewall/time-machine/index.js +267 -0
  123. package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +436 -0
  124. package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +490 -0
  125. package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +530 -0
  126. package/bin/runners/lib/agent-firewall/truthpack/index.js +67 -0
  127. package/bin/runners/lib/agent-firewall/truthpack/loader.js +137 -0
  128. package/bin/runners/lib/agent-firewall/unblock/planner.js +337 -0
  129. package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +118 -0
  130. package/bin/runners/lib/ai-bridge.js +416 -0
  131. package/bin/runners/lib/analysis-core.js +309 -0
  132. package/bin/runners/lib/analyzers.js +2500 -0
  133. package/bin/runners/lib/api-client.js +269 -0
  134. package/bin/runners/lib/approve-output.js +235 -0
  135. package/bin/runners/lib/artifact-envelope.js +540 -0
  136. package/bin/runners/lib/assets/vibecheck-logo.png +0 -0
  137. package/bin/runners/lib/audit-bridge.js +391 -0
  138. package/bin/runners/lib/auth-shared.js +977 -0
  139. package/bin/runners/lib/auth-truth.js +193 -0
  140. package/bin/runners/lib/auth.js +215 -0
  141. package/bin/runners/lib/authority-badge.js +425 -0
  142. package/bin/runners/lib/backup.js +62 -0
  143. package/bin/runners/lib/billing.js +107 -0
  144. package/bin/runners/lib/checkpoint.js +941 -0
  145. package/bin/runners/lib/claims.js +118 -0
  146. package/bin/runners/lib/classify-output.js +204 -0
  147. package/bin/runners/lib/cleanup/engine.js +571 -0
  148. package/bin/runners/lib/cleanup/index.js +53 -0
  149. package/bin/runners/lib/cleanup/output.js +375 -0
  150. package/bin/runners/lib/cleanup/rules.js +1060 -0
  151. package/bin/runners/lib/cli-output.js +400 -0
  152. package/bin/runners/lib/cli-ui.js +540 -0
  153. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  154. package/bin/runners/lib/compliance-bridge.js +165 -0
  155. package/bin/runners/lib/contracts/auth-contract.js +202 -0
  156. package/bin/runners/lib/contracts/env-contract.js +181 -0
  157. package/bin/runners/lib/contracts/external-contract.js +206 -0
  158. package/bin/runners/lib/contracts/guard.js +168 -0
  159. package/bin/runners/lib/contracts/index.js +89 -0
  160. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  161. package/bin/runners/lib/contracts/route-contract.js +199 -0
  162. package/bin/runners/lib/contracts.js +804 -0
  163. package/bin/runners/lib/default-config.js +127 -0
  164. package/bin/runners/lib/detect.js +89 -0
  165. package/bin/runners/lib/detectors-v2.js +622 -0
  166. package/bin/runners/lib/doctor/autofix.js +254 -0
  167. package/bin/runners/lib/doctor/diagnosis-receipt.js +454 -0
  168. package/bin/runners/lib/doctor/failure-signatures.js +526 -0
  169. package/bin/runners/lib/doctor/fix-script.js +336 -0
  170. package/bin/runners/lib/doctor/index.js +37 -0
  171. package/bin/runners/lib/doctor/modules/build-tools.js +453 -0
  172. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  173. package/bin/runners/lib/doctor/modules/index.js +105 -0
  174. package/bin/runners/lib/doctor/modules/network.js +250 -0
  175. package/bin/runners/lib/doctor/modules/os-quirks.js +706 -0
  176. package/bin/runners/lib/doctor/modules/project.js +312 -0
  177. package/bin/runners/lib/doctor/modules/repo-integrity.js +485 -0
  178. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  179. package/bin/runners/lib/doctor/modules/security.js +350 -0
  180. package/bin/runners/lib/doctor/modules/system.js +213 -0
  181. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  182. package/bin/runners/lib/doctor/reporter.js +262 -0
  183. package/bin/runners/lib/doctor/safe-repair.js +384 -0
  184. package/bin/runners/lib/doctor/service.js +262 -0
  185. package/bin/runners/lib/doctor/types.js +113 -0
  186. package/bin/runners/lib/doctor/ui.js +263 -0
  187. package/bin/runners/lib/doctor-enhanced.js +233 -0
  188. package/bin/runners/lib/doctor-output.js +226 -0
  189. package/bin/runners/lib/doctor-v2.js +608 -0
  190. package/bin/runners/lib/drift.js +425 -0
  191. package/bin/runners/lib/enforcement.js +72 -0
  192. package/bin/runners/lib/engine/ast-cache.js +210 -0
  193. package/bin/runners/lib/engine/auth-extractor.js +211 -0
  194. package/bin/runners/lib/engine/billing-extractor.js +112 -0
  195. package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
  196. package/bin/runners/lib/engine/env-extractor.js +207 -0
  197. package/bin/runners/lib/engine/express-extractor.js +208 -0
  198. package/bin/runners/lib/engine/extractors.js +849 -0
  199. package/bin/runners/lib/engine/index.js +207 -0
  200. package/bin/runners/lib/engine/repo-index.js +514 -0
  201. package/bin/runners/lib/engine/types.js +124 -0
  202. package/bin/runners/lib/engines/accessibility-engine.js +190 -0
  203. package/bin/runners/lib/engines/api-consistency-engine.js +162 -0
  204. package/bin/runners/lib/engines/ast-cache.js +99 -0
  205. package/bin/runners/lib/engines/attack-detector.js +1192 -0
  206. package/bin/runners/lib/engines/code-quality-engine.js +255 -0
  207. package/bin/runners/lib/engines/console-logs-engine.js +115 -0
  208. package/bin/runners/lib/engines/cross-file-analysis-engine.js +268 -0
  209. package/bin/runners/lib/engines/dead-code-engine.js +198 -0
  210. package/bin/runners/lib/engines/deprecated-api-engine.js +226 -0
  211. package/bin/runners/lib/engines/empty-catch-engine.js +150 -0
  212. package/bin/runners/lib/engines/file-filter.js +131 -0
  213. package/bin/runners/lib/engines/hardcoded-secrets-engine.js +251 -0
  214. package/bin/runners/lib/engines/mock-data-engine.js +272 -0
  215. package/bin/runners/lib/engines/parallel-processor.js +71 -0
  216. package/bin/runners/lib/engines/performance-issues-engine.js +265 -0
  217. package/bin/runners/lib/engines/security-vulnerabilities-engine.js +243 -0
  218. package/bin/runners/lib/engines/todo-fixme-engine.js +115 -0
  219. package/bin/runners/lib/engines/type-aware-engine.js +152 -0
  220. package/bin/runners/lib/engines/unsafe-regex-engine.js +225 -0
  221. package/bin/runners/lib/engines/vibecheck-engines/README.md +53 -0
  222. package/bin/runners/lib/engines/vibecheck-engines/index.js +15 -0
  223. package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
  224. package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
  225. package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
  226. package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
  227. package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
  228. package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
  229. package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
  230. package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +139 -0
  231. package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
  232. package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
  233. package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
  234. package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
  235. package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
  236. package/bin/runners/lib/engines/vibecheck-engines/package.json +13 -0
  237. package/bin/runners/lib/enterprise-detect.js +603 -0
  238. package/bin/runners/lib/enterprise-init.js +942 -0
  239. package/bin/runners/lib/entitlements-v2.js +265 -0
  240. package/bin/runners/lib/entitlements.generated.js +0 -0
  241. package/bin/runners/lib/entitlements.js +340 -0
  242. package/bin/runners/lib/env-resolver.js +417 -0
  243. package/bin/runners/lib/env-template.js +66 -0
  244. package/bin/runners/lib/env.js +189 -0
  245. package/bin/runners/lib/error-handler.js +368 -0
  246. package/bin/runners/lib/error-messages.js +289 -0
  247. package/bin/runners/lib/evidence-pack.js +684 -0
  248. package/bin/runners/lib/exit-codes.js +275 -0
  249. package/bin/runners/lib/extractors/client-calls.js +990 -0
  250. package/bin/runners/lib/extractors/fastify-route-dump.js +573 -0
  251. package/bin/runners/lib/extractors/fastify-routes.js +426 -0
  252. package/bin/runners/lib/extractors/index.js +363 -0
  253. package/bin/runners/lib/extractors/next-routes.js +524 -0
  254. package/bin/runners/lib/extractors/proof-graph.js +431 -0
  255. package/bin/runners/lib/extractors/route-matcher.js +451 -0
  256. package/bin/runners/lib/extractors/truthpack-v2.js +377 -0
  257. package/bin/runners/lib/extractors/ui-bindings.js +547 -0
  258. package/bin/runners/lib/finding-id.js +69 -0
  259. package/bin/runners/lib/finding-sorter.js +89 -0
  260. package/bin/runners/lib/findings-schema.js +281 -0
  261. package/bin/runners/lib/fingerprint.js +377 -0
  262. package/bin/runners/lib/firewall-prompt.js +50 -0
  263. package/bin/runners/lib/fix-output.js +228 -0
  264. package/bin/runners/lib/global-flags.js +250 -0
  265. package/bin/runners/lib/graph/graph-builder.js +265 -0
  266. package/bin/runners/lib/graph/html-renderer.js +413 -0
  267. package/bin/runners/lib/graph/index.js +32 -0
  268. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  269. package/bin/runners/lib/graph/static-extractor.js +518 -0
  270. package/bin/runners/lib/help-formatter.js +413 -0
  271. package/bin/runners/lib/html-proof-report.js +913 -0
  272. package/bin/runners/lib/html-report.js +650 -0
  273. package/bin/runners/lib/init-wizard.js +601 -0
  274. package/bin/runners/lib/interactive-menu.js +1496 -0
  275. package/bin/runners/lib/json-output.js +76 -0
  276. package/bin/runners/lib/llm.js +75 -0
  277. package/bin/runners/lib/logger.js +38 -0
  278. package/bin/runners/lib/meter.js +61 -0
  279. package/bin/runners/lib/missions/briefing.js +427 -0
  280. package/bin/runners/lib/missions/checkpoint.js +753 -0
  281. package/bin/runners/lib/missions/evidence.js +126 -0
  282. package/bin/runners/lib/missions/hardening.js +851 -0
  283. package/bin/runners/lib/missions/plan.js +648 -0
  284. package/bin/runners/lib/missions/safety-gates.js +645 -0
  285. package/bin/runners/lib/missions/schema.js +478 -0
  286. package/bin/runners/lib/missions/templates.js +317 -0
  287. package/bin/runners/lib/next-action.js +560 -0
  288. package/bin/runners/lib/packs/bundle.js +675 -0
  289. package/bin/runners/lib/packs/evidence-pack.js +671 -0
  290. package/bin/runners/lib/packs/pack-factory.js +837 -0
  291. package/bin/runners/lib/packs/permissions-pack.js +686 -0
  292. package/bin/runners/lib/packs/proof-graph-pack.js +779 -0
  293. package/bin/runners/lib/patch.js +40 -0
  294. package/bin/runners/lib/permissions/auth-model.js +213 -0
  295. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  296. package/bin/runners/lib/permissions/index.js +45 -0
  297. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  298. package/bin/runners/lib/pkgjson.js +28 -0
  299. package/bin/runners/lib/policy.js +295 -0
  300. package/bin/runners/lib/polish/accessibility.js +62 -0
  301. package/bin/runners/lib/polish/analyzer.js +93 -0
  302. package/bin/runners/lib/polish/backend.js +87 -0
  303. package/bin/runners/lib/polish/configuration.js +83 -0
  304. package/bin/runners/lib/polish/documentation.js +83 -0
  305. package/bin/runners/lib/polish/frontend.js +817 -0
  306. package/bin/runners/lib/polish/index.js +27 -0
  307. package/bin/runners/lib/polish/infrastructure.js +80 -0
  308. package/bin/runners/lib/polish/internationalization.js +85 -0
  309. package/bin/runners/lib/polish/libraries.js +180 -0
  310. package/bin/runners/lib/polish/observability.js +75 -0
  311. package/bin/runners/lib/polish/performance.js +64 -0
  312. package/bin/runners/lib/polish/privacy.js +110 -0
  313. package/bin/runners/lib/polish/resilience.js +92 -0
  314. package/bin/runners/lib/polish/security.js +78 -0
  315. package/bin/runners/lib/polish/seo.js +71 -0
  316. package/bin/runners/lib/polish/styles.js +62 -0
  317. package/bin/runners/lib/polish/utils.js +104 -0
  318. package/bin/runners/lib/preflight.js +142 -0
  319. package/bin/runners/lib/prerequisites.js +149 -0
  320. package/bin/runners/lib/prove-output.js +220 -0
  321. package/bin/runners/lib/reality/correlation-detectors.js +359 -0
  322. package/bin/runners/lib/reality/index.js +318 -0
  323. package/bin/runners/lib/reality/request-hashing.js +416 -0
  324. package/bin/runners/lib/reality/request-mapper.js +453 -0
  325. package/bin/runners/lib/reality/safety-rails.js +463 -0
  326. package/bin/runners/lib/reality/semantic-snapshot.js +408 -0
  327. package/bin/runners/lib/reality/toast-detector.js +393 -0
  328. package/bin/runners/lib/reality-findings.js +84 -0
  329. package/bin/runners/lib/reality-output.js +231 -0
  330. package/bin/runners/lib/receipts.js +179 -0
  331. package/bin/runners/lib/redact.js +29 -0
  332. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  333. package/bin/runners/lib/replay/index.js +263 -0
  334. package/bin/runners/lib/replay/player.js +348 -0
  335. package/bin/runners/lib/replay/recorder.js +331 -0
  336. package/bin/runners/lib/report-engine.js +626 -0
  337. package/bin/runners/lib/report-html.js +1233 -0
  338. package/bin/runners/lib/report-output.js +366 -0
  339. package/bin/runners/lib/report-templates.js +967 -0
  340. package/bin/runners/lib/report.js +135 -0
  341. package/bin/runners/lib/route-detection.js +1209 -0
  342. package/bin/runners/lib/route-truth.js +1322 -0
  343. package/bin/runners/lib/safelist/index.js +96 -0
  344. package/bin/runners/lib/safelist/integration.js +334 -0
  345. package/bin/runners/lib/safelist/matcher.js +696 -0
  346. package/bin/runners/lib/safelist/schema.js +948 -0
  347. package/bin/runners/lib/safelist/store.js +438 -0
  348. package/bin/runners/lib/sandbox/index.js +59 -0
  349. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  350. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  351. package/bin/runners/lib/sandbox/worktree.js +174 -0
  352. package/bin/runners/lib/scan-cache.js +330 -0
  353. package/bin/runners/lib/scan-output-schema.js +344 -0
  354. package/bin/runners/lib/scan-output.js +631 -0
  355. package/bin/runners/lib/scan-runner.js +135 -0
  356. package/bin/runners/lib/schema-validator.js +350 -0
  357. package/bin/runners/lib/schemas/ajv-validator.js +464 -0
  358. package/bin/runners/lib/schemas/contracts.schema.json +160 -0
  359. package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
  360. package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
  361. package/bin/runners/lib/schemas/finding.schema.json +100 -0
  362. package/bin/runners/lib/schemas/mission-pack.schema.json +206 -0
  363. package/bin/runners/lib/schemas/proof-graph.schema.json +176 -0
  364. package/bin/runners/lib/schemas/reality-report.schema.json +162 -0
  365. package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
  366. package/bin/runners/lib/schemas/run-request.schema.json +108 -0
  367. package/bin/runners/lib/schemas/share-pack.schema.json +180 -0
  368. package/bin/runners/lib/schemas/ship-manifest.schema.json +251 -0
  369. package/bin/runners/lib/schemas/ship-report.schema.json +117 -0
  370. package/bin/runners/lib/schemas/truthpack-v2.schema.json +303 -0
  371. package/bin/runners/lib/schemas/validator.js +465 -0
  372. package/bin/runners/lib/schemas/verdict.schema.json +140 -0
  373. package/bin/runners/lib/score-history.js +282 -0
  374. package/bin/runners/lib/security-bridge.js +249 -0
  375. package/bin/runners/lib/server-usage.js +513 -0
  376. package/bin/runners/lib/share-pack.js +239 -0
  377. package/bin/runners/lib/ship-gate.js +832 -0
  378. package/bin/runners/lib/ship-manifest.js +1153 -0
  379. package/bin/runners/lib/ship-output-enterprise.js +239 -0
  380. package/bin/runners/lib/ship-output.js +1128 -0
  381. package/bin/runners/lib/snippets.js +67 -0
  382. package/bin/runners/lib/status-output.js +340 -0
  383. package/bin/runners/lib/terminal-ui.js +356 -0
  384. package/bin/runners/lib/truth.js +1691 -0
  385. package/bin/runners/lib/ui.js +562 -0
  386. package/bin/runners/lib/unified-cli-output.js +947 -0
  387. package/bin/runners/lib/unified-output.js +197 -0
  388. package/bin/runners/lib/upsell.js +410 -0
  389. package/bin/runners/lib/usage.js +153 -0
  390. package/bin/runners/lib/validate-patch.js +156 -0
  391. package/bin/runners/lib/verdict-engine.js +628 -0
  392. package/bin/runners/lib/verification.js +345 -0
  393. package/bin/runners/lib/why-tree.js +650 -0
  394. package/bin/runners/reality/engine.js +917 -0
  395. package/bin/runners/reality/flows.js +122 -0
  396. package/bin/runners/reality/report.js +378 -0
  397. package/bin/runners/reality/session.js +193 -0
  398. package/bin/runners/runAIAgent.js +229 -0
  399. package/bin/runners/runAgent.d.ts +5 -0
  400. package/bin/runners/runAgent.js +161 -0
  401. package/bin/runners/runAllowlist.js +418 -0
  402. package/bin/runners/runApprove.js +320 -0
  403. package/bin/runners/runAudit.js +692 -0
  404. package/bin/runners/runAuth.js +731 -0
  405. package/bin/runners/runCI.js +353 -0
  406. package/bin/runners/runCheckpoint.js +530 -0
  407. package/bin/runners/runClassify.js +928 -0
  408. package/bin/runners/runCleanup.js +343 -0
  409. package/bin/runners/runContext.d.ts +4 -0
  410. package/bin/runners/runContext.js +175 -0
  411. package/bin/runners/runDoctor.js +877 -0
  412. package/bin/runners/runEvidencePack.js +362 -0
  413. package/bin/runners/runFirewall.d.ts +5 -0
  414. package/bin/runners/runFirewall.js +134 -0
  415. package/bin/runners/runFirewallHook.d.ts +5 -0
  416. package/bin/runners/runFirewallHook.js +56 -0
  417. package/bin/runners/runFix.js +1355 -0
  418. package/bin/runners/runForge.js +451 -0
  419. package/bin/runners/runGuard.js +262 -0
  420. package/bin/runners/runInit.js +1927 -0
  421. package/bin/runners/runIntent.js +906 -0
  422. package/bin/runners/runKickoff.js +878 -0
  423. package/bin/runners/runLabs.js +424 -0
  424. package/bin/runners/runLaunch.js +2000 -0
  425. package/bin/runners/runLink.js +785 -0
  426. package/bin/runners/runMcp.js +1875 -0
  427. package/bin/runners/runPacks.js +2089 -0
  428. package/bin/runners/runPolish.d.ts +4 -0
  429. package/bin/runners/runPolish.js +390 -0
  430. package/bin/runners/runPromptFirewall.js +211 -0
  431. package/bin/runners/runProve.js +1411 -0
  432. package/bin/runners/runQuickstart.js +531 -0
  433. package/bin/runners/runReality.js +2260 -0
  434. package/bin/runners/runReport.js +726 -0
  435. package/bin/runners/runRuntime.js +110 -0
  436. package/bin/runners/runSafelist.js +1190 -0
  437. package/bin/runners/runScan.js +688 -0
  438. package/bin/runners/runShield.js +1282 -0
  439. package/bin/runners/runShip.js +1660 -0
  440. package/bin/runners/runTruth.d.ts +5 -0
  441. package/bin/runners/runTruth.js +101 -0
  442. package/bin/runners/runValidate.js +179 -0
  443. package/bin/runners/runWatch.js +478 -0
  444. package/bin/runners/utils.js +360 -0
  445. package/bin/scan.js +617 -0
  446. package/bin/vibecheck.js +1617 -0
  447. package/dist/guardrail/index.d.ts +2405 -0
  448. package/dist/guardrail/index.js +9747 -0
  449. package/dist/guardrail/index.js.map +1 -0
  450. package/dist/scanner/index.d.ts +282 -0
  451. package/dist/scanner/index.js +3395 -0
  452. package/dist/scanner/index.js.map +1 -0
  453. package/package.json +123 -104
  454. package/README.md +0 -491
  455. package/dist/index.js +0 -99711
  456. package/dist/index.js.map +0 -1
@@ -0,0 +1,817 @@
1
+ /**
2
+ * Frontend Polish Engine
3
+ *
4
+ * Checks: Error boundaries, loading states, empty states, toasts,
5
+ * form validation, animations, hover states, haptics, ARIA,
6
+ * focus traps, skip links, data caching, memoization, logging,
7
+ * error tracking, lazy images, dark mode, confirm dialogs,
8
+ * optimistic updates, keyboard shortcuts, scroll-to-top, progress bars.
9
+ */
10
+
11
+ const path = require("path");
12
+ const {
13
+ pathExists,
14
+ findFile,
15
+ findAllFiles,
16
+ readFileSafe,
17
+ } = require("./utils");
18
+ const {
19
+ LIBRARY_ALTERNATIVES,
20
+ hasLibrary,
21
+ detectProjectType,
22
+ adjustSeverity,
23
+ } = require("./libraries");
24
+
25
+ module.exports = async function frontendEngine(projectPath) {
26
+ const issues = [];
27
+ const srcPath = path.join(projectPath, "src");
28
+ const appPath = path.join(projectPath, "app");
29
+ const pagesPath = path.join(projectPath, "pages");
30
+ const componentsPath = path.join(srcPath, "components");
31
+
32
+ const hasSrc = await pathExists(srcPath);
33
+ const hasApp = await pathExists(appPath);
34
+ const hasPages = await pathExists(pagesPath);
35
+
36
+ if (!hasSrc && !hasApp && !hasPages) return issues;
37
+
38
+ const searchPath = hasSrc ? srcPath : hasApp ? appPath : pagesPath;
39
+ const packageJson = await readFileSafe(path.join(projectPath, "package.json"));
40
+
41
+ const projectType = await detectProjectType(projectPath, packageJson);
42
+ if (projectType.skipFrontend) return issues;
43
+
44
+ // Detect installed libraries
45
+ const errorBoundaryLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.errorBoundary);
46
+ const toastLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.toast);
47
+ const spinnerLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.spinner);
48
+ const skeletonLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.skeleton);
49
+ const formLib = hasLibrary(packageJson, LIBRARY_ALTERNATIVES.formValidation);
50
+
51
+ // ── Error Handling & Boundaries ──────────────────────────────────────────
52
+
53
+ const hasErrorBoundary = await findFile(searchPath, /ErrorBoundary|error\.(tsx?|jsx?)$/i);
54
+ if (!hasErrorBoundary && !errorBoundaryLib && !projectType.uiLibrary) {
55
+ issues.push({
56
+ id: "missing-error-boundary",
57
+ category: "Frontend",
58
+ severity: adjustSeverity("critical", projectType, "missing-error-boundary"),
59
+ title: "Missing Error Boundary",
60
+ description: "No error boundary component found. React errors will crash the entire app.",
61
+ suggestion: "Add ErrorBoundary component to catch and handle React errors gracefully.",
62
+ autoFixable: true,
63
+ confidence: 0.9,
64
+ aiPrompt: `Create a reusable ErrorBoundary component for React/Next.js that:
65
+ 1. Catches JavaScript errors anywhere in the child component tree
66
+ 2. Logs errors to console and optionally to an error tracking service
67
+ 3. Displays a user-friendly fallback UI with:
68
+ - A friendly error message
69
+ - A "Try Again" button that resets the error state
70
+ - Option to report the error
71
+ 4. Supports custom fallback UI via props
72
+ 5. Uses TypeScript with proper typing
73
+ 6. Includes a useErrorBoundary hook for functional components
74
+ 7. Has smooth fade-in animation for the fallback UI
75
+
76
+ Place it in src/components/ErrorBoundary.tsx`,
77
+ });
78
+ }
79
+
80
+ const has404 = await findFile(searchPath, /not-found|NotFound|404/i);
81
+ const hasNextAppRouter404 = hasApp && (await pathExists(path.join(appPath, "not-found.tsx")));
82
+ if (!has404 && !hasNextAppRouter404) {
83
+ issues.push({
84
+ id: "missing-404",
85
+ category: "Frontend",
86
+ severity: adjustSeverity("medium", projectType, "missing-404"),
87
+ title: "Missing 404 Page",
88
+ description: "No custom 404/NotFound page found. Users will see default browser error.",
89
+ suggestion: "Add a custom 404 page with navigation options.",
90
+ autoFixable: true,
91
+ confidence: 0.85,
92
+ aiPrompt: `Create a beautiful, user-friendly 404 Not Found page that:
93
+ 1. Has a visually appealing design with subtle animations
94
+ 2. Shows a clear "Page Not Found" message
95
+ 3. Includes helpful navigation options:
96
+ - Go back to previous page button
97
+ - Go to homepage button
98
+ - Search functionality (if applicable)
99
+ - Popular/suggested links
100
+ 4. Has a fun illustration or animation (CSS-based, no external images)
101
+ 5. Is fully responsive for mobile
102
+ 6. Maintains the site's design language
103
+ 7. Includes proper meta tags for SEO
104
+
105
+ For Next.js App Router: Create app/not-found.tsx
106
+ For Pages Router: Create pages/404.tsx`,
107
+ });
108
+ }
109
+
110
+ // ── Loading States & Skeletons ───────────────────────────────────────────
111
+
112
+ const hasLoadingSpinner = await findFile(searchPath, /Spinner|LoadingSpinner|Loading\.(tsx?|jsx?)$/i);
113
+ if (!hasLoadingSpinner && !spinnerLib && !projectType.uiLibrary) {
114
+ issues.push({
115
+ id: "missing-spinner",
116
+ category: "Frontend",
117
+ severity: adjustSeverity("high", projectType, "missing-spinner"),
118
+ title: "Missing Loading Spinner",
119
+ description: "No spinner component found. Users need visual feedback during loading.",
120
+ suggestion: spinnerLib
121
+ ? `Consider using the ${spinnerLib} library you have installed.`
122
+ : "Add a reusable Spinner component with multiple sizes and variants.",
123
+ autoFixable: true,
124
+ confidence: 0.7,
125
+ aiPrompt: `Create a modern, reusable Spinner/Loading component that:
126
+ 1. Has multiple size variants: sm, md, lg, xl
127
+ 2. Supports custom colors via props or CSS variables
128
+ 3. Has multiple styles: circular spinner, dots, pulse, bars
129
+ 4. Uses pure CSS animations (no external dependencies)
130
+ 5. Is accessible with proper ARIA attributes (role="status", aria-label)
131
+ 6. Supports dark/light mode automatically
132
+ 7. Can be used inline or as an overlay
133
+ 8. Has smooth entrance/exit animations
134
+ 9. TypeScript with proper prop types
135
+
136
+ Create: src/components/ui/Spinner.tsx and src/components/ui/Spinner.css`,
137
+ });
138
+ }
139
+
140
+ const hasSkeleton = await findFile(searchPath, /Skeleton|Shimmer|ContentLoader/i);
141
+ if (!hasSkeleton && !skeletonLib && !projectType.uiLibrary) {
142
+ issues.push({
143
+ id: "missing-skeleton",
144
+ category: "Frontend",
145
+ severity: adjustSeverity("high", projectType, "missing-skeleton"),
146
+ title: "Missing Skeleton Loaders",
147
+ description: "No skeleton/shimmer components found. Skeleton loaders provide better perceived performance than spinners.",
148
+ suggestion: skeletonLib
149
+ ? `Consider using the ${skeletonLib} library you have installed.`
150
+ : "Add skeleton components for content placeholders.",
151
+ autoFixable: true,
152
+ confidence: 0.65,
153
+ aiPrompt: `Create a comprehensive Skeleton loading system with:
154
+
155
+ 1. Base Skeleton component with:
156
+ - Shimmer animation effect
157
+ - Multiple variants: text, circular, rectangular, rounded
158
+ - Customizable width, height, border-radius
159
+ - Animation that flows left-to-right with gradient
160
+
161
+ 2. Pre-built skeleton patterns:
162
+ - SkeletonText (paragraph lines with varying widths)
163
+ - SkeletonAvatar (circular profile picture placeholder)
164
+ - SkeletonCard (card layout placeholder)
165
+ - SkeletonTable (table rows placeholder)
166
+ - SkeletonList (list items placeholder)
167
+ - SkeletonImage (image placeholder with aspect ratio)
168
+
169
+ 3. Features:
170
+ - CSS-only animations (performant)
171
+ - Dark/light mode support
172
+ - Customizable animation speed
173
+ - Can disable animation for reduced motion preference
174
+ - TypeScript with proper types
175
+
176
+ Create: src/components/ui/Skeleton.tsx with all variants`,
177
+ });
178
+ }
179
+
180
+ const hasLoadingPage = await findFile(searchPath, /loading\.(tsx?|jsx?)$/i);
181
+ if (!hasLoadingPage && hasApp) {
182
+ issues.push({
183
+ id: "missing-loading-page",
184
+ category: "Frontend",
185
+ severity: "medium",
186
+ title: "Missing Next.js Loading State",
187
+ description: "No loading.tsx found. Next.js App Router supports automatic loading states.",
188
+ suggestion: "Add loading.tsx files for route segments.",
189
+ autoFixable: true,
190
+ aiPrompt: `Create a loading.tsx file for Next.js App Router that:
191
+ 1. Shows a full-page skeleton loader matching your layout
192
+ 2. Uses your Skeleton components for consistency
193
+ 3. Includes a subtle progress indicator
194
+ 4. Maintains layout structure to prevent layout shift
195
+ 5. Has smooth fade-out when content loads
196
+
197
+ Create: app/loading.tsx (root level) and consider adding to major route segments`,
198
+ });
199
+ }
200
+
201
+ // ── Empty States & Feedback ──────────────────────────────────────────────
202
+
203
+ const hasEmptyState = await findFile(searchPath, /EmptyState|Empty|NoData|NoResults/i);
204
+ if (!hasEmptyState) {
205
+ issues.push({
206
+ id: "missing-empty-states",
207
+ category: "Frontend",
208
+ severity: "medium",
209
+ title: "Missing Empty States",
210
+ description: "No empty state components found. Users need helpful messages when data is empty.",
211
+ suggestion: "Add EmptyState components for lists and data displays.",
212
+ autoFixable: true,
213
+ aiPrompt: `Create a versatile EmptyState component system with:
214
+
215
+ 1. Base EmptyState component with:
216
+ - Icon slot (customizable)
217
+ - Title and description
218
+ - Action button(s)
219
+ - Illustration option
220
+
221
+ 2. Pre-built variants:
222
+ - EmptySearch: "No results found" with search tips
223
+ - EmptyList: "No items yet" with add item CTA
224
+ - EmptyInbox: "All caught up!" positive empty state
225
+ - EmptyError: "Something went wrong" with retry
226
+ - EmptyPermission: "Access denied" with request access
227
+ - EmptyOffline: "You're offline" with retry when online
228
+
229
+ 3. Features:
230
+ - Subtle entrance animation
231
+ - Responsive design
232
+ - Supports custom illustrations
233
+ - Action buttons with loading states
234
+ - TypeScript with proper props
235
+
236
+ Create: src/components/ui/EmptyState.tsx with all variants`,
237
+ });
238
+ }
239
+
240
+ const hasToast = await findFile(searchPath, /Toast|Notification|Snackbar|Toaster/i);
241
+ if (!hasToast && !toastLib && !projectType.uiLibrary) {
242
+ issues.push({
243
+ id: "missing-toast",
244
+ category: "Frontend",
245
+ severity: adjustSeverity("high", projectType, "missing-toast"),
246
+ title: "Missing Toast/Notification System",
247
+ description: "No toast or notification component found for user feedback.",
248
+ suggestion: toastLib
249
+ ? `Consider using the ${toastLib} library you have installed.`
250
+ : "Add a toast/notification system for user feedback on actions.",
251
+ autoFixable: true,
252
+ confidence: 0.75,
253
+ aiPrompt: `Create a complete Toast notification system with:
254
+
255
+ 1. Toast component with:
256
+ - Variants: success, error, warning, info, loading
257
+ - Auto-dismiss with configurable duration
258
+ - Manual dismiss button
259
+ - Progress bar showing time remaining
260
+ - Stack multiple toasts
261
+ - Position options: top-right, top-center, bottom-right, etc.
262
+
263
+ 2. Toast provider/context:
264
+ - useToast() hook for easy triggering
265
+ - toast.success(), toast.error(), etc. methods
266
+ - toast.promise() for async operations
267
+ - Global configuration
268
+
269
+ 3. Features:
270
+ - Smooth slide-in/out animations
271
+ - Swipe to dismiss on mobile
272
+ - Pause on hover
273
+ - Accessible with ARIA live regions
274
+ - Queue management
275
+ - TypeScript with proper types
276
+
277
+ Create: src/components/ui/Toast.tsx and src/hooks/useToast.ts`,
278
+ });
279
+ }
280
+
281
+ // ── Forms & Input Feedback ───────────────────────────────────────────────
282
+
283
+ const hasFormValidation = await findFile(searchPath, /FormError|FieldError|ValidationMessage/i);
284
+ if (!hasFormValidation && !formLib && !projectType.uiLibrary) {
285
+ issues.push({
286
+ id: "missing-form-validation-ui",
287
+ category: "Frontend",
288
+ severity: adjustSeverity("high", projectType, "missing-form-validation-ui"),
289
+ title: "Missing Form Validation UI",
290
+ description: "No form validation components found. Users need clear feedback on form errors.",
291
+ suggestion: formLib
292
+ ? `The ${formLib} library you have installed provides form validation. Make sure to display errors.`
293
+ : "Add form validation components with clear error states.",
294
+ autoFixable: true,
295
+ confidence: 0.65,
296
+ aiPrompt: `Create a comprehensive form validation UI system with:
297
+
298
+ 1. FormField wrapper component with:
299
+ - Label with required indicator
300
+ - Help text / description
301
+ - Error message display
302
+ - Success state indicator
303
+ - Character counter for text inputs
304
+
305
+ 2. Input components with built-in validation states:
306
+ - TextInput with error/success borders
307
+ - SelectInput with validation
308
+ - Checkbox/Radio with error states
309
+ - TextArea with validation
310
+
311
+ 3. Validation feedback:
312
+ - Inline error messages with icons
313
+ - Shake animation on error
314
+ - Real-time validation feedback
315
+ - Form-level error summary
316
+ - Success checkmark animation
317
+
318
+ 4. Features:
319
+ - Works with react-hook-form or standalone
320
+ - Accessible error announcements
321
+ - Touch-friendly error targets
322
+ - TypeScript with proper types
323
+
324
+ Create: src/components/ui/FormField.tsx and related input components`,
325
+ });
326
+ }
327
+
328
+ // ── Micro-Interactions & Animations ──────────────────────────────────────
329
+
330
+ const hasAnimationLib =
331
+ packageJson && /framer-motion|react-spring|@react-spring|gsap|animejs/i.test(packageJson);
332
+ const hasAnimations = await findFile(searchPath, /animate|motion|transition|useSpring/i);
333
+ if (!hasAnimationLib && !hasAnimations) {
334
+ issues.push({
335
+ id: "missing-animations",
336
+ category: "Frontend",
337
+ severity: "medium",
338
+ title: "Missing Animation System",
339
+ description: "No animation library or utilities found. Animations make UX feel polished.",
340
+ suggestion: "Add framer-motion or CSS animations for micro-interactions.",
341
+ autoFixable: true,
342
+ aiPrompt: `Create a lightweight animation system with:
343
+
344
+ 1. CSS animation utilities (no library needed):
345
+ - Fade in/out
346
+ - Slide in from directions
347
+ - Scale up/down
348
+ - Bounce, pulse, shake
349
+ - Stagger children animations
350
+
351
+ 2. Animation wrapper components:
352
+ - <FadeIn> - fade in on mount
353
+ - <SlideIn direction="up|down|left|right">
354
+ - <ScaleIn> - scale from 0 to 1
355
+ - <AnimatePresence> - animate on unmount
356
+ - <StaggerChildren> - stagger child animations
357
+
358
+ 3. CSS utilities:
359
+ - .animate-fade-in, .animate-slide-up, etc.
360
+ - Animation delay utilities
361
+ - Reduced motion media query support
362
+ - Duration and easing variables
363
+
364
+ 4. Hooks:
365
+ - useInView() - trigger animation when element is visible
366
+ - useAnimation() - programmatic control
367
+
368
+ Create: src/styles/animations.css and src/components/ui/Animate.tsx
369
+
370
+ Or install framer-motion: npm install framer-motion`,
371
+ });
372
+ }
373
+
374
+ const cssFiles = await findAllFiles(searchPath, /\.(css|scss|tsx?|jsx?)$/);
375
+ let foundHoverStates = false;
376
+ for (const file of cssFiles.slice(0, 20)) {
377
+ const content = await readFileSafe(file);
378
+ if (content && /:hover|onMouseEnter|hover:/i.test(content)) {
379
+ foundHoverStates = true;
380
+ break;
381
+ }
382
+ }
383
+ if (!foundHoverStates) {
384
+ issues.push({
385
+ id: "missing-hover-states",
386
+ category: "Frontend",
387
+ severity: "medium",
388
+ title: "Missing Hover States",
389
+ description: "No hover effects detected. Interactive elements need visual feedback on hover.",
390
+ suggestion: "Add hover states to buttons, links, and interactive elements.",
391
+ autoFixable: true,
392
+ aiPrompt: `Add comprehensive hover states to your components:
393
+
394
+ 1. Button hover effects:
395
+ - Subtle background color shift
396
+ - Slight scale transform (1.02)
397
+ - Shadow elevation change
398
+ - Underline animation for text buttons
399
+
400
+ 2. Card hover effects:
401
+ - Lift effect with shadow
402
+ - Border color change
403
+ - Subtle background shift
404
+ - Scale transform
405
+
406
+ 3. Link hover effects:
407
+ - Underline animation (slide in)
408
+ - Color transition
409
+ - Arrow/icon movement
410
+
411
+ 4. Interactive elements:
412
+ - Focus-visible states (keyboard users)
413
+ - Active/pressed states
414
+ - Disabled state styling
415
+
416
+ 5. CSS utilities to add:
417
+ \`\`\`css
418
+ .hover-lift:hover {
419
+ transform: translateY(-2px);
420
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
421
+ }
422
+
423
+ .hover-scale:hover {
424
+ transform: scale(1.02);
425
+ }
426
+
427
+ .hover-glow:hover {
428
+ box-shadow: 0 0 20px rgba(var(--primary-rgb), 0.3);
429
+ }
430
+ \`\`\`
431
+
432
+ Add to: src/styles/interactions.css or your global styles`,
433
+ });
434
+ }
435
+
436
+ // ── Haptic Feedback & Mobile UX ──────────────────────────────────────────
437
+
438
+ const hasHapticFeedback = await findFile(searchPath, /haptic|vibrate|navigator\.vibrate/i);
439
+ if (!hasHapticFeedback) {
440
+ issues.push({
441
+ id: "missing-haptic-feedback",
442
+ category: "Frontend",
443
+ severity: "low",
444
+ title: "Missing Haptic Feedback",
445
+ description: "No haptic feedback found. Mobile users benefit from tactile feedback on interactions.",
446
+ suggestion: "Add haptic feedback for key interactions on mobile.",
447
+ autoFixable: true,
448
+ aiPrompt: `Create a haptic feedback utility system:
449
+
450
+ 1. useHaptic() hook:
451
+ \`\`\`typescript
452
+ const useHaptic = () => {
453
+ const trigger = (type: 'light' | 'medium' | 'heavy' | 'success' | 'error') => {
454
+ if (!navigator.vibrate) return;
455
+ const patterns = {
456
+ light: [10],
457
+ medium: [20],
458
+ heavy: [30],
459
+ success: [10, 50, 10],
460
+ error: [50, 30, 50, 30, 50],
461
+ };
462
+ navigator.vibrate(patterns[type]);
463
+ };
464
+ return { trigger };
465
+ };
466
+ \`\`\`
467
+
468
+ 2. Integration points:
469
+ - Button clicks (light)
470
+ - Form submission success (success)
471
+ - Form validation error (error)
472
+ - Toggle switches (light)
473
+ - Pull-to-refresh complete (medium)
474
+ - Delete/destructive actions (heavy)
475
+
476
+ Create: src/hooks/useHaptic.ts`,
477
+ });
478
+ }
479
+
480
+ const hasPullToRefresh = await findFile(searchPath, /PullToRefresh|pull-to-refresh|usePullRefresh/i);
481
+ if (!hasPullToRefresh && packageJson && /react-native|mobile|pwa/i.test(packageJson)) {
482
+ issues.push({
483
+ id: "missing-pull-refresh",
484
+ category: "Frontend",
485
+ severity: "low",
486
+ title: "Missing Pull-to-Refresh",
487
+ description: "No pull-to-refresh found. Mobile/PWA apps benefit from this gesture.",
488
+ suggestion: "Add pull-to-refresh for mobile list views.",
489
+ autoFixable: true,
490
+ aiPrompt: `Create a pull-to-refresh component for mobile:
491
+
492
+ 1. PullToRefresh wrapper component:
493
+ - Touch gesture detection
494
+ - Visual pull indicator
495
+ - Loading spinner during refresh
496
+ - Haptic feedback on trigger
497
+ - Smooth animations
498
+
499
+ 2. Features:
500
+ - Configurable pull threshold
501
+ - Custom pull indicator
502
+ - Callback on refresh
503
+ - Disable on desktop
504
+
505
+ Create: src/components/ui/PullToRefresh.tsx`,
506
+ });
507
+ }
508
+
509
+ // ── Accessibility (ARIA & A11Y) ──────────────────────────────────────────
510
+
511
+ const hasAriaLive = await findFile(searchPath, /aria-live|role="alert"|role="status"/i);
512
+ if (!hasAriaLive) {
513
+ issues.push({
514
+ id: "missing-aria-live",
515
+ category: "Frontend",
516
+ severity: "high",
517
+ title: "Missing ARIA Live Regions",
518
+ description: "No ARIA live regions found. Screen readers won't announce dynamic content changes.",
519
+ suggestion: "Add aria-live regions for toasts, alerts, and dynamic updates.",
520
+ autoFixable: true,
521
+ aiPrompt: `Add ARIA live regions for accessibility:
522
+
523
+ 1. Create an Announcer component for screen readers:
524
+ \`\`\`tsx
525
+ const Announcer = () => {
526
+ const [message, setMessage] = useState('');
527
+ useEffect(() => {
528
+ window.announce = (msg: string) => setMessage(msg);
529
+ return () => delete window.announce;
530
+ }, []);
531
+ return (
532
+ <div role="status" aria-live="polite" aria-atomic="true" className="sr-only">
533
+ {message}
534
+ </div>
535
+ );
536
+ };
537
+ \`\`\`
538
+
539
+ 2. Places to add aria-live:
540
+ - Toast notifications: aria-live="polite"
541
+ - Error alerts: aria-live="assertive"
542
+ - Loading states: aria-live="polite" aria-busy="true"
543
+ - Search results count
544
+ - Form validation errors
545
+
546
+ Create: src/components/ui/Announcer.tsx`,
547
+ });
548
+ }
549
+
550
+ const hasFocusTrap = await findFile(searchPath, /FocusTrap|focus-trap|useFocusTrap/i);
551
+ const hasModal = await findFile(searchPath, /Modal|Dialog|Drawer/i);
552
+ if (hasModal && !hasFocusTrap) {
553
+ issues.push({
554
+ id: "missing-focus-trap",
555
+ category: "Frontend",
556
+ severity: "high",
557
+ title: "Missing Focus Trap for Modals",
558
+ description: "Modal/Dialog found but no focus trap. Keyboard users can tab outside the modal.",
559
+ suggestion: "Add focus trap to modals and dialogs.",
560
+ autoFixable: true,
561
+ aiPrompt: `Add focus trapping to modals and dialogs:
562
+
563
+ 1. Create useFocusTrap hook that:
564
+ - Traps Tab/Shift+Tab within the modal
565
+ - Focuses first focusable element on open
566
+ - Returns focus to trigger element on close
567
+ - Handles Escape key to close
568
+ - Prevents body scroll when open
569
+ - Sets aria-modal="true" on modal
570
+
571
+ Create: src/hooks/useFocusTrap.ts`,
572
+ });
573
+ }
574
+
575
+ const hasSkipLink = await findFile(searchPath, /SkipLink|skip-to-content|skip-nav/i);
576
+ if (!hasSkipLink) {
577
+ issues.push({
578
+ id: "missing-skip-link",
579
+ category: "Frontend",
580
+ severity: "medium",
581
+ title: "Missing Skip Link",
582
+ description: "No skip-to-content link found. Keyboard users can't skip navigation.",
583
+ suggestion: "Add a skip-to-main-content link at the top of pages.",
584
+ autoFixable: true,
585
+ aiPrompt: `Add a skip link for keyboard navigation:
586
+
587
+ \`\`\`tsx
588
+ export const SkipLink = () => (
589
+ <a href="#main-content" className="skip-link">
590
+ Skip to main content
591
+ </a>
592
+ );
593
+ \`\`\`
594
+
595
+ Place at the very top of your layout, before the header.
596
+ Add id="main-content" to your <main> element.`,
597
+ });
598
+ }
599
+
600
+ // ── Caching & Performance ────────────────────────────────────────────────
601
+
602
+ const hasSWR = packageJson && /swr|@tanstack\/react-query|react-query/i.test(packageJson);
603
+ if (!hasSWR) {
604
+ issues.push({
605
+ id: "missing-data-caching",
606
+ category: "Frontend",
607
+ severity: "high",
608
+ title: "Missing Data Caching Library",
609
+ description: "No SWR or React Query found. Data fetching lacks caching, revalidation, and deduplication.",
610
+ suggestion: "Add SWR or TanStack Query for data caching and synchronization.",
611
+ autoFixable: false,
612
+ aiPrompt: `Add a data fetching and caching solution:
613
+
614
+ Option 1: SWR (lighter weight) - npm install swr
615
+ Option 2: TanStack Query (more features) - npm install @tanstack/react-query
616
+
617
+ Benefits: automatic caching, background revalidation, request deduplication, optimistic updates, offline support, retry logic.`,
618
+ });
619
+ }
620
+
621
+ const hasMemoization = await findFile(searchPath, /useMemo|useCallback|React\.memo/i);
622
+ if (!hasMemoization) {
623
+ issues.push({
624
+ id: "missing-memoization",
625
+ category: "Frontend",
626
+ severity: "low",
627
+ title: "No Memoization Detected",
628
+ description: "No useMemo/useCallback/React.memo usage found. May have unnecessary re-renders.",
629
+ suggestion: "Review components for memoization opportunities.",
630
+ autoFixable: false,
631
+ aiPrompt: `Review components for memoization opportunities:
632
+ - useMemo for expensive calculations
633
+ - useCallback for functions passed as props
634
+ - React.memo for components receiving same props
635
+ Focus on: list items, charts, components receiving objects/arrays as props.`,
636
+ });
637
+ }
638
+
639
+ // ── Logging & Debugging ──────────────────────────────────────────────────
640
+
641
+ const hasLogger = await findFile(searchPath, /logger|logging|winston|pino|loglevel/i);
642
+ if (!hasLogger) {
643
+ issues.push({
644
+ id: "missing-frontend-logger",
645
+ category: "Frontend",
646
+ severity: "medium",
647
+ title: "Missing Logging System",
648
+ description: "No structured logging found. console.log statements are not suitable for production.",
649
+ suggestion: "Add a logging utility that can be disabled in production.",
650
+ autoFixable: true,
651
+ aiPrompt: `Create a frontend logging utility (lib/logger.ts) with:
652
+ - Log levels: debug, info, warn, error
653
+ - Silent in production (except warn/error)
654
+ - Error-level logs sent to error tracking service
655
+ - Performance timing helpers (time/timeEnd)
656
+ - Group logging support`,
657
+ });
658
+ }
659
+
660
+ const hasErrorTracking =
661
+ packageJson && /sentry|bugsnag|rollbar|logrocket|@sentry/i.test(packageJson);
662
+ if (!hasErrorTracking) {
663
+ issues.push({
664
+ id: "missing-error-tracking",
665
+ category: "Frontend",
666
+ severity: "high",
667
+ title: "Missing Error Tracking",
668
+ description: "No error tracking service found. Production errors will go unnoticed.",
669
+ suggestion: "Add Sentry, Bugsnag, or similar for production error monitoring.",
670
+ autoFixable: false,
671
+ aiPrompt: `Set up error tracking with Sentry:
672
+ 1. npm install @sentry/nextjs
673
+ 2. npx @sentry/wizard@latest -i nextjs
674
+ 3. Configure SENTRY_DSN and SENTRY_AUTH_TOKEN env vars
675
+ 4. Integrate with error boundary
676
+ 5. Set user context on auth`,
677
+ });
678
+ }
679
+
680
+ // ── Image & Media Optimization ───────────────────────────────────────────
681
+
682
+ const hasLazyImages = await findFile(searchPath, /loading="lazy"|LazyImage|Image.*priority/i);
683
+ if (!hasLazyImages) {
684
+ issues.push({
685
+ id: "missing-lazy-images",
686
+ category: "Frontend",
687
+ severity: "medium",
688
+ title: "Missing Lazy Loading for Images",
689
+ description: "No lazy loading for images detected. All images load immediately.",
690
+ suggestion: "Add lazy loading to below-the-fold images.",
691
+ autoFixable: true,
692
+ aiPrompt: `Implement lazy loading for images:
693
+ - Next.js: Use next/image (lazy by default, add priority for above-fold)
694
+ - Regular img: Add loading="lazy" decoding="async"
695
+ - Create a LazyImage wrapper component`,
696
+ });
697
+ }
698
+
699
+ // ── Theme & Dark Mode ────────────────────────────────────────────────────
700
+
701
+ const hasDarkMode = await findFile(searchPath, /dark-mode|darkMode|theme-toggle|ThemeProvider|useTheme/i);
702
+ if (!hasDarkMode) {
703
+ issues.push({
704
+ id: "missing-dark-mode",
705
+ category: "Frontend",
706
+ severity: "low",
707
+ title: "Missing Dark Mode Support",
708
+ description: "No dark mode implementation found. Many users prefer dark mode.",
709
+ suggestion: "Add dark mode toggle with system preference detection.",
710
+ autoFixable: true,
711
+ aiPrompt: `Implement dark mode with system preference detection:
712
+ 1. ThemeProvider context + useTheme hook
713
+ 2. CSS variables for light/dark themes
714
+ 3. System preference detection via prefers-color-scheme
715
+ 4. Persist choice in localStorage
716
+ 5. Theme toggle component`,
717
+ });
718
+ }
719
+
720
+ // ── Confirmation & Destructive Actions ───────────────────────────────────
721
+
722
+ const hasConfirmDialog = await findFile(searchPath, /ConfirmDialog|Confirm|AlertDialog|useConfirm/i);
723
+ if (!hasConfirmDialog) {
724
+ issues.push({
725
+ id: "missing-confirm-dialog",
726
+ category: "Frontend",
727
+ severity: "high",
728
+ title: "Missing Confirmation Dialog",
729
+ description: "No confirmation dialog found. Destructive actions should require confirmation.",
730
+ suggestion: "Add a confirmation dialog for delete, logout, and irreversible actions.",
731
+ autoFixable: true,
732
+ aiPrompt: `Create a confirmation dialog system:
733
+ 1. ConfirmDialog component with danger/warning/info variants
734
+ 2. useConfirm() hook returning a promise-based API:
735
+ const shouldDelete = await confirm({ title: 'Delete?', message: '...' });
736
+ 3. Loading state support on confirm button
737
+ 4. Focus trap and keyboard handling`,
738
+ });
739
+ }
740
+
741
+ // ── Optimistic Updates ───────────────────────────────────────────────────
742
+
743
+ const hasOptimisticUpdates = await findFile(searchPath, /optimistic|mutate.*onMutate|useMutation/i);
744
+ if (!hasOptimisticUpdates && hasSWR) {
745
+ issues.push({
746
+ id: "missing-optimistic-updates",
747
+ category: "Frontend",
748
+ severity: "low",
749
+ title: "No Optimistic Updates",
750
+ description: "Data mutations may feel slow without optimistic updates.",
751
+ suggestion: "Add optimistic updates for better perceived performance.",
752
+ autoFixable: false,
753
+ aiPrompt: `Implement optimistic updates for mutations with SWR or TanStack Query.
754
+ Pattern: update cache immediately, send request, revert on error.`,
755
+ });
756
+ }
757
+
758
+ // ── Keyboard Shortcuts ───────────────────────────────────────────────────
759
+
760
+ const hasKeyboardShortcuts = await findFile(searchPath, /useHotkeys|Keyboard|shortcut|Cmd\+|Ctrl\+/i);
761
+ if (!hasKeyboardShortcuts) {
762
+ issues.push({
763
+ id: "missing-keyboard-shortcuts",
764
+ category: "Frontend",
765
+ severity: "low",
766
+ title: "Missing Keyboard Shortcuts",
767
+ description: "No keyboard shortcuts detected. Power users benefit from keyboard navigation.",
768
+ suggestion: "Add keyboard shortcuts for common actions.",
769
+ autoFixable: true,
770
+ aiPrompt: `Implement keyboard shortcuts:
771
+ 1. useHotkey hook with cross-platform Cmd/Ctrl support
772
+ 2. Common shortcuts: Cmd+K (search), Cmd+S (save), Escape (close), ? (help)
773
+ 3. Display shortcut hints in UI via <kbd> elements`,
774
+ });
775
+ }
776
+
777
+ // ── Scroll Behavior ──────────────────────────────────────────────────────
778
+
779
+ const hasScrollToTop = await findFile(searchPath, /ScrollToTop|scroll-to-top|BackToTop/i);
780
+ if (!hasScrollToTop) {
781
+ issues.push({
782
+ id: "missing-scroll-to-top",
783
+ category: "Frontend",
784
+ severity: "low",
785
+ title: "Missing Scroll-to-Top Button",
786
+ description: "No scroll-to-top button found. Long pages need easy navigation back to top.",
787
+ suggestion: "Add a scroll-to-top button for long pages.",
788
+ autoFixable: true,
789
+ aiPrompt: `Create a scroll-to-top button:
790
+ - Show after scrolling 500px
791
+ - Smooth scroll animation
792
+ - Fixed position bottom-right
793
+ - Accessible with aria-label`,
794
+ });
795
+ }
796
+
797
+ // ── Progress Indicators ──────────────────────────────────────────────────
798
+
799
+ const hasProgressBar = await findFile(searchPath, /Progress|ProgressBar|NProgress|nprogress/i);
800
+ if (!hasProgressBar) {
801
+ issues.push({
802
+ id: "missing-progress-bar",
803
+ category: "Frontend",
804
+ severity: "medium",
805
+ title: "Missing Progress Indicators",
806
+ description: "No progress bar found. Users need visual feedback for page transitions and uploads.",
807
+ suggestion: "Add progress bar for navigation and long operations.",
808
+ autoFixable: true,
809
+ aiPrompt: `Add progress indicators:
810
+ 1. NProgress-style page transition bar (npm install nprogress)
811
+ 2. Custom ProgressBar component with role="progressbar"
812
+ 3. File upload progress indicator`,
813
+ });
814
+ }
815
+
816
+ return issues;
817
+ };