@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
@@ -1,18 +1,15 @@
1
- import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { logsDirFor } from "./project-dir.js";
3
3
  import { join } from "node:path";
4
4
  import { assertAuthorizedExploreTarget, normalizeAllowlist } from "@jevitate/explore";
5
5
  import { PlaywrightBrowserPort } from "@jevitate/playwright";
6
6
  import { Recorder } from "@jevitate/recorder";
7
- import { resolveDataDir } from "./data-dir.js";
8
7
  export async function runRecording(opts) {
9
8
  // Guardrail #1 — authorize BEFORE opening a browser. Throws on refusal.
10
9
  const origin = assertAuthorizedExploreTarget(opts.url, opts.allowlist);
11
10
  const portFactory = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
12
11
  const port = portFactory();
13
- const profileDir = await mkdtemp(join(tmpdir(), "jevitate-record-"));
14
12
  const session = await port.open({
15
- profileDir,
16
13
  headless: opts.headless ?? false,
17
14
  allowedOrigins: [...opts.allowlist],
18
15
  baseUrl: origin,
@@ -29,7 +26,7 @@ export async function runRecording(opts) {
29
26
  await (opts.waitForStop ?? waitForEnterKey)();
30
27
  const recording = await recorder.stop(opts.retro);
31
28
  const finalUrl = session.page.url();
32
- const outDir = opts.outDir ?? resolveDataDir(["recordings"]);
29
+ const outDir = opts.outDir ?? logsDirFor();
33
30
  await mkdir(outDir, { recursive: true });
34
31
  const iso = (opts.nowIso ?? (() => new Date().toISOString()))();
35
32
  const recordingPath = join(outDir, `record-${iso.replace(/[:.]/g, "-")}.json`);
@@ -39,7 +36,6 @@ export async function runRecording(opts) {
39
36
  }
40
37
  finally {
41
38
  await session.close();
42
- await rm(profileDir, { recursive: true, force: true });
43
39
  }
44
40
  }
45
41
  /**
@@ -54,39 +50,54 @@ export function resolveRecordAllowlist(url, allow) {
54
50
  return normalizeAllowlist([url]);
55
51
  }
56
52
  /**
57
- * The default stop signal for an interactive `jevitate record` session:
58
- * resolves the first time the user presses Enter on stdin. Best-effort — if
59
- * stdin is not a TTY / not readable, it resolves immediately rather than
60
- * hanging the capture forever.
53
+ * The default stop signal for an interactive `jevitate record` session: resolves the first time
54
+ * the user presses Enter on stdin, OR on SIGINT (Ctrl-C, #124) — both end the take the SAME way,
55
+ * through `recorder.stop()` + the write to disk in `runRecording`'s normal path, so a take is
56
+ * never silently lost. SIGINT matters most for `--headless` (no visible window to interact with,
57
+ * so Ctrl-C is the natural way to signal "done"): registering a listener here means Node does NOT
58
+ * fall back to its default "kill the process" SIGINT behavior — the take is saved first.
59
+ * Best-effort on stdin — if it is not a TTY / not readable, resolves immediately rather than
60
+ * hanging the capture forever (SIGINT still works either way).
61
61
  */
62
62
  export function waitForEnterKey() {
63
63
  return new Promise((resolve) => {
64
+ let settled = false;
64
65
  const stdin = process.stdin;
65
- if (!stdin || !stdin.readable) {
66
- resolve();
67
- return;
68
- }
66
+ const onSigint = () => finish();
69
67
  const onData = (chunk) => {
70
- if (chunk.includes(0x0a) || chunk.includes(0x0d)) {
71
- cleanup();
72
- resolve();
73
- }
68
+ if (chunk.includes(0x0a) || chunk.includes(0x0d))
69
+ finish();
74
70
  };
75
- const cleanup = () => {
76
- stdin.off("data", onData);
77
- try {
78
- stdin.pause();
79
- }
80
- catch {
81
- // stdin may already be closed; nothing to pause.
71
+ function cleanup() {
72
+ process.off("SIGINT", onSigint);
73
+ if (stdin && stdin.readable) {
74
+ stdin.off("data", onData);
75
+ try {
76
+ stdin.pause();
77
+ }
78
+ catch {
79
+ // stdin may already be closed; nothing to pause.
80
+ }
82
81
  }
83
- };
82
+ }
83
+ function finish() {
84
+ if (settled)
85
+ return;
86
+ settled = true;
87
+ cleanup();
88
+ resolve();
89
+ }
90
+ process.on("SIGINT", onSigint);
91
+ if (!stdin || !stdin.readable) {
92
+ finish();
93
+ return;
94
+ }
84
95
  try {
85
96
  stdin.resume();
86
97
  stdin.on("data", onData);
87
98
  }
88
99
  catch {
89
- resolve();
100
+ finish();
90
101
  }
91
102
  });
92
103
  }
@@ -1 +1 @@
1
- {"version":3,"file":"record-api.js","sourceRoot":"","sources":["../src/record-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record-api.js","sourceRoot":"","sources":["../src/record-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 record` (record-by-demonstration). */
4
+ export declare function registerRecordCommands(program: Command, deps: CliDeps): void;
@@ -0,0 +1,64 @@
1
+ import { UnauthorizedExploreTargetError } from "@jevitate/explore";
2
+ import { ok, fail } from "./envelope.js";
3
+ import { runRecording, resolveRecordAllowlist } from "./record-api.js";
4
+ import { emitJson } from "./cli-shared.js";
5
+ /** Registers `jevitate record` (record-by-demonstration). */
6
+ export function registerRecordCommands(program, deps) {
7
+ // Additive: `jevitate record` — record-by-demonstration (Ticket #22). Opens a
8
+ // real browser on an authorized origin, lets the user demonstrate a flow, and
9
+ // captures it into a schema-valid, replayable Recording written to disk. The
10
+ // authorized-origin guard is enforced FIRST (fail-closed) inside runRecording,
11
+ // before any browser is opened; the temp profile dir is always cleaned up.
12
+ program
13
+ .command("record")
14
+ .description("record a demonstrated flow into a Recording (authoring plane)")
15
+ .option("--url <url>", "start URL to demonstrate from (must be an authorized origin)")
16
+ .option("--intent <text>", "your framing of the journey (carried to Recording.intent)")
17
+ .option("--retro <text>", "optional retrospective note (carried to Recording.retro)")
18
+ .option("--allow <origin>", "authorized origin (repeatable); REPLACES the default allowlist when given (the URL's own origin is used only when --allow is omitted entirely) -- include the URL's own origin explicitly if you still need it", (v, prev) => [...prev, v], [])
19
+ .option("--headless", "run headless (default: headed — a record session is a live demonstration)", false)
20
+ .option("--out <dir>", "directory to write the emitted Recording (default: .jevitate/logs/<date> in the project, else ~/.jevitate/logs/<date>)")
21
+ .option("--json", "emit a JSON envelope")
22
+ .action(async function () {
23
+ const o = this.opts();
24
+ if (!o.url) {
25
+ emitJson(program, fail("E_RECORD_ARGS", "--url is required"));
26
+ return;
27
+ }
28
+ const allowlist = resolveRecordAllowlist(o.url, o.allow);
29
+ try {
30
+ const result = await runRecording({
31
+ url: o.url,
32
+ allowlist,
33
+ intent: o.intent,
34
+ retro: o.retro,
35
+ outDir: o.out,
36
+ headless: o.headless ?? false,
37
+ browserPortFactory: deps.record?.browserPortFactory,
38
+ recorderFactory: deps.record?.recorderFactory,
39
+ waitForStop: deps.record?.waitForStop,
40
+ });
41
+ const summary = {
42
+ recordingPath: result.recordingPath,
43
+ steps: result.steps,
44
+ pages: result.pages,
45
+ finalUrl: result.finalUrl,
46
+ };
47
+ if (o.json) {
48
+ emitJson(program, ok(summary));
49
+ }
50
+ else {
51
+ program.configureOutput().writeOut?.(`${JSON.stringify(summary)}\n`);
52
+ }
53
+ }
54
+ catch (err) {
55
+ if (err instanceof UnauthorizedExploreTargetError) {
56
+ emitJson(program, fail("E_UNAUTHORIZED_EXPLORE_TARGET", err.message));
57
+ }
58
+ else {
59
+ emitJson(program, fail("E_RECORD_RUN", String(err instanceof Error ? err.message : err)));
60
+ }
61
+ }
62
+ });
63
+ }
64
+ //# sourceMappingURL=record-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-cli.js","sourceRoot":"","sources":["../src/record-cli.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 recording`: `promote|diff|fit|postdoc`. */
4
+ export declare function registerRecordingCommands(program: Command, deps: CliDeps): void;
@@ -0,0 +1,248 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import * as clack from "@clack/prompts";
3
+ import { RecordingSchema, AuthoringTakeSchema, PostdocDecisionsSchema, promoteToVariable, diffTakes, applyPostdoc, flattenBaseFillSteps, fitInteractionPolicy, } from "@jevitate/recording";
4
+ import { ok, fail } from "./envelope.js";
5
+ import { nonNegativeIntArg } from "./cli-args.js";
6
+ import { emitJson } from "./cli-shared.js";
7
+ /** Registers `jevitate recording`: `promote|diff|fit|postdoc`. */
8
+ export function registerRecordingCommands(program, deps) {
9
+ /**
10
+ * Reads one "take file" for `recording diff`/`recording postdoc` (#124): a JSON object written
11
+ * by `jevitate record` — `{ recording, values }` (`AuthoringTakeSchema`). A raw `Recording` — the
12
+ * kind `explore`/`explore-author-journey`/a usability run emits directly, `{version, site, pages,
13
+ * ...}` at the TOP level, no `recording`/`values` wrapper — is a common, easy mistake to hand
14
+ * here; `AuthoringTakeSchema`'s `.strict()` rejects it with an opaque `Unrecognized keys: version,
15
+ * site, intent, pages` zod dump. Detected BEFORE the schema parse so the caller gets a message
16
+ * that names the actual problem and how to fix it, not a zod dump.
17
+ */
18
+ async function readAuthoringTake(file) {
19
+ const raw = await readFile(file, "utf8");
20
+ let json;
21
+ try {
22
+ json = JSON.parse(raw);
23
+ }
24
+ catch (err) {
25
+ throw new Error(`'${file}' is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
26
+ }
27
+ if (json !== null && typeof json === "object" && !Array.isArray(json) && "pages" in json && !("recording" in json)) {
28
+ throw new Error(`'${file}' looks like a Recording (it has a top-level "pages"), not a take file. ` +
29
+ `'recording diff'/'recording postdoc' need a take file written by 'jevitate record' — shape ` +
30
+ `{ recording, values } — not a raw Recording from 'explore', 'explore-author-journey', or a ` +
31
+ `usability run. Wrap it as { "recording": <the Recording>, "values": {} } if you want to ` +
32
+ `diff/postdoc it anyway.`);
33
+ }
34
+ const parsed = AuthoringTakeSchema.parse(json);
35
+ return { recording: parsed.recording, values: new Map(Object.entries(parsed.values)) };
36
+ }
37
+ const recording = program.command("recording").description("inspect and edit recorded takes (promote, edit steps, diff, postdoc)");
38
+ recording
39
+ .command("promote <file>")
40
+ .requiredOption("--page <n>", "page index", nonNegativeIntArg)
41
+ .requiredOption("--step <n>", "step index within the page", nonNegativeIntArg)
42
+ .requiredOption("--var <name>", "variable name to bind")
43
+ .action(async function (file) {
44
+ const { page, step, var: varName } = this.opts();
45
+ try {
46
+ const raw = await readFile(file, "utf8");
47
+ const rec = RecordingSchema.parse(JSON.parse(raw));
48
+ const result = promoteToVariable(rec, { page: Number(page), step: Number(step) }, varName);
49
+ program.configureOutput().writeOut?.(`${JSON.stringify(result, null, 2)}\n`);
50
+ process.exitCode = 0;
51
+ }
52
+ catch (err) {
53
+ emitJson(program, fail("E_INVALID_RECORDING", String(err)));
54
+ }
55
+ });
56
+ recording
57
+ .command("diff <takeA> <takeB> [more...]")
58
+ .option("--json", "emit a JSON envelope")
59
+ .action(async function (takeA, takeB, more) {
60
+ const { json } = this.opts();
61
+ try {
62
+ const files = [takeA, takeB, ...more];
63
+ const takes = await Promise.all(files.map(readAuthoringTake));
64
+ const diffResult = diffTakes(takes);
65
+ const envelope = ok(diffResult);
66
+ if (json) {
67
+ emitJson(program, envelope);
68
+ }
69
+ else {
70
+ const out = program.configureOutput().writeOut;
71
+ diffResult.columns.forEach((col, i) => {
72
+ const type = col.inferredType ? `, type=${col.inferredType}` : "";
73
+ out?.(`column ${i}: ${col.kind} (confidence ${col.confidence.toFixed(2)}${type}) values=${JSON.stringify(col.values)}\n`);
74
+ });
75
+ process.exitCode = 0;
76
+ }
77
+ }
78
+ catch (err) {
79
+ emitJson(program, fail("E_INVALID_TAKE", String(err)));
80
+ }
81
+ });
82
+ recording
83
+ .command("fit <file>")
84
+ .option("--json", "emit a JSON envelope")
85
+ .action(async function (file) {
86
+ const { json } = this.opts();
87
+ try {
88
+ const raw = await readFile(file, "utf8");
89
+ const rec = RecordingSchema.parse(JSON.parse(raw));
90
+ const interaction = fitInteractionPolicy(rec);
91
+ const policy = { version: "1.0.0", interaction };
92
+ if (json) {
93
+ emitJson(program, ok(policy));
94
+ }
95
+ else {
96
+ program.configureOutput().writeOut?.(`${JSON.stringify(policy, null, 2)}\n`);
97
+ process.exitCode = 0;
98
+ }
99
+ }
100
+ catch (err) {
101
+ emitJson(program, fail("E_INVALID_RECORDING", String(err)));
102
+ }
103
+ });
104
+ recording
105
+ .command("postdoc <take> [more...]")
106
+ .option("--decisions <file>", "path to a PostdocDecision[] JSON file (non-interactive mode)")
107
+ .option("--out <file>", "write the resulting Recording to this file instead of stdout")
108
+ .option("--json", "emit a JSON envelope")
109
+ .action(async function (take, more) {
110
+ const { decisions: decisionsFile, out, json } = this.opts();
111
+ try {
112
+ const files = [take, ...more];
113
+ const takes = await Promise.all(files.map(readAuthoringTake));
114
+ const diff = diffTakes(takes);
115
+ let decisions;
116
+ if (decisionsFile !== undefined) {
117
+ decisions = await loadDecisions(decisionsFile);
118
+ }
119
+ else {
120
+ decisions = await promptForDecisions(takes[0]);
121
+ }
122
+ const result = applyPostdoc(takes[0], diff, decisions);
123
+ if (out !== undefined) {
124
+ await writeFile(out, `${JSON.stringify(result, null, 2)}\n`, "utf8");
125
+ }
126
+ if (json) {
127
+ emitJson(program, ok(result));
128
+ }
129
+ else if (out === undefined) {
130
+ program.configureOutput().writeOut?.(`${JSON.stringify(result, null, 2)}\n`);
131
+ process.exitCode = 0;
132
+ }
133
+ else {
134
+ process.exitCode = 0;
135
+ }
136
+ }
137
+ catch (err) {
138
+ if (err instanceof DecisionsParseError) {
139
+ emitJson(program, fail("E_INVALID_DECISIONS", String(err.cause)));
140
+ }
141
+ else {
142
+ emitJson(program, fail("E_INVALID_TAKE", String(err)));
143
+ }
144
+ }
145
+ });
146
+ }
147
+ /**
148
+ * Distinguishes a malformed `--decisions <file>` (E_INVALID_DECISIONS) from
149
+ * every other failure mode of the `postdoc` action (E_INVALID_TAKE) without
150
+ * making `loadDecisions` itself responsible for emitting the CLI envelope —
151
+ * matching this file's existing pattern of one try/catch per subcommand
152
+ * mapping to one error code.
153
+ */
154
+ class DecisionsParseError extends Error {
155
+ cause;
156
+ constructor(cause) {
157
+ super(String(cause));
158
+ this.cause = cause;
159
+ }
160
+ }
161
+ async function loadDecisions(file) {
162
+ let raw;
163
+ let parsed;
164
+ try {
165
+ raw = await readFile(file, "utf8");
166
+ parsed = JSON.parse(raw);
167
+ }
168
+ catch (err) {
169
+ throw new DecisionsParseError(err);
170
+ }
171
+ const result = PostdocDecisionsSchema.safeParse(parsed);
172
+ if (!result.success) {
173
+ throw new DecisionsParseError(result.error);
174
+ }
175
+ return result.data;
176
+ }
177
+ /**
178
+ * Thin `@clack/prompts` adapter: walks `authoring`'s fill/select steps in
179
+ * order and asks the human how to classify each one. ALL logic (variance
180
+ * guards, secret-materialization checks, the actual step rewrite) lives in
181
+ * `applyPostdoc`/`diffTakes` — this function only collects a
182
+ * `PostdocDecision[]` to hand them.
183
+ */
184
+ async function promptForDecisions(authoring) {
185
+ clack.intro("recording postdoc — review captured fill/select steps");
186
+ const decisions = [];
187
+ const fillSteps = flattenBaseFillSteps(authoring.recording);
188
+ for (const { ref } of fillSteps) {
189
+ const classify = await clack.select({
190
+ message: `Step ${ref.page}:${ref.step} — how should this value be classified?`,
191
+ options: [
192
+ { value: "constant", label: "constant", hint: "fix this value in the artifact" },
193
+ { value: "variable", label: "variable", hint: "prompt for a value at replay time" },
194
+ { value: "handback", label: "handback", hint: "hand control to a human at replay time" },
195
+ ],
196
+ });
197
+ if (clack.isCancel(classify)) {
198
+ clack.cancel("postdoc review cancelled");
199
+ process.exit(1);
200
+ }
201
+ const label = await promptOptionalText("Label for this step? (blank to skip)");
202
+ const chunk = await promptOptionalText("Chunk name for this step? (blank to skip)");
203
+ let decision;
204
+ if (classify === "constant") {
205
+ const acknowledgeVaried = await clack.confirm({
206
+ message: "Acknowledge this value varied across takes anyway?",
207
+ initialValue: false,
208
+ });
209
+ if (clack.isCancel(acknowledgeVaried)) {
210
+ clack.cancel("postdoc review cancelled");
211
+ process.exit(1);
212
+ }
213
+ decision = { step: ref, classify: "constant", ...(acknowledgeVaried ? { acknowledgeVaried: true } : {}) };
214
+ }
215
+ else if (classify === "variable") {
216
+ const name = await clack.text({ message: "Variable name?" });
217
+ if (clack.isCancel(name)) {
218
+ clack.cancel("postdoc review cancelled");
219
+ process.exit(1);
220
+ }
221
+ decision = { step: ref, classify: "variable", name };
222
+ }
223
+ else {
224
+ const prompt = await clack.text({ message: "Handback prompt for the human operator?" });
225
+ if (clack.isCancel(prompt)) {
226
+ clack.cancel("postdoc review cancelled");
227
+ process.exit(1);
228
+ }
229
+ decision = { step: ref, classify: "handback", prompt };
230
+ }
231
+ if (label !== undefined)
232
+ decision = { ...decision, label };
233
+ if (chunk !== undefined)
234
+ decision = { ...decision, chunk };
235
+ decisions.push(decision);
236
+ }
237
+ clack.outro("review complete");
238
+ return decisions;
239
+ }
240
+ async function promptOptionalText(message) {
241
+ const value = await clack.text({ message, defaultValue: "" });
242
+ if (clack.isCancel(value)) {
243
+ clack.cancel("postdoc review cancelled");
244
+ process.exit(1);
245
+ }
246
+ return value === "" ? undefined : value;
247
+ }
248
+ //# sourceMappingURL=recording-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recording-cli.js","sourceRoot":"","sources":["../src/recording-cli.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,53 @@
1
1
  import type { Actor } from "@jevitate/screenplay";
2
+ import { type ResolvedJourneyEnvironment } from "./environments.js";
3
+ import { type PersistedFinding } from "./verify-fix-api.js";
4
+ /** #213: `--id <id>` already names a committed regression — refused unless `--force`, checked
5
+ * BEFORE any reproduce/minimize attempt runs (never a browser-driven overwrite the caller didn't ask for). */
6
+ export declare class RegressionExistsError extends Error {
7
+ readonly code: "E_REGRESSION_EXISTS";
8
+ constructor(id: string, dir: string);
9
+ }
10
+ /**
11
+ * The clear, actionable refusal #81 requires: a Recording with no failure to
12
+ * reproduce is refused rather than "minimized" into a vacuous artifact that
13
+ * can only ever pass.
14
+ */
15
+ export declare class NoFailureToReproduceError extends Error {
16
+ readonly code: "E_REGRESSION_NO_FAILURE";
17
+ constructor(message?: string);
18
+ }
19
+ /** `--result` was given but carries no usable oracle at all: no failed `--success` check (of ANY
20
+ * kind — page/reloadThen/requestMade/responseStatus), no matching declared-invariant defect, and no
21
+ * APP-caused failed-action step (jevitate's own engine refusals — #92's repeated-side-effect guard,
22
+ * a budget/fail-closed cutoff, … — are never a valid oracle; #119/#129). */
23
+ export declare class NoOracleInResultError extends Error {
24
+ readonly code: "E_REGRESSION_NO_ORACLE";
25
+ constructor(resultPath: string, detail: string);
26
+ }
27
+ /**
28
+ * #213: `--fingerprint` names one of the mission's OWN findings, but a hard-signal one (http-5xx,
29
+ * hang, server-log, adversarial-misuse, … — everything but `invariant`, which `captureInvariantRegression`
30
+ * already handles). Its oracle is the signal itself, never a page/success-check assertion —
31
+ * `deriveOracle` (transcript/checks only) can never express it, so falling through to it just
32
+ * produces a generic "no usable oracle" that reads as the `--result` file being unusable, when the
33
+ * real answer is: this isn't the tool for it. Points at the route that IS: `ledger add` (repro
34
+ * material for `ledger verify` / `verify-fix`).
35
+ */
36
+ export declare class RegressionHardSignalOracleError extends Error {
37
+ readonly code: "E_REGRESSION_HARD_SIGNAL";
38
+ constructor(resultPath: string, finding: PersistedFinding);
39
+ }
40
+ /** An explicit `--fingerprint` disagrees with the oracle derived from `--result`. */
41
+ export declare class FingerprintMismatchError extends Error {
42
+ readonly code: "E_REGRESSION_FINGERPRINT_MISMATCH";
43
+ constructor(given: string, derived: string);
44
+ }
45
+ /** An invariant defect matched by `--fingerprint`, but `verify-fix`'s own replay says it does not
46
+ * currently reproduce (fixed, or inconclusive) — never fabricated into a regression. */
47
+ export declare class InvariantNotReproducingError extends Error {
48
+ readonly code: "E_REGRESSION_INVARIANT_NOT_REPRODUCING";
49
+ constructor(invariantId: string, verdict: string, reason: string);
50
+ }
2
51
  export interface RunRegressionCaptureOptions {
3
52
  failingRecordingPath: string;
4
53
  id: string;
@@ -6,6 +55,25 @@ export interface RunRegressionCaptureOptions {
6
55
  attempts?: number;
7
56
  bugSummary?: string;
8
57
  makeActor: () => Promise<Actor>;
58
+ /**
59
+ * Path to a mission result JSON (what `jevitate explore` writes alongside its Recording as
60
+ * `<recording>.result.json`) — supplies a failure oracle (#81 item 2) when the Recording alone
61
+ * carries no reproducible failure, because the failing action itself was never captured as a
62
+ * step (see `@jevitate/explore`'s `RunRecorder`: only successful actions are recorded).
63
+ */
64
+ resultPath?: string;
65
+ /**
66
+ * An explicit failure fingerprint. Accepts EITHER a `stepSignature` (see `@jevitate/regression`'s
67
+ * `fingerprintFailure`) alone pinning which structural step in `--from` counts as "the" failure,
68
+ * OR — combined with `--result` (#119/#129) — the SAME defect/invariant fingerprint every other
69
+ * command (`verify-fix`, the mission report) uses: when it matches one of the mission's OWN
70
+ * declared-invariant defects, that invariant is re-checked (via `verify-fix`'s own machinery)
71
+ * rather than turned into a Recording step. Combined with a page-checkable `--result` oracle, it
72
+ * cross-checks the derived oracle.
73
+ */
74
+ fingerprint?: string;
75
+ /** #213: overwrite an existing `<id>.recording.json`/`.meta.json` — default: refused (fail closed). */
76
+ force?: boolean;
9
77
  }
10
78
  export type RunRegressionCaptureResult = {
11
79
  recordingPath: string;
@@ -15,3 +83,36 @@ export type RunRegressionCaptureResult = {
15
83
  rate: number;
16
84
  };
17
85
  export declare function runRegressionCapture(opts: RunRegressionCaptureOptions): Promise<RunRegressionCaptureResult>;
86
+ /** No committed `<id>.recording.json`/`<id>.meta.json` in the regressions directory. */
87
+ export declare class RegressionNotFoundError extends Error {
88
+ readonly code: "E_REGRESSION_NOT_FOUND";
89
+ constructor(id: string, dir: string);
90
+ }
91
+ export interface RunRegressionRunOptions {
92
+ readonly id: string;
93
+ readonly regressionsDir: string;
94
+ readonly makeActor: () => Promise<Actor>;
95
+ /** Fresh-context replays for a declared-invariant oracle (mirrors `verify-fix --replays`). Default 3. */
96
+ readonly attempts?: number;
97
+ /**
98
+ * #247 (`--env`/`--base-url`): replay against this environment — the committed Recording's
99
+ * same-origin URLs (and an invariant oracle's baseUrl/allowlist) move onto it; a step on an origin
100
+ * it does not allow is refused before any browser opens. Absent: the recorded site, as before.
101
+ */
102
+ readonly environment?: ResolvedJourneyEnvironment;
103
+ }
104
+ export type RegressionRunVerdict = "reproduces" | "fixed" | "inconclusive" | "intermittent";
105
+ export interface RegressionRunReport {
106
+ readonly id: string;
107
+ readonly verdict: RegressionRunVerdict;
108
+ readonly reason: string;
109
+ }
110
+ /**
111
+ * `regression run <id>` (#129 item 4): replays a committed regression and reports whether it still
112
+ * REPRODUCES or is now FIXED. Dispatches on `meta.oracle` — absent (the default/original) means the
113
+ * committed Recording's own trailing `assert` step IS the oracle, replayed by `@jevitate/regression`'s
114
+ * `replayRegression` (its `expect` failing/holding is the verdict, no different from any other
115
+ * `RecordingInterpreter` run); a `network`/`invariant` oracle is re-evaluated the SAME way capture
116
+ * established it (`replayAndCheckNetwork` / `verifyFix`'s invariant re-check) — never duplicated.
117
+ */
118
+ export declare function runRegressionRun(opts: RunRegressionRunOptions): Promise<RegressionRunReport>;