@jevitate/cli 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-cli.d.ts +31 -11
  3. package/dist/ai-cli.js +131 -88
  4. package/dist/ai-cli.js.map +1 -1
  5. package/dist/author-journey-cli.d.ts +4 -0
  6. package/dist/author-journey-cli.js +111 -0
  7. package/dist/author-journey-cli.js.map +1 -0
  8. package/dist/bin.js +60349 -16477
  9. package/dist/bin.js.map +1 -1
  10. package/dist/browser-run-options.d.ts +89 -0
  11. package/dist/browser-run-options.js +175 -0
  12. package/dist/browser-run-options.js.map +1 -0
  13. package/dist/build-info.generated.d.ts +2 -0
  14. package/dist/build-info.generated.js +10 -0
  15. package/dist/build-info.generated.js.map +1 -0
  16. package/dist/campaign-api.d.ts +151 -0
  17. package/dist/campaign-api.js +446 -0
  18. package/dist/campaign-api.js.map +1 -0
  19. package/dist/campaign-cli.d.ts +6 -0
  20. package/dist/campaign-cli.js +66 -0
  21. package/dist/campaign-cli.js.map +1 -0
  22. package/dist/check-api.d.ts +5 -0
  23. package/dist/check-api.js +234 -0
  24. package/dist/check-api.js.map +1 -0
  25. package/dist/check-budget.d.ts +26 -0
  26. package/dist/check-budget.js +90 -0
  27. package/dist/check-budget.js.map +1 -0
  28. package/dist/check-cli.d.ts +31 -0
  29. package/dist/check-cli.js +109 -0
  30. package/dist/check-cli.js.map +1 -0
  31. package/dist/check-execute.d.ts +29 -0
  32. package/dist/check-execute.js +420 -0
  33. package/dist/check-execute.js.map +1 -0
  34. package/dist/check-plan.d.ts +118 -0
  35. package/dist/check-plan.js +516 -0
  36. package/dist/check-plan.js.map +1 -0
  37. package/dist/check-suite.d.ts +184 -0
  38. package/dist/check-suite.js +540 -0
  39. package/dist/check-suite.js.map +1 -0
  40. package/dist/check-types.d.ts +181 -0
  41. package/dist/check-types.js +35 -0
  42. package/dist/check-types.js.map +1 -0
  43. package/dist/cli-args.d.ts +26 -0
  44. package/dist/cli-args.js +50 -0
  45. package/dist/cli-args.js.map +1 -0
  46. package/dist/cli-output.d.ts +106 -0
  47. package/dist/cli-output.js +563 -0
  48. package/dist/cli-output.js.map +1 -0
  49. package/dist/cli-reference.d.ts +3 -0
  50. package/dist/cli-reference.js +81 -0
  51. package/dist/cli-reference.js.map +1 -0
  52. package/dist/cli-refusal.d.ts +12 -0
  53. package/dist/cli-refusal.js +52 -0
  54. package/dist/cli-refusal.js.map +1 -0
  55. package/dist/cli-shared.d.ts +340 -0
  56. package/dist/cli-shared.js +537 -0
  57. package/dist/cli-shared.js.map +1 -0
  58. package/dist/cli-surface.d.ts +33 -0
  59. package/dist/cli-surface.js +48 -0
  60. package/dist/cli-surface.js.map +1 -0
  61. package/dist/conversation-options.d.ts +15 -0
  62. package/dist/conversation-options.js +10 -0
  63. package/dist/conversation-options.js.map +1 -0
  64. package/dist/credentials-file.d.ts +15 -0
  65. package/dist/credentials-file.js +56 -0
  66. package/dist/credentials-file.js.map +1 -0
  67. package/dist/data-dir.d.ts +1 -1
  68. package/dist/data-dir.js +1 -1
  69. package/dist/defect-evidence.d.ts +141 -0
  70. package/dist/defect-evidence.js +505 -0
  71. package/dist/defect-evidence.js.map +1 -0
  72. package/dist/demo-aspect-api.d.ts +209 -0
  73. package/dist/demo-aspect-api.js +398 -0
  74. package/dist/demo-aspect-api.js.map +1 -0
  75. package/dist/demo-aspect-cli.d.ts +3 -0
  76. package/dist/demo-aspect-cli.js +243 -0
  77. package/dist/demo-aspect-cli.js.map +1 -0
  78. package/dist/demo-capture.d.ts +142 -0
  79. package/dist/demo-capture.js +537 -0
  80. package/dist/demo-capture.js.map +1 -0
  81. package/dist/engine.d.ts +35 -0
  82. package/dist/engine.js +25 -0
  83. package/dist/engine.js.map +1 -0
  84. package/dist/environments.d.ts +155 -0
  85. package/dist/environments.js +364 -0
  86. package/dist/environments.js.map +1 -0
  87. package/dist/exit-codes.d.ts +46 -0
  88. package/dist/exit-codes.js +91 -0
  89. package/dist/exit-codes.js.map +1 -0
  90. package/dist/explore-adversarial.d.ts +144 -0
  91. package/dist/explore-adversarial.js +227 -0
  92. package/dist/explore-adversarial.js.map +1 -0
  93. package/dist/explore-api.d.ts +7 -187
  94. package/dist/explore-api.js +7 -301
  95. package/dist/explore-api.js.map +1 -1
  96. package/dist/explore-author.d.ts +79 -0
  97. package/dist/explore-author.js +86 -0
  98. package/dist/explore-author.js.map +1 -0
  99. package/dist/explore-cli.d.ts +7 -0
  100. package/dist/explore-cli.js +1199 -0
  101. package/dist/explore-cli.js.map +1 -0
  102. package/dist/explore-coverage.d.ts +173 -0
  103. package/dist/explore-coverage.js +246 -0
  104. package/dist/explore-coverage.js.map +1 -0
  105. package/dist/explore-feature.d.ts +125 -0
  106. package/dist/explore-feature.js +218 -0
  107. package/dist/explore-feature.js.map +1 -0
  108. package/dist/explore-goal.d.ts +271 -0
  109. package/dist/explore-goal.js +417 -0
  110. package/dist/explore-goal.js.map +1 -0
  111. package/dist/explore-shared.d.ts +177 -0
  112. package/dist/explore-shared.js +149 -0
  113. package/dist/explore-shared.js.map +1 -0
  114. package/dist/explore-specs.d.ts +53 -0
  115. package/dist/explore-specs.js +333 -0
  116. package/dist/explore-specs.js.map +1 -0
  117. package/dist/findings-filing.d.ts +64 -0
  118. package/dist/findings-filing.js +108 -0
  119. package/dist/findings-filing.js.map +1 -0
  120. package/dist/fixture-auth.d.ts +63 -0
  121. package/dist/fixture-auth.js +95 -0
  122. package/dist/fixture-auth.js.map +1 -0
  123. package/dist/fixture-cli.d.ts +99 -0
  124. package/dist/fixture-cli.js +292 -0
  125. package/dist/fixture-cli.js.map +1 -0
  126. package/dist/github-issue-filer.d.ts +62 -0
  127. package/dist/github-issue-filer.js +189 -0
  128. package/dist/github-issue-filer.js.map +1 -0
  129. package/dist/host-health-run.d.ts +25 -0
  130. package/dist/host-health-run.js +33 -0
  131. package/dist/host-health-run.js.map +1 -0
  132. package/dist/http-5xx-outcome.d.ts +6 -0
  133. package/dist/http-5xx-outcome.js +39 -0
  134. package/dist/http-5xx-outcome.js.map +1 -0
  135. package/dist/inbox-cli.d.ts +7 -0
  136. package/dist/inbox-cli.js +197 -0
  137. package/dist/inbox-cli.js.map +1 -0
  138. package/dist/index.d.ts +1 -0
  139. package/dist/index.js +1 -0
  140. package/dist/index.js.map +1 -1
  141. package/dist/init-cli.d.ts +4 -0
  142. package/dist/init-cli.js +156 -0
  143. package/dist/init-cli.js.map +1 -0
  144. package/dist/init-keys.d.ts +30 -2
  145. package/dist/init-keys.js +19 -5
  146. package/dist/init-keys.js.map +1 -1
  147. package/dist/init-next-steps.d.ts +35 -0
  148. package/dist/init-next-steps.js +79 -0
  149. package/dist/init-next-steps.js.map +1 -0
  150. package/dist/invariants-file.d.ts +34 -0
  151. package/dist/invariants-file.js +68 -0
  152. package/dist/invariants-file.js.map +1 -0
  153. package/dist/invariants-validate.d.ts +30 -0
  154. package/dist/invariants-validate.js +105 -0
  155. package/dist/invariants-validate.js.map +1 -0
  156. package/dist/journey-annotate-api.d.ts +76 -0
  157. package/dist/journey-annotate-api.js +269 -0
  158. package/dist/journey-annotate-api.js.map +1 -0
  159. package/dist/journey-annotate-cli.d.ts +9 -0
  160. package/dist/journey-annotate-cli.js +181 -0
  161. package/dist/journey-annotate-cli.js.map +1 -0
  162. package/dist/journey-api.d.ts +104 -2
  163. package/dist/journey-api.js +163 -20
  164. package/dist/journey-api.js.map +1 -1
  165. package/dist/journey-cli.d.ts +4 -0
  166. package/dist/journey-cli.js +411 -0
  167. package/dist/journey-cli.js.map +1 -0
  168. package/dist/journey-demo-api.d.ts +114 -0
  169. package/dist/journey-demo-api.js +405 -0
  170. package/dist/journey-demo-api.js.map +1 -0
  171. package/dist/journey-demo-cli.d.ts +10 -0
  172. package/dist/journey-demo-cli.js +158 -0
  173. package/dist/journey-demo-cli.js.map +1 -0
  174. package/dist/journey-prefix.d.ts +194 -0
  175. package/dist/journey-prefix.js +279 -0
  176. package/dist/journey-prefix.js.map +1 -0
  177. package/dist/key-report.d.ts +49 -0
  178. package/dist/key-report.js +101 -0
  179. package/dist/key-report.js.map +1 -0
  180. package/dist/kill-signal.d.ts +193 -0
  181. package/dist/kill-signal.js +283 -0
  182. package/dist/kill-signal.js.map +1 -0
  183. package/dist/launch-armed.d.ts +37 -0
  184. package/dist/launch-armed.js +31 -0
  185. package/dist/launch-armed.js.map +1 -0
  186. package/dist/ledger-api.d.ts +106 -0
  187. package/dist/ledger-api.js +239 -0
  188. package/dist/ledger-api.js.map +1 -0
  189. package/dist/ledger-cli.d.ts +18 -0
  190. package/dist/ledger-cli.js +107 -0
  191. package/dist/ledger-cli.js.map +1 -0
  192. package/dist/load-api.d.ts +29 -11
  193. package/dist/load-api.js +23 -15
  194. package/dist/load-api.js.map +1 -1
  195. package/dist/load-cli.d.ts +4 -0
  196. package/dist/load-cli.js +97 -0
  197. package/dist/load-cli.js.map +1 -0
  198. package/dist/log-correlation.d.ts +200 -0
  199. package/dist/log-correlation.js +394 -0
  200. package/dist/log-correlation.js.map +1 -0
  201. package/dist/log-lines.d.ts +131 -0
  202. package/dist/log-lines.js +389 -0
  203. package/dist/log-lines.js.map +1 -0
  204. package/dist/log-sources.d.ts +71 -0
  205. package/dist/log-sources.js +236 -0
  206. package/dist/log-sources.js.map +1 -0
  207. package/dist/log-trace.d.ts +80 -0
  208. package/dist/log-trace.js +210 -0
  209. package/dist/log-trace.js.map +1 -0
  210. package/dist/logs-cli.d.ts +3 -0
  211. package/dist/logs-cli.js +51 -0
  212. package/dist/logs-cli.js.map +1 -0
  213. package/dist/logs-retention.d.ts +28 -0
  214. package/dist/logs-retention.js +85 -0
  215. package/dist/logs-retention.js.map +1 -0
  216. package/dist/masked-input.d.ts +22 -0
  217. package/dist/masked-input.js +99 -0
  218. package/dist/masked-input.js.map +1 -0
  219. package/dist/mcp-api.d.ts +91 -1
  220. package/dist/mcp-api.js +514 -18
  221. package/dist/mcp-api.js.map +1 -1
  222. package/dist/mcp-args.d.ts +50 -0
  223. package/dist/mcp-args.js +164 -0
  224. package/dist/mcp-args.js.map +1 -0
  225. package/dist/mcp-cli-bridge.d.ts +34 -0
  226. package/dist/mcp-cli-bridge.js +62 -0
  227. package/dist/mcp-cli-bridge.js.map +1 -0
  228. package/dist/mcp-cli-runner.d.ts +29 -0
  229. package/dist/mcp-cli-runner.js +44 -0
  230. package/dist/mcp-cli-runner.js.map +1 -0
  231. package/dist/mcp-cli-tools.d.ts +129 -0
  232. package/dist/mcp-cli-tools.js +737 -0
  233. package/dist/mcp-cli-tools.js.map +1 -0
  234. package/dist/mcp-paths.d.ts +28 -0
  235. package/dist/mcp-paths.js +76 -0
  236. package/dist/mcp-paths.js.map +1 -0
  237. package/dist/mission-actors.d.ts +40 -0
  238. package/dist/mission-actors.js +72 -0
  239. package/dist/mission-actors.js.map +1 -0
  240. package/dist/mission-api.d.ts +35 -0
  241. package/dist/mission-api.js +60 -3
  242. package/dist/mission-api.js.map +1 -1
  243. package/dist/mission-cli.d.ts +4 -0
  244. package/dist/mission-cli.js +248 -0
  245. package/dist/mission-cli.js.map +1 -0
  246. package/dist/mission-exit.d.ts +22 -0
  247. package/dist/mission-exit.js +26 -0
  248. package/dist/mission-exit.js.map +1 -0
  249. package/dist/mission-fixtures.d.ts +234 -0
  250. package/dist/mission-fixtures.js +862 -0
  251. package/dist/mission-fixtures.js.map +1 -0
  252. package/dist/mission-journal.d.ts +60 -0
  253. package/dist/mission-journal.js +115 -0
  254. package/dist/mission-journal.js.map +1 -0
  255. package/dist/mission-queue-cli.d.ts +10 -0
  256. package/dist/mission-queue-cli.js +198 -0
  257. package/dist/mission-queue-cli.js.map +1 -0
  258. package/dist/mission-queue-runner.d.ts +126 -0
  259. package/dist/mission-queue-runner.js +406 -0
  260. package/dist/mission-queue-runner.js.map +1 -0
  261. package/dist/multi-run-cli.d.ts +37 -0
  262. package/dist/multi-run-cli.js +116 -0
  263. package/dist/multi-run-cli.js.map +1 -0
  264. package/dist/multi-run.d.ts +339 -0
  265. package/dist/multi-run.js +619 -0
  266. package/dist/multi-run.js.map +1 -0
  267. package/dist/openrouter-call.d.ts +22 -0
  268. package/dist/openrouter-call.js +64 -0
  269. package/dist/openrouter-call.js.map +1 -0
  270. package/dist/profile-cli.d.ts +4 -0
  271. package/dist/profile-cli.js +57 -0
  272. package/dist/profile-cli.js.map +1 -0
  273. package/dist/program.d.ts +3 -75
  274. package/dist/program.js +123 -1921
  275. package/dist/program.js.map +1 -1
  276. package/dist/project-dir.d.ts +96 -0
  277. package/dist/project-dir.js +221 -0
  278. package/dist/project-dir.js.map +1 -0
  279. package/dist/record-api.d.ts +13 -7
  280. package/dist/record-api.js +44 -30
  281. package/dist/record-api.js.map +1 -1
  282. package/dist/record-cli.d.ts +4 -0
  283. package/dist/record-cli.js +76 -0
  284. package/dist/record-cli.js.map +1 -0
  285. package/dist/recording-cli.d.ts +4 -0
  286. package/dist/recording-cli.js +248 -0
  287. package/dist/recording-cli.js.map +1 -0
  288. package/dist/regression-api.d.ts +107 -0
  289. package/dist/regression-api.js +387 -6
  290. package/dist/regression-api.js.map +1 -1
  291. package/dist/regression-cli.d.ts +4 -0
  292. package/dist/regression-cli.js +284 -0
  293. package/dist/regression-cli.js.map +1 -0
  294. package/dist/report-api.d.ts +146 -0
  295. package/dist/report-api.js +431 -0
  296. package/dist/report-api.js.map +1 -0
  297. package/dist/report-cli.d.ts +12 -0
  298. package/dist/report-cli.js +147 -0
  299. package/dist/report-cli.js.map +1 -0
  300. package/dist/resource-preflight.d.ts +87 -0
  301. package/dist/resource-preflight.js +160 -0
  302. package/dist/resource-preflight.js.map +1 -0
  303. package/dist/result-schema.d.ts +22 -0
  304. package/dist/result-schema.js +28 -0
  305. package/dist/result-schema.js.map +1 -0
  306. package/dist/run-index.d.ts +29 -0
  307. package/dist/run-index.js +70 -0
  308. package/dist/run-index.js.map +1 -0
  309. package/dist/run-key-preflight.d.ts +42 -0
  310. package/dist/run-key-preflight.js +82 -0
  311. package/dist/run-key-preflight.js.map +1 -0
  312. package/dist/run-screenshots.d.ts +123 -0
  313. package/dist/run-screenshots.js +235 -0
  314. package/dist/run-screenshots.js.map +1 -0
  315. package/dist/runtime-env.d.ts +8 -0
  316. package/dist/runtime-env.js +23 -0
  317. package/dist/runtime-env.js.map +1 -0
  318. package/dist/secret-args.d.ts +23 -0
  319. package/dist/secret-args.js +45 -0
  320. package/dist/secret-args.js.map +1 -0
  321. package/dist/serve-cli.d.ts +4 -0
  322. package/dist/serve-cli.js +95 -0
  323. package/dist/serve-cli.js.map +1 -0
  324. package/dist/server-log-verify.d.ts +36 -0
  325. package/dist/server-log-verify.js +120 -0
  326. package/dist/server-log-verify.js.map +1 -0
  327. package/dist/session-check.d.ts +14 -0
  328. package/dist/session-check.js +44 -0
  329. package/dist/session-check.js.map +1 -0
  330. package/dist/site-cli.d.ts +4 -0
  331. package/dist/site-cli.js +127 -0
  332. package/dist/site-cli.js.map +1 -0
  333. package/dist/site-gate-cli.d.ts +28 -0
  334. package/dist/site-gate-cli.js +59 -0
  335. package/dist/site-gate-cli.js.map +1 -0
  336. package/dist/source-api.js +20 -4
  337. package/dist/source-api.js.map +1 -1
  338. package/dist/source-cli.d.ts +4 -0
  339. package/dist/source-cli.js +284 -0
  340. package/dist/source-cli.js.map +1 -0
  341. package/dist/source-run-api.d.ts +27 -1
  342. package/dist/source-run-api.js +22 -11
  343. package/dist/source-run-api.js.map +1 -1
  344. package/dist/storage-state-snapshot.d.ts +50 -0
  345. package/dist/storage-state-snapshot.js +87 -0
  346. package/dist/storage-state-snapshot.js.map +1 -0
  347. package/dist/suite-explore-options.d.ts +321 -0
  348. package/dist/suite-explore-options.js +162 -0
  349. package/dist/suite-explore-options.js.map +1 -0
  350. package/dist/target-config.d.ts +115 -0
  351. package/dist/target-config.js +225 -0
  352. package/dist/target-config.js.map +1 -0
  353. package/dist/transcript-file.d.ts +12 -0
  354. package/dist/transcript-file.js +23 -0
  355. package/dist/transcript-file.js.map +1 -0
  356. package/dist/type-fixture-file.d.ts +9 -0
  357. package/dist/type-fixture-file.js +48 -0
  358. package/dist/type-fixture-file.js.map +1 -0
  359. package/dist/ui-api.d.ts +3 -0
  360. package/dist/ui-api.js +11 -4
  361. package/dist/ui-api.js.map +1 -1
  362. package/dist/usability-capture.d.ts +43 -0
  363. package/dist/usability-capture.js +327 -0
  364. package/dist/usability-capture.js.map +1 -0
  365. package/dist/usage-config.d.ts +36 -0
  366. package/dist/usage-config.js +114 -0
  367. package/dist/usage-config.js.map +1 -0
  368. package/dist/ux-api.d.ts +3 -75
  369. package/dist/ux-api.js +3 -220
  370. package/dist/ux-api.js.map +1 -1
  371. package/dist/ux-claim-probe.d.ts +45 -0
  372. package/dist/ux-claim-probe.js +386 -0
  373. package/dist/ux-claim-probe.js.map +1 -0
  374. package/dist/ux-cli.d.ts +4 -0
  375. package/dist/ux-cli.js +109 -0
  376. package/dist/ux-cli.js.map +1 -0
  377. package/dist/ux-config.d.ts +29 -0
  378. package/dist/ux-config.js +103 -0
  379. package/dist/ux-config.js.map +1 -0
  380. package/dist/ux-evidence.d.ts +54 -0
  381. package/dist/ux-evidence.js +197 -0
  382. package/dist/ux-evidence.js.map +1 -0
  383. package/dist/ux-product.d.ts +14 -0
  384. package/dist/ux-product.js +39 -0
  385. package/dist/ux-product.js.map +1 -0
  386. package/dist/ux-review.d.ts +116 -0
  387. package/dist/ux-review.js +171 -0
  388. package/dist/ux-review.js.map +1 -0
  389. package/dist/ux-usability.d.ts +263 -0
  390. package/dist/ux-usability.js +580 -0
  391. package/dist/ux-usability.js.map +1 -0
  392. package/dist/verify-fix-api.d.ts +194 -0
  393. package/dist/verify-fix-api.js +506 -0
  394. package/dist/verify-fix-api.js.map +1 -0
  395. package/dist/verify-fix-cli.d.ts +4 -0
  396. package/dist/verify-fix-cli.js +115 -0
  397. package/dist/verify-fix-cli.js.map +1 -0
  398. package/package.json +23 -18
  399. package/skills/jevitate-ci-check/SKILL.md +77 -0
  400. package/skills/jevitate-demo/SKILL.md +61 -0
  401. package/skills/jevitate-explore/SKILL.md +96 -87
  402. package/skills/jevitate-getting-started/SKILL.md +89 -0
  403. package/skills/jevitate-load-test/SKILL.md +11 -2
  404. package/skills/jevitate-mission-scope/SKILL.md +19 -11
  405. package/skills/jevitate-record/SKILL.md +23 -5
  406. package/skills/jevitate-run-journey/SKILL.md +61 -17
  407. package/skills/jevitate-sources/SKILL.md +57 -14
  408. package/skills/jevitate-test-campaign/SKILL.md +203 -0
  409. package/skills/jevitate-ux-review/SKILL.md +106 -16
  410. package/skills/jevitate-verify-fix/SKILL.md +76 -0
@@ -0,0 +1,123 @@
1
+ import type { Page } from "playwright";
2
+ import { type TranscriptEntry } from "@jevitate/explore";
3
+ import type { StepObserver } from "@jevitate/interpreter";
4
+ import type { BrowserPort } from "@jevitate/playwright";
5
+ import { SecretPixelMask } from "./demo-capture.js";
6
+ /**
7
+ * #251 — `--screenshots [dir]` / `--screenshots steps`: a screenshot capture mode for any run
8
+ * (explore strategies, `journey run`/`annotate`/`demo`, `verify-fix`).
9
+ *
10
+ * - `screens` (the default): one screenshot per DISTINCT screen — deduplicated by the page-state
11
+ * fingerprint coverage already uses (`coverageStateFingerprint`: the url template plus the
12
+ * control table), so a new screen is a new state;
13
+ * - `steps`: one per step.
14
+ *
15
+ * Every image is the viewport after the step acted, with the demo overlay hidden and every
16
+ * registered secret masked in pixels ({@link SecretPixelMask}); a capture whose mask cannot be
17
+ * proven is SKIPPED and its reason recorded (fail closed). An `index.md` contact sheet lists each
18
+ * image with its step, route and what happened (all text redacted, proven secret-free before it is
19
+ * written). The paths go in the result as `screenshotPaths` (+ `screenshotIndex`, and
20
+ * `screenshotsSkipped` when a capture was refused).
21
+ */
22
+ export type ScreenshotMode = "screens" | "steps";
23
+ export interface ScreenshotsSpec {
24
+ readonly mode: ScreenshotMode;
25
+ /** Where the images go; absent ⇒ `<run artifact stem>.screenshots/` beside the run's output. */
26
+ readonly dir?: string;
27
+ }
28
+ /** An unusable `--screenshots` value: refused before anything runs (exit 64). */
29
+ export declare class ScreenshotsArgError extends Error {
30
+ readonly code: "E_SCREENSHOTS_ARGS";
31
+ constructor(message: string);
32
+ }
33
+ /**
34
+ * `--screenshots` → the spec: bare / `screens` → one per distinct screen; `steps` → one per step;
35
+ * `screens:<dir>` / `steps:<dir>` → that mode into `<dir>`; any other value is the directory
36
+ * (screens mode). An empty value is refused.
37
+ */
38
+ export declare function parseScreenshotsArg(v: string | boolean | undefined, where?: string): ScreenshotsSpec | undefined;
39
+ /** The run's screenshot folder: `spec.dir`, else `<dir of artifact>/<artifact stem>.screenshots`. */
40
+ export declare function screenshotsDirFor(spec: ScreenshotsSpec, artifactPath: string): string;
41
+ export interface ScreenshotEntry {
42
+ /** 1-based image number. */
43
+ readonly n: number;
44
+ /** The step it shows (after that step acted). */
45
+ readonly step: number;
46
+ /** The route (path) it was taken on, redacted. */
47
+ readonly route: string;
48
+ /** What the step did (redacted). */
49
+ readonly what: string;
50
+ readonly path: string;
51
+ }
52
+ export interface ScreenshotSkip {
53
+ readonly step: number;
54
+ readonly reason: string;
55
+ }
56
+ /** The additive result fields (schemaVersion 1). */
57
+ export interface ScreenshotsResult {
58
+ readonly screenshotPaths: string[];
59
+ readonly screenshotIndex: string;
60
+ readonly screenshotsSkipped?: ScreenshotSkip[];
61
+ }
62
+ export interface RunScreenshotsOptions {
63
+ readonly spec: ScreenshotsSpec;
64
+ /** The resolved folder (see {@link screenshotsDirFor}). */
65
+ readonly dir: string;
66
+ /** Every registered secret: masked in pixels, redacted in the index. */
67
+ readonly secrets: readonly string[];
68
+ /** The contact sheet's heading (redacted). */
69
+ readonly title: string;
70
+ /** A shared mask (e.g. the one a masking port installed); default: a new one over `secrets`. */
71
+ readonly mask?: SecretPixelMask;
72
+ }
73
+ /** A transcript step as one "what happened" line. */
74
+ export declare function describeTranscriptEntry(e: TranscriptEntry): string;
75
+ export declare class RunScreenshots {
76
+ #private;
77
+ readonly mask: SecretPixelMask;
78
+ constructor(opts: RunScreenshotsOptions);
79
+ get mode(): ScreenshotMode;
80
+ /** Captures the page after `step` (queued: captures never overlap). Never throws. */
81
+ capture(page: Page, at: {
82
+ readonly step: number;
83
+ readonly url?: string;
84
+ readonly what: string;
85
+ }): Promise<void>;
86
+ /** TranscriptLog listener hook (explore runners): captures the page after the step just recorded. */
87
+ noteEntry(page: Page, entry: TranscriptEntry): void;
88
+ /** Every capture done; writes `index.md`; the result fields. */
89
+ finish(): Promise<ScreenshotsResult>;
90
+ /** The Markdown contact sheet (images linked relative to the index). */
91
+ contactSheet(): string;
92
+ }
93
+ /** A per-step observer for an interpreter-driven replay (journey run/annotate/demo, verify-fix). */
94
+ export declare function screenshotObserver(shots: RunScreenshots, pageOf: (actor: Parameters<NonNullable<StepObserver["afterStep"]>>[0]["actor"]) => Page, whatOf: (index: number) => string): StepObserver;
95
+ /** Runs every observer's hooks in order (an observer never changes the replay). */
96
+ export declare function composeObservers(...observers: ReadonlyArray<StepObserver | undefined>): StepObserver;
97
+ /** The human summary line for a run's screenshots (#251). */
98
+ export declare function formatScreenshotsLine(r: {
99
+ readonly screenshotPaths?: readonly string[];
100
+ readonly screenshotIndex?: string;
101
+ readonly screenshotsSkipped?: readonly ScreenshotSkip[];
102
+ }): string;
103
+ /** One run's capture wiring (#250/#251): the masked port and the (optional) screenshots. */
104
+ export interface RunCapture {
105
+ readonly mask: SecretPixelMask;
106
+ /** `factory` whose sessions carry the live pixel mask when the run records video or screenshots. */
107
+ wrap(factory: () => BrowserPort): () => BrowserPort;
108
+ /** TranscriptLog hook: a screenshot of `page` after the step (no-op without `--screenshots`). */
109
+ noteEntry(page: Page, entry: TranscriptEntry): void;
110
+ /** Awaits every capture, writes the index; the result fields (`{}` without `--screenshots`). */
111
+ finish(): Promise<Partial<ScreenshotsResult>>;
112
+ }
113
+ /**
114
+ * The capture wiring an explore runner threads through its session and listener. `artifactPath` is
115
+ * read on first use (the run's Recording path: screenshots go in `<stem>.screenshots/` beside it).
116
+ */
117
+ export declare function runCaptureFor(o: {
118
+ readonly recordsVideo: boolean;
119
+ readonly screenshots: ScreenshotsSpec | undefined;
120
+ readonly secrets: readonly string[];
121
+ readonly artifactPath: () => string;
122
+ readonly title: string;
123
+ }): RunCapture;
@@ -0,0 +1,235 @@
1
+ import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join, resolve as resolvePath } from "node:path";
3
+ import { assertNoSecretInPayload, redactText, redactUrl } from "@jevitate/ai-core";
4
+ import { coverageStateFingerprint, snapshot } from "@jevitate/explore";
5
+ import { captureStepScreenshot, maskingPort, SecretPixelMask } from "./demo-capture.js";
6
+ import { clock } from "@jevitate/domain";
7
+ /** An unusable `--screenshots` value: refused before anything runs (exit 64). */
8
+ export class ScreenshotsArgError extends Error {
9
+ code = "E_SCREENSHOTS_ARGS";
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = "ScreenshotsArgError";
13
+ }
14
+ }
15
+ /**
16
+ * `--screenshots` → the spec: bare / `screens` → one per distinct screen; `steps` → one per step;
17
+ * `screens:<dir>` / `steps:<dir>` → that mode into `<dir>`; any other value is the directory
18
+ * (screens mode). An empty value is refused.
19
+ */
20
+ export function parseScreenshotsArg(v, where = "--screenshots") {
21
+ if (v === undefined || v === false)
22
+ return undefined;
23
+ if (v === true)
24
+ return { mode: "screens" };
25
+ const t = v.trim();
26
+ if (t === "")
27
+ throw new ScreenshotsArgError(`${where} needs a mode or a directory: screens, steps, screens:<dir>, steps:<dir> or <dir>`);
28
+ if (t === "screens" || t === "steps")
29
+ return { mode: t };
30
+ const m = /^(screens|steps):(.*)$/.exec(t);
31
+ if (m !== null) {
32
+ const dir = (m[2] ?? "").trim();
33
+ if (dir === "")
34
+ throw new ScreenshotsArgError(`${where} ${m[1]}: needs a directory after the colon`);
35
+ return { mode: m[1], dir: resolvePath(dir) };
36
+ }
37
+ return { mode: "screens", dir: resolvePath(t) };
38
+ }
39
+ /** The run's screenshot folder: `spec.dir`, else `<dir of artifact>/<artifact stem>.screenshots`. */
40
+ export function screenshotsDirFor(spec, artifactPath) {
41
+ if (spec.dir !== undefined)
42
+ return spec.dir;
43
+ const stem = basename(artifactPath).replace(/\.result\.json$/, "").replace(/\.json$/, "");
44
+ return join(dirname(artifactPath), `${stem}.screenshots`);
45
+ }
46
+ const FINGERPRINT_MS = 10_000;
47
+ function oneLine(s) {
48
+ return s.replace(/\s+/g, " ").trim();
49
+ }
50
+ function routeOf(url) {
51
+ try {
52
+ const u = new URL(url);
53
+ return u.pathname + (u.search === "" ? "" : u.search);
54
+ }
55
+ catch {
56
+ return url;
57
+ }
58
+ }
59
+ /** A transcript step as one "what happened" line. */
60
+ export function describeTranscriptEntry(e) {
61
+ const act = e.op === null ? "no action" : `${e.op}${e.target === null ? "" : ` ${e.target}`}`;
62
+ return e.actOk ? act : `${act} — failed${e.reason === undefined ? "" : `: ${e.reason}`}`;
63
+ }
64
+ export class RunScreenshots {
65
+ mask;
66
+ #opts;
67
+ #entries = [];
68
+ #skipped = [];
69
+ #seen = new Set();
70
+ #queue = Promise.resolve();
71
+ #prepared;
72
+ #maxStep = 0;
73
+ constructor(opts) {
74
+ this.#opts = opts;
75
+ this.mask = opts.mask ?? new SecretPixelMask(opts.secrets);
76
+ }
77
+ get mode() {
78
+ return this.#opts.spec.mode;
79
+ }
80
+ /** Registered secrets plus those the app revealed during the run (#298) — what the index must not hold. */
81
+ #known() {
82
+ return [...this.#opts.secrets, ...this.mask.revealed()];
83
+ }
84
+ #redact(s) {
85
+ return redactText(s, this.#known());
86
+ }
87
+ /** Creates the folder once and clears a previous run's images (never another file). */
88
+ #prepare() {
89
+ this.#prepared ??= (async () => {
90
+ await mkdir(this.#opts.dir, { recursive: true });
91
+ for (const f of await readdir(this.#opts.dir))
92
+ if (/^\d+-step-\d+\.png$/.test(f))
93
+ await rm(join(this.#opts.dir, f), { force: true });
94
+ })();
95
+ return this.#prepared;
96
+ }
97
+ /** Captures the page after `step` (queued: captures never overlap). Never throws. */
98
+ capture(page, at) {
99
+ const run = async () => {
100
+ this.#maxStep = Math.max(this.#maxStep, at.step);
101
+ try {
102
+ if (page.isClosed())
103
+ throw new Error("the page is closed");
104
+ await this.#prepare();
105
+ if (this.#opts.spec.mode === "screens") {
106
+ const fp = await Promise.race([
107
+ snapshot(page).then((s) => coverageStateFingerprint(s)),
108
+ new Promise((r) => clock.setTimeout(() => r(null), FINGERPRINT_MS)),
109
+ ]).catch(() => null);
110
+ // An unreadable state cannot be proven a repeat: it is captured (never silently dropped).
111
+ if (fp !== null && this.#seen.has(fp))
112
+ return;
113
+ await this.#shoot(page, at);
114
+ if (fp !== null && this.#entries.some((e) => e.step === at.step))
115
+ this.#seen.add(fp);
116
+ return;
117
+ }
118
+ await this.#shoot(page, at);
119
+ }
120
+ catch (err) {
121
+ this.#skipped.push({ step: at.step, reason: this.#redact(oneLine(err instanceof Error ? err.message : String(err))).slice(0, 300) });
122
+ }
123
+ };
124
+ const next = this.#queue.then(run, run);
125
+ this.#queue = next;
126
+ return next;
127
+ }
128
+ async #shoot(page, at) {
129
+ const n = this.#entries.length + 1;
130
+ const path = join(this.#opts.dir, `${String(n).padStart(2, "0")}-step-${String(at.step).padStart(2, "0")}.png`);
131
+ await captureStepScreenshot(page, path, { step: at.step }, [this.mask.layer()]);
132
+ const url = at.url ?? page.url();
133
+ this.#entries.push({
134
+ n,
135
+ step: at.step,
136
+ route: this.#redact(redactUrl(routeOf(url))),
137
+ what: this.#redact(oneLine(at.what)).slice(0, 300),
138
+ path,
139
+ });
140
+ }
141
+ /** TranscriptLog listener hook (explore runners): captures the page after the step just recorded. */
142
+ noteEntry(page, entry) {
143
+ void this.capture(page, { step: entry.step, what: describeTranscriptEntry(entry) });
144
+ }
145
+ /** Every capture done; writes `index.md`; the result fields. */
146
+ async finish() {
147
+ await this.#queue;
148
+ await this.#prepare();
149
+ const index = join(this.#opts.dir, "index.md");
150
+ const md = this.contactSheet();
151
+ assertNoSecretInPayload(md, this.#known(), "screenshot index"); // the last line: never at rest
152
+ await writeFile(index, md, "utf8");
153
+ return {
154
+ screenshotPaths: this.#entries.map((e) => e.path),
155
+ screenshotIndex: index,
156
+ ...(this.#skipped.length === 0 ? {} : { screenshotsSkipped: [...this.#skipped] }),
157
+ };
158
+ }
159
+ /** The Markdown contact sheet (images linked relative to the index). */
160
+ contactSheet() {
161
+ const mode = this.#opts.spec.mode === "screens" ? "one per distinct screen" : "one per step";
162
+ const lines = [
163
+ `# Screenshots: ${oneLine(this.#redact(this.#opts.title))}`,
164
+ "",
165
+ `Mode: ${mode} · ${this.#entries.length} screenshot(s) over ${this.#maxStep} step(s). The demo overlay is hidden; registered secrets, elements the app marks as secret and credential-shaped values are masked in every image.`,
166
+ "",
167
+ ];
168
+ for (const e of this.#entries) {
169
+ const file = basename(e.path);
170
+ lines.push(`## ${e.n}. Step ${e.step} · \`${e.route.replace(/`/g, "'")}\``, "", `**What happened:** ${e.what}`, "", `![Step ${e.step}: ${e.route.replace(/[[\]]/g, "")}](${encodeURI(file)})`, "");
171
+ }
172
+ if (this.#skipped.length > 0) {
173
+ lines.push("## Not captured", "", ...this.#skipped.map((s) => `- step ${s.step}: ${s.reason}`), "");
174
+ }
175
+ // Re-redacted as a whole: a secret the app revealed after an entry was written is scrubbed too (#298).
176
+ return `${this.#redact(lines.join("\n")).trimEnd()}\n`;
177
+ }
178
+ }
179
+ /** A per-step observer for an interpreter-driven replay (journey run/annotate/demo, verify-fix). */
180
+ export function screenshotObserver(shots, pageOf, whatOf) {
181
+ return {
182
+ afterStep: async ({ actor, index, outcome }) => {
183
+ const what = `${whatOf(index)}${outcome === "done" ? "" : outcome === "failed" ? " — failed" : " — waiting for a human"}`;
184
+ await shots.capture(pageOf(actor), { step: index + 1, what });
185
+ },
186
+ };
187
+ }
188
+ /** Runs every observer's hooks in order (an observer never changes the replay). */
189
+ export function composeObservers(...observers) {
190
+ const list = observers.filter((o) => o !== undefined);
191
+ const each = async (fn) => {
192
+ for (const o of list) {
193
+ try {
194
+ await fn(o);
195
+ }
196
+ catch {
197
+ // One observer's failure never skips the next (nor changes the replay).
198
+ }
199
+ }
200
+ };
201
+ return {
202
+ beforeStep: (ctx) => each((o) => o.beforeStep?.(ctx)),
203
+ afterStep: (ctx) => each((o) => o.afterStep?.(ctx)),
204
+ };
205
+ }
206
+ /** The human summary line for a run's screenshots (#251). */
207
+ export function formatScreenshotsLine(r) {
208
+ if (r.screenshotIndex === undefined)
209
+ return "";
210
+ const skipped = r.screenshotsSkipped ?? [];
211
+ return (`screenshots: ${(r.screenshotPaths ?? []).length} — index ${r.screenshotIndex}` +
212
+ `${skipped.length === 0 ? "" : ` (${skipped.length} not captured: ${skipped.map((s) => `step ${s.step}: ${s.reason}`).join("; ")})`}\n`);
213
+ }
214
+ /**
215
+ * The capture wiring an explore runner threads through its session and listener. `artifactPath` is
216
+ * read on first use (the run's Recording path: screenshots go in `<stem>.screenshots/` beside it).
217
+ */
218
+ export function runCaptureFor(o) {
219
+ const mask = new SecretPixelMask(o.secrets);
220
+ const capturing = o.recordsVideo || o.screenshots !== undefined;
221
+ let shots;
222
+ const shotsOf = () => {
223
+ if (o.screenshots === undefined)
224
+ return undefined;
225
+ shots ??= new RunScreenshots({ spec: o.screenshots, dir: screenshotsDirFor(o.screenshots, o.artifactPath()), secrets: o.secrets, title: o.title, mask });
226
+ return shots;
227
+ };
228
+ return {
229
+ mask,
230
+ wrap: (factory) => (capturing ? () => maskingPort(factory(), mask) : factory),
231
+ noteEntry: (page, entry) => shotsOf()?.noteEntry(page, entry),
232
+ finish: async () => (await shotsOf()?.finish()) ?? {},
233
+ };
234
+ }
235
+ //# sourceMappingURL=run-screenshots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-screenshots.js","sourceRoot":"","sources":["../src/run-screenshots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Numeric `JEVITATE_*` tuning variables are validated ONCE, when the CLI starts, so a typo is a
3
+ * usage error (exit 64) before any browser opens — never a crash mid-run on the first click, and
4
+ * never a silent fall back to the default.
5
+ *
6
+ * Returns the problems found (empty when every set variable is valid).
7
+ */
8
+ export declare function runtimeEnvProblems(env?: NodeJS.ProcessEnv): string[];
@@ -0,0 +1,23 @@
1
+ import { clickTimeoutMs } from "@jevitate/explore";
2
+ import { governanceFromEnv, pageUnresponsiveMsFromEnv } from "@jevitate/playwright";
3
+ /**
4
+ * Numeric `JEVITATE_*` tuning variables are validated ONCE, when the CLI starts, so a typo is a
5
+ * usage error (exit 64) before any browser opens — never a crash mid-run on the first click, and
6
+ * never a silent fall back to the default.
7
+ *
8
+ * Returns the problems found (empty when every set variable is valid).
9
+ */
10
+ export function runtimeEnvProblems(env = process.env) {
11
+ const problems = [];
12
+ // #205: JEVITATE_RESOURCE_GOVERNANCE / JEVITATE_MAX_BROWSERS / JEVITATE_MAX_BROWSER_MEMORY_MB.
13
+ for (const check of [pageUnresponsiveMsFromEnv, clickTimeoutMs, governanceFromEnv]) {
14
+ try {
15
+ check(env);
16
+ }
17
+ catch (err) {
18
+ problems.push(err instanceof Error ? err.message : String(err));
19
+ }
20
+ }
21
+ return problems;
22
+ }
23
+ //# sourceMappingURL=runtime-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-env.js","sourceRoot":"","sources":["../src/runtime-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAEpF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,+FAA+F;IAC/F,KAAK,MAAM,KAAK,IAAI,CAAC,yBAAyB,EAAE,cAAc,EAAE,iBAAiB,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC;YACH,KAAK,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `--secret` values (#195 part 4): a literal, or `env:VAR` — read from the environment so the value
3
+ * never sits in the process list or shell history (the same `env:` binding `--secret-field` uses).
4
+ * Resolved HERE, at the CLI dispatch, before any browser opens; the resolved value is registered as a
5
+ * run secret exactly like a literal one (redacted from every model call, transcript and artifact).
6
+ *
7
+ * Fail closed: an unset/empty variable or a malformed ref is a refusal — never an empty secret, and
8
+ * never the literal text `env:VAR` standing in for the value. An error names the variable, never a
9
+ * value (a malformed ref is not echoed: it may be a value pasted in place of the variable name).
10
+ */
11
+ export declare class SecretArgError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ /** The warning a literal `--secret` earns (it still works): the value is visible to other processes. */
15
+ export declare const LITERAL_SECRET_WARNING = "warning: a literal --secret is visible in the process list and shell history; pass --secret env:VAR to read it from the environment\n";
16
+ /**
17
+ * Resolves each `--secret` value: `env:VAR` → `env[VAR]`, anything else → itself. `literals` counts
18
+ * the values given literally (for the caller's warning). Throws `SecretArgError`.
19
+ */
20
+ export declare function resolveSecretArgs(values: readonly string[], env: Readonly<Record<string, string | undefined>>, flag: string): {
21
+ secrets: string[];
22
+ literals: number;
23
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `--secret` values (#195 part 4): a literal, or `env:VAR` — read from the environment so the value
3
+ * never sits in the process list or shell history (the same `env:` binding `--secret-field` uses).
4
+ * Resolved HERE, at the CLI dispatch, before any browser opens; the resolved value is registered as a
5
+ * run secret exactly like a literal one (redacted from every model call, transcript and artifact).
6
+ *
7
+ * Fail closed: an unset/empty variable or a malformed ref is a refusal — never an empty secret, and
8
+ * never the literal text `env:VAR` standing in for the value. An error names the variable, never a
9
+ * value (a malformed ref is not echoed: it may be a value pasted in place of the variable name).
10
+ */
11
+ export class SecretArgError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "SecretArgError";
15
+ }
16
+ }
17
+ const ENV_REF = "env:";
18
+ const VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
19
+ /** The warning a literal `--secret` earns (it still works): the value is visible to other processes. */
20
+ export const LITERAL_SECRET_WARNING = "warning: a literal --secret is visible in the process list and shell history; pass --secret env:VAR to read it from the environment\n";
21
+ /**
22
+ * Resolves each `--secret` value: `env:VAR` → `env[VAR]`, anything else → itself. `literals` counts
23
+ * the values given literally (for the caller's warning). Throws `SecretArgError`.
24
+ */
25
+ export function resolveSecretArgs(values, env, flag) {
26
+ const secrets = [];
27
+ let literals = 0;
28
+ for (const v of values) {
29
+ if (!v.startsWith(ENV_REF)) {
30
+ secrets.push(v);
31
+ literals += 1;
32
+ continue;
33
+ }
34
+ const name = v.slice(ENV_REF.length);
35
+ if (!VAR_NAME_RE.test(name)) {
36
+ throw new SecretArgError(`${flag} env:<VAR> expects an environment variable name (letters, digits, _; not starting with a digit)`);
37
+ }
38
+ const value = env[name];
39
+ if (value === undefined || value === "")
40
+ throw new SecretArgError(`${flag} env:${name}: environment variable ${name} is not set`);
41
+ secrets.push(value);
42
+ }
43
+ return { secrets, literals };
44
+ }
45
+ //# sourceMappingURL=secret-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-args.js","sourceRoot":"","sources":["../src/secret-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,GAAG,MAAM,CAAC;AACvB,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C,wGAAwG;AACxG,MAAM,CAAC,MAAM,sBAAsB,GACjC,uIAAuI,CAAC;AAE1I;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyB,EACzB,GAAiD,EACjD,IAAY;IAEZ,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,iGAAiG,CAAC,CAAC;QACrI,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,QAAQ,IAAI,0BAA0B,IAAI,aAAa,CAAC,CAAC;QAClI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ import { type CliDeps } from "./cli-shared.js";
3
+ /** Registers the long-running servers: `jevitate mcp` and `jevitate ui`. */
4
+ export declare function registerServeCommands(program: Command, deps: CliDeps, buildProgram: (deps: CliDeps) => Command): void;
@@ -0,0 +1,95 @@
1
+ import { envCredentialStore, OpenRouterGenerationGateway } from "@jevitate/ai-core";
2
+ import { loadLocalCredentials } from "./credentials-file.js";
3
+ import { fail } from "./envelope.js";
4
+ import { startMcpServer } from "./mcp-api.js";
5
+ import { realOpenRouterCall } from "./openrouter-call.js";
6
+ import { startUiServer } from "./ui-api.js";
7
+ import { intArg } from "./cli-args.js";
8
+ import { renderPrintConfig } from "./init-mcp.js";
9
+ import { mcpToolDeps } from "./mcp-cli-bridge.js";
10
+ import { makeInProcessCliRunner } from "./mcp-cli-runner.js";
11
+ import { resolveJourneysDir, resolveInboxDir, emitJson, DEFAULT_EXPLORE_CATALOG, DEFAULT_EXPLORE_CONSTRAINTS, } from "./cli-shared.js";
12
+ /** Registers the long-running servers: `jevitate mcp` and `jevitate ui`. */
13
+ export function registerServeCommands(program, deps, buildProgram) {
14
+ // Additive: `jevitate mcp` (Ticket #20) — start an MCP stdio server that
15
+ // exposes ONLY `@jevitate/mcp-facade`'s allowlisted tools (never the raw
16
+ // browser primitives in FORBIDDEN_TOOLS). This is the subcommand form of the
17
+ // MCP server (single-bundle deployment — no separate published package).
18
+ // The server owns stdin/stdout as the MCP protocol channel, so on success it
19
+ // blocks and writes NOTHING to stdout; only a setup failure (before the
20
+ // transport connects) emits a JSON envelope.
21
+ program
22
+ .command("mcp")
23
+ .description("start an MCP stdio server exposing only the allowlisted Jevitate tools")
24
+ .option("--dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)")
25
+ .option("--print-config <harness>", "print the config snippet to register `jevitate mcp` in a harness (claude | cursor | codex | json) and exit — prints only, writes nothing")
26
+ .action(async function () {
27
+ const { dir, printConfig } = this.opts();
28
+ // `--print-config <harness>` is the universal escape hatch: render the
29
+ // exact registration snippet and exit WITHOUT starting the server (safe:
30
+ // no writes, no stdio takeover). An unknown harness is a fail envelope.
31
+ if (printConfig !== undefined) {
32
+ const harness = printConfig;
33
+ if (harness !== "claude" && harness !== "cursor" && harness !== "codex" && harness !== "json") {
34
+ emitJson(program, fail("E_MCP_PRINT_CONFIG", `--print-config must be one of claude | cursor | codex | json (got '${printConfig}')`));
35
+ return;
36
+ }
37
+ program.configureOutput().writeOut?.(`${renderPrintConfig(harness)}\n`);
38
+ process.exitCode = 0;
39
+ return;
40
+ }
41
+ try {
42
+ // Credential store + generation gateway for the allowlisted
43
+ // `ai_generate_text` tool. The gateway is the REAL OpenRouter adapter:
44
+ // the key is read only inside it (Authorization header only), every
45
+ // outbound payload passes the never-to-model guard, and the facade's
46
+ // preflight returns a typed `setup_required` when the key is absent —
47
+ // so no `--real/--fake` flag is needed for the non-interactive server.
48
+ const aiStore = envCredentialStore(deps.ai?.env ?? process.env, deps.ai?.localConfig ?? loadLocalCredentials());
49
+ const generationGateway = deps.ai?.gateway ??
50
+ new OpenRouterGenerationGateway({
51
+ store: aiStore,
52
+ catalog: deps.ai?.catalog ?? DEFAULT_EXPLORE_CATALOG,
53
+ constraints: deps.ai?.constraints ?? DEFAULT_EXPLORE_CONSTRAINTS,
54
+ call: await realOpenRouterCall(),
55
+ });
56
+ // #254: the same default stores the CLI's `inbox`/`mission queue`/`mission result` read (mcpToolDeps).
57
+ // #255: the CLI-mirroring tools run the SAME program in process, over the same journeys dir.
58
+ const journeysDir = resolveJourneysDir(deps, dir);
59
+ const runCli = makeInProcessCliRunner(() => buildProgram({ ...deps, journeysDir }));
60
+ await startMcpServer(mcpToolDeps(deps, { journeysDir, credentialStore: aiStore, generationGateway, runCli }));
61
+ }
62
+ catch (err) {
63
+ emitJson(program, fail("E_MCP_SERVE", String(err instanceof Error ? err.message : err)));
64
+ }
65
+ });
66
+ // Additive: `jevitate ui` (Task 8) — starts the local, loopback-only HTTP
67
+ // HITL approval dashboard (ui-api.ts's `startUiServer`). Resolves the SAME
68
+ // inbox dir `jevitate mcp`'s inbox tools serve (resolveInboxDir), so the
69
+ // two commands agree on where approvals/handbacks/reviews live. On success
70
+ // it prints the bound URL (carrying the capability token) and stays alive —
71
+ // the open HTTP server keeps the process running, the same way `mcp`'s open
72
+ // stdio transport does.
73
+ program
74
+ .command("ui")
75
+ .description("start the local HITL approval dashboard (loopback-only HTTP server)")
76
+ .option("--port <n>", "explicit port (fails on conflict; default 4180, retries on conflict)", intArg({ min: 0, max: 65535 }))
77
+ .option("--no-open", "do not open the dashboard URL in the default browser")
78
+ .option("--inbox-dir <path>", "inbox store directory (default: ~/.jevitate/inbox — same dir `jevitate mcp` serves)")
79
+ .action(async function () {
80
+ const o = this.opts();
81
+ try {
82
+ const start = deps.ui?.startUiServer ?? startUiServer;
83
+ const handle = await start({
84
+ inboxDir: resolveInboxDir(deps, o.inboxDir),
85
+ open: o.open ?? true,
86
+ ...(o.port !== undefined ? { port: Number(o.port) } : {}),
87
+ });
88
+ program.configureOutput().writeOut?.(`${handle.url}\n`);
89
+ }
90
+ catch (err) {
91
+ emitJson(program, fail("E_UI_SERVE", String(err instanceof Error ? err.message : err)));
92
+ }
93
+ });
94
+ }
95
+ //# sourceMappingURL=serve-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-cli.js","sourceRoot":"","sources":["../src/serve-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Recording } from "@jevitate/recording";
2
+ import { type VerifyFixResult, type VerifySession } from "@jevitate/explore";
3
+ /**
4
+ * `verify-fix` for a `server-log` defect (#142): NOT a re-check of `@jevitate/explore`'s
5
+ * `verifyFix` (which looks for a fingerprint among DOM/console/network signals — a server log line
6
+ * is none of those). Instead, this replays the defect's recorded steps in a fresh browser session
7
+ * AND re-opens the SAME log sources for the SAME drain window, and asks whether a line matching
8
+ * the SAME matcher and the SAME normalized message reappears. Kept entirely in the CLI layer (new
9
+ * file) — `packages/explore/src/verify-fix.ts` is untouched.
10
+ *
11
+ * Mirrors `verifyFix`'s own replay discipline (#74): `replays` fresh-context attempts, only ones
12
+ * that actually reached the defect's step count as evidence, and the pure `verifyReplayVerdict`
13
+ * rule (fired on every ran attempt ⇒ still-reproduces, none ⇒ fixed, a mix ⇒ intermittent — never
14
+ * "fixed" off one clean replay).
15
+ */
16
+ export interface VerifyServerLogParams {
17
+ readonly recording: Recording;
18
+ /** Flat index of the last Recording step to replay (the defect's `repro.recordingStepIndex`). */
19
+ readonly recordingStepIndex: number;
20
+ readonly fingerprint: string;
21
+ /** The defect's persisted log sources (raw `--log-source` specs) and matcher (raw `--log-defect`). */
22
+ readonly sources: readonly string[];
23
+ readonly matcher: string;
24
+ readonly normalizedMessage: string;
25
+ readonly drainMs: number;
26
+ /** #282: the run's `--log-scope` (raw specs): only lines in scope count, as in the original run. */
27
+ readonly scope?: readonly string[];
28
+ readonly allowLogCmd: boolean;
29
+ /** Opens a FRESH browser session (never the one the defect was found in). */
30
+ readonly openSession: () => Promise<VerifySession>;
31
+ readonly settleCeilingMs?: number;
32
+ readonly targetTimeoutMs?: number;
33
+ /** Fresh-context replays (#74). Default `DEFAULT_VERIFY_REPLAYS` (mirrors `@jevitate/explore`). */
34
+ readonly replays?: number;
35
+ }
36
+ export declare function verifyServerLogDefect(params: VerifyServerLogParams): Promise<VerifyFixResult>;