@vibecheckai/cli 2.8.2 → 3.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 (454) hide show
  1. package/README.md +8 -8
  2. package/bin/_deprecations.js +35 -0
  3. package/bin/_router.js +46 -0
  4. package/bin/cli-hygiene.js +241 -0
  5. package/bin/guardrail.js +834 -0
  6. package/bin/runners/cli-utils.js +1070 -0
  7. package/bin/runners/context/ai-task-decomposer.js +337 -0
  8. package/bin/runners/context/analyzer.js +462 -0
  9. package/bin/runners/context/api-contracts.js +427 -0
  10. package/bin/runners/context/context-diff.js +342 -0
  11. package/bin/runners/context/context-pruner.js +291 -0
  12. package/bin/runners/context/dependency-graph.js +414 -0
  13. package/bin/runners/context/generators/claude.js +107 -0
  14. package/bin/runners/context/generators/codex.js +108 -0
  15. package/bin/runners/context/generators/copilot.js +119 -0
  16. package/bin/runners/context/generators/cursor.js +514 -0
  17. package/bin/runners/context/generators/mcp.js +151 -0
  18. package/bin/runners/context/generators/windsurf.js +180 -0
  19. package/bin/runners/context/git-context.js +302 -0
  20. package/bin/runners/context/index.js +1042 -0
  21. package/bin/runners/context/insights.js +173 -0
  22. package/bin/runners/context/mcp-server/generate-rules.js +337 -0
  23. package/bin/runners/context/mcp-server/index.js +1176 -0
  24. package/bin/runners/context/mcp-server/package.json +24 -0
  25. package/bin/runners/context/memory.js +200 -0
  26. package/bin/runners/context/monorepo.js +215 -0
  27. package/bin/runners/context/multi-repo-federation.js +404 -0
  28. package/bin/runners/context/patterns.js +253 -0
  29. package/bin/runners/context/proof-context.js +972 -0
  30. package/bin/runners/context/security-scanner.js +303 -0
  31. package/bin/runners/context/semantic-search.js +350 -0
  32. package/bin/runners/context/shared.js +264 -0
  33. package/bin/runners/context/team-conventions.js +310 -0
  34. package/bin/runners/lib/ai-bridge.js +416 -0
  35. package/bin/runners/lib/analysis-core.js +271 -0
  36. package/bin/runners/lib/analyzers.js +541 -0
  37. package/bin/runners/lib/audit-bridge.js +391 -0
  38. package/bin/runners/lib/auth-truth.js +193 -0
  39. package/bin/runners/lib/auth.js +215 -0
  40. package/bin/runners/lib/backup.js +62 -0
  41. package/bin/runners/lib/billing.js +107 -0
  42. package/bin/runners/lib/claims.js +118 -0
  43. package/bin/runners/lib/cli-ui.js +540 -0
  44. package/bin/runners/lib/compliance-bridge-new.js +0 -0
  45. package/bin/runners/lib/compliance-bridge.js +165 -0
  46. package/bin/runners/lib/contracts/auth-contract.js +194 -0
  47. package/bin/runners/lib/contracts/env-contract.js +178 -0
  48. package/bin/runners/lib/contracts/external-contract.js +198 -0
  49. package/bin/runners/lib/contracts/guard.js +168 -0
  50. package/bin/runners/lib/contracts/index.js +89 -0
  51. package/bin/runners/lib/contracts/plan-validator.js +311 -0
  52. package/bin/runners/lib/contracts/route-contract.js +192 -0
  53. package/bin/runners/lib/detect.js +89 -0
  54. package/bin/runners/lib/doctor/autofix.js +254 -0
  55. package/bin/runners/lib/doctor/index.js +37 -0
  56. package/bin/runners/lib/doctor/modules/dependencies.js +325 -0
  57. package/bin/runners/lib/doctor/modules/index.js +46 -0
  58. package/bin/runners/lib/doctor/modules/network.js +250 -0
  59. package/bin/runners/lib/doctor/modules/project.js +312 -0
  60. package/bin/runners/lib/doctor/modules/runtime.js +224 -0
  61. package/bin/runners/lib/doctor/modules/security.js +348 -0
  62. package/bin/runners/lib/doctor/modules/system.js +213 -0
  63. package/bin/runners/lib/doctor/modules/vibecheck.js +394 -0
  64. package/bin/runners/lib/doctor/reporter.js +262 -0
  65. package/bin/runners/lib/doctor/service.js +262 -0
  66. package/bin/runners/lib/doctor/types.js +113 -0
  67. package/bin/runners/lib/doctor/ui.js +263 -0
  68. package/bin/runners/lib/doctor-enhanced.js +233 -0
  69. package/bin/runners/lib/doctor-v2.js +608 -0
  70. package/bin/runners/lib/enforcement.js +72 -0
  71. package/bin/runners/lib/enterprise-detect.js +603 -0
  72. package/bin/runners/lib/enterprise-init.js +942 -0
  73. package/bin/runners/lib/entitlements-v2.js +381 -0
  74. package/bin/runners/lib/entitlements.generated.js +0 -0
  75. package/bin/runners/lib/entitlements.js +332 -0
  76. package/bin/runners/lib/env-template.js +66 -0
  77. package/bin/runners/lib/env.js +189 -0
  78. package/bin/runners/lib/error-handler.js +320 -0
  79. package/bin/runners/lib/firewall-prompt.js +50 -0
  80. package/bin/runners/lib/graph/graph-builder.js +265 -0
  81. package/bin/runners/lib/graph/html-renderer.js +413 -0
  82. package/bin/runners/lib/graph/index.js +32 -0
  83. package/bin/runners/lib/graph/runtime-collector.js +215 -0
  84. package/bin/runners/lib/graph/static-extractor.js +518 -0
  85. package/bin/runners/lib/init-wizard.js +308 -0
  86. package/bin/runners/lib/json-output.js +76 -0
  87. package/bin/runners/lib/llm.js +75 -0
  88. package/bin/runners/lib/meter.js +61 -0
  89. package/bin/runners/lib/missions/evidence.js +126 -0
  90. package/bin/runners/lib/missions/plan.js +69 -0
  91. package/bin/runners/lib/missions/templates.js +147 -0
  92. package/bin/runners/lib/patch.js +40 -0
  93. package/bin/runners/lib/permissions/auth-model.js +213 -0
  94. package/bin/runners/lib/permissions/idor-prover.js +205 -0
  95. package/bin/runners/lib/permissions/index.js +45 -0
  96. package/bin/runners/lib/permissions/matrix-builder.js +198 -0
  97. package/bin/runners/lib/pkgjson.js +28 -0
  98. package/bin/runners/lib/preflight.js +142 -0
  99. package/bin/runners/lib/reality-findings.js +84 -0
  100. package/bin/runners/lib/redact.js +29 -0
  101. package/bin/runners/lib/replay/capsule-manager.js +154 -0
  102. package/bin/runners/lib/replay/index.js +263 -0
  103. package/bin/runners/lib/replay/player.js +348 -0
  104. package/bin/runners/lib/replay/recorder.js +331 -0
  105. package/bin/runners/lib/report-engine.js +447 -0
  106. package/bin/runners/lib/report-html.js +1117 -0
  107. package/bin/runners/lib/report-templates.js +964 -0
  108. package/bin/runners/lib/route-detection.js +1140 -0
  109. package/bin/runners/lib/route-truth.js +477 -0
  110. package/bin/runners/lib/sandbox/index.js +59 -0
  111. package/bin/runners/lib/sandbox/proof-chain.js +399 -0
  112. package/bin/runners/lib/sandbox/sandbox-runner.js +205 -0
  113. package/bin/runners/lib/sandbox/worktree.js +174 -0
  114. package/bin/runners/lib/scan-cache.js +330 -0
  115. package/bin/runners/lib/scan-output-schema.js +344 -0
  116. package/bin/runners/lib/score-history.js +282 -0
  117. package/bin/runners/lib/security-bridge.js +249 -0
  118. package/bin/runners/lib/server-usage.js +513 -0
  119. package/bin/runners/lib/share-pack.js +239 -0
  120. package/bin/runners/lib/snippets.js +67 -0
  121. package/bin/runners/lib/truth.js +667 -0
  122. package/bin/runners/lib/unified-output.js +189 -0
  123. package/bin/runners/lib/validate-patch.js +156 -0
  124. package/bin/runners/lib/verification.js +345 -0
  125. package/bin/runners/reality/engine.js +917 -0
  126. package/bin/runners/reality/flows.js +122 -0
  127. package/bin/runners/reality/report.js +378 -0
  128. package/bin/runners/reality/session.js +193 -0
  129. package/bin/runners/runAIAgent.js +2 -0
  130. package/bin/runners/runAudit.js +2 -0
  131. package/bin/runners/runAuth.js +106 -0
  132. package/bin/runners/runAutopilot.js +2 -0
  133. package/bin/runners/runBadge.js +2 -0
  134. package/bin/runners/runCertify.js +2 -0
  135. package/bin/runners/runClaimVerifier.js +483 -0
  136. package/bin/runners/runContext.js +56 -0
  137. package/bin/runners/runContextCompiler.js +385 -0
  138. package/bin/runners/runCtx.js +187 -0
  139. package/bin/runners/runCtxGuard.js +176 -0
  140. package/bin/runners/runCtxSync.js +116 -0
  141. package/bin/runners/runDashboard.js +10 -0
  142. package/bin/runners/runDoctor.js +245 -0
  143. package/bin/runners/runEnhancedShip.js +2 -0
  144. package/bin/runners/runFix.js +735 -0
  145. package/bin/runners/runFixPacks.js +2 -0
  146. package/bin/runners/runGate.js +17 -0
  147. package/bin/runners/runGraph.js +283 -0
  148. package/bin/runners/runInit.js +260 -0
  149. package/bin/runners/runInitGha.js +101 -0
  150. package/bin/runners/runInstall.js +76 -0
  151. package/bin/runners/runInteractive.js +388 -0
  152. package/bin/runners/runLaunch.js +2 -0
  153. package/bin/runners/runMcp.js +19 -0
  154. package/bin/runners/runMdc.js +2 -0
  155. package/bin/runners/runMissionGenerator.js +282 -0
  156. package/bin/runners/runNaturalLanguage.js +3 -0
  157. package/bin/runners/runPR.js +96 -0
  158. package/bin/runners/runPermissions.js +290 -0
  159. package/bin/runners/runPromptFirewall.js +211 -0
  160. package/bin/runners/runProof.js +2 -0
  161. package/bin/runners/runProve.js +392 -0
  162. package/bin/runners/runReality.js +489 -0
  163. package/bin/runners/runRealitySniff.js +2 -0
  164. package/bin/runners/runReplay.js +469 -0
  165. package/bin/runners/runReport.js +478 -0
  166. package/bin/runners/runScan.js +835 -0
  167. package/bin/runners/runShare.js +34 -0
  168. package/bin/runners/runShip.js +1062 -0
  169. package/bin/runners/runStatus.js +136 -0
  170. package/bin/runners/runTruthpack.js +634 -0
  171. package/bin/runners/runUpgrade.js +2 -0
  172. package/bin/runners/runValidate.js +2 -0
  173. package/bin/runners/runVerifyAgentOutput.js +2 -0
  174. package/bin/runners/runWatch.js +230 -0
  175. package/bin/runners/utils.js +360 -0
  176. package/bin/scan.js +612 -0
  177. package/bin/vibecheck.js +834 -0
  178. package/package.json +11 -11
  179. package/dist/autopatch/verified-autopatch.d.ts +0 -111
  180. package/dist/autopatch/verified-autopatch.d.ts.map +0 -1
  181. package/dist/autopatch/verified-autopatch.js +0 -503
  182. package/dist/autopatch/verified-autopatch.js.map +0 -1
  183. package/dist/bundles/index.js +0 -8
  184. package/dist/bundles/vibecheck-core.js +0 -25799
  185. package/dist/bundles/vibecheck-security.js +0 -208693
  186. package/dist/bundles/vibecheck-ship.js +0 -2318
  187. package/dist/commands/baseline.d.ts +0 -7
  188. package/dist/commands/baseline.d.ts.map +0 -1
  189. package/dist/commands/baseline.js +0 -79
  190. package/dist/commands/baseline.js.map +0 -1
  191. package/dist/commands/cache.d.ts +0 -13
  192. package/dist/commands/cache.d.ts.map +0 -1
  193. package/dist/commands/cache.js +0 -165
  194. package/dist/commands/cache.js.map +0 -1
  195. package/dist/commands/checkpoint.d.ts +0 -8
  196. package/dist/commands/checkpoint.d.ts.map +0 -1
  197. package/dist/commands/checkpoint.js +0 -35
  198. package/dist/commands/checkpoint.js.map +0 -1
  199. package/dist/commands/doctor.d.ts +0 -17
  200. package/dist/commands/doctor.d.ts.map +0 -1
  201. package/dist/commands/doctor.js +0 -226
  202. package/dist/commands/doctor.js.map +0 -1
  203. package/dist/commands/evidence.d.ts +0 -45
  204. package/dist/commands/evidence.d.ts.map +0 -1
  205. package/dist/commands/evidence.js +0 -197
  206. package/dist/commands/evidence.js.map +0 -1
  207. package/dist/commands/explain.d.ts +0 -8
  208. package/dist/commands/explain.d.ts.map +0 -1
  209. package/dist/commands/explain.js +0 -52
  210. package/dist/commands/explain.js.map +0 -1
  211. package/dist/commands/fix-consolidated.d.ts +0 -19
  212. package/dist/commands/fix-consolidated.d.ts.map +0 -1
  213. package/dist/commands/fix-consolidated.js +0 -165
  214. package/dist/commands/fix-consolidated.js.map +0 -1
  215. package/dist/commands/index.d.ts +0 -8
  216. package/dist/commands/index.d.ts.map +0 -1
  217. package/dist/commands/index.js +0 -15
  218. package/dist/commands/index.js.map +0 -1
  219. package/dist/commands/init.d.ts +0 -8
  220. package/dist/commands/init.d.ts.map +0 -1
  221. package/dist/commands/init.js +0 -125
  222. package/dist/commands/init.js.map +0 -1
  223. package/dist/commands/launcher.d.ts +0 -10
  224. package/dist/commands/launcher.d.ts.map +0 -1
  225. package/dist/commands/launcher.js +0 -174
  226. package/dist/commands/launcher.js.map +0 -1
  227. package/dist/commands/on.d.ts +0 -8
  228. package/dist/commands/on.d.ts.map +0 -1
  229. package/dist/commands/on.js +0 -123
  230. package/dist/commands/on.js.map +0 -1
  231. package/dist/commands/replay.d.ts +0 -8
  232. package/dist/commands/replay.d.ts.map +0 -1
  233. package/dist/commands/replay.js +0 -52
  234. package/dist/commands/replay.js.map +0 -1
  235. package/dist/commands/scan-consolidated.d.ts +0 -61
  236. package/dist/commands/scan-consolidated.d.ts.map +0 -1
  237. package/dist/commands/scan-consolidated.js +0 -243
  238. package/dist/commands/scan-consolidated.js.map +0 -1
  239. package/dist/commands/scan-secrets.d.ts +0 -47
  240. package/dist/commands/scan-secrets.d.ts.map +0 -1
  241. package/dist/commands/scan-secrets.js +0 -225
  242. package/dist/commands/scan-secrets.js.map +0 -1
  243. package/dist/commands/scan-vulnerabilities-enhanced.d.ts +0 -41
  244. package/dist/commands/scan-vulnerabilities-enhanced.d.ts.map +0 -1
  245. package/dist/commands/scan-vulnerabilities-enhanced.js +0 -368
  246. package/dist/commands/scan-vulnerabilities-enhanced.js.map +0 -1
  247. package/dist/commands/scan-vulnerabilities-osv.d.ts +0 -58
  248. package/dist/commands/scan-vulnerabilities-osv.d.ts.map +0 -1
  249. package/dist/commands/scan-vulnerabilities-osv.js +0 -722
  250. package/dist/commands/scan-vulnerabilities-osv.js.map +0 -1
  251. package/dist/commands/scan-vulnerabilities.d.ts +0 -32
  252. package/dist/commands/scan-vulnerabilities.d.ts.map +0 -1
  253. package/dist/commands/scan-vulnerabilities.js +0 -283
  254. package/dist/commands/scan-vulnerabilities.js.map +0 -1
  255. package/dist/commands/secrets-allowlist.d.ts +0 -7
  256. package/dist/commands/secrets-allowlist.d.ts.map +0 -1
  257. package/dist/commands/secrets-allowlist.js +0 -85
  258. package/dist/commands/secrets-allowlist.js.map +0 -1
  259. package/dist/commands/ship-consolidated.d.ts +0 -58
  260. package/dist/commands/ship-consolidated.d.ts.map +0 -1
  261. package/dist/commands/ship-consolidated.js +0 -515
  262. package/dist/commands/ship-consolidated.js.map +0 -1
  263. package/dist/commands/stats.d.ts +0 -8
  264. package/dist/commands/stats.d.ts.map +0 -1
  265. package/dist/commands/stats.js +0 -134
  266. package/dist/commands/stats.js.map +0 -1
  267. package/dist/commands/upgrade.d.ts +0 -8
  268. package/dist/commands/upgrade.d.ts.map +0 -1
  269. package/dist/commands/upgrade.js +0 -30
  270. package/dist/commands/upgrade.js.map +0 -1
  271. package/dist/fix/applicator.d.ts +0 -44
  272. package/dist/fix/applicator.d.ts.map +0 -1
  273. package/dist/fix/applicator.js +0 -144
  274. package/dist/fix/applicator.js.map +0 -1
  275. package/dist/fix/backup.d.ts +0 -38
  276. package/dist/fix/backup.d.ts.map +0 -1
  277. package/dist/fix/backup.js +0 -154
  278. package/dist/fix/backup.js.map +0 -1
  279. package/dist/fix/engine.d.ts +0 -55
  280. package/dist/fix/engine.d.ts.map +0 -1
  281. package/dist/fix/engine.js +0 -285
  282. package/dist/fix/engine.js.map +0 -1
  283. package/dist/fix/index.d.ts +0 -5
  284. package/dist/fix/index.d.ts.map +0 -1
  285. package/dist/fix/index.js +0 -12
  286. package/dist/fix/index.js.map +0 -1
  287. package/dist/fix/interactive.d.ts +0 -22
  288. package/dist/fix/interactive.d.ts.map +0 -1
  289. package/dist/fix/interactive.js +0 -172
  290. package/dist/fix/interactive.js.map +0 -1
  291. package/dist/formatters/index.d.ts +0 -6
  292. package/dist/formatters/index.d.ts.map +0 -1
  293. package/dist/formatters/index.js +0 -11
  294. package/dist/formatters/index.js.map +0 -1
  295. package/dist/formatters/sarif-enhanced.d.ts +0 -78
  296. package/dist/formatters/sarif-enhanced.d.ts.map +0 -1
  297. package/dist/formatters/sarif-enhanced.js +0 -144
  298. package/dist/formatters/sarif-enhanced.js.map +0 -1
  299. package/dist/formatters/sarif-v2.d.ts +0 -121
  300. package/dist/formatters/sarif-v2.d.ts.map +0 -1
  301. package/dist/formatters/sarif-v2.js +0 -356
  302. package/dist/formatters/sarif-v2.js.map +0 -1
  303. package/dist/formatters/sarif.d.ts +0 -72
  304. package/dist/formatters/sarif.d.ts.map +0 -1
  305. package/dist/formatters/sarif.js +0 -146
  306. package/dist/formatters/sarif.js.map +0 -1
  307. package/dist/index.d.ts +0 -61
  308. package/dist/index.d.ts.map +0 -1
  309. package/dist/index.js +0 -4388
  310. package/dist/index.js.map +0 -1
  311. package/dist/init/ci-generator.d.ts +0 -18
  312. package/dist/init/ci-generator.d.ts.map +0 -1
  313. package/dist/init/ci-generator.js +0 -317
  314. package/dist/init/ci-generator.js.map +0 -1
  315. package/dist/init/detect-framework.d.ts +0 -15
  316. package/dist/init/detect-framework.d.ts.map +0 -1
  317. package/dist/init/detect-framework.js +0 -301
  318. package/dist/init/detect-framework.js.map +0 -1
  319. package/dist/init/hooks-installer.d.ts +0 -22
  320. package/dist/init/hooks-installer.d.ts.map +0 -1
  321. package/dist/init/hooks-installer.js +0 -310
  322. package/dist/init/hooks-installer.js.map +0 -1
  323. package/dist/init/index.d.ts +0 -8
  324. package/dist/init/index.d.ts.map +0 -1
  325. package/dist/init/index.js +0 -22
  326. package/dist/init/index.js.map +0 -1
  327. package/dist/init/templates.d.ts +0 -402
  328. package/dist/init/templates.d.ts.map +0 -1
  329. package/dist/init/templates.js +0 -240
  330. package/dist/init/templates.js.map +0 -1
  331. package/dist/mcp/server.d.ts +0 -12
  332. package/dist/mcp/server.d.ts.map +0 -1
  333. package/dist/mcp/server.js +0 -42
  334. package/dist/mcp/server.js.map +0 -1
  335. package/dist/mcp/telemetry.d.ts +0 -40
  336. package/dist/mcp/telemetry.d.ts.map +0 -1
  337. package/dist/mcp/telemetry.js +0 -98
  338. package/dist/mcp/telemetry.js.map +0 -1
  339. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts +0 -32
  340. package/dist/reality/no-dead-buttons/button-sweep-generator.d.ts.map +0 -1
  341. package/dist/reality/no-dead-buttons/button-sweep-generator.js +0 -236
  342. package/dist/reality/no-dead-buttons/button-sweep-generator.js.map +0 -1
  343. package/dist/reality/no-dead-buttons/index.d.ts +0 -11
  344. package/dist/reality/no-dead-buttons/index.d.ts.map +0 -1
  345. package/dist/reality/no-dead-buttons/index.js +0 -18
  346. package/dist/reality/no-dead-buttons/index.js.map +0 -1
  347. package/dist/reality/no-dead-buttons/static-scanner.d.ts +0 -34
  348. package/dist/reality/no-dead-buttons/static-scanner.d.ts.map +0 -1
  349. package/dist/reality/no-dead-buttons/static-scanner.js +0 -230
  350. package/dist/reality/no-dead-buttons/static-scanner.js.map +0 -1
  351. package/dist/reality/reality-graph.d.ts +0 -192
  352. package/dist/reality/reality-graph.d.ts.map +0 -1
  353. package/dist/reality/reality-graph.js +0 -600
  354. package/dist/reality/reality-graph.js.map +0 -1
  355. package/dist/reality/reality-runner.d.ts +0 -89
  356. package/dist/reality/reality-runner.d.ts.map +0 -1
  357. package/dist/reality/reality-runner.js +0 -540
  358. package/dist/reality/reality-runner.js.map +0 -1
  359. package/dist/reality/receipt-generator.d.ts +0 -152
  360. package/dist/reality/receipt-generator.d.ts.map +0 -1
  361. package/dist/reality/receipt-generator.js +0 -495
  362. package/dist/reality/receipt-generator.js.map +0 -1
  363. package/dist/reality/runtime-tracer.d.ts +0 -75
  364. package/dist/reality/runtime-tracer.d.ts.map +0 -1
  365. package/dist/reality/runtime-tracer.js +0 -109
  366. package/dist/reality/runtime-tracer.js.map +0 -1
  367. package/dist/runtime/auth-utils.d.ts +0 -43
  368. package/dist/runtime/auth-utils.d.ts.map +0 -1
  369. package/dist/runtime/auth-utils.js +0 -130
  370. package/dist/runtime/auth-utils.js.map +0 -1
  371. package/dist/runtime/client.d.ts +0 -74
  372. package/dist/runtime/client.d.ts.map +0 -1
  373. package/dist/runtime/client.js +0 -222
  374. package/dist/runtime/client.js.map +0 -1
  375. package/dist/runtime/creds.d.ts +0 -48
  376. package/dist/runtime/creds.d.ts.map +0 -1
  377. package/dist/runtime/creds.js +0 -245
  378. package/dist/runtime/creds.js.map +0 -1
  379. package/dist/runtime/exit-codes.d.ts +0 -49
  380. package/dist/runtime/exit-codes.d.ts.map +0 -1
  381. package/dist/runtime/exit-codes.js +0 -93
  382. package/dist/runtime/exit-codes.js.map +0 -1
  383. package/dist/runtime/index.d.ts +0 -9
  384. package/dist/runtime/index.d.ts.map +0 -1
  385. package/dist/runtime/index.js +0 -25
  386. package/dist/runtime/index.js.map +0 -1
  387. package/dist/runtime/json-output.d.ts +0 -42
  388. package/dist/runtime/json-output.d.ts.map +0 -1
  389. package/dist/runtime/json-output.js +0 -59
  390. package/dist/runtime/json-output.js.map +0 -1
  391. package/dist/runtime/semver.d.ts +0 -37
  392. package/dist/runtime/semver.d.ts.map +0 -1
  393. package/dist/runtime/semver.js +0 -110
  394. package/dist/runtime/semver.js.map +0 -1
  395. package/dist/scan/dead-ui-detector.d.ts +0 -48
  396. package/dist/scan/dead-ui-detector.d.ts.map +0 -1
  397. package/dist/scan/dead-ui-detector.js +0 -170
  398. package/dist/scan/dead-ui-detector.js.map +0 -1
  399. package/dist/scan/playwright-sweep.d.ts +0 -40
  400. package/dist/scan/playwright-sweep.d.ts.map +0 -1
  401. package/dist/scan/playwright-sweep.js +0 -216
  402. package/dist/scan/playwright-sweep.js.map +0 -1
  403. package/dist/scan/proof-bundle.d.ts +0 -25
  404. package/dist/scan/proof-bundle.d.ts.map +0 -1
  405. package/dist/scan/proof-bundle.js +0 -203
  406. package/dist/scan/proof-bundle.js.map +0 -1
  407. package/dist/scan/proof-graph.d.ts +0 -59
  408. package/dist/scan/proof-graph.d.ts.map +0 -1
  409. package/dist/scan/proof-graph.js +0 -64
  410. package/dist/scan/proof-graph.js.map +0 -1
  411. package/dist/scan/reality-sniff.d.ts +0 -56
  412. package/dist/scan/reality-sniff.d.ts.map +0 -1
  413. package/dist/scan/reality-sniff.js +0 -200
  414. package/dist/scan/reality-sniff.js.map +0 -1
  415. package/dist/scan/structural-verifier.d.ts +0 -20
  416. package/dist/scan/structural-verifier.d.ts.map +0 -1
  417. package/dist/scan/structural-verifier.js +0 -112
  418. package/dist/scan/structural-verifier.js.map +0 -1
  419. package/dist/scan/verification-engine.d.ts +0 -47
  420. package/dist/scan/verification-engine.d.ts.map +0 -1
  421. package/dist/scan/verification-engine.js +0 -141
  422. package/dist/scan/verification-engine.js.map +0 -1
  423. package/dist/scanner/baseline.d.ts +0 -52
  424. package/dist/scanner/baseline.d.ts.map +0 -1
  425. package/dist/scanner/baseline.js +0 -85
  426. package/dist/scanner/baseline.js.map +0 -1
  427. package/dist/scanner/incremental.d.ts +0 -30
  428. package/dist/scanner/incremental.d.ts.map +0 -1
  429. package/dist/scanner/incremental.js +0 -82
  430. package/dist/scanner/incremental.js.map +0 -1
  431. package/dist/scanner/parallel.d.ts +0 -43
  432. package/dist/scanner/parallel.d.ts.map +0 -1
  433. package/dist/scanner/parallel.js +0 -99
  434. package/dist/scanner/parallel.js.map +0 -1
  435. package/dist/standalone.d.ts +0 -1
  436. package/dist/standalone.d.ts.map +0 -1
  437. package/dist/standalone.js +0 -1
  438. package/dist/standalone.js.map +0 -1
  439. package/dist/truth-pack/index.d.ts +0 -102
  440. package/dist/truth-pack/index.d.ts.map +0 -1
  441. package/dist/truth-pack/index.js +0 -694
  442. package/dist/truth-pack/index.js.map +0 -1
  443. package/dist/ui/frame.d.ts +0 -68
  444. package/dist/ui/frame.d.ts.map +0 -1
  445. package/dist/ui/frame.js +0 -165
  446. package/dist/ui/frame.js.map +0 -1
  447. package/dist/ui/index.d.ts +0 -5
  448. package/dist/ui/index.d.ts.map +0 -1
  449. package/dist/ui/index.js +0 -16
  450. package/dist/ui/index.js.map +0 -1
  451. package/dist/ui.d.ts +0 -36
  452. package/dist/ui.d.ts.map +0 -1
  453. package/dist/ui.js +0 -45
  454. package/dist/ui.js.map +0 -1
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Permissions Module Index
3
+ * Exports all permission verification functionality
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const {
9
+ extractAuthModel,
10
+ extractRolePatterns,
11
+ inferRoles,
12
+ buildRouteAuthMap
13
+ } = require("./auth-model");
14
+
15
+ const {
16
+ buildAuthZMatrix,
17
+ detectViolations,
18
+ formatMatrix
19
+ } = require("./matrix-builder");
20
+
21
+ const {
22
+ detectIDORCandidates,
23
+ buildIDORTestPlan,
24
+ executeIDORTest,
25
+ formatIDORPlan
26
+ } = require("./idor-prover");
27
+
28
+ module.exports = {
29
+ // Auth model extraction
30
+ extractAuthModel,
31
+ extractRolePatterns,
32
+ inferRoles,
33
+ buildRouteAuthMap,
34
+
35
+ // AuthZ matrix
36
+ buildAuthZMatrix,
37
+ detectViolations,
38
+ formatMatrix,
39
+
40
+ // IDOR detection
41
+ detectIDORCandidates,
42
+ buildIDORTestPlan,
43
+ executeIDORTest,
44
+ formatIDORPlan
45
+ };
@@ -0,0 +1,198 @@
1
+ /**
2
+ * AuthZ Matrix Builder
3
+ * Builds authorization matrix from auth model and runtime verification
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const crypto = require("crypto");
9
+
10
+ function sha256(text) {
11
+ return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16);
12
+ }
13
+
14
+ /**
15
+ * Build AuthZ matrix from auth model
16
+ */
17
+ function buildAuthZMatrix(authModel, runtimeResults = null) {
18
+ const matrix = {
19
+ meta: {
20
+ version: "1.0.0",
21
+ generatedAt: new Date().toISOString()
22
+ },
23
+ roles: authModel.roles.map(r => r.name),
24
+ routes: [],
25
+ violations: []
26
+ };
27
+
28
+ for (const route of authModel.routes) {
29
+ const routeAuthZ = {
30
+ path: route.path,
31
+ method: route.method,
32
+ declared: route.declared,
33
+ actual: {
34
+ anon: null,
35
+ user: null,
36
+ admin: null
37
+ }
38
+ };
39
+
40
+ // Merge runtime results if available
41
+ if (runtimeResults) {
42
+ const runtimeForRoute = runtimeResults.filter(r =>
43
+ matchesRoute(route.path, r.path)
44
+ );
45
+
46
+ for (const result of runtimeForRoute) {
47
+ if (result.role === "anon") {
48
+ routeAuthZ.actual.anon = {
49
+ status: result.status,
50
+ redirected: result.redirected,
51
+ accessible: result.status >= 200 && result.status < 400 && !result.redirected
52
+ };
53
+ } else if (result.role === "user") {
54
+ routeAuthZ.actual.user = {
55
+ status: result.status,
56
+ redirected: result.redirected,
57
+ accessible: result.status >= 200 && result.status < 400 && !result.redirected
58
+ };
59
+ } else if (result.role === "admin") {
60
+ routeAuthZ.actual.admin = {
61
+ status: result.status,
62
+ redirected: result.redirected,
63
+ accessible: result.status >= 200 && result.status < 400 && !result.redirected
64
+ };
65
+ }
66
+ }
67
+ }
68
+
69
+ matrix.routes.push(routeAuthZ);
70
+ }
71
+
72
+ // Detect violations
73
+ matrix.violations = detectViolations(matrix);
74
+
75
+ return matrix;
76
+ }
77
+
78
+ /**
79
+ * Detect authorization violations
80
+ */
81
+ function detectViolations(matrix) {
82
+ const violations = [];
83
+
84
+ for (const route of matrix.routes) {
85
+ // Check: protected route accessible anonymously
86
+ if (route.declared.protected && route.actual.anon?.accessible) {
87
+ violations.push({
88
+ id: `AUTHZ_ANON_${sha256(route.path)}`,
89
+ severity: "BLOCK",
90
+ type: "anon_access",
91
+ route: route.path,
92
+ method: route.method,
93
+ expected: "protected (should require auth)",
94
+ actual: "accessible anonymously",
95
+ message: `Protected route ${route.path} accessible without authentication`,
96
+ evidence: []
97
+ });
98
+ }
99
+
100
+ // Check: role mismatch (admin route accessible by user)
101
+ if (route.declared.roles?.includes("admin") &&
102
+ !route.declared.roles?.includes("user") &&
103
+ route.actual.user?.accessible) {
104
+ violations.push({
105
+ id: `AUTHZ_ROLE_${sha256(route.path)}`,
106
+ severity: "BLOCK",
107
+ type: "role_mismatch",
108
+ route: route.path,
109
+ method: route.method,
110
+ expected: "admin only",
111
+ actual: "accessible by user role",
112
+ message: `Admin route ${route.path} accessible by non-admin users`,
113
+ evidence: []
114
+ });
115
+ }
116
+
117
+ // Check: protected route blocked after login (broken auth)
118
+ if (route.declared.protected &&
119
+ route.actual.anon?.redirected &&
120
+ route.actual.user && !route.actual.user.accessible) {
121
+ violations.push({
122
+ id: `AUTHZ_BLOCKED_${sha256(route.path)}`,
123
+ severity: "WARN",
124
+ type: "blocked_after_auth",
125
+ route: route.path,
126
+ method: route.method,
127
+ expected: "accessible after auth",
128
+ actual: `blocked (status ${route.actual.user.status})`,
129
+ message: `Protected route ${route.path} not accessible after authentication`,
130
+ evidence: []
131
+ });
132
+ }
133
+ }
134
+
135
+ return violations;
136
+ }
137
+
138
+ /**
139
+ * Format matrix for display
140
+ */
141
+ function formatMatrix(matrix) {
142
+ const lines = [];
143
+
144
+ lines.push("# AuthZ Matrix\n");
145
+ lines.push(`Generated: ${matrix.meta.generatedAt}`);
146
+ lines.push(`Roles: ${matrix.roles.join(", ")}\n`);
147
+
148
+ // Build table header
149
+ const header = ["Route", "Method", "Declared", "Anon", "User", "Admin"];
150
+ lines.push(`| ${header.join(" | ")} |`);
151
+ lines.push(`| ${header.map(() => "---").join(" | ")} |`);
152
+
153
+ for (const route of matrix.routes) {
154
+ const declared = route.declared.protected ? "🔒" : "🌐";
155
+ const anon = formatAccess(route.actual.anon);
156
+ const user = formatAccess(route.actual.user);
157
+ const admin = formatAccess(route.actual.admin);
158
+
159
+ lines.push(`| ${route.path} | ${route.method} | ${declared} | ${anon} | ${user} | ${admin} |`);
160
+ }
161
+
162
+ if (matrix.violations.length > 0) {
163
+ lines.push("\n## Violations\n");
164
+ for (const v of matrix.violations) {
165
+ const icon = v.severity === "BLOCK" ? "🛑" : "⚠️";
166
+ lines.push(`${icon} **${v.type}**: ${v.message}`);
167
+ }
168
+ }
169
+
170
+ return lines.join("\n");
171
+ }
172
+
173
+ function formatAccess(result) {
174
+ if (!result) return "?";
175
+ if (result.accessible) return "✅";
176
+ if (result.redirected) return "↩️";
177
+ return `❌ ${result.status}`;
178
+ }
179
+
180
+ function matchesRoute(pattern, actual) {
181
+ const patternParts = pattern.split("/").filter(Boolean);
182
+ const actualParts = actual.split("/").filter(Boolean);
183
+
184
+ if (patternParts.length !== actualParts.length) return false;
185
+
186
+ for (let i = 0; i < patternParts.length; i++) {
187
+ const p = patternParts[i];
188
+ if (p.startsWith(":") || p.startsWith("*")) continue;
189
+ if (p !== actualParts[i]) return false;
190
+ }
191
+ return true;
192
+ }
193
+
194
+ module.exports = {
195
+ buildAuthZMatrix,
196
+ detectViolations,
197
+ formatMatrix
198
+ };
@@ -0,0 +1,28 @@
1
+ // bin/runners/lib/pkgjson.js
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ function readPkg(root) {
6
+ const p = path.join(root, "package.json");
7
+ if (!fs.existsSync(p)) throw new Error("package.json not found");
8
+ return { path: p, json: JSON.parse(fs.readFileSync(p, "utf8")) };
9
+ }
10
+
11
+ function writePkg(pkgPath, json) {
12
+ fs.writeFileSync(pkgPath, JSON.stringify(json, null, 2) + "\n", "utf8");
13
+ }
14
+
15
+ function upsertScripts(pkg, scripts) {
16
+ pkg.scripts = pkg.scripts || {};
17
+ const changed = [];
18
+
19
+ for (const [k, v] of Object.entries(scripts)) {
20
+ if (pkg.scripts[k] === v) continue;
21
+ pkg.scripts[k] = v;
22
+ changed.push(k);
23
+ }
24
+
25
+ return changed;
26
+ }
27
+
28
+ module.exports = { readPkg, writePkg, upsertScripts };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Preflight checks - Run before any vibecheck command
3
+ *
4
+ * Validates:
5
+ * - Node version
6
+ * - Required dependencies
7
+ * - Project structure
8
+ * - Configuration
9
+ */
10
+
11
+ "use strict";
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+
16
+ const MIN_NODE_VERSION = 18;
17
+
18
+ function checkNodeVersion() {
19
+ const version = process.version;
20
+ const major = parseInt(version.slice(1).split(".")[0], 10);
21
+ if (major < MIN_NODE_VERSION) {
22
+ return {
23
+ ok: false,
24
+ message: `Node.js ${MIN_NODE_VERSION}+ required (you have ${version})`
25
+ };
26
+ }
27
+ return { ok: true };
28
+ }
29
+
30
+ function checkPlaywright() {
31
+ try {
32
+ require.resolve("playwright");
33
+ return { ok: true };
34
+ } catch {
35
+ return {
36
+ ok: false,
37
+ optional: true,
38
+ message: "Playwright not installed. Reality mode requires: npm i -D playwright"
39
+ };
40
+ }
41
+ }
42
+
43
+ function checkFastGlob() {
44
+ try {
45
+ require.resolve("fast-glob");
46
+ return { ok: true };
47
+ } catch {
48
+ return {
49
+ ok: false,
50
+ message: "fast-glob not installed. Run: npm install"
51
+ };
52
+ }
53
+ }
54
+
55
+ function checkProjectRoot(root) {
56
+ const pkgPath = path.join(root, "package.json");
57
+ if (!fs.existsSync(pkgPath)) {
58
+ return {
59
+ ok: false,
60
+ message: "No package.json found. Are you in a project directory?"
61
+ };
62
+ }
63
+ return { ok: true };
64
+ }
65
+
66
+ function checkGit(root) {
67
+ const gitPath = path.join(root, ".git");
68
+ if (!fs.existsSync(gitPath)) {
69
+ return {
70
+ ok: false,
71
+ optional: true,
72
+ message: "Not a git repository. Some features may not work."
73
+ };
74
+ }
75
+ return { ok: true };
76
+ }
77
+
78
+ function checkWritable(root) {
79
+ const vibecheckDir = path.join(root, ".vibecheck");
80
+ try {
81
+ fs.mkdirSync(vibecheckDir, { recursive: true });
82
+ const testFile = path.join(vibecheckDir, ".write_test");
83
+ fs.writeFileSync(testFile, "test");
84
+ fs.unlinkSync(testFile);
85
+ return { ok: true };
86
+ } catch {
87
+ return {
88
+ ok: false,
89
+ message: "Cannot write to .vibecheck directory. Check permissions."
90
+ };
91
+ }
92
+ }
93
+
94
+ function runPreflight(root, { silent = false, strict = false } = {}) {
95
+ const checks = [
96
+ { name: "Node.js", check: checkNodeVersion },
97
+ { name: "Project", check: () => checkProjectRoot(root) },
98
+ { name: "Writable", check: () => checkWritable(root) },
99
+ { name: "Git", check: () => checkGit(root) },
100
+ { name: "fast-glob", check: checkFastGlob },
101
+ { name: "Playwright", check: checkPlaywright },
102
+ ];
103
+
104
+ const results = [];
105
+ let hasError = false;
106
+
107
+ for (const { name, check } of checks) {
108
+ const result = check();
109
+ results.push({ name, ...result });
110
+
111
+ if (!result.ok && !result.optional) {
112
+ hasError = true;
113
+ }
114
+ }
115
+
116
+ if (!silent && hasError) {
117
+ console.error("\n⚠️ Preflight checks failed:\n");
118
+ for (const r of results) {
119
+ if (!r.ok && !r.optional) {
120
+ console.error(` ✗ ${r.name}: ${r.message}`);
121
+ }
122
+ }
123
+ console.error("");
124
+ }
125
+
126
+ if (!silent && !hasError) {
127
+ // Show optional warnings
128
+ const optionalWarnings = results.filter(r => !r.ok && r.optional);
129
+ if (optionalWarnings.length && process.env.VIBECHECK_VERBOSE) {
130
+ for (const r of optionalWarnings) {
131
+ console.warn(` ⚠ ${r.name}: ${r.message}`);
132
+ }
133
+ }
134
+ }
135
+
136
+ return {
137
+ ok: !hasError,
138
+ results
139
+ };
140
+ }
141
+
142
+ module.exports = { runPreflight, checkNodeVersion, checkPlaywright };
@@ -0,0 +1,84 @@
1
+ // bin/runners/lib/reality-findings.js
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+
5
+ function loadLastReality(repoRoot, maxAgeHours = 12) {
6
+ const p = path.join(repoRoot, ".vibecheck", "reality", "last_reality.json");
7
+ if (!fs.existsSync(p)) return null;
8
+
9
+ const obj = JSON.parse(fs.readFileSync(p, "utf8"));
10
+ const finishedAt = obj?.meta?.finishedAt ? new Date(obj.meta.finishedAt).getTime() : 0;
11
+ if (!finishedAt) return null;
12
+
13
+ const ageMs = Date.now() - finishedAt;
14
+ if (ageMs > maxAgeHours * 3600 * 1000) return null; // stale
15
+
16
+ return obj;
17
+ }
18
+
19
+ function findingsFromReality(repoRoot) {
20
+ const r = loadLastReality(repoRoot);
21
+ if (!r) return [];
22
+
23
+ const out = [];
24
+ for (const f of r.findings || []) {
25
+ // Preserve original category (DeadUI, AuthCoverage, etc.)
26
+ const category = f.category || "DeadUI";
27
+
28
+ // Generate appropriate fix hints based on category
29
+ let fixHints;
30
+ if (category === "AuthCoverage") {
31
+ fixHints = [
32
+ "Verify your Next.js matcher config protects this route.",
33
+ "Ensure middleware redirects unauthenticated users.",
34
+ "Check that session/auth state is being validated server-side."
35
+ ];
36
+ } else {
37
+ fixHints = [
38
+ "Ensure the element has a real onClick/handler and it returns a real result.",
39
+ "If it calls /api/*, ensure the route exists and returns success only on res.ok.",
40
+ "If it's intentionally disabled, reflect that visually and remove the click affordance."
41
+ ];
42
+ }
43
+
44
+ out.push({
45
+ id: `F_REALITY_${f.id}`,
46
+ severity: f.severity === "BLOCK" ? "BLOCK" : "WARN",
47
+ category,
48
+ title: f.title,
49
+ why: category === "AuthCoverage"
50
+ ? "Reality Runner detected an auth boundary violation."
51
+ : "Reality Runner found a UI interaction that fails in the running app.",
52
+ confidence: "high",
53
+ evidence: [
54
+ {
55
+ id: `ev_${f.id}`,
56
+ file: f.page ? String(f.page).replace(/^https?:\/\//, "") : "runtime",
57
+ lines: "0-0",
58
+ snippetHash: (f.screenshot || "runtime").slice(0, 80),
59
+ reason: f.reason
60
+ }
61
+ ],
62
+ fixHints
63
+ });
64
+ }
65
+
66
+ // escalate raw runtime console errors into WARN
67
+ const ce = (r.consoleErrors || []).slice(0, 5);
68
+ if (ce.length) {
69
+ out.push({
70
+ id: "F_REALITY_CONSOLE_ERRORS",
71
+ severity: "WARN",
72
+ category: "DeadUI",
73
+ title: `Console errors observed during Reality run (${ce.length})`,
74
+ why: "Console errors often correlate with broken UI handlers or missing data paths.",
75
+ confidence: "med",
76
+ evidence: [],
77
+ fixHints: ["Open the Reality report and fix the first error in the consoleErrors list."]
78
+ });
79
+ }
80
+
81
+ return out;
82
+ }
83
+
84
+ module.exports = { findingsFromReality };
@@ -0,0 +1,29 @@
1
+ // bin/runners/lib/redact.js
2
+ function redactString(s) {
3
+ if (typeof s !== "string") return s;
4
+
5
+ return s
6
+ .replace(/(api[_-]?key|secret|token|password)\s*[:=]\s*["']?([^"'\s]{6,})["']?/gi, "$1: [REDACTED]")
7
+ .replace(/(bearer)\s+([a-z0-9_\-\.=]{12,})/gi, "$1 [REDACTED]")
8
+ .replace(/sk-[a-z0-9]{16,}/gi, "[REDACTED]")
9
+ .replace(/[a-z0-9+\/=]{80,}/gi, "[REDACTED_BLOB]");
10
+ }
11
+
12
+ function redactObject(obj) {
13
+ if (obj == null) return obj;
14
+ if (typeof obj === "string") return redactString(obj);
15
+ if (typeof obj !== "object") return obj;
16
+ if (Array.isArray(obj)) return obj.map(redactObject);
17
+
18
+ const out = {};
19
+ for (const [k, v] of Object.entries(obj)) {
20
+ if (/api[_-]?key|secret|token|password|private/i.test(k)) {
21
+ out[k] = "[REDACTED]";
22
+ continue;
23
+ }
24
+ out[k] = redactObject(v);
25
+ }
26
+ return out;
27
+ }
28
+
29
+ module.exports = { redactObject };
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Replay Capsule Manager
3
+ * Handles saving, loading, and managing replay capsules
4
+ */
5
+
6
+ const fs = require('fs').promises;
7
+ const path = require('path');
8
+ const { v4: uuidv4 } = require('uuid');
9
+ const crypto = require('crypto');
10
+
11
+ class CapsuleManager {
12
+ constructor(basePath) {
13
+ this.basePath = path.join(basePath, '.vibecheck', 'replays');
14
+ }
15
+
16
+ async init() {
17
+ await fs.mkdir(this.basePath, { recursive: true });
18
+ }
19
+
20
+ async saveCapsule(capsule) {
21
+ const id = capsule.id || uuidv4();
22
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
23
+ const capsuleDir = path.join(this.basePath, `${timestamp}_${id}`);
24
+
25
+ await fs.mkdir(capsuleDir, { recursive: true });
26
+
27
+ // Save metadata
28
+ const metadata = {
29
+ id,
30
+ createdAt: new Date().toISOString(),
31
+ name: capsule.name || `Replay ${timestamp}`,
32
+ description: capsule.description || '',
33
+ tags: capsule.tags || [],
34
+ steps: capsule.steps ? capsule.steps.length : 0,
35
+ duration: capsule.duration || 0,
36
+ status: 'captured',
37
+ ...capsule.metadata
38
+ };
39
+
40
+ // Save steps
41
+ const steps = capsule.steps || [];
42
+
43
+ // Generate deterministic hash for the capsule
44
+ const hash = crypto
45
+ .createHash('sha256')
46
+ .update(JSON.stringify({ metadata, steps }))
47
+ .digest('hex');
48
+
49
+ metadata.hash = hash;
50
+
51
+ await Promise.all([
52
+ fs.writeFile(
53
+ path.join(capsuleDir, 'metadata.json'),
54
+ JSON.stringify(metadata, null, 2),
55
+ 'utf8'
56
+ ),
57
+ fs.writeFile(
58
+ path.join(capsuleDir, 'steps.json'),
59
+ JSON.stringify(steps, null, 2),
60
+ 'utf8'
61
+ )
62
+ ]);
63
+
64
+ return { id, path: capsuleDir, metadata };
65
+ }
66
+
67
+ async loadCapsule(capsuleId) {
68
+ const capsules = await this.listCapsules();
69
+ const capsule = capsules.find(c => c.id === capsuleId || c.metadata.id === capsuleId);
70
+
71
+ if (!capsule) {
72
+ throw new Error(`Capsule ${capsuleId} not found`);
73
+ }
74
+
75
+ const [metadata, steps] = await Promise.all([
76
+ fs.readFile(path.join(capsule.path, 'metadata.json'), 'utf8')
77
+ .then(JSON.parse),
78
+ fs.readFile(path.join(capsule.path, 'steps.json'), 'utf8')
79
+ .then(JSON.parse)
80
+ ]);
81
+
82
+ return { metadata, steps };
83
+ }
84
+
85
+ async listCapsules() {
86
+ try {
87
+ const dirs = await fs.readdir(this.basePath, { withFileTypes: true });
88
+ const capsules = [];
89
+
90
+ for (const dir of dirs) {
91
+ if (!dir.isDirectory()) continue;
92
+
93
+ try {
94
+ const metadataPath = path.join(this.basePath, dir.name, 'metadata.json');
95
+ const metadata = JSON.parse(await fs.readFile(metadataPath, 'utf8'));
96
+
97
+ capsules.push({
98
+ id: metadata.id,
99
+ name: metadata.name,
100
+ path: path.join(this.basePath, dir.name),
101
+ metadata,
102
+ timestamp: new Date(metadata.createdAt).getTime()
103
+ });
104
+ } catch (err) {
105
+ console.error(`Error loading capsule ${dir.name}:`, err.message);
106
+ }
107
+ }
108
+
109
+ // Sort by timestamp, newest first
110
+ return capsules.sort((a, b) => b.timestamp - a.timestamp);
111
+ } catch (err) {
112
+ if (err.code === 'ENOENT') {
113
+ return [];
114
+ }
115
+ throw err;
116
+ }
117
+ }
118
+
119
+ async deleteCapsule(capsuleId) {
120
+ const capsules = await this.listCapsules();
121
+ const capsule = capsules.find(c => c.id === capsuleId || c.metadata.id === capsuleId);
122
+
123
+ if (!capsule) {
124
+ throw new Error(`Capsule ${capsuleId} not found`);
125
+ }
126
+
127
+ await fs.rm(capsule.path, { recursive: true, force: true });
128
+ return true;
129
+ }
130
+
131
+ async exportCapsule(capsuleId, outputPath) {
132
+ const { metadata, steps } = await this.loadCapsule(capsuleId);
133
+ const exportData = { metadata, steps };
134
+
135
+ await fs.writeFile(
136
+ outputPath,
137
+ JSON.stringify(exportData, null, 2),
138
+ 'utf8'
139
+ );
140
+
141
+ return outputPath;
142
+ }
143
+
144
+ async importCapsule(filePath) {
145
+ const data = JSON.parse(await fs.readFile(filePath, 'utf8'));
146
+ return this.saveCapsule({
147
+ ...data.metadata,
148
+ steps: data.steps,
149
+ imported: true
150
+ });
151
+ }
152
+ }
153
+
154
+ module.exports = CapsuleManager;