@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
package/dist/load-api.js CHANGED
@@ -1,13 +1,14 @@
1
- import { mkdtemp, rm } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
1
  import { FsJourneyStore, JourneyRegistry, deriveParamSchema, validateParams } from "@jevitate/journey";
2
+ import { gateJourney } from "./site-gate-cli.js";
5
3
  import { safeRunPolicy } from "@jevitate/domain";
6
4
  import { PlaywrightBrowserPort } from "@jevitate/playwright";
5
+ import { sessionLaunchOptions } from "./browser-run-options.js";
7
6
  import { CastActor, BrowseTheWeb } from "@jevitate/screenplay";
8
7
  import { RecordingInterpreter } from "@jevitate/interpreter";
9
8
  import { JourneyRunner } from "@jevitate/runtime";
10
9
  import { runLoadTest } from "@jevitate/load";
10
+ import { JourneyRequiresAuthError } from "./journey-api.js";
11
+ import { applyJourneyEnvironment } from "./environments.js";
11
12
  /** Distinct from `@jevitate/journey`'s ParamValidationError-style "unknown id" cases elsewhere, so CLI callers can branch without string-matching. */
12
13
  export class UnknownLoadJourneyError extends Error {
13
14
  }
@@ -21,18 +22,25 @@ export class UnknownLoadJourneyError extends Error {
21
22
  *
22
23
  * NOTE on "seeded ⇒ reproducible / human-paced" (corrected post-review):
23
24
  * `opts.seed` makes the ACTOR POOL's composition reproducible (via
24
- * `deriveActorSeeds` inside `runLoadTest`) — it does not yet make the real
25
- * run human-paced, because `JourneyRunner` (constructed below) has no
26
- * pacing hook to seed. Only the offline `modeledCapacityReport` path is
27
- * genuinely human-paced today, via `@jevitate/domain`'s `simulateTiming()`.
25
+ * `deriveActorSeeds` inside `runLoadTest`), and — with a site policy that declares pacing — each
26
+ * actor's clicks and keystrokes are human-paced, seeded from `seed` and the actor's index. A load
27
+ * run is the operator's deliberate burst: the policy's throttles, budgets and quiet hours do not
28
+ * refuse it; only its pacing applies.
28
29
  */
29
30
  export async function runJourneyLoadTest(opts) {
30
31
  const store = new FsJourneyStore(opts.dir);
31
32
  const registry = new JourneyRegistry(store);
32
- const journey = await registry.get(opts.id);
33
- if (!journey) {
33
+ const stored = await registry.get(opts.id);
34
+ if (!stored) {
34
35
  throw new UnknownLoadJourneyError(`unknown journey '${opts.id}'`);
35
36
  }
37
+ const journey = applyJourneyEnvironment(stored, opts.environment);
38
+ const allowedOrigins = opts.environment === undefined ? [journey.recording.site] : [...opts.environment.allowedOrigins];
39
+ // #118: a Journey that declares it needs auth refuses BEFORE any browser launch when no
40
+ // storageState was given — a clear, typed failure instead of a deep `replay-target-not-found`.
41
+ if (journey.metadata.requiresAuth === true && opts.storageState === undefined) {
42
+ throw new JourneyRequiresAuthError(`journey '${opts.id}' requires auth (metadata.requiresAuth) — run with --storage-state <file>`);
43
+ }
36
44
  validateParams(deriveParamSchema(journey.recording), opts.params);
37
45
  const policy = opts.policy ?? safeRunPolicy();
38
46
  const browserPortFactory = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
@@ -43,15 +51,16 @@ export async function runJourneyLoadTest(opts) {
43
51
  iterationsPerActor: opts.iterationsPerActor,
44
52
  seed: opts.seed,
45
53
  runnerFactory: async (actorIndex) => {
46
- const profileDir = await mkdtemp(join(tmpdir(), `doit-load-actor-${actorIndex}-`));
47
54
  const port = browserPortFactory();
48
55
  const session = await port.open({
49
- profileDir,
50
- headless: true,
51
- allowedOrigins: [journey.recording.site],
56
+ ...sessionLaunchOptions(opts.browser),
57
+ allowedOrigins,
52
58
  baseUrl: journey.recording.site,
59
+ ...opts.emulation,
60
+ ...(opts.storageState !== undefined ? { storageState: opts.storageState } : {}),
53
61
  });
54
- const actor = CastActor.named(`load-actor-${actorIndex}`).whoCan(new BrowseTheWeb(session, [journey.recording.site]));
62
+ const gate = await gateJourney(opts.siteGate, journey.recording, { enforceLimits: false, runId: `load-${opts.seed}-${actorIndex}` });
63
+ const actor = CastActor.named(`load-actor-${actorIndex}`).whoCan(new BrowseTheWeb(session, allowedOrigins), ...gate.abilities);
55
64
  const runner = new JourneyRunner(actor, new RecordingInterpreter());
56
65
  // `runLoadTest` calls `run()` exactly `iterationsPerActor` times for
57
66
  // this actor — success or failure, never more, never fewer (see
@@ -73,7 +82,6 @@ export async function runJourneyLoadTest(opts) {
73
82
  remainingIterations--;
74
83
  if (remainingIterations <= 0) {
75
84
  await session.close();
76
- await rm(profileDir, { recursive: true, force: true });
77
85
  }
78
86
  }
79
87
  },
@@ -1 +1 @@
1
- {"version":3,"file":"load-api.js","sourceRoot":"","sources":["../src/load-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load-api.js","sourceRoot":"","sources":["../src/load-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ import { type CliDeps } from "./cli-shared.js";
3
+ /** Registers `jevitate load run`. */
4
+ export declare function registerLoadCommands(program: Command, deps: CliDeps): void;
@@ -0,0 +1,97 @@
1
+ import { existsSync } from "node:fs";
2
+ import { ok, fail } from "./envelope.js";
3
+ import { JourneyRequiresAuthError } from "./journey-api.js";
4
+ import { runJourneyLoadTest, UnknownLoadJourneyError } from "./load-api.js";
5
+ import { withSiteGate } from "./site-gate-cli.js";
6
+ import { withEngine } from "./engine.js";
7
+ import { finiteNumberArg, positiveIntArg } from "./cli-args.js";
8
+ import { environmentFromFlags, isEnvironmentError, withEnvironmentFlags } from "./environments.js";
9
+ import { resolveDbPath, resolveJourneysDir, withBrowserLaunchFlags, browserOption, withEmulationFlags, emulationFromFlags, collectParam, emitJson, environmentSeams, } from "./cli-shared.js";
10
+ /** Registers `jevitate load run`. */
11
+ export function registerLoadCommands(program, deps) {
12
+ const load = program.command("load").description("run a promoted Journey as a load test");
13
+ withEnvironmentFlags(withBrowserLaunchFlags(withEmulationFlags(load.command("run <journeyId>"))))
14
+ .option("--dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)")
15
+ .option("--param <kv>", "param as key=value (repeatable)", collectParam, {})
16
+ // `--authorized-origin` is mandatory, but enforced IN THE ACTION (below)
17
+ // via a `fail` envelope rather than commander's `.requiredOption` — which
18
+ // hard-exits via `process.exit`, inconsistent with this CLI's convention
19
+ // of emitting a JSON envelope + setting `process.exitCode` (see emitJson).
20
+ .option("--authorized-origin <origin>", "allowed load-test target origin (repeatable) — required, fails closed if omitted", (v, prev) => [...prev, v], [])
21
+ .option("--concurrency <n>", "pool size", positiveIntArg, 1)
22
+ .option("--iterations <n>", "iterations per actor", positiveIntArg, 1)
23
+ .option("--seed <n>", "master RNG seed", finiteNumberArg, 1)
24
+ .option("--storage-state <file>", "Playwright storageState JSON to start every actor's session authenticated (#118: required when the journey declares metadata.requiresAuth); must exist")
25
+ .option("--json", "emit a JSON envelope")
26
+ .action(async function (journeyId) {
27
+ const { dir, param, authorizedOrigin, concurrency, iterations, seed, storageState: storageStateFlag, json, env: envName, baseUrl, ...emulationFlags } = this.opts();
28
+ if (authorizedOrigin.length === 0) {
29
+ emitJson(program, fail("E_LOAD_RUN", "at least one --authorized-origin is required (refusing to load-test with an empty allowlist)"));
30
+ return;
31
+ }
32
+ // #247: --env/--base-url choose where the load runs (unknown env / bad file → 64, nothing opened).
33
+ let environment;
34
+ try {
35
+ environment = environmentFromFlags({ ...(envName === undefined ? {} : { env: envName }), ...(baseUrl === undefined ? {} : { baseUrl }) }, environmentSeams(deps));
36
+ }
37
+ catch (err) {
38
+ if (!isEnvironmentError(err))
39
+ throw err;
40
+ emitJson(program, fail(err.code, err.message));
41
+ return;
42
+ }
43
+ const storageState = storageStateFlag ?? environment?.storageState;
44
+ if (storageState !== undefined && !existsSync(storageState)) {
45
+ emitJson(program, fail("E_LOAD_RUN_ARGS", `storage state not found: ${storageState}`));
46
+ return;
47
+ }
48
+ let loadRunEmulation;
49
+ try {
50
+ loadRunEmulation = emulationFromFlags(emulationFlags);
51
+ }
52
+ catch (err) {
53
+ emitJson(program, fail("E_LOAD_RUN_ARGS", err instanceof Error ? err.message : String(err)));
54
+ return;
55
+ }
56
+ try {
57
+ const report = await withSiteGate(resolveDbPath(deps), (siteGate) => runJourneyLoadTest({
58
+ ...(siteGate === undefined ? {} : { siteGate }),
59
+ dir: resolveJourneysDir(deps, dir),
60
+ id: journeyId,
61
+ params: param,
62
+ concurrency: Number(concurrency),
63
+ iterationsPerActor: Number(iterations),
64
+ seed: Number(seed),
65
+ authorizedOrigins: authorizedOrigin,
66
+ browserPortFactory: deps.explore?.browserPortFactory,
67
+ ...browserOption(this.opts()),
68
+ ...(loadRunEmulation === undefined ? {} : { emulation: loadRunEmulation }),
69
+ ...(storageState !== undefined ? { storageState } : {}),
70
+ ...(environment === undefined ? {} : { environment }),
71
+ })).then((r) => withEngine(r));
72
+ const envelope = ok(report);
73
+ if (json) {
74
+ emitJson(program, envelope);
75
+ }
76
+ else {
77
+ program.configureOutput().writeOut?.(`${JSON.stringify(report, null, 2)}\n`);
78
+ process.exitCode = 0;
79
+ }
80
+ }
81
+ catch (err) {
82
+ if (isEnvironmentError(err)) {
83
+ emitJson(program, fail(err.code, err.message));
84
+ }
85
+ else if (err instanceof UnknownLoadJourneyError) {
86
+ emitJson(program, fail("E_UNKNOWN_JOURNEY", String(err.message)));
87
+ }
88
+ else if (err instanceof JourneyRequiresAuthError) {
89
+ emitJson(program, fail("E_JOURNEY_REQUIRES_AUTH", String(err.message)));
90
+ }
91
+ else {
92
+ emitJson(program, fail("E_LOAD_RUN", String(err instanceof Error ? err.message : err)));
93
+ }
94
+ }
95
+ });
96
+ }
97
+ //# sourceMappingURL=load-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-cli.js","sourceRoot":"","sources":["../src/load-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ import { type MissionOutcome } from "@jevitate/domain";
2
+ import { type TranscriptEntry } from "@jevitate/explore";
3
+ import { type LogSourceSpec } from "./log-sources.js";
4
+ import { type LogDefectMatcher, type LogIgnoreMatcher, type LogLevel } from "./log-lines.js";
5
+ import { type RequestEvents } from "./log-trace.js";
6
+ /**
7
+ * Correlates tailed backend log lines to the mission step they landed during (#142): each step's
8
+ * "window" runs from the previous step's settle time to this step's own settle time (a mission's
9
+ * `TranscriptListener` fires the moment a step is recorded — already the crash-safe incremental-
10
+ * flush seam `MissionJournal` uses, per-step wall-clock epochs come for free from `Date.now()` at
11
+ * that call, with no change needed to `@jevitate/explore`'s mission loop). The LAST step's window
12
+ * is additionally held open for `drainMs` (`--server-log-drain-ms`) so async backend work that
13
+ * settles after the browser gave up is still caught, never blocking the mission itself: the
14
+ * runtime's own await (waiting out the drain) happens AFTER the mission function has already
15
+ * returned.
16
+ *
17
+ * Fail closed: every line is redacted with the run's own secret list before it is ever attached to
18
+ * a step, turned into a defect, or counted in the summary — a log line can contain secrets the page
19
+ * never showed.
20
+ *
21
+ * #204 — by trace / correlation id first: a line that carries an id one of the run's requests sent
22
+ * or received (`traceparent`, `x-request-id`, …; see `log-trace.ts`) is attached to EXACTLY that
23
+ * request (`request: { method, url, status, id }`) and to the step that sent it, whenever it
24
+ * landed. Only a line with no id falls back to the time window. Once ids demonstrably correlate, a
25
+ * line carrying ANOTHER id is other work (another user, a background job) and is never this run's.
26
+ *
27
+ * #282 — `--log-scope`: when given, only lines matching it (a tenant id, a run marker) are
28
+ * attributed; the rest count as `ignoredLines`. A line carrying one of the run's ids is in scope.
29
+ */
30
+ export interface ServerLogEvidence {
31
+ readonly level: LogLevel;
32
+ /** Redacted human message. */
33
+ readonly message: string;
34
+ /** Redacted raw line. */
35
+ readonly raw: string;
36
+ readonly source: string;
37
+ readonly epochMs: number;
38
+ /** The logger's own target/category, when known (#169). */
39
+ readonly target?: string;
40
+ /**
41
+ * #204: the run's request this line was correlated to by a trace/correlation id it carries —
42
+ * method, redacted URL, response status (null: no response) and the id. Unset: attached by time.
43
+ */
44
+ readonly request?: ServerLogRequest;
45
+ }
46
+ /** #204: the request a server log line belongs to, by a correlation id both carry. */
47
+ export interface ServerLogRequest {
48
+ readonly method: string;
49
+ readonly url: string;
50
+ readonly status: number | null;
51
+ readonly id: string;
52
+ }
53
+ export type TranscriptEntryWithLogs = TranscriptEntry & {
54
+ readonly serverLogs?: readonly ServerLogEvidence[];
55
+ };
56
+ export interface ServerLogSourceStatus {
57
+ readonly spec: string;
58
+ readonly opened: boolean;
59
+ readonly linesRead: number;
60
+ readonly truncated: boolean;
61
+ readonly error?: string;
62
+ /** True when this source was declared `--log-quiet-ok` (#169): zero lines from it is expected,
63
+ * not a sign the oracle never actually watched the backend. */
64
+ readonly quietOk?: boolean;
65
+ }
66
+ export interface ServerLogTopMessage {
67
+ readonly level: LogLevel;
68
+ /** Normalized message class (ids/numbers/uuids/timestamps stripped). */
69
+ readonly message: string;
70
+ /** The logger's own target/category, when known (#169) — kept distinct in this summary too. */
71
+ readonly target?: string;
72
+ readonly count: number;
73
+ }
74
+ export interface ServerLogsSummary {
75
+ readonly sources: readonly ServerLogSourceStatus[];
76
+ readonly byLevel: Readonly<Record<string, number>>;
77
+ readonly topMessages: readonly ServerLogTopMessage[];
78
+ readonly attachedLines: number;
79
+ readonly unattributedLines: number;
80
+ /** Lines excluded by `--log-ignore` (#169 item 3) — known noise, never attached, never a defect
81
+ * candidate, not counted in `byLevel`/`topMessages` — plus lines outside `--log-scope` (#282) and
82
+ * lines carrying another request's correlation id (#204), broken down in `correlation`. */
83
+ readonly ignoredLines: number;
84
+ /**
85
+ * #204/#282: how lines were correlated — set when a request carried a correlation id or
86
+ * `--log-scope` was given. `idMatchedLines`: attached to their exact request by id;
87
+ * `foreignLines`: carried another request's id (never this run's); `outOfScopeLines`: outside
88
+ * `--log-scope`. The last two are included in `ignoredLines`.
89
+ */
90
+ readonly correlation?: {
91
+ readonly requestsWithIds: number;
92
+ readonly idMatchedLines: number;
93
+ readonly foreignLines: number;
94
+ readonly outOfScopeLines: number;
95
+ };
96
+ /**
97
+ * False when `--log-defect` was given but at least one declared source is unhealthy: it never
98
+ * opened/errored, OR it opened and delivered not one line while NOT declared `--log-quiet-ok`
99
+ * (#169) — an absence of `server-log` defects then proves nothing about the backend; it must never
100
+ * be read as "held"/clean (#142).
101
+ */
102
+ readonly oracleOk: boolean;
103
+ /** Why `oracleOk` is false — which source(s), and whether they failed to open or were silently
104
+ * quiet. Unset when `oracleOk` is true. */
105
+ readonly oracleReason?: string;
106
+ }
107
+ export interface ServerLogDefect {
108
+ readonly fingerprint: string;
109
+ readonly related: string[];
110
+ readonly kind: "server-log";
111
+ readonly title: string;
112
+ readonly route: string;
113
+ readonly level: LogLevel;
114
+ /** First occurrence's redacted message. */
115
+ readonly message: string;
116
+ readonly occurrences: number;
117
+ readonly repro: {
118
+ readonly recordingStepIndex: number;
119
+ };
120
+ /** #204: the request the first occurrence was correlated to by id, when it was. */
121
+ readonly request?: ServerLogRequest;
122
+ /** So `verify-fix` can re-open the SAME sources and re-check the SAME matcher (#142). */
123
+ readonly serverLog: {
124
+ readonly sources: readonly string[];
125
+ readonly matcher: string;
126
+ readonly normalizedMessage: string;
127
+ readonly drainMs: number;
128
+ /** #282: the run's `--log-scope` (raw specs): verify-fix counts only lines in scope too. */
129
+ readonly scope?: readonly string[];
130
+ };
131
+ }
132
+ export interface ServerLogRuntimeResult {
133
+ readonly transcript: readonly TranscriptEntryWithLogs[];
134
+ readonly summary: ServerLogsSummary;
135
+ readonly defects: ServerLogDefect[];
136
+ }
137
+ export declare const DEFAULT_SERVER_LOG_DRAIN_MS = 3000;
138
+ export interface ServerLogRuntimeOptions {
139
+ readonly sources: readonly LogSourceSpec[];
140
+ /** Already-parsed `--log-defect` matchers (empty ⇒ evidence attachment only, no defects). */
141
+ readonly logDefect: readonly LogDefectMatcher[];
142
+ readonly drainMs?: number;
143
+ readonly secrets: readonly string[];
144
+ /** Raw `--log-source` specs (matched against a source's own `spec.raw`) that are allowed to
145
+ * deliver zero lines without making `oracleOk` false (#169's `--log-quiet-ok`). */
146
+ readonly quietOk?: readonly string[];
147
+ /** Already-parsed `--log-ignore` matchers (#169 item 3): known-noise lines excluded from
148
+ * correlation AND the defect oracle, counted separately (`serverLogs.ignoredLines`). */
149
+ readonly logIgnore?: readonly LogIgnoreMatcher[];
150
+ /** #282: `--log-scope` matchers (same `/regex/` or substring grammar as `--log-ignore`): only lines
151
+ * matching one are attributed (or carrying one of the run's correlation ids); the rest are ignored. */
152
+ readonly logScope?: readonly LogIgnoreMatcher[];
153
+ /** #204: extra response/request headers carrying a correlation id (`--log-correlation-header`). */
154
+ readonly correlationHeaders?: readonly string[];
155
+ /** #204: `--log-id-pattern`s: how an id is written in a log line of the operator's own format. */
156
+ readonly idPatterns?: readonly RegExp[];
157
+ /** The journal's own listener — still called for every entry (the crash-safe flush is unchanged). */
158
+ readonly onTranscriptEntry?: (entry: TranscriptEntry, all: readonly TranscriptEntry[]) => void;
159
+ }
160
+ /**
161
+ * Opens every source and starts correlating (#142). Returns `undefined` when `sources` is empty —
162
+ * a complete no-op, so a run without `--log-source` pays nothing.
163
+ */
164
+ export declare function openServerLogRuntime(opts: ServerLogRuntimeOptions): ServerLogRuntime | undefined;
165
+ export declare class ServerLogRuntime {
166
+ #private;
167
+ constructor(opts: ServerLogRuntimeOptions);
168
+ /**
169
+ * #204: records the correlation ids of every request this page sends and receives. Call before
170
+ * the page's first navigation (the seed load's requests count too).
171
+ */
172
+ observe(page: RequestEvents): void;
173
+ /** Wraps the journal's own `TranscriptListener`: unchanged persistence, plus this step's epoch. */
174
+ readonly onTranscriptEntry: (entry: TranscriptEntry, all: readonly TranscriptEntry[]) => void;
175
+ /** Call once the mission function has returned. Waits out the drain window, closes every source,
176
+ * and returns the correlated transcript/summary/defects. Idempotent (a second call is a no-op
177
+ * empty result) — never blocks the mission itself, only this post-processing step. */
178
+ finish(transcript: readonly TranscriptEntry[]): Promise<ServerLogRuntimeResult>;
179
+ /**
180
+ * Safety net for the mission-threw-before-`finish` path: closes every source immediately, with NO
181
+ * drain wait and no correlation. A no-op once `finish` already ran. Never throws.
182
+ */
183
+ abort(): Promise<void>;
184
+ }
185
+ /** Parses `--log-defect` values, failing closed on the first bad one. */
186
+ export declare function parseLogDefectSpecs(raw: readonly string[]): LogDefectMatcher[];
187
+ /** Parses `--log-ignore` values, failing closed on the first bad one (#169 item 3). */
188
+ export declare function parseLogIgnoreSpecs(raw: readonly string[]): LogIgnoreMatcher[];
189
+ /** Parses `--log-scope` values (#282): the `--log-ignore` grammar, a `/regex/flags/` or a substring. */
190
+ export declare function parseLogScopeSpecs(raw: readonly string[]): LogIgnoreMatcher[];
191
+ /**
192
+ * Folds a server-log correlation result into an already-computed `MissionOutcome` (#142, follow-up
193
+ * on the exit-code requirement): a found `server-log` defect is at least `defects-found` — via
194
+ * `worstOutcome`, so it never DOWNGRADES a worse outcome (hang/crashed/inconclusive already proves
195
+ * more, or the same, than a defect). An unreadable `--log-defect` oracle (`oracleOk: false`) turns
196
+ * an otherwise-`clean` run `inconclusive` — its absence of defects proves nothing when the source
197
+ * that would have caught them was never demonstrably read. `undefined` (no `--log-source`) is a
198
+ * complete no-op.
199
+ */
200
+ export declare function applyServerLogOutcome(outcome: MissionOutcome, run: ServerLogRuntimeResult | undefined): MissionOutcome;