@jevitate/cli 0.1.0 → 0.2.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 (375) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-cli.js +40 -30
  3. package/dist/ai-cli.js.map +1 -1
  4. package/dist/author-journey-cli.d.ts +4 -0
  5. package/dist/author-journey-cli.js +109 -0
  6. package/dist/author-journey-cli.js.map +1 -0
  7. package/dist/bin.js +58077 -22454
  8. package/dist/bin.js.map +1 -1
  9. package/dist/browser-run-options.d.ts +58 -0
  10. package/dist/browser-run-options.js +106 -0
  11. package/dist/browser-run-options.js.map +1 -0
  12. package/dist/build-info.generated.d.ts +2 -0
  13. package/dist/build-info.generated.js +10 -0
  14. package/dist/build-info.generated.js.map +1 -0
  15. package/dist/check-api.d.ts +5 -0
  16. package/dist/check-api.js +233 -0
  17. package/dist/check-api.js.map +1 -0
  18. package/dist/check-budget.d.ts +26 -0
  19. package/dist/check-budget.js +89 -0
  20. package/dist/check-budget.js.map +1 -0
  21. package/dist/check-cli.d.ts +31 -0
  22. package/dist/check-cli.js +109 -0
  23. package/dist/check-cli.js.map +1 -0
  24. package/dist/check-execute.d.ts +25 -0
  25. package/dist/check-execute.js +385 -0
  26. package/dist/check-execute.js.map +1 -0
  27. package/dist/check-plan.d.ts +113 -0
  28. package/dist/check-plan.js +448 -0
  29. package/dist/check-plan.js.map +1 -0
  30. package/dist/check-suite.d.ts +171 -0
  31. package/dist/check-suite.js +515 -0
  32. package/dist/check-suite.js.map +1 -0
  33. package/dist/check-types.d.ts +181 -0
  34. package/dist/check-types.js +35 -0
  35. package/dist/check-types.js.map +1 -0
  36. package/dist/cli-args.d.ts +26 -0
  37. package/dist/cli-args.js +50 -0
  38. package/dist/cli-args.js.map +1 -0
  39. package/dist/cli-output.d.ts +102 -0
  40. package/dist/cli-output.js +516 -0
  41. package/dist/cli-output.js.map +1 -0
  42. package/dist/cli-reference.d.ts +3 -0
  43. package/dist/cli-reference.js +81 -0
  44. package/dist/cli-reference.js.map +1 -0
  45. package/dist/cli-refusal.d.ts +12 -0
  46. package/dist/cli-refusal.js +52 -0
  47. package/dist/cli-refusal.js.map +1 -0
  48. package/dist/cli-shared.d.ts +330 -0
  49. package/dist/cli-shared.js +492 -0
  50. package/dist/cli-shared.js.map +1 -0
  51. package/dist/cli-surface.d.ts +33 -0
  52. package/dist/cli-surface.js +48 -0
  53. package/dist/cli-surface.js.map +1 -0
  54. package/dist/conversation-options.d.ts +15 -0
  55. package/dist/conversation-options.js +10 -0
  56. package/dist/conversation-options.js.map +1 -0
  57. package/dist/credentials-file.d.ts +15 -0
  58. package/dist/credentials-file.js +56 -0
  59. package/dist/credentials-file.js.map +1 -0
  60. package/dist/data-dir.d.ts +1 -1
  61. package/dist/data-dir.js +1 -1
  62. package/dist/defect-evidence.d.ts +141 -0
  63. package/dist/defect-evidence.js +502 -0
  64. package/dist/defect-evidence.js.map +1 -0
  65. package/dist/demo-aspect-api.d.ts +209 -0
  66. package/dist/demo-aspect-api.js +397 -0
  67. package/dist/demo-aspect-api.js.map +1 -0
  68. package/dist/demo-aspect-cli.d.ts +3 -0
  69. package/dist/demo-aspect-cli.js +241 -0
  70. package/dist/demo-aspect-cli.js.map +1 -0
  71. package/dist/demo-capture.d.ts +108 -0
  72. package/dist/demo-capture.js +438 -0
  73. package/dist/demo-capture.js.map +1 -0
  74. package/dist/engine.d.ts +35 -0
  75. package/dist/engine.js +25 -0
  76. package/dist/engine.js.map +1 -0
  77. package/dist/environments.d.ts +155 -0
  78. package/dist/environments.js +364 -0
  79. package/dist/environments.js.map +1 -0
  80. package/dist/exit-codes.d.ts +46 -0
  81. package/dist/exit-codes.js +91 -0
  82. package/dist/exit-codes.js.map +1 -0
  83. package/dist/explore-adversarial.d.ts +137 -0
  84. package/dist/explore-adversarial.js +218 -0
  85. package/dist/explore-adversarial.js.map +1 -0
  86. package/dist/explore-api.d.ts +7 -187
  87. package/dist/explore-api.js +7 -301
  88. package/dist/explore-api.js.map +1 -1
  89. package/dist/explore-author.d.ts +79 -0
  90. package/dist/explore-author.js +86 -0
  91. package/dist/explore-author.js.map +1 -0
  92. package/dist/explore-cli.d.ts +7 -0
  93. package/dist/explore-cli.js +963 -0
  94. package/dist/explore-cli.js.map +1 -0
  95. package/dist/explore-coverage.d.ts +158 -0
  96. package/dist/explore-coverage.js +240 -0
  97. package/dist/explore-coverage.js.map +1 -0
  98. package/dist/explore-feature.d.ts +127 -0
  99. package/dist/explore-feature.js +220 -0
  100. package/dist/explore-feature.js.map +1 -0
  101. package/dist/explore-goal.d.ts +253 -0
  102. package/dist/explore-goal.js +374 -0
  103. package/dist/explore-goal.js.map +1 -0
  104. package/dist/explore-shared.d.ts +152 -0
  105. package/dist/explore-shared.js +129 -0
  106. package/dist/explore-shared.js.map +1 -0
  107. package/dist/explore-specs.d.ts +53 -0
  108. package/dist/explore-specs.js +333 -0
  109. package/dist/explore-specs.js.map +1 -0
  110. package/dist/findings-filing.d.ts +64 -0
  111. package/dist/findings-filing.js +108 -0
  112. package/dist/findings-filing.js.map +1 -0
  113. package/dist/fixture-auth.d.ts +52 -0
  114. package/dist/fixture-auth.js +82 -0
  115. package/dist/fixture-auth.js.map +1 -0
  116. package/dist/fixture-cli.d.ts +70 -0
  117. package/dist/fixture-cli.js +178 -0
  118. package/dist/fixture-cli.js.map +1 -0
  119. package/dist/github-issue-filer.d.ts +62 -0
  120. package/dist/github-issue-filer.js +188 -0
  121. package/dist/github-issue-filer.js.map +1 -0
  122. package/dist/host-health-run.d.ts +24 -0
  123. package/dist/host-health-run.js +27 -0
  124. package/dist/host-health-run.js.map +1 -0
  125. package/dist/http-5xx-outcome.d.ts +6 -0
  126. package/dist/http-5xx-outcome.js +39 -0
  127. package/dist/http-5xx-outcome.js.map +1 -0
  128. package/dist/inbox-cli.d.ts +7 -0
  129. package/dist/inbox-cli.js +197 -0
  130. package/dist/inbox-cli.js.map +1 -0
  131. package/dist/index.d.ts +1 -0
  132. package/dist/index.js +1 -0
  133. package/dist/index.js.map +1 -1
  134. package/dist/init-cli.d.ts +4 -0
  135. package/dist/init-cli.js +127 -0
  136. package/dist/init-cli.js.map +1 -0
  137. package/dist/init-keys.d.ts +19 -2
  138. package/dist/init-keys.js +15 -4
  139. package/dist/init-keys.js.map +1 -1
  140. package/dist/init-next-steps.d.ts +35 -0
  141. package/dist/init-next-steps.js +79 -0
  142. package/dist/init-next-steps.js.map +1 -0
  143. package/dist/invariants-file.d.ts +34 -0
  144. package/dist/invariants-file.js +68 -0
  145. package/dist/invariants-file.js.map +1 -0
  146. package/dist/invariants-validate.d.ts +30 -0
  147. package/dist/invariants-validate.js +105 -0
  148. package/dist/invariants-validate.js.map +1 -0
  149. package/dist/journey-annotate-api.d.ts +76 -0
  150. package/dist/journey-annotate-api.js +256 -0
  151. package/dist/journey-annotate-api.js.map +1 -0
  152. package/dist/journey-annotate-cli.d.ts +9 -0
  153. package/dist/journey-annotate-cli.js +179 -0
  154. package/dist/journey-annotate-cli.js.map +1 -0
  155. package/dist/journey-api.d.ts +79 -2
  156. package/dist/journey-api.js +136 -19
  157. package/dist/journey-api.js.map +1 -1
  158. package/dist/journey-cli.d.ts +4 -0
  159. package/dist/journey-cli.js +370 -0
  160. package/dist/journey-cli.js.map +1 -0
  161. package/dist/journey-demo-api.d.ts +112 -0
  162. package/dist/journey-demo-api.js +392 -0
  163. package/dist/journey-demo-api.js.map +1 -0
  164. package/dist/journey-demo-cli.d.ts +10 -0
  165. package/dist/journey-demo-cli.js +155 -0
  166. package/dist/journey-demo-cli.js.map +1 -0
  167. package/dist/kill-signal.d.ts +193 -0
  168. package/dist/kill-signal.js +284 -0
  169. package/dist/kill-signal.js.map +1 -0
  170. package/dist/launch-armed.d.ts +37 -0
  171. package/dist/launch-armed.js +31 -0
  172. package/dist/launch-armed.js.map +1 -0
  173. package/dist/ledger-api.d.ts +106 -0
  174. package/dist/ledger-api.js +237 -0
  175. package/dist/ledger-api.js.map +1 -0
  176. package/dist/ledger-cli.d.ts +18 -0
  177. package/dist/ledger-cli.js +107 -0
  178. package/dist/ledger-cli.js.map +1 -0
  179. package/dist/load-api.d.ts +29 -11
  180. package/dist/load-api.js +23 -15
  181. package/dist/load-api.js.map +1 -1
  182. package/dist/load-cli.d.ts +4 -0
  183. package/dist/load-cli.js +97 -0
  184. package/dist/load-cli.js.map +1 -0
  185. package/dist/log-correlation.d.ts +147 -0
  186. package/dist/log-correlation.js +325 -0
  187. package/dist/log-correlation.js.map +1 -0
  188. package/dist/log-lines.d.ts +131 -0
  189. package/dist/log-lines.js +389 -0
  190. package/dist/log-lines.js.map +1 -0
  191. package/dist/log-sources.d.ts +71 -0
  192. package/dist/log-sources.js +235 -0
  193. package/dist/log-sources.js.map +1 -0
  194. package/dist/logs-cli.d.ts +3 -0
  195. package/dist/logs-cli.js +51 -0
  196. package/dist/logs-cli.js.map +1 -0
  197. package/dist/logs-retention.d.ts +28 -0
  198. package/dist/logs-retention.js +84 -0
  199. package/dist/logs-retention.js.map +1 -0
  200. package/dist/mcp-api.d.ts +89 -1
  201. package/dist/mcp-api.js +472 -18
  202. package/dist/mcp-api.js.map +1 -1
  203. package/dist/mcp-args.d.ts +38 -0
  204. package/dist/mcp-args.js +131 -0
  205. package/dist/mcp-args.js.map +1 -0
  206. package/dist/mcp-cli-bridge.d.ts +34 -0
  207. package/dist/mcp-cli-bridge.js +62 -0
  208. package/dist/mcp-cli-bridge.js.map +1 -0
  209. package/dist/mcp-cli-runner.d.ts +29 -0
  210. package/dist/mcp-cli-runner.js +44 -0
  211. package/dist/mcp-cli-runner.js.map +1 -0
  212. package/dist/mcp-cli-tools.d.ts +125 -0
  213. package/dist/mcp-cli-tools.js +680 -0
  214. package/dist/mcp-cli-tools.js.map +1 -0
  215. package/dist/mcp-paths.d.ts +28 -0
  216. package/dist/mcp-paths.js +76 -0
  217. package/dist/mcp-paths.js.map +1 -0
  218. package/dist/mission-actors.d.ts +40 -0
  219. package/dist/mission-actors.js +72 -0
  220. package/dist/mission-actors.js.map +1 -0
  221. package/dist/mission-api.d.ts +35 -0
  222. package/dist/mission-api.js +58 -2
  223. package/dist/mission-api.js.map +1 -1
  224. package/dist/mission-cli.d.ts +4 -0
  225. package/dist/mission-cli.js +247 -0
  226. package/dist/mission-cli.js.map +1 -0
  227. package/dist/mission-exit.d.ts +22 -0
  228. package/dist/mission-exit.js +26 -0
  229. package/dist/mission-exit.js.map +1 -0
  230. package/dist/mission-fixtures.d.ts +225 -0
  231. package/dist/mission-fixtures.js +828 -0
  232. package/dist/mission-fixtures.js.map +1 -0
  233. package/dist/mission-journal.d.ts +60 -0
  234. package/dist/mission-journal.js +115 -0
  235. package/dist/mission-journal.js.map +1 -0
  236. package/dist/mission-queue-cli.d.ts +10 -0
  237. package/dist/mission-queue-cli.js +198 -0
  238. package/dist/mission-queue-cli.js.map +1 -0
  239. package/dist/mission-queue-runner.d.ts +126 -0
  240. package/dist/mission-queue-runner.js +397 -0
  241. package/dist/mission-queue-runner.js.map +1 -0
  242. package/dist/multi-run-cli.d.ts +37 -0
  243. package/dist/multi-run-cli.js +110 -0
  244. package/dist/multi-run-cli.js.map +1 -0
  245. package/dist/multi-run.d.ts +339 -0
  246. package/dist/multi-run.js +619 -0
  247. package/dist/multi-run.js.map +1 -0
  248. package/dist/openrouter-call.d.ts +22 -0
  249. package/dist/openrouter-call.js +63 -0
  250. package/dist/openrouter-call.js.map +1 -0
  251. package/dist/profile-cli.d.ts +4 -0
  252. package/dist/profile-cli.js +57 -0
  253. package/dist/profile-cli.js.map +1 -0
  254. package/dist/program.d.ts +3 -75
  255. package/dist/program.js +119 -1921
  256. package/dist/program.js.map +1 -1
  257. package/dist/project-dir.d.ts +96 -0
  258. package/dist/project-dir.js +220 -0
  259. package/dist/project-dir.js.map +1 -0
  260. package/dist/record-api.d.ts +10 -6
  261. package/dist/record-api.js +39 -28
  262. package/dist/record-api.js.map +1 -1
  263. package/dist/record-cli.d.ts +4 -0
  264. package/dist/record-cli.js +64 -0
  265. package/dist/record-cli.js.map +1 -0
  266. package/dist/recording-cli.d.ts +4 -0
  267. package/dist/recording-cli.js +248 -0
  268. package/dist/recording-cli.js.map +1 -0
  269. package/dist/regression-api.d.ts +101 -0
  270. package/dist/regression-api.js +384 -5
  271. package/dist/regression-api.js.map +1 -1
  272. package/dist/regression-cli.d.ts +4 -0
  273. package/dist/regression-cli.js +232 -0
  274. package/dist/regression-cli.js.map +1 -0
  275. package/dist/report-api.d.ts +146 -0
  276. package/dist/report-api.js +430 -0
  277. package/dist/report-api.js.map +1 -0
  278. package/dist/report-cli.d.ts +12 -0
  279. package/dist/report-cli.js +147 -0
  280. package/dist/report-cli.js.map +1 -0
  281. package/dist/result-schema.d.ts +22 -0
  282. package/dist/result-schema.js +28 -0
  283. package/dist/result-schema.js.map +1 -0
  284. package/dist/run-index.d.ts +29 -0
  285. package/dist/run-index.js +70 -0
  286. package/dist/run-index.js.map +1 -0
  287. package/dist/run-screenshots.d.ts +123 -0
  288. package/dist/run-screenshots.js +229 -0
  289. package/dist/run-screenshots.js.map +1 -0
  290. package/dist/runtime-env.d.ts +8 -0
  291. package/dist/runtime-env.js +22 -0
  292. package/dist/runtime-env.js.map +1 -0
  293. package/dist/secret-args.d.ts +23 -0
  294. package/dist/secret-args.js +45 -0
  295. package/dist/secret-args.js.map +1 -0
  296. package/dist/serve-cli.d.ts +4 -0
  297. package/dist/serve-cli.js +95 -0
  298. package/dist/serve-cli.js.map +1 -0
  299. package/dist/server-log-verify.d.ts +34 -0
  300. package/dist/server-log-verify.js +115 -0
  301. package/dist/server-log-verify.js.map +1 -0
  302. package/dist/session-check.d.ts +14 -0
  303. package/dist/session-check.js +44 -0
  304. package/dist/session-check.js.map +1 -0
  305. package/dist/site-cli.d.ts +4 -0
  306. package/dist/site-cli.js +127 -0
  307. package/dist/site-cli.js.map +1 -0
  308. package/dist/site-gate-cli.d.ts +28 -0
  309. package/dist/site-gate-cli.js +58 -0
  310. package/dist/site-gate-cli.js.map +1 -0
  311. package/dist/source-api.js +18 -3
  312. package/dist/source-api.js.map +1 -1
  313. package/dist/source-cli.d.ts +4 -0
  314. package/dist/source-cli.js +284 -0
  315. package/dist/source-cli.js.map +1 -0
  316. package/dist/source-run-api.d.ts +27 -1
  317. package/dist/source-run-api.js +22 -11
  318. package/dist/source-run-api.js.map +1 -1
  319. package/dist/storage-state-snapshot.d.ts +50 -0
  320. package/dist/storage-state-snapshot.js +87 -0
  321. package/dist/storage-state-snapshot.js.map +1 -0
  322. package/dist/suite-explore-options.d.ts +289 -0
  323. package/dist/suite-explore-options.js +140 -0
  324. package/dist/suite-explore-options.js.map +1 -0
  325. package/dist/target-config.d.ts +109 -0
  326. package/dist/target-config.js +216 -0
  327. package/dist/target-config.js.map +1 -0
  328. package/dist/transcript-file.d.ts +12 -0
  329. package/dist/transcript-file.js +23 -0
  330. package/dist/transcript-file.js.map +1 -0
  331. package/dist/ui-api.d.ts +3 -0
  332. package/dist/ui-api.js +7 -1
  333. package/dist/ui-api.js.map +1 -1
  334. package/dist/usability-capture.d.ts +43 -0
  335. package/dist/usability-capture.js +326 -0
  336. package/dist/usability-capture.js.map +1 -0
  337. package/dist/usage-config.d.ts +36 -0
  338. package/dist/usage-config.js +114 -0
  339. package/dist/usage-config.js.map +1 -0
  340. package/dist/ux-api.d.ts +3 -75
  341. package/dist/ux-api.js +3 -220
  342. package/dist/ux-api.js.map +1 -1
  343. package/dist/ux-cli.d.ts +4 -0
  344. package/dist/ux-cli.js +102 -0
  345. package/dist/ux-cli.js.map +1 -0
  346. package/dist/ux-config.d.ts +29 -0
  347. package/dist/ux-config.js +103 -0
  348. package/dist/ux-config.js.map +1 -0
  349. package/dist/ux-evidence.d.ts +54 -0
  350. package/dist/ux-evidence.js +197 -0
  351. package/dist/ux-evidence.js.map +1 -0
  352. package/dist/ux-review.d.ts +112 -0
  353. package/dist/ux-review.js +151 -0
  354. package/dist/ux-review.js.map +1 -0
  355. package/dist/ux-usability.d.ts +238 -0
  356. package/dist/ux-usability.js +494 -0
  357. package/dist/ux-usability.js.map +1 -0
  358. package/dist/verify-fix-api.d.ts +173 -0
  359. package/dist/verify-fix-api.js +454 -0
  360. package/dist/verify-fix-api.js.map +1 -0
  361. package/dist/verify-fix-cli.d.ts +4 -0
  362. package/dist/verify-fix-cli.js +110 -0
  363. package/dist/verify-fix-cli.js.map +1 -0
  364. package/package.json +19 -14
  365. package/skills/jevitate-ci-check/SKILL.md +77 -0
  366. package/skills/jevitate-demo/SKILL.md +61 -0
  367. package/skills/jevitate-explore/SKILL.md +88 -87
  368. package/skills/jevitate-getting-started/SKILL.md +88 -0
  369. package/skills/jevitate-load-test/SKILL.md +11 -2
  370. package/skills/jevitate-mission-scope/SKILL.md +19 -11
  371. package/skills/jevitate-record/SKILL.md +23 -5
  372. package/skills/jevitate-run-journey/SKILL.md +61 -17
  373. package/skills/jevitate-sources/SKILL.md +57 -14
  374. package/skills/jevitate-ux-review/SKILL.md +106 -16
  375. package/skills/jevitate-verify-fix/SKILL.md +76 -0
@@ -0,0 +1,106 @@
1
+ import { type RunVerifyFixOptions, type VerifyFixReport } from "./verify-fix-api.js";
2
+ import { type EngineInfo } from "./engine.js";
3
+ /**
4
+ * The finding ledger (#195 part 6): a built-in store of the repro material `verify-fix` needs,
5
+ * keyed by fingerprint, so "is it still fixed?" can be asked months later from the fingerprint
6
+ * alone — after the run's `.jevitate/logs/<date>/` output has been pruned by retention.
7
+ *
8
+ * It extends the committed regressions store rather than duplicating it: entries live in
9
+ * `<regressions>/ledger/<fingerprint>.json` (default `.jevitate/regressions/ledger/`, committed with
10
+ * the app's code, like `regression capture`'s artifacts). Each entry is a minimal, self-contained
11
+ * mission result — `{ ledger, result }` — that `runVerifyFix` reads exactly like a `<stem>.result.json`.
12
+ *
13
+ * What an entry holds is ALLOW-LISTED, never a copy of the result: the finding itself (with its own
14
+ * path Recording, when it has one), the run's Recording only when the finding has none, the scope
15
+ * (`seedUrl` + `allowlist`), the declared-invariant spec and the fixture spec the replay re-checks,
16
+ * and the write controls the run fired (for hang-replay safety). Never a storage state, a session
17
+ * PATH, an actor's session, the transcript, page text, screenshots or usage: a replay of an
18
+ * authenticated target takes `--storage-state` (or the operator's targets.json session) at verify
19
+ * time. A value the caller names as secret (`--secret`) anywhere in the material refuses the add.
20
+ */
21
+ export declare const LEDGER_ENTRY_VERSION: 1;
22
+ export declare class LedgerError extends Error {
23
+ readonly code: "E_LEDGER_INPUT" | "E_LEDGER_NOT_FOUND" | "E_LEDGER_SECRET";
24
+ constructor(code: LedgerError["code"], message: string);
25
+ }
26
+ export interface LedgerMeta {
27
+ readonly version: typeof LEDGER_ENTRY_VERSION;
28
+ readonly fingerprint: string;
29
+ readonly kind: string;
30
+ readonly title?: string;
31
+ /** The tracker ticket the finding was filed as (`--ticket`). */
32
+ readonly ticket?: string;
33
+ readonly addedAt: string;
34
+ /** Where the material came from: the result's file NAME (never a machine-local path), its strategy and build. */
35
+ readonly source: {
36
+ readonly result: string;
37
+ readonly strategy?: string;
38
+ readonly missionOutcome?: string;
39
+ readonly engine?: EngineInfo;
40
+ };
41
+ /** The build that added it. */
42
+ readonly addedBy: EngineInfo;
43
+ }
44
+ export interface LedgerEntry {
45
+ readonly ledger: LedgerMeta;
46
+ readonly result: Record<string, unknown>;
47
+ }
48
+ /** `<regressions>/ledger` — `.jevitate/regressions/ledger` in a project, else `~/.jevitate/regressions/ledger`. */
49
+ export declare function ledgerDir(regressionsDir?: string): string;
50
+ export interface LedgerAddOptions {
51
+ readonly resultPath: string;
52
+ readonly fingerprint: string;
53
+ readonly ticket?: string;
54
+ /** `<regressions>` dir (CLI `--dir`); default `.jevitate/regressions`. */
55
+ readonly regressionsDir?: string;
56
+ /** Values that must never be stored (CLI `--secret`): an add whose material contains one is refused. */
57
+ readonly secrets?: readonly string[];
58
+ /** Test seam. */
59
+ readonly nowIso?: () => string;
60
+ }
61
+ export interface LedgerAddResult {
62
+ readonly entryPath: string;
63
+ readonly fingerprint: string;
64
+ readonly kind: string;
65
+ readonly title?: string;
66
+ readonly ticket?: string;
67
+ /** True when an entry for this fingerprint already existed (its `addedAt` is kept). */
68
+ readonly updated: boolean;
69
+ }
70
+ /** `jevitate ledger add <result> <fp>`: stores the redacted repro material `verify-fix` needs. */
71
+ export declare function ledgerAdd(opts: LedgerAddOptions): LedgerAddResult;
72
+ /** Every entry in the ledger, oldest first. */
73
+ export declare function ledgerList(regressionsDir?: string): Array<LedgerMeta & {
74
+ readonly entryPath: string;
75
+ }>;
76
+ /**
77
+ * The ledger entry for a fingerprint — its own, or the entry whose finding lists it as `related`
78
+ * (the same defect seen at another point). What `verify-fix --fingerprint <fp>` replays when no
79
+ * `--result` is given.
80
+ */
81
+ export declare function ledgerEntryFor(fingerprint: string, regressionsDir?: string): string;
82
+ /** Which entries to re-check, plus every `verify-fix` option (passed to each replay as `verify-fix` takes it). */
83
+ export interface RunLedgerVerifyOptions extends Omit<RunVerifyFixOptions, "resultPath" | "fingerprint"> {
84
+ /** Fingerprints to verify; default every entry (narrowed by `ticket`). */
85
+ readonly fingerprints?: readonly string[];
86
+ readonly ticket?: string;
87
+ readonly regressionsDir?: string;
88
+ }
89
+ export interface LedgerVerifyItem {
90
+ readonly fingerprint: string;
91
+ readonly ticket?: string;
92
+ readonly title?: string;
93
+ readonly verdict: VerifyFixReport["verdict"];
94
+ readonly exitCode: number;
95
+ readonly reason?: string;
96
+ readonly report?: VerifyFixReport;
97
+ }
98
+ export interface LedgerVerifyResult {
99
+ readonly kind: "ledger-verify";
100
+ readonly entries: LedgerVerifyItem[];
101
+ readonly summary: Readonly<Record<VerifyFixReport["verdict"], number>>;
102
+ /** 0 every entry fixed · 1 any still reproduces · 4 any intermittent · 2 any inconclusive (worst wins, in that order). */
103
+ readonly exitCode: number;
104
+ }
105
+ /** `jevitate ledger verify`: re-checks every (or the named) ledger entry with `verify-fix`, from the ledger alone. */
106
+ export declare function runLedgerVerify(opts: RunLedgerVerifyOptions): Promise<LedgerVerifyResult>;
@@ -0,0 +1,237 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import { basename, join } from "node:path";
3
+ import { projectDataDir } from "./project-dir.js";
4
+ import { VERIFY_FIX_EXIT_CODES, VerifyFixInputError, findFinding, parsePersistedMission, runVerifyFix, } from "./verify-fix-api.js";
5
+ import { currentEngineInfo } from "./engine.js";
6
+ /**
7
+ * The finding ledger (#195 part 6): a built-in store of the repro material `verify-fix` needs,
8
+ * keyed by fingerprint, so "is it still fixed?" can be asked months later from the fingerprint
9
+ * alone — after the run's `.jevitate/logs/<date>/` output has been pruned by retention.
10
+ *
11
+ * It extends the committed regressions store rather than duplicating it: entries live in
12
+ * `<regressions>/ledger/<fingerprint>.json` (default `.jevitate/regressions/ledger/`, committed with
13
+ * the app's code, like `regression capture`'s artifacts). Each entry is a minimal, self-contained
14
+ * mission result — `{ ledger, result }` — that `runVerifyFix` reads exactly like a `<stem>.result.json`.
15
+ *
16
+ * What an entry holds is ALLOW-LISTED, never a copy of the result: the finding itself (with its own
17
+ * path Recording, when it has one), the run's Recording only when the finding has none, the scope
18
+ * (`seedUrl` + `allowlist`), the declared-invariant spec and the fixture spec the replay re-checks,
19
+ * and the write controls the run fired (for hang-replay safety). Never a storage state, a session
20
+ * PATH, an actor's session, the transcript, page text, screenshots or usage: a replay of an
21
+ * authenticated target takes `--storage-state` (or the operator's targets.json session) at verify
22
+ * time. A value the caller names as secret (`--secret`) anywhere in the material refuses the add.
23
+ */
24
+ export const LEDGER_ENTRY_VERSION = 1;
25
+ export class LedgerError extends Error {
26
+ code;
27
+ constructor(code, message) {
28
+ super(message);
29
+ this.name = "LedgerError";
30
+ this.code = code;
31
+ }
32
+ }
33
+ /** `<regressions>/ledger` — `.jevitate/regressions/ledger` in a project, else `~/.jevitate/regressions/ledger`. */
34
+ export function ledgerDir(regressionsDir) {
35
+ return join(regressionsDir ?? projectDataDir(["regressions"]), "ledger");
36
+ }
37
+ const FINGERPRINT = /^[0-9a-f]{16}$/;
38
+ function isRecord(v) {
39
+ return v !== null && typeof v === "object" && !Array.isArray(v);
40
+ }
41
+ function entryPath(dir, fingerprint) {
42
+ if (!FINGERPRINT.test(fingerprint))
43
+ throw new LedgerError("E_LEDGER_INPUT", `not a finding fingerprint: ${JSON.stringify(fingerprint)} (16 hex characters)`);
44
+ return join(dir, `${fingerprint}.json`);
45
+ }
46
+ /** The raw finding object (as persisted) whose fingerprint or `related` list is `fp`. */
47
+ function rawFinding(result, fp) {
48
+ for (const list of [result.defects, result.hangs, result.serverLogDefects]) {
49
+ if (!Array.isArray(list))
50
+ continue;
51
+ for (const item of list) {
52
+ if (!isRecord(item))
53
+ continue;
54
+ const related = Array.isArray(item.related) ? item.related : [];
55
+ if (item.fingerprint === fp || related.includes(fp))
56
+ return item;
57
+ }
58
+ }
59
+ return undefined;
60
+ }
61
+ /** Refuses repro material that contains any value the caller declared secret. */
62
+ function assertNoSecrets(material, secrets) {
63
+ const text = JSON.stringify(material);
64
+ const leaked = secrets.filter((s) => s.length > 0 && text.includes(s));
65
+ if (leaked.length > 0) {
66
+ throw new LedgerError("E_LEDGER_SECRET", `the finding's repro material contains ${leaked.length} value(s) passed as --secret — refusing to store it (the ledger is committed with the repo)`);
67
+ }
68
+ }
69
+ /** `jevitate ledger add <result> <fp>`: stores the redacted repro material `verify-fix` needs. */
70
+ export function ledgerAdd(opts) {
71
+ let raw;
72
+ try {
73
+ raw = JSON.parse(readFileSync(opts.resultPath, "utf8"));
74
+ }
75
+ catch (e) {
76
+ throw new LedgerError("E_LEDGER_INPUT", `cannot read mission result ${opts.resultPath}: ${e instanceof Error ? e.message : String(e)}`);
77
+ }
78
+ let mission;
79
+ try {
80
+ mission = parsePersistedMission(raw);
81
+ }
82
+ catch (e) {
83
+ throw new LedgerError("E_LEDGER_INPUT", `${opts.resultPath}: ${e instanceof Error ? e.message : String(e)}`);
84
+ }
85
+ const finding = findFinding(mission, opts.fingerprint);
86
+ const result = isRecord(raw) && isRecord(raw.result) ? raw.result : {};
87
+ const item = finding === undefined ? undefined : rawFinding(result, finding.fingerprint);
88
+ if (finding === undefined || item === undefined) {
89
+ throw new LedgerError("E_LEDGER_INPUT", `no finding with fingerprint ${opts.fingerprint} in ${opts.resultPath}`);
90
+ }
91
+ // The replay needs a Recording: the finding's own path, else the run's.
92
+ const ownRecording = isRecord(item.repro) && item.repro.recording !== undefined;
93
+ if (!ownRecording && mission.recording === null) {
94
+ throw new LedgerError("E_LEDGER_INPUT", `finding ${finding.fingerprint} has no Recording to replay — nothing verify-fix could re-check`);
95
+ }
96
+ const list = finding.kind === "hang" ? "hangs" : "defects";
97
+ const persistedFixtures = isRecord(result.fixtures) ? result.fixtures : undefined;
98
+ const material = {
99
+ ...(typeof result.schemaVersion === "number" ? { schemaVersion: result.schemaVersion } : {}),
100
+ ...(typeof result.strategy === "string" ? { strategy: result.strategy } : {}),
101
+ // The scope only: never a storage-state path or an actor's session (machine-local, and a pointer at credentials).
102
+ target: { seedUrl: mission.target.seedUrl, allowlist: [...mission.target.allowlist] },
103
+ recording: ownRecording ? null : mission.recording,
104
+ defects: list === "defects" ? [item] : [],
105
+ hangs: list === "hangs" ? [item] : [],
106
+ ...(finding.kind === "invariant" && mission.invariantSpec !== undefined ? { invariantSpec: mission.invariantSpec } : {}),
107
+ // The fixture's spec, hook HASHES and non-secret outputs — what a replay restores; hooks are never stored.
108
+ ...(persistedFixtures === undefined
109
+ ? {}
110
+ : {
111
+ fixtures: {
112
+ identity: persistedFixtures.identity,
113
+ ...(persistedFixtures.spec === undefined ? {} : { spec: persistedFixtures.spec }),
114
+ hooks: isRecord(persistedFixtures.hooks) ? persistedFixtures.hooks : {},
115
+ outputs: isRecord(persistedFixtures.outputs) ? persistedFixtures.outputs : {},
116
+ },
117
+ }),
118
+ // Only which controls fired a write (hang-replay safety, #153/#181) — never the requests themselves.
119
+ sideEffects: (Array.isArray(result.sideEffects) ? result.sideEffects : []).flatMap((e) => isRecord(e) && typeof e.control === "string" ? [{ control: e.control }] : []),
120
+ };
121
+ assertNoSecrets(material, opts.secrets ?? []);
122
+ const dir = ledgerDir(opts.regressionsDir);
123
+ const path = entryPath(dir, finding.fingerprint);
124
+ const previous = existsSync(path) ? readEntry(path) : undefined;
125
+ const ticket = opts.ticket ?? previous?.ledger.ticket;
126
+ const meta = {
127
+ version: LEDGER_ENTRY_VERSION,
128
+ fingerprint: finding.fingerprint,
129
+ kind: finding.kind,
130
+ ...(finding.title === undefined ? {} : { title: finding.title }),
131
+ ...(ticket === undefined ? {} : { ticket }),
132
+ addedAt: previous?.ledger.addedAt ?? (opts.nowIso ?? (() => new Date().toISOString()))(),
133
+ source: {
134
+ result: basename(opts.resultPath),
135
+ ...(typeof result.strategy === "string" ? { strategy: result.strategy } : {}),
136
+ ...(isRecord(raw) && typeof raw.missionOutcome === "string" ? { missionOutcome: raw.missionOutcome } : {}),
137
+ ...(isRecord(result.engine) ? { engine: result.engine } : {}),
138
+ },
139
+ addedBy: currentEngineInfo(),
140
+ };
141
+ const entry = { ledger: meta, result: material };
142
+ // The entry must itself be a mission result verify-fix can read (fail closed before writing).
143
+ const check = findFinding(parsePersistedMission(entry), finding.fingerprint);
144
+ if (check === undefined)
145
+ throw new LedgerError("E_LEDGER_INPUT", `finding ${finding.fingerprint} did not survive into its ledger entry`);
146
+ mkdirSync(dir, { recursive: true });
147
+ writeFileSync(path, `${JSON.stringify(entry, null, 2)}\n`, "utf8");
148
+ return {
149
+ entryPath: path,
150
+ fingerprint: finding.fingerprint,
151
+ kind: finding.kind,
152
+ ...(finding.title === undefined ? {} : { title: finding.title }),
153
+ ...(ticket === undefined ? {} : { ticket }),
154
+ updated: previous !== undefined,
155
+ };
156
+ }
157
+ function readEntry(path) {
158
+ let raw;
159
+ try {
160
+ raw = JSON.parse(readFileSync(path, "utf8"));
161
+ }
162
+ catch (e) {
163
+ throw new LedgerError("E_LEDGER_INPUT", `cannot read ledger entry ${path}: ${e instanceof Error ? e.message : String(e)}`);
164
+ }
165
+ if (!isRecord(raw) || !isRecord(raw.ledger) || !isRecord(raw.result) || typeof raw.ledger.fingerprint !== "string") {
166
+ throw new LedgerError("E_LEDGER_INPUT", `not a ledger entry: ${path}`);
167
+ }
168
+ return raw;
169
+ }
170
+ /** Every entry in the ledger, oldest first. */
171
+ export function ledgerList(regressionsDir) {
172
+ const dir = ledgerDir(regressionsDir);
173
+ if (!existsSync(dir))
174
+ return [];
175
+ return readdirSync(dir)
176
+ .filter((f) => FINGERPRINT.test(f.replace(/\.json$/, "")) && f.endsWith(".json"))
177
+ .map((f) => {
178
+ const entryPath = join(dir, f);
179
+ return { ...readEntry(entryPath).ledger, entryPath };
180
+ })
181
+ .sort((a, b) => a.addedAt.localeCompare(b.addedAt) || a.fingerprint.localeCompare(b.fingerprint));
182
+ }
183
+ /**
184
+ * The ledger entry for a fingerprint — its own, or the entry whose finding lists it as `related`
185
+ * (the same defect seen at another point). What `verify-fix --fingerprint <fp>` replays when no
186
+ * `--result` is given.
187
+ */
188
+ export function ledgerEntryFor(fingerprint, regressionsDir) {
189
+ const dir = ledgerDir(regressionsDir);
190
+ const own = entryPath(dir, fingerprint);
191
+ if (existsSync(own))
192
+ return own;
193
+ for (const e of ledgerList(regressionsDir)) {
194
+ if (findFinding(parsePersistedMission(readEntry(e.entryPath)), fingerprint) !== undefined)
195
+ return e.entryPath;
196
+ }
197
+ throw new LedgerError("E_LEDGER_NOT_FOUND", `no ledger entry for fingerprint ${fingerprint} in ${dir} — add one with \`jevitate ledger add <result> ${fingerprint}\`, or pass --result`);
198
+ }
199
+ /** A regression beats a flaky signal beats a check that could not run; only all-`fixed` passes. */
200
+ const VERDICT_SEVERITY = { fixed: 0, inconclusive: 1, intermittent: 2, "still-reproduces": 3 };
201
+ /** `jevitate ledger verify`: re-checks every (or the named) ledger entry with `verify-fix`, from the ledger alone. */
202
+ export async function runLedgerVerify(opts) {
203
+ const { fingerprints: _fps, ticket: _ticket, regressionsDir: _dir, ...verify } = opts;
204
+ const all = ledgerList(opts.regressionsDir);
205
+ const chosen = opts.fingerprints !== undefined && opts.fingerprints.length > 0
206
+ ? opts.fingerprints.map((fp) => {
207
+ const entryPath = ledgerEntryFor(fp, opts.regressionsDir);
208
+ const meta = readEntry(entryPath).ledger;
209
+ return { ...meta, entryPath, fingerprint: fp };
210
+ })
211
+ : all.filter((e) => opts.ticket === undefined || e.ticket === opts.ticket);
212
+ const entries = [];
213
+ for (const e of chosen) {
214
+ const base = { fingerprint: e.fingerprint, ...(e.ticket === undefined ? {} : { ticket: e.ticket }), ...(e.title === undefined ? {} : { title: e.title }) };
215
+ try {
216
+ const report = await runVerifyFix({ ...verify, resultPath: e.entryPath, fingerprint: e.fingerprint });
217
+ entries.push({ ...base, verdict: report.verdict, exitCode: report.exitCode, ...(report.reason === undefined ? {} : { reason: report.reason }), report });
218
+ }
219
+ catch (err) {
220
+ // An entry that cannot be replayed (a missing session, a refused origin) is inconclusive — never fixed.
221
+ if (!(err instanceof VerifyFixInputError) && !(err instanceof LedgerError))
222
+ throw err;
223
+ entries.push({ ...base, verdict: "inconclusive", exitCode: VERIFY_FIX_EXIT_CODES.inconclusive, reason: err.message });
224
+ }
225
+ }
226
+ const summary = { fixed: 0, "still-reproduces": 0, intermittent: 0, inconclusive: 0 };
227
+ for (const e of entries)
228
+ summary[e.verdict] += 1;
229
+ // #227: nothing chosen (an empty ledger, or fingerprints/ticket matching nothing) verified nothing
230
+ // — `entries.reduce(..., "fixed")`'s empty-array identity would otherwise read as "FIXED: 0
231
+ // entries" at exit 0, a false pass. Inconclusive (2): the command proved nothing either way.
232
+ if (entries.length === 0)
233
+ return { kind: "ledger-verify", entries, summary, exitCode: VERIFY_FIX_EXIT_CODES.inconclusive };
234
+ const worst = entries.reduce((w, e) => (VERDICT_SEVERITY[e.verdict] > VERDICT_SEVERITY[w] ? e.verdict : w), "fixed");
235
+ return { kind: "ledger-verify", entries, summary, exitCode: VERIFY_FIX_EXIT_CODES[worst] };
236
+ }
237
+ //# sourceMappingURL=ledger-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-api.js","sourceRoot":"","sources":["../src/ledger-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { Command } from "commander";
2
+ import type { BrowserLaunchOptions, BrowserPort } from "@jevitate/playwright";
3
+ /**
4
+ * `jevitate ledger add|list|verify` (#195 part 6) — registered by `program.ts`, which supplies the
5
+ * browser wiring. See `ledger-api.ts` for what an entry holds (and never holds).
6
+ *
7
+ * Exit codes (exit-codes.ts): `add`/`list` 0 ok · 64 refused input (bad fingerprint, missing entry,
8
+ * a secret in the material) · 2 an unexpected failure. `verify` 0 every entry fixed · 1 any still
9
+ * reproduces · 4 any intermittent · 2 any inconclusive · 64 the ledger/arguments were unusable.
10
+ * Without `--json`, a human summary (#210).
11
+ */
12
+ export interface LedgerCliDeps {
13
+ readonly targetsConfigPath?: string;
14
+ readonly browserPortFactory?: () => BrowserPort;
15
+ /** Maps the command's browser launch flags to launch options (program.ts's `browserLaunchFromFlags`). */
16
+ readonly browserLaunch?: (flags: object) => BrowserLaunchOptions | undefined;
17
+ }
18
+ export declare function registerLedgerCommands(program: Command, deps: LedgerCliDeps, withLaunchFlags: (cmd: Command) => Command): void;
@@ -0,0 +1,107 @@
1
+ import { UnauthorizedExploreTargetError } from "@jevitate/explore";
2
+ import { ok, fail } from "./envelope.js";
3
+ import { withEngine } from "./engine.js";
4
+ import { LedgerError, ledgerAdd, ledgerList, runLedgerVerify } from "./ledger-api.js";
5
+ import { TargetConfigError, loadTargetsFile } from "./target-config.js";
6
+ import { VerifyFixInputError } from "./verify-fix-api.js";
7
+ import { positiveIntArg } from "./cli-args.js";
8
+ import { emitEnvelope, formatLedgerAddHuman, formatLedgerListHuman, formatLedgerVerifyHuman } from "./cli-output.js";
9
+ function emit(program, envelope, out, exitCode) {
10
+ emitEnvelope(program, envelope, { ...out, ...(exitCode === undefined ? {} : { exitCode }) });
11
+ }
12
+ /** A refusal's exit code is its class (exit-codes.ts): 64 for unusable input, 2 for an unexpected failure. */
13
+ function refuse(program, err, out) {
14
+ if (err instanceof LedgerError || err instanceof VerifyFixInputError || err instanceof TargetConfigError) {
15
+ emit(program, fail(err.code, err.message), out);
16
+ }
17
+ else if (err instanceof UnauthorizedExploreTargetError) {
18
+ emit(program, fail("E_UNAUTHORIZED_EXPLORE_TARGET", err.message), out);
19
+ }
20
+ else {
21
+ emit(program, fail("E_LEDGER", err instanceof Error ? err.message : String(err)), out);
22
+ }
23
+ }
24
+ const collect = (v, prev) => [...prev, v];
25
+ const DIR_HELP = "regressions directory; the ledger is its ledger/ subdirectory (default: the repo's .jevitate/regressions)";
26
+ export function registerLedgerCommands(program, deps, withLaunchFlags) {
27
+ const ledger = program
28
+ .command("ledger")
29
+ .description("keep each finding's repro material by fingerprint, so verify-fix works long after the run's output is gone");
30
+ ledger
31
+ .command("add")
32
+ .description("store a finding's redacted repro material (never a session or storage state) in the committed ledger")
33
+ .argument("<result>", "the mission's <stem>.result.json that contains the finding")
34
+ .argument("<fingerprint>", "the defect/hang fingerprint")
35
+ .option("--ticket <id>", "the tracker ticket the finding was filed as")
36
+ .option("--dir <path>", DIR_HELP)
37
+ .option("--secret <value>", "refuse the entry if its material contains this value (repeatable)", collect, [])
38
+ .option("--json", "emit a JSON envelope (default: a human summary)")
39
+ .action(function (result, fingerprint) {
40
+ const o = this.opts();
41
+ // #230: the follow-up hints carry the same --dir the user passed.
42
+ const out = { json: o.json === true, command: "ledger add", human: (data) => formatLedgerAddHuman(data, { dir: o.dir }) };
43
+ try {
44
+ const added = ledgerAdd({
45
+ resultPath: result,
46
+ fingerprint,
47
+ secrets: o.secret,
48
+ ...(o.ticket === undefined ? {} : { ticket: o.ticket }),
49
+ ...(o.dir === undefined ? {} : { regressionsDir: o.dir }),
50
+ });
51
+ emit(program, ok(added), out);
52
+ }
53
+ catch (err) {
54
+ refuse(program, err, out);
55
+ }
56
+ });
57
+ ledger
58
+ .command("list")
59
+ .description("list the ledger's entries (fingerprint, kind, title, ticket, when added)")
60
+ .option("--dir <path>", DIR_HELP)
61
+ .option("--json", "emit a JSON envelope (default: a human summary)")
62
+ .action(function () {
63
+ const o = this.opts();
64
+ // #230: the follow-up hint carries the same --dir the user passed.
65
+ const out = { json: o.json === true, command: "ledger list", human: (data) => formatLedgerListHuman(data, { dir: o.dir }) };
66
+ try {
67
+ emit(program, ok({ entries: ledgerList(o.dir) }), out);
68
+ }
69
+ catch (err) {
70
+ refuse(program, err, out);
71
+ }
72
+ });
73
+ withLaunchFlags(ledger
74
+ .command("verify")
75
+ .description("re-check every ledger entry (or the named ones) with verify-fix, from the ledger alone"))
76
+ .argument("[fingerprints...]", "only these entries (default: every entry)")
77
+ .option("--ticket <id>", "only the entries filed as this ticket")
78
+ .option("--dir <path>", DIR_HELP)
79
+ .option("--storage-state <file>", "the session to replay an authenticated target with (entries never store one)")
80
+ .option("--replays <n>", "fresh-context replays per entry that confirm a fix (default 3)", positiveIntArg)
81
+ .option("--allow-log-cmd", "re-checking a server-log entry whose source is cmd:<command> needs this too", false)
82
+ .option("--json", "emit a JSON envelope (default: a human summary)")
83
+ .action(async function (fingerprints) {
84
+ const o = this.opts();
85
+ // #230: the follow-up hint carries the same --dir the user passed.
86
+ const out = { json: o.json === true, command: "ledger verify", human: (data) => formatLedgerVerifyHuman(data, { dir: o.dir }) };
87
+ try {
88
+ const browser = deps.browserLaunch?.(o);
89
+ const result = await runLedgerVerify({
90
+ fingerprints,
91
+ ...(o.ticket === undefined ? {} : { ticket: o.ticket }),
92
+ ...(o.dir === undefined ? {} : { regressionsDir: o.dir }),
93
+ targets: loadTargetsFile(deps.targetsConfigPath),
94
+ ...(o.storageState === undefined ? {} : { storageState: o.storageState }),
95
+ ...(o.replays === undefined ? {} : { replays: Number(o.replays) }),
96
+ ...(o.allowLogCmd === true ? { allowLogCmd: true } : {}),
97
+ ...(deps.browserPortFactory === undefined ? {} : { browserPortFactory: deps.browserPortFactory }),
98
+ ...(browser === undefined ? {} : { browser }),
99
+ });
100
+ emit(program, ok(withEngine(result)), out, result.exitCode);
101
+ }
102
+ catch (err) {
103
+ refuse(program, err, out);
104
+ }
105
+ });
106
+ }
107
+ //# sourceMappingURL=ledger-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger-cli.js","sourceRoot":"","sources":["../src/ledger-cli.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
+ import type { SiteGateDeps } from "@jevitate/runtime";
1
2
  import { type RunPolicy } from "@jevitate/domain";
2
- import { type BrowserPort } from "@jevitate/playwright";
3
+ import { type BrowserLaunchOptions, type BrowserPort, type EmulationSpec } from "@jevitate/playwright";
3
4
  import { type CapacityReport } from "@jevitate/load";
5
+ import { type ResolvedJourneyEnvironment } from "./environments.js";
4
6
  /** Distinct from `@jevitate/journey`'s ParamValidationError-style "unknown id" cases elsewhere, so CLI callers can branch without string-matching. */
5
7
  export declare class UnknownLoadJourneyError extends Error {
6
8
  }
@@ -11,12 +13,9 @@ export interface RunJourneyLoadTestOptions {
11
13
  concurrency: number;
12
14
  iterationsPerActor: number;
13
15
  /**
14
- * Governs deterministic actor fan-out/scheduling only (see
15
- * `@jevitate/load`'s `RunLoadTestConfig.seed` doc comment) — the real
16
- * `JourneyRunner` this function drives per pool member has no pacing
17
- * hook, so this `seed` does NOT (yet) produce human-speed pacing of the
18
- * real run the way `modeledCapacityReport`'s `seed` drives
19
- * `simulateTiming()`. Known gap, deferred to a future slice.
16
+ * Governs deterministic actor fan-out/scheduling, and seeds each actor's human-like pacing when a
17
+ * site policy declares one (`jevitate site policy set <origin>`): actor N's pacing is reproducible
18
+ * from `seed` and N.
20
19
  */
21
20
  seed: number;
22
21
  authorizedOrigins: readonly string[];
@@ -29,6 +28,25 @@ export interface RunJourneyLoadTestOptions {
29
28
  * to `() => new PlaywrightBrowserPort()`.
30
29
  */
31
30
  browserPortFactory?: () => BrowserPort;
31
+ /**
32
+ * Playwright storageState JSON to seed EVERY pool member's session from (CLI `--storage-state`,
33
+ * #118) — the deterministic authenticated pre-step a Journey authored behind a login needs.
34
+ * Contains live session cookies: handed only to the browser, never logged, never returned in
35
+ * the report.
36
+ */
37
+ storageState?: string;
38
+ /** How Chromium is launched (executable/channel/extra args). Default: pinned Chromium. */
39
+ browser?: BrowserLaunchOptions;
40
+ /** Per-mission viewport/device emulation (#149, CLI `--viewport <W>x<H>` / `--device "<name>"`) — applied to EVERY pool member's session. */
41
+ emulation?: EmulationSpec;
42
+ /** The site-policy gate (`jevitate site policy set`): only its pacing applies to a load run. */
43
+ siteGate?: SiteGateDeps;
44
+ /**
45
+ * #247 (`--env`/`--base-url`): load-test this environment — the Journey's recorded URLs move onto
46
+ * its baseUrl (which must still be an `--authorized-origin`); a step on an origin it does not
47
+ * allow is refused before any browser opens. Absent: the recorded site, as before.
48
+ */
49
+ environment?: ResolvedJourneyEnvironment;
32
50
  }
33
51
  /**
34
52
  * The programmatic surface behind `jevitate load run` — resolves a published
@@ -40,9 +58,9 @@ export interface RunJourneyLoadTestOptions {
40
58
  *
41
59
  * NOTE on "seeded ⇒ reproducible / human-paced" (corrected post-review):
42
60
  * `opts.seed` makes the ACTOR POOL's composition reproducible (via
43
- * `deriveActorSeeds` inside `runLoadTest`) — it does not yet make the real
44
- * run human-paced, because `JourneyRunner` (constructed below) has no
45
- * pacing hook to seed. Only the offline `modeledCapacityReport` path is
46
- * genuinely human-paced today, via `@jevitate/domain`'s `simulateTiming()`.
61
+ * `deriveActorSeeds` inside `runLoadTest`), and — with a site policy that declares pacing — each
62
+ * actor's clicks and keystrokes are human-paced, seeded from `seed` and the actor's index. A load
63
+ * run is the operator's deliberate burst: the policy's throttles, budgets and quiet hours do not
64
+ * refuse it; only its pacing applies.
47
65
  */
48
66
  export declare function runJourneyLoadTest(opts: RunJourneyLoadTestOptions): Promise<CapacityReport>;