@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,22 @@
1
+ import type { ServerLogDefect } from "./log-correlation.js";
2
+ /**
3
+ * The versioned result schema every explore strategy's result follows (#195 part 5) — defined in
4
+ * `@jevitate/domain` (zod + TS) and re-exported here as part of the CLI's published surface. See
5
+ * `mission-result.ts` there for the contract; this module holds the helpers the runners fill the
6
+ * common fields with, so every strategy fills them the same way.
7
+ */
8
+ export { MISSION_RESULT_SCHEMA_VERSION, MissionResultSchema, PersistedMissionResultSchema, RESULT_STRATEGIES, RESULT_MISSION_OUTCOMES, ResultDefectSchema, type MissionResult, type MissionResultCore, type PersistedMissionResult, type ResultDefect, type ResultMissionOutcome, type ResultStrategy, } from "@jevitate/domain";
9
+ /** A `server-log` defect a strategy reports but never gates on (usability: every UX finding is advisory). */
10
+ export type AdvisoryServerLogDefect = ServerLogDefect & {
11
+ readonly advisory: true;
12
+ };
13
+ /**
14
+ * All of a run's defects in ONE list (#195): the strategy's own (hard-signal / declared-invariant)
15
+ * defects first, then its `server-log` defects — each fingerprint once. What `defects` holds on every
16
+ * strategy's result; `serverLogDefects` remains only as a deprecated alias of the server-log subset.
17
+ */
18
+ export declare function unifiedDefects<D extends {
19
+ readonly fingerprint: string;
20
+ }>(own: readonly D[] | undefined, serverLog: readonly ServerLogDefect[] | undefined): Array<D | ServerLogDefect>;
21
+ /** A usability run's `server-log` defects, marked advisory: reported in `defects`, never gating its outcome. */
22
+ export declare function advisoryDefects(serverLog: readonly ServerLogDefect[] | undefined): AdvisoryServerLogDefect[];
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The versioned result schema every explore strategy's result follows (#195 part 5) — defined in
3
+ * `@jevitate/domain` (zod + TS) and re-exported here as part of the CLI's published surface. See
4
+ * `mission-result.ts` there for the contract; this module holds the helpers the runners fill the
5
+ * common fields with, so every strategy fills them the same way.
6
+ */
7
+ export { MISSION_RESULT_SCHEMA_VERSION, MissionResultSchema, PersistedMissionResultSchema, RESULT_STRATEGIES, RESULT_MISSION_OUTCOMES, ResultDefectSchema, } from "@jevitate/domain";
8
+ /**
9
+ * All of a run's defects in ONE list (#195): the strategy's own (hard-signal / declared-invariant)
10
+ * defects first, then its `server-log` defects — each fingerprint once. What `defects` holds on every
11
+ * strategy's result; `serverLogDefects` remains only as a deprecated alias of the server-log subset.
12
+ */
13
+ export function unifiedDefects(own, serverLog) {
14
+ const seen = new Set();
15
+ const out = [];
16
+ for (const d of [...(own ?? []), ...(serverLog ?? [])]) {
17
+ if (seen.has(d.fingerprint))
18
+ continue;
19
+ seen.add(d.fingerprint);
20
+ out.push(d);
21
+ }
22
+ return out;
23
+ }
24
+ /** A usability run's `server-log` defects, marked advisory: reported in `defects`, never gating its outcome. */
25
+ export function advisoryDefects(serverLog) {
26
+ return unifiedDefects([], serverLog).map((d) => ({ ...d, advisory: true }));
27
+ }
28
+ //# sourceMappingURL=result-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-schema.js","sourceRoot":"","sources":["../src/result-schema.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,OAAO,EACL,6BAA6B,EAC7B,mBAAmB,EACnB,4BAA4B,EAC5B,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,GAOnB,MAAM,kBAAkB,CAAC;AAK1B;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,GAA6B,EAC7B,SAAiD;IAEjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAA+B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC;YAAE,SAAS;QACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACxB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,eAAe,CAAC,SAAiD;IAC/E,OAAO,cAAc,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC;AACvF,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { type LayoutDeps } from "./project-dir.js";
2
+ /**
3
+ * #213: which runs belong to THIS project — so a bare `jevitate report`/`diff` reads the current
4
+ * project's runs, never every app's `~/.jevitate/logs` (a fresh project merged 167 unrelated runs),
5
+ * and still finds the runs written to an `--out` dir.
6
+ *
7
+ * Mechanism: every persisted result is recorded, best-effort, as one line
8
+ * `{"project": <key>, "path": <absolute result path>}` in the per-user index `~/.jevitate/run-index.jsonl`
9
+ * (machine-local, like the logs themselves; never in a repo). The project key is the directory that
10
+ * holds the project's `.jevitate/`, else the git root of the working directory, else the working
11
+ * directory itself. A bare report reads: the project's own `.jevitate/logs` (only this project writes
12
+ * there) plus every indexed result of this project that still exists — wherever it was written.
13
+ *
14
+ * `JEVITATE_RUN_INDEX=off` turns recording off (the test suite does, so it never touches the real index).
15
+ */
16
+ export interface RunIndexDeps extends LayoutDeps {
17
+ readonly env?: NodeJS.ProcessEnv;
18
+ /** Test seam: the index file (default `~/.jevitate/run-index.jsonl`). */
19
+ readonly indexPath?: string;
20
+ }
21
+ export declare function runIndexPath(deps?: RunIndexDeps): string;
22
+ /** The current project's key: the dir holding its `.jevitate/`, else the git root, else the cwd. */
23
+ export declare function projectKey(deps?: LayoutDeps): string;
24
+ /** Records one persisted result for the current project. Never throws: an index is a convenience. */
25
+ export declare function recordRun(resultPath: string, deps?: RunIndexDeps): void;
26
+ /** Every indexed result of the current project that still exists, oldest first, each once. */
27
+ export declare function indexedRunsFor(deps?: RunIndexDeps): string[];
28
+ /** The current project's own dated logs dirs (`<repo>/.jevitate/logs/<date>`) — none outside a project. */
29
+ export declare function projectLogDirs(deps?: LayoutDeps): string[];
@@ -0,0 +1,70 @@
1
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { findGitRoot, findProjectDir, homeDataRoot } from "./project-dir.js";
4
+ export function runIndexPath(deps = {}) {
5
+ return deps.indexPath ?? join(homeDataRoot(deps), "run-index.jsonl");
6
+ }
7
+ /** The current project's key: the dir holding its `.jevitate/`, else the git root, else the cwd. */
8
+ export function projectKey(deps = {}) {
9
+ const project = findProjectDir(deps);
10
+ if (project !== null)
11
+ return dirname(project);
12
+ const cwd = resolve((deps.cwd ?? (() => process.cwd()))());
13
+ return findGitRoot(cwd) ?? cwd;
14
+ }
15
+ /** Records one persisted result for the current project. Never throws: an index is a convenience. */
16
+ export function recordRun(resultPath, deps = {}) {
17
+ if ((deps.env ?? process.env)["JEVITATE_RUN_INDEX"] === "off")
18
+ return;
19
+ try {
20
+ const path = runIndexPath(deps);
21
+ mkdirSync(dirname(path), { recursive: true });
22
+ appendFileSync(path, `${JSON.stringify({ project: projectKey(deps), path: resolve(resultPath) })}\n`, { encoding: "utf8", mode: 0o600 });
23
+ }
24
+ catch {
25
+ // best-effort: a run's result is never replaced by an index failure
26
+ }
27
+ }
28
+ /** Every indexed result of the current project that still exists, oldest first, each once. */
29
+ export function indexedRunsFor(deps = {}) {
30
+ const path = runIndexPath(deps);
31
+ if (!existsSync(path))
32
+ return [];
33
+ const key = projectKey(deps);
34
+ const out = new Set();
35
+ let text;
36
+ try {
37
+ text = readFileSync(path, "utf8");
38
+ }
39
+ catch {
40
+ return [];
41
+ }
42
+ for (const line of text.split("\n")) {
43
+ if (line.trim() === "")
44
+ continue;
45
+ try {
46
+ const e = JSON.parse(line);
47
+ if (e.project === key && typeof e.path === "string" && existsSync(e.path))
48
+ out.add(e.path);
49
+ }
50
+ catch {
51
+ continue; // a torn line names nothing
52
+ }
53
+ }
54
+ return [...out];
55
+ }
56
+ /** The current project's own dated logs dirs (`<repo>/.jevitate/logs/<date>`) — none outside a project. */
57
+ export function projectLogDirs(deps = {}) {
58
+ const project = findProjectDir(deps);
59
+ if (project === null)
60
+ return [];
61
+ const root = join(project, "logs");
62
+ if (!existsSync(root))
63
+ return [];
64
+ return readdirSync(root)
65
+ .filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d))
66
+ .sort()
67
+ .reverse()
68
+ .map((d) => join(root, d));
69
+ }
70
+ //# sourceMappingURL=run-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-index.js","sourceRoot":"","sources":["../src/run-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import type { Page } from "playwright";
2
+ import { type TranscriptEntry } from "@jevitate/explore";
3
+ import type { StepObserver } from "@jevitate/interpreter";
4
+ import type { BrowserPort } from "@jevitate/playwright";
5
+ import { SecretPixelMask } from "./demo-capture.js";
6
+ /**
7
+ * #251 — `--screenshots [dir]` / `--screenshots steps`: a screenshot capture mode for any run
8
+ * (explore strategies, `journey run`/`annotate`/`demo`, `verify-fix`).
9
+ *
10
+ * - `screens` (the default): one screenshot per DISTINCT screen — deduplicated by the page-state
11
+ * fingerprint coverage already uses (`coverageStateFingerprint`: the url template plus the
12
+ * control table), so a new screen is a new state;
13
+ * - `steps`: one per step.
14
+ *
15
+ * Every image is the viewport after the step acted, with the demo overlay hidden and every
16
+ * registered secret masked in pixels ({@link SecretPixelMask}); a capture whose mask cannot be
17
+ * proven is SKIPPED and its reason recorded (fail closed). An `index.md` contact sheet lists each
18
+ * image with its step, route and what happened (all text redacted, proven secret-free before it is
19
+ * written). The paths go in the result as `screenshotPaths` (+ `screenshotIndex`, and
20
+ * `screenshotsSkipped` when a capture was refused).
21
+ */
22
+ export type ScreenshotMode = "screens" | "steps";
23
+ export interface ScreenshotsSpec {
24
+ readonly mode: ScreenshotMode;
25
+ /** Where the images go; absent ⇒ `<run artifact stem>.screenshots/` beside the run's output. */
26
+ readonly dir?: string;
27
+ }
28
+ /** An unusable `--screenshots` value: refused before anything runs (exit 64). */
29
+ export declare class ScreenshotsArgError extends Error {
30
+ readonly code: "E_SCREENSHOTS_ARGS";
31
+ constructor(message: string);
32
+ }
33
+ /**
34
+ * `--screenshots` → the spec: bare / `screens` → one per distinct screen; `steps` → one per step;
35
+ * `screens:<dir>` / `steps:<dir>` → that mode into `<dir>`; any other value is the directory
36
+ * (screens mode). An empty value is refused.
37
+ */
38
+ export declare function parseScreenshotsArg(v: string | boolean | undefined, where?: string): ScreenshotsSpec | undefined;
39
+ /** The run's screenshot folder: `spec.dir`, else `<dir of artifact>/<artifact stem>.screenshots`. */
40
+ export declare function screenshotsDirFor(spec: ScreenshotsSpec, artifactPath: string): string;
41
+ export interface ScreenshotEntry {
42
+ /** 1-based image number. */
43
+ readonly n: number;
44
+ /** The step it shows (after that step acted). */
45
+ readonly step: number;
46
+ /** The route (path) it was taken on, redacted. */
47
+ readonly route: string;
48
+ /** What the step did (redacted). */
49
+ readonly what: string;
50
+ readonly path: string;
51
+ }
52
+ export interface ScreenshotSkip {
53
+ readonly step: number;
54
+ readonly reason: string;
55
+ }
56
+ /** The additive result fields (schemaVersion 1). */
57
+ export interface ScreenshotsResult {
58
+ readonly screenshotPaths: string[];
59
+ readonly screenshotIndex: string;
60
+ readonly screenshotsSkipped?: ScreenshotSkip[];
61
+ }
62
+ export interface RunScreenshotsOptions {
63
+ readonly spec: ScreenshotsSpec;
64
+ /** The resolved folder (see {@link screenshotsDirFor}). */
65
+ readonly dir: string;
66
+ /** Every registered secret: masked in pixels, redacted in the index. */
67
+ readonly secrets: readonly string[];
68
+ /** The contact sheet's heading (redacted). */
69
+ readonly title: string;
70
+ /** A shared mask (e.g. the one a masking port installed); default: a new one over `secrets`. */
71
+ readonly mask?: SecretPixelMask;
72
+ }
73
+ /** A transcript step as one "what happened" line. */
74
+ export declare function describeTranscriptEntry(e: TranscriptEntry): string;
75
+ export declare class RunScreenshots {
76
+ #private;
77
+ readonly mask: SecretPixelMask;
78
+ constructor(opts: RunScreenshotsOptions);
79
+ get mode(): ScreenshotMode;
80
+ /** Captures the page after `step` (queued: captures never overlap). Never throws. */
81
+ capture(page: Page, at: {
82
+ readonly step: number;
83
+ readonly url?: string;
84
+ readonly what: string;
85
+ }): Promise<void>;
86
+ /** TranscriptLog listener hook (explore runners): captures the page after the step just recorded. */
87
+ noteEntry(page: Page, entry: TranscriptEntry): void;
88
+ /** Every capture done; writes `index.md`; the result fields. */
89
+ finish(): Promise<ScreenshotsResult>;
90
+ /** The Markdown contact sheet (images linked relative to the index). */
91
+ contactSheet(): string;
92
+ }
93
+ /** A per-step observer for an interpreter-driven replay (journey run/annotate/demo, verify-fix). */
94
+ export declare function screenshotObserver(shots: RunScreenshots, pageOf: (actor: Parameters<NonNullable<StepObserver["afterStep"]>>[0]["actor"]) => Page, whatOf: (index: number) => string): StepObserver;
95
+ /** Runs every observer's hooks in order (an observer never changes the replay). */
96
+ export declare function composeObservers(...observers: ReadonlyArray<StepObserver | undefined>): StepObserver;
97
+ /** The human summary line for a run's screenshots (#251). */
98
+ export declare function formatScreenshotsLine(r: {
99
+ readonly screenshotPaths?: readonly string[];
100
+ readonly screenshotIndex?: string;
101
+ readonly screenshotsSkipped?: readonly ScreenshotSkip[];
102
+ }): string;
103
+ /** One run's capture wiring (#250/#251): the masked port and the (optional) screenshots. */
104
+ export interface RunCapture {
105
+ readonly mask: SecretPixelMask;
106
+ /** `factory` whose sessions carry the live pixel mask when the run records video or screenshots. */
107
+ wrap(factory: () => BrowserPort): () => BrowserPort;
108
+ /** TranscriptLog hook: a screenshot of `page` after the step (no-op without `--screenshots`). */
109
+ noteEntry(page: Page, entry: TranscriptEntry): void;
110
+ /** Awaits every capture, writes the index; the result fields (`{}` without `--screenshots`). */
111
+ finish(): Promise<Partial<ScreenshotsResult>>;
112
+ }
113
+ /**
114
+ * The capture wiring an explore runner threads through its session and listener. `artifactPath` is
115
+ * read on first use (the run's Recording path: screenshots go in `<stem>.screenshots/` beside it).
116
+ */
117
+ export declare function runCaptureFor(o: {
118
+ readonly recordsVideo: boolean;
119
+ readonly screenshots: ScreenshotsSpec | undefined;
120
+ readonly secrets: readonly string[];
121
+ readonly artifactPath: () => string;
122
+ readonly title: string;
123
+ }): RunCapture;
@@ -0,0 +1,229 @@
1
+ import { mkdir, readdir, rm, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join, resolve as resolvePath } from "node:path";
3
+ import { assertNoSecretInPayload, redactText, redactUrl } from "@jevitate/ai-core";
4
+ import { coverageStateFingerprint, snapshot } from "@jevitate/explore";
5
+ import { captureStepScreenshot, maskingPort, SecretPixelMask } from "./demo-capture.js";
6
+ /** An unusable `--screenshots` value: refused before anything runs (exit 64). */
7
+ export class ScreenshotsArgError extends Error {
8
+ code = "E_SCREENSHOTS_ARGS";
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "ScreenshotsArgError";
12
+ }
13
+ }
14
+ /**
15
+ * `--screenshots` → the spec: bare / `screens` → one per distinct screen; `steps` → one per step;
16
+ * `screens:<dir>` / `steps:<dir>` → that mode into `<dir>`; any other value is the directory
17
+ * (screens mode). An empty value is refused.
18
+ */
19
+ export function parseScreenshotsArg(v, where = "--screenshots") {
20
+ if (v === undefined || v === false)
21
+ return undefined;
22
+ if (v === true)
23
+ return { mode: "screens" };
24
+ const t = v.trim();
25
+ if (t === "")
26
+ throw new ScreenshotsArgError(`${where} needs a mode or a directory: screens, steps, screens:<dir>, steps:<dir> or <dir>`);
27
+ if (t === "screens" || t === "steps")
28
+ return { mode: t };
29
+ const m = /^(screens|steps):(.*)$/.exec(t);
30
+ if (m !== null) {
31
+ const dir = (m[2] ?? "").trim();
32
+ if (dir === "")
33
+ throw new ScreenshotsArgError(`${where} ${m[1]}: needs a directory after the colon`);
34
+ return { mode: m[1], dir: resolvePath(dir) };
35
+ }
36
+ return { mode: "screens", dir: resolvePath(t) };
37
+ }
38
+ /** The run's screenshot folder: `spec.dir`, else `<dir of artifact>/<artifact stem>.screenshots`. */
39
+ export function screenshotsDirFor(spec, artifactPath) {
40
+ if (spec.dir !== undefined)
41
+ return spec.dir;
42
+ const stem = basename(artifactPath).replace(/\.result\.json$/, "").replace(/\.json$/, "");
43
+ return join(dirname(artifactPath), `${stem}.screenshots`);
44
+ }
45
+ const FINGERPRINT_MS = 10_000;
46
+ function oneLine(s) {
47
+ return s.replace(/\s+/g, " ").trim();
48
+ }
49
+ function routeOf(url) {
50
+ try {
51
+ const u = new URL(url);
52
+ return u.pathname + (u.search === "" ? "" : u.search);
53
+ }
54
+ catch {
55
+ return url;
56
+ }
57
+ }
58
+ /** A transcript step as one "what happened" line. */
59
+ export function describeTranscriptEntry(e) {
60
+ const act = e.op === null ? "no action" : `${e.op}${e.target === null ? "" : ` ${e.target}`}`;
61
+ return e.actOk ? act : `${act} — failed${e.reason === undefined ? "" : `: ${e.reason}`}`;
62
+ }
63
+ export class RunScreenshots {
64
+ mask;
65
+ #opts;
66
+ #entries = [];
67
+ #skipped = [];
68
+ #seen = new Set();
69
+ #queue = Promise.resolve();
70
+ #prepared;
71
+ #maxStep = 0;
72
+ constructor(opts) {
73
+ this.#opts = opts;
74
+ this.mask = opts.mask ?? new SecretPixelMask(opts.secrets);
75
+ }
76
+ get mode() {
77
+ return this.#opts.spec.mode;
78
+ }
79
+ #redact(s) {
80
+ return redactText(s, this.#opts.secrets);
81
+ }
82
+ /** Creates the folder once and clears a previous run's images (never another file). */
83
+ #prepare() {
84
+ this.#prepared ??= (async () => {
85
+ await mkdir(this.#opts.dir, { recursive: true });
86
+ for (const f of await readdir(this.#opts.dir))
87
+ if (/^\d+-step-\d+\.png$/.test(f))
88
+ await rm(join(this.#opts.dir, f), { force: true });
89
+ })();
90
+ return this.#prepared;
91
+ }
92
+ /** Captures the page after `step` (queued: captures never overlap). Never throws. */
93
+ capture(page, at) {
94
+ const run = async () => {
95
+ this.#maxStep = Math.max(this.#maxStep, at.step);
96
+ try {
97
+ if (page.isClosed())
98
+ throw new Error("the page is closed");
99
+ await this.#prepare();
100
+ if (this.#opts.spec.mode === "screens") {
101
+ const fp = await Promise.race([
102
+ snapshot(page).then((s) => coverageStateFingerprint(s)),
103
+ new Promise((r) => setTimeout(() => r(null), FINGERPRINT_MS)),
104
+ ]).catch(() => null);
105
+ // An unreadable state cannot be proven a repeat: it is captured (never silently dropped).
106
+ if (fp !== null && this.#seen.has(fp))
107
+ return;
108
+ await this.#shoot(page, at);
109
+ if (fp !== null && this.#entries.some((e) => e.step === at.step))
110
+ this.#seen.add(fp);
111
+ return;
112
+ }
113
+ await this.#shoot(page, at);
114
+ }
115
+ catch (err) {
116
+ this.#skipped.push({ step: at.step, reason: this.#redact(oneLine(err instanceof Error ? err.message : String(err))).slice(0, 300) });
117
+ }
118
+ };
119
+ const next = this.#queue.then(run, run);
120
+ this.#queue = next;
121
+ return next;
122
+ }
123
+ async #shoot(page, at) {
124
+ const n = this.#entries.length + 1;
125
+ const path = join(this.#opts.dir, `${String(n).padStart(2, "0")}-step-${String(at.step).padStart(2, "0")}.png`);
126
+ await captureStepScreenshot(page, path, { step: at.step }, [this.mask.layer()]);
127
+ const url = at.url ?? page.url();
128
+ this.#entries.push({
129
+ n,
130
+ step: at.step,
131
+ route: this.#redact(redactUrl(routeOf(url))),
132
+ what: this.#redact(oneLine(at.what)).slice(0, 300),
133
+ path,
134
+ });
135
+ }
136
+ /** TranscriptLog listener hook (explore runners): captures the page after the step just recorded. */
137
+ noteEntry(page, entry) {
138
+ void this.capture(page, { step: entry.step, what: describeTranscriptEntry(entry) });
139
+ }
140
+ /** Every capture done; writes `index.md`; the result fields. */
141
+ async finish() {
142
+ await this.#queue;
143
+ await this.#prepare();
144
+ const index = join(this.#opts.dir, "index.md");
145
+ const md = this.contactSheet();
146
+ assertNoSecretInPayload(md, this.#opts.secrets, "screenshot index"); // the last line: never at rest
147
+ await writeFile(index, md, "utf8");
148
+ return {
149
+ screenshotPaths: this.#entries.map((e) => e.path),
150
+ screenshotIndex: index,
151
+ ...(this.#skipped.length === 0 ? {} : { screenshotsSkipped: [...this.#skipped] }),
152
+ };
153
+ }
154
+ /** The Markdown contact sheet (images linked relative to the index). */
155
+ contactSheet() {
156
+ const mode = this.#opts.spec.mode === "screens" ? "one per distinct screen" : "one per step";
157
+ const lines = [
158
+ `# Screenshots: ${oneLine(this.#redact(this.#opts.title))}`,
159
+ "",
160
+ `Mode: ${mode} · ${this.#entries.length} screenshot(s) over ${this.#maxStep} step(s). The demo overlay is hidden and registered secrets are masked in every image.`,
161
+ "",
162
+ ];
163
+ for (const e of this.#entries) {
164
+ const file = basename(e.path);
165
+ lines.push(`## ${e.n}. Step ${e.step} · \`${e.route.replace(/`/g, "'")}\``, "", `**What happened:** ${e.what}`, "", `![Step ${e.step}: ${e.route.replace(/[[\]]/g, "")}](${encodeURI(file)})`, "");
166
+ }
167
+ if (this.#skipped.length > 0) {
168
+ lines.push("## Not captured", "", ...this.#skipped.map((s) => `- step ${s.step}: ${s.reason}`), "");
169
+ }
170
+ return `${lines.join("\n").trimEnd()}\n`;
171
+ }
172
+ }
173
+ /** A per-step observer for an interpreter-driven replay (journey run/annotate/demo, verify-fix). */
174
+ export function screenshotObserver(shots, pageOf, whatOf) {
175
+ return {
176
+ afterStep: async ({ actor, index, outcome }) => {
177
+ const what = `${whatOf(index)}${outcome === "done" ? "" : outcome === "failed" ? " — failed" : " — waiting for a human"}`;
178
+ await shots.capture(pageOf(actor), { step: index + 1, what });
179
+ },
180
+ };
181
+ }
182
+ /** Runs every observer's hooks in order (an observer never changes the replay). */
183
+ export function composeObservers(...observers) {
184
+ const list = observers.filter((o) => o !== undefined);
185
+ const each = async (fn) => {
186
+ for (const o of list) {
187
+ try {
188
+ await fn(o);
189
+ }
190
+ catch {
191
+ // One observer's failure never skips the next (nor changes the replay).
192
+ }
193
+ }
194
+ };
195
+ return {
196
+ beforeStep: (ctx) => each((o) => o.beforeStep?.(ctx)),
197
+ afterStep: (ctx) => each((o) => o.afterStep?.(ctx)),
198
+ };
199
+ }
200
+ /** The human summary line for a run's screenshots (#251). */
201
+ export function formatScreenshotsLine(r) {
202
+ if (r.screenshotIndex === undefined)
203
+ return "";
204
+ const skipped = r.screenshotsSkipped ?? [];
205
+ return (`screenshots: ${(r.screenshotPaths ?? []).length} — index ${r.screenshotIndex}` +
206
+ `${skipped.length === 0 ? "" : ` (${skipped.length} not captured: ${skipped.map((s) => `step ${s.step}: ${s.reason}`).join("; ")})`}\n`);
207
+ }
208
+ /**
209
+ * The capture wiring an explore runner threads through its session and listener. `artifactPath` is
210
+ * read on first use (the run's Recording path: screenshots go in `<stem>.screenshots/` beside it).
211
+ */
212
+ export function runCaptureFor(o) {
213
+ const mask = new SecretPixelMask(o.secrets);
214
+ const capturing = o.recordsVideo || o.screenshots !== undefined;
215
+ let shots;
216
+ const shotsOf = () => {
217
+ if (o.screenshots === undefined)
218
+ return undefined;
219
+ shots ??= new RunScreenshots({ spec: o.screenshots, dir: screenshotsDirFor(o.screenshots, o.artifactPath()), secrets: o.secrets, title: o.title, mask });
220
+ return shots;
221
+ };
222
+ return {
223
+ mask,
224
+ wrap: (factory) => (capturing ? () => maskingPort(factory(), mask) : factory),
225
+ noteEntry: (page, entry) => shotsOf()?.noteEntry(page, entry),
226
+ finish: async () => (await shotsOf()?.finish()) ?? {},
227
+ };
228
+ }
229
+ //# sourceMappingURL=run-screenshots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-screenshots.js","sourceRoot":"","sources":["../src/run-screenshots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Numeric `JEVITATE_*` tuning variables are validated ONCE, when the CLI starts, so a typo is a
3
+ * usage error (exit 64) before any browser opens — never a crash mid-run on the first click, and
4
+ * never a silent fall back to the default.
5
+ *
6
+ * Returns the problems found (empty when every set variable is valid).
7
+ */
8
+ export declare function runtimeEnvProblems(env?: NodeJS.ProcessEnv): string[];
@@ -0,0 +1,22 @@
1
+ import { clickTimeoutMs } from "@jevitate/explore";
2
+ import { pageUnresponsiveMsFromEnv } from "@jevitate/playwright";
3
+ /**
4
+ * Numeric `JEVITATE_*` tuning variables are validated ONCE, when the CLI starts, so a typo is a
5
+ * usage error (exit 64) before any browser opens — never a crash mid-run on the first click, and
6
+ * never a silent fall back to the default.
7
+ *
8
+ * Returns the problems found (empty when every set variable is valid).
9
+ */
10
+ export function runtimeEnvProblems(env = process.env) {
11
+ const problems = [];
12
+ for (const check of [pageUnresponsiveMsFromEnv, clickTimeoutMs]) {
13
+ try {
14
+ check(env);
15
+ }
16
+ catch (err) {
17
+ problems.push(err instanceof Error ? err.message : String(err));
18
+ }
19
+ }
20
+ return problems;
21
+ }
22
+ //# sourceMappingURL=runtime-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-env.js","sourceRoot":"","sources":["../src/runtime-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,CAAC,yBAAyB,EAAE,cAAc,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC;YACH,KAAK,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `--secret` values (#195 part 4): a literal, or `env:VAR` — read from the environment so the value
3
+ * never sits in the process list or shell history (the same `env:` binding `--secret-field` uses).
4
+ * Resolved HERE, at the CLI dispatch, before any browser opens; the resolved value is registered as a
5
+ * run secret exactly like a literal one (redacted from every model call, transcript and artifact).
6
+ *
7
+ * Fail closed: an unset/empty variable or a malformed ref is a refusal — never an empty secret, and
8
+ * never the literal text `env:VAR` standing in for the value. An error names the variable, never a
9
+ * value (a malformed ref is not echoed: it may be a value pasted in place of the variable name).
10
+ */
11
+ export declare class SecretArgError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ /** The warning a literal `--secret` earns (it still works): the value is visible to other processes. */
15
+ export declare const LITERAL_SECRET_WARNING = "warning: a literal --secret is visible in the process list and shell history; pass --secret env:VAR to read it from the environment\n";
16
+ /**
17
+ * Resolves each `--secret` value: `env:VAR` → `env[VAR]`, anything else → itself. `literals` counts
18
+ * the values given literally (for the caller's warning). Throws `SecretArgError`.
19
+ */
20
+ export declare function resolveSecretArgs(values: readonly string[], env: Readonly<Record<string, string | undefined>>, flag: string): {
21
+ secrets: string[];
22
+ literals: number;
23
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `--secret` values (#195 part 4): a literal, or `env:VAR` — read from the environment so the value
3
+ * never sits in the process list or shell history (the same `env:` binding `--secret-field` uses).
4
+ * Resolved HERE, at the CLI dispatch, before any browser opens; the resolved value is registered as a
5
+ * run secret exactly like a literal one (redacted from every model call, transcript and artifact).
6
+ *
7
+ * Fail closed: an unset/empty variable or a malformed ref is a refusal — never an empty secret, and
8
+ * never the literal text `env:VAR` standing in for the value. An error names the variable, never a
9
+ * value (a malformed ref is not echoed: it may be a value pasted in place of the variable name).
10
+ */
11
+ export class SecretArgError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "SecretArgError";
15
+ }
16
+ }
17
+ const ENV_REF = "env:";
18
+ const VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
19
+ /** The warning a literal `--secret` earns (it still works): the value is visible to other processes. */
20
+ export const LITERAL_SECRET_WARNING = "warning: a literal --secret is visible in the process list and shell history; pass --secret env:VAR to read it from the environment\n";
21
+ /**
22
+ * Resolves each `--secret` value: `env:VAR` → `env[VAR]`, anything else → itself. `literals` counts
23
+ * the values given literally (for the caller's warning). Throws `SecretArgError`.
24
+ */
25
+ export function resolveSecretArgs(values, env, flag) {
26
+ const secrets = [];
27
+ let literals = 0;
28
+ for (const v of values) {
29
+ if (!v.startsWith(ENV_REF)) {
30
+ secrets.push(v);
31
+ literals += 1;
32
+ continue;
33
+ }
34
+ const name = v.slice(ENV_REF.length);
35
+ if (!VAR_NAME_RE.test(name)) {
36
+ throw new SecretArgError(`${flag} env:<VAR> expects an environment variable name (letters, digits, _; not starting with a digit)`);
37
+ }
38
+ const value = env[name];
39
+ if (value === undefined || value === "")
40
+ throw new SecretArgError(`${flag} env:${name}: environment variable ${name} is not set`);
41
+ secrets.push(value);
42
+ }
43
+ return { secrets, literals };
44
+ }
45
+ //# sourceMappingURL=secret-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-args.js","sourceRoot":"","sources":["../src/secret-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,GAAG,MAAM,CAAC;AACvB,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C,wGAAwG;AACxG,MAAM,CAAC,MAAM,sBAAsB,GACjC,uIAAuI,CAAC;AAE1I;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAyB,EACzB,GAAiD,EACjD,IAAY;IAEZ,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,QAAQ,IAAI,CAAC,CAAC;YACd,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,iGAAiG,CAAC,CAAC;QACrI,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,QAAQ,IAAI,0BAA0B,IAAI,aAAa,CAAC,CAAC;QAClI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}