@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
package/dist/ux-api.js CHANGED
@@ -8,224 +8,7 @@
8
8
  // This is the ONLY place @jevitate/ux meets @jevitate/explore — the dep
9
9
  // direction stays ux ⟂ explore (both are consumed here, neither imports the
10
10
  // other). Findings are advisory; a UX finding never gates a run.
11
- import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
12
- import { tmpdir } from "node:os";
13
- import { join } from "node:path";
14
- import { PlaywrightBrowserPort } from "@jevitate/playwright";
15
- import { CastActor, BrowseTheWeb } from "@jevitate/screenplay";
16
- import { explore, assertAuthorizedExploreTarget, } from "@jevitate/explore";
17
- import { UxAnalyzer, a11yChecks, buildReport, loadV1Rubric, } from "@jevitate/ux";
18
- import { resolveDataDir } from "./data-dir.js";
19
- const DEFAULT_JUDGMENT_BUDGET = 40;
20
- function emptyBehavior() {
21
- return { noProgress: false, backtracks: 0, formReentry: 0, dwellMs: 0, errors: 0 };
22
- }
23
- /** explore's live `Control` → ux `Control` (same shape by design; drop `stability`). */
24
- function toUxControl(c) {
25
- return {
26
- index: c.index,
27
- role: c.role,
28
- name: c.name,
29
- tag: c.tag,
30
- inputType: c.inputType,
31
- enabled: c.enabled,
32
- summary: c.summary,
33
- descriptor: c.descriptor,
34
- };
35
- }
36
- /** a11y facts computable from a live snapshot's controls (honest subset). */
37
- function a11yFactsFromControls(controls) {
38
- return {
39
- controls: controls.map((c) => ({
40
- controlRef: `control:${c.index}`,
41
- accessibleName: c.name.trim().length > 0 ? c.name : null,
42
- focusOrder: c.index,
43
- targetSize: null,
44
- contrastRatio: null,
45
- })),
46
- };
47
- }
48
- /** A live Snapshot (+ extracted page text) → one screen's UxEvidence. */
49
- export function snapshotToEvidence(snap, visibleText, appContext, job, history) {
50
- const controls = snap.controls.map(toUxControl);
51
- return {
52
- screenId: snap.signature,
53
- url: snap.url,
54
- controls,
55
- visibleText,
56
- appContext,
57
- ...(job !== undefined ? { job } : {}),
58
- history,
59
- behavior: emptyBehavior(),
60
- a11yFacts: a11yFactsFromControls(controls),
61
- };
62
- }
63
- function descriptorSummary(d) {
64
- const parts = [d.role, d.name ?? d.testId ?? d.text].filter((s) => !!s);
65
- return parts.join(" ") || "control";
66
- }
67
- function stepTarget(step) {
68
- if ("target" in step && step.target)
69
- return step.target;
70
- return undefined;
71
- }
72
- /**
73
- * A saved Recording → per-page UxEvidence. A Recording is deterministic and
74
- * thin: it carries the CONTROLS the user touched (via each step's descriptor)
75
- * and the page url, but NOT the full visible text or a11y geometry. So offline
76
- * analysis is honestly partial — items needing `visibleText`/`a11yFacts` Skip,
77
- * and coverage reports it. (The live mode carries the rich per-screen snapshot.)
78
- */
79
- export function recordingToEvidence(recording, appContext, job) {
80
- const screens = [];
81
- const history = [];
82
- for (let i = 0; i < recording.pages.length; i++) {
83
- const page = recording.pages[i];
84
- const controls = [];
85
- let idx = 0;
86
- const seen = new Set();
87
- for (const rs of page.steps) {
88
- const d = stepTarget(rs.step);
89
- if (!d)
90
- continue;
91
- const key = JSON.stringify(d);
92
- if (seen.has(key))
93
- continue;
94
- seen.add(key);
95
- controls.push({
96
- index: idx++,
97
- role: d.role ?? "",
98
- name: d.name ?? d.testId ?? d.text ?? "",
99
- tag: "",
100
- inputType: null,
101
- enabled: true,
102
- summary: descriptorSummary(d),
103
- descriptor: d,
104
- });
105
- }
106
- const screenId = `${page.url}#${i}`;
107
- screens.push({
108
- screenId,
109
- url: page.url,
110
- controls,
111
- visibleText: "",
112
- appContext,
113
- ...(job !== undefined ? { job } : {}),
114
- history: [...history],
115
- behavior: emptyBehavior(),
116
- a11yFacts: { controls: [] },
117
- });
118
- history.push({ screenId, url: page.url });
119
- }
120
- return screens;
121
- }
122
- /**
123
- * Offline UX review. FAIL-FAST: an analyzer `failed` outcome throws
124
- * `UxAnalysisFailedError` (the CLI maps it to a non-zero fail envelope) — never
125
- * a fabricated "clean" report.
126
- */
127
- export async function runUxReview(opts) {
128
- const analyzer = new UxAnalyzer({ judge: opts.judge, a11yChecker: a11yChecks });
129
- const screens = recordingToEvidence(opts.recording, opts.appContext, opts.appContext.job);
130
- const outcome = await analyzer.analyze({
131
- screens,
132
- rubric: loadV1Rubric(),
133
- appContext: opts.appContext,
134
- secrets: opts.secrets,
135
- judgmentBudget: opts.judgmentBudget ?? DEFAULT_JUDGMENT_BUDGET,
136
- });
137
- if (outcome.kind === "failed") {
138
- throw new UxAnalysisFailedError(outcome.reason, outcome.screenId, outcome.rubricItemId);
139
- }
140
- const report = buildReport(outcome);
141
- const outDir = opts.outDir ?? resolveDataDir(["ux-reports"]);
142
- await mkdir(outDir, { recursive: true });
143
- const iso = (opts.nowIso ?? (() => new Date().toISOString()))();
144
- const reportPath = join(outDir, `ux-${iso.replace(/[:.]/g, "-")}.json`);
145
- await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
146
- return { report, reportPath };
147
- }
148
- export class UxAnalysisFailedError extends Error {
149
- screenId;
150
- rubricItemId;
151
- code = "E_UX_ANALYSIS";
152
- constructor(reason, screenId, rubricItemId) {
153
- super(`UX analysis failed: ${reason}${screenId ? ` (screen ${screenId})` : ""}`);
154
- this.screenId = screenId;
155
- this.rubricItemId = rubricItemId;
156
- this.name = "UxAnalysisFailedError";
157
- }
158
- }
159
- /**
160
- * Live usability mission. Guardrail #1 authorizes BEFORE opening a browser.
161
- * Reuses explore()'s loop (goal = the job) and, via the additive onSnapshot
162
- * hook, collects one screen's evidence per observation — then analyzes ONCE
163
- * after the run. A UX finding NEVER gates the loop (the hook's result is
164
- * ignored by explore). The temp profile dir is always removed.
165
- */
166
- export async function runUsabilityMission(opts) {
167
- const origin = assertAuthorizedExploreTarget(opts.url, opts.allowlist);
168
- const portFactory = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
169
- const port = portFactory();
170
- const profileDir = await mkdtemp(join(tmpdir(), "jevitate-usability-"));
171
- const session = await port.open({
172
- profileDir,
173
- headless: true,
174
- allowedOrigins: [...opts.allowlist],
175
- baseUrl: origin,
176
- });
177
- const collected = [];
178
- const history = [];
179
- const extract = opts.extractText ??
180
- (async (s) => s.page.evaluate(() => (typeof document !== "undefined" && document.body ? document.body.innerText : "")));
181
- try {
182
- const actor = CastActor.named("usability-mission").whoCan(new BrowseTheWeb(session, [...opts.allowlist]));
183
- const run = await explore({
184
- actor,
185
- judge: opts.judge,
186
- gen: opts.gen,
187
- goal: opts.job,
188
- allowlist: opts.allowlist,
189
- startUrl: opts.url,
190
- bounds: opts.bounds,
191
- secrets: opts.secrets,
192
- site: origin,
193
- missionContext: "usability review: pursue the stated job as a plausible first-time user, using only what is on screen",
194
- onSnapshot: async (snap) => {
195
- let visibleText = "";
196
- try {
197
- visibleText = await extract(session);
198
- }
199
- catch {
200
- visibleText = ""; // best-effort; the analyzer Skips visibleText items honestly
201
- }
202
- const ev = snapshotToEvidence(snap, visibleText, opts.appContext, opts.job, [...history]);
203
- collected.push(ev);
204
- history.push({ screenId: ev.screenId, url: ev.url });
205
- },
206
- });
207
- const analyzer = new UxAnalyzer({ judge: opts.judge, a11yChecker: a11yChecks });
208
- const outcome = await analyzer.analyze({
209
- screens: collected,
210
- rubric: loadV1Rubric(),
211
- appContext: opts.appContext,
212
- secrets: opts.secrets,
213
- judgmentBudget: opts.judgmentBudget ?? DEFAULT_JUDGMENT_BUDGET,
214
- });
215
- if (outcome.kind === "failed") {
216
- throw new UxAnalysisFailedError(outcome.reason, outcome.screenId, outcome.rubricItemId);
217
- }
218
- const report = buildReport(outcome);
219
- const outDir = opts.outDir ?? resolveDataDir(["ux-reports"]);
220
- await mkdir(outDir, { recursive: true });
221
- const iso = (opts.nowIso ?? (() => new Date().toISOString()))();
222
- const reportPath = join(outDir, `usability-${iso.replace(/[:.]/g, "-")}.json`);
223
- await writeFile(reportPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
224
- return { report, reportPath, stop: run.stop, screensObserved: collected.length };
225
- }
226
- finally {
227
- await session.close();
228
- await rm(profileDir, { recursive: true, force: true });
229
- }
230
- }
11
+ export { UsabilityInvariantsUnsupportedError, runUsabilityMission } from "./ux-usability.js";
12
+ export { UxAnalysisFailedError, discoverRecordingSidecars, loadRecordingSidecars, runUxReview } from "./ux-review.js";
13
+ export { captureFromTranscript, extractTypedValues, recordingToEvidence, snapshotToEvidence } from "./ux-evidence.js";
231
14
  //# sourceMappingURL=ux-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ux-api.js","sourceRoot":"","sources":["../src/ux-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ux-api.js","sourceRoot":"","sources":["../src/ux-api.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,8EAA8E;AAC9E,iEAAiE;AACjE,yEAAyE;AACzE,2EAA2E;AAC3E,+EAA+E;AAC/E,EAAE;AACF,wEAAwE;AACxE,4EAA4E;AAC5E,iEAAiE;AACjE,OAAO,EAAmE,mCAAmC,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9J,OAAO,EAAgG,qBAAqB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACpN,OAAO,EAAmC,qBAAqB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Command } from "commander";
2
+ import { type CliDeps } from "./cli-shared.js";
3
+ /** Registers `jevitate ux <recording>`. */
4
+ export declare function registerUxCommands(program: Command, deps: CliDeps): void;
package/dist/ux-cli.js ADDED
@@ -0,0 +1,102 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { RecordingSchema } from "@jevitate/recording";
3
+ import { MissingCredentialError } from "@jevitate/ai-core";
4
+ import { ok, fail } from "./envelope.js";
5
+ import { withEngine } from "./engine.js";
6
+ import { discoverRecordingSidecars, loadRecordingSidecars, runUxReview, UxAnalysisFailedError } from "./ux-api.js";
7
+ import { UxConfigError } from "./ux-config.js";
8
+ import { MinConfidenceError, QualityPolicyError, MaxFindingsPerRouteError } from "@jevitate/ux";
9
+ import { emitJson, GatewaySelectionError, buildExploreGateways } from "./cli-shared.js";
10
+ /** Registers `jevitate ux <recording>`. */
11
+ export function registerUxCommands(program, deps) {
12
+ // Additive: `jevitate ux <recording>` (issue #30) — offline UX review of a
13
+ // saved Recording. Findings are advisory; a `failed` analysis is a non-zero
14
+ // fail envelope (never a fabricated clean report).
15
+ program
16
+ .command("ux <recording>")
17
+ .description("offline UX review of a saved Recording — ranked, cited usability findings")
18
+ .option("--app-class <class>", "app class for calibration (required), e.g. consumer|admin|internal")
19
+ .option("--show <labels>", "opt-in filter on the quality grade (comma list of actionable,relevant-minor,generic,wrong); others are suppressed and counted; default JEVITATE_UX_SHOW, then ~/.jevitate/config.json ux.show, then ALL grades — the grader is uncalibrated (#133), so by default every finding is shown with its grade")
20
+ .option("--min-confidence <n>", "findings below this FINDING confidence (0..1, a finding's own violation/applicability/grounding score — NOT its quality-grade confidence, a separate independent-grader number shown as finding.quality.confidence) are suppressed and counted in report.suppressed; default JEVITATE_UX_MIN_CONFIDENCE, then ~/.jevitate/config.json ux.minConfidence, then 0.3")
21
+ .option("--max-findings-per-page <n>", "cap on UX findings per route/page, highest-confidence first; the rest are counted in report.suppressed as per-page-cap, never dropped silently; default JEVITATE_UX_MAX_FINDINGS_PER_PAGE, then ~/.jevitate/config.json ux.maxFindingsPerPage, then 5")
22
+ .option("--persona <p>", "optional persona for calibration")
23
+ .option("--job <text>", "the job the flow pursues (improves relevance)")
24
+ .option("--out <dir>", "directory to write the UX report")
25
+ .option("--result <file>", "mission result JSON (as written alongside the Recording by `jevitate explore`) — supplies blocked/disabled-target evidence the Recording alone cannot carry; default: <stem>.result.json, else <stem>.transcript.json, next to the Recording")
26
+ .option("--evidence <file>", "a live usability run's evidence sidecar (screens as analyzed + run signals); default: <stem>.evidence.json next to the Recording — with it, offline review reproduces the live run's findings")
27
+ .option("--real", "use live Jev gateways (requires keys)", false)
28
+ .option("--fake-ai", "use deterministic fake gateways", false)
29
+ .option("--json", "emit a JSON envelope")
30
+ .action(async function (recordingPath) {
31
+ const o = this.opts();
32
+ if (!o.appClass) {
33
+ emitJson(program, fail("E_UX_ARGS", "--app-class is required"));
34
+ return;
35
+ }
36
+ let recording;
37
+ try {
38
+ recording = RecordingSchema.parse(JSON.parse(await readFile(recordingPath, "utf8")));
39
+ }
40
+ catch (err) {
41
+ // #218: an unreadable or invalid Recording is unusable input — a usage error (64).
42
+ emitJson(program, fail("E_UX_INPUT", String(err instanceof Error ? err.message : err)));
43
+ return;
44
+ }
45
+ // #85 item 2 / #134: the artifacts next to the Recording — the live usability run's evidence
46
+ // sidecar, the mission result or transcript — are discovered automatically (explicit flags
47
+ // win). Absent or unreadable, the report says so (`report.evidenceCaveats`) rather than
48
+ // silently seeing less.
49
+ const found = discoverRecordingSidecars(recordingPath);
50
+ const sidecars = await loadRecordingSidecars({
51
+ ...((o.evidence ?? found.evidencePath) === undefined ? {} : { evidencePath: o.evidence ?? found.evidencePath }),
52
+ ...((o.result ?? found.resultPath) === undefined ? {} : { resultPath: o.result ?? found.resultPath }),
53
+ ...(o.result === undefined && found.transcriptPath !== undefined ? { transcriptPath: found.transcriptPath } : {}),
54
+ });
55
+ let uxJudge;
56
+ let uxGen;
57
+ let uxUsage;
58
+ try {
59
+ ({ judge: uxJudge, gen: uxGen, usage: uxUsage } = await buildExploreGateways(deps, { real: o.real ?? false, fakeAi: o.fakeAi ?? false }));
60
+ }
61
+ catch (err) {
62
+ if (err instanceof MissingCredentialError || err instanceof GatewaySelectionError) {
63
+ emitJson(program, fail("E_AI_SETUP_REQUIRED", err.message));
64
+ }
65
+ else {
66
+ emitJson(program, fail("E_UX_SETUP", String(err instanceof Error ? err.message : err)));
67
+ }
68
+ return;
69
+ }
70
+ try {
71
+ const result = await runUxReview({
72
+ recording,
73
+ appContext: {
74
+ appClass: o.appClass,
75
+ ...(o.persona ? { persona: o.persona } : {}),
76
+ ...(o.job ? { job: o.job } : {}),
77
+ },
78
+ judge: uxJudge,
79
+ gen: uxGen,
80
+ usage: uxUsage,
81
+ ...(o.minConfidence !== undefined ? { minConfidence: o.minConfidence } : {}),
82
+ ...(o.show !== undefined ? { show: o.show } : {}),
83
+ ...(o.maxFindingsPerPage !== undefined ? { maxFindingsPerRoute: o.maxFindingsPerPage } : {}),
84
+ outDir: o.out,
85
+ ...sidecars,
86
+ });
87
+ emitJson(program, ok(withEngine({ ...result, sidecars: found })));
88
+ }
89
+ catch (err) {
90
+ if (err instanceof UxAnalysisFailedError) {
91
+ emitJson(program, fail("E_UX_ANALYSIS", err.message));
92
+ }
93
+ else if (err instanceof MinConfidenceError || err instanceof QualityPolicyError || err instanceof MaxFindingsPerRouteError || err instanceof UxConfigError) {
94
+ emitJson(program, fail("E_UX_ARGS", err.message));
95
+ }
96
+ else {
97
+ emitJson(program, fail("E_UX_RUN", String(err instanceof Error ? err.message : err)));
98
+ }
99
+ }
100
+ });
101
+ }
102
+ //# sourceMappingURL=ux-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ux-cli.js","sourceRoot":"","sources":["../src/ux-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The UX-review slice of `~/.jevitate/config.json`:
3
+ *
4
+ * ```json
5
+ * { "ux": { "minConfidence": 0.75, "show": ["actionable", "relevant-minor"] } }
6
+ * ```
7
+ *
8
+ * A missing file (or missing key) is "not configured"; a malformed file or a non-numeric value
9
+ * fails closed — it is never silently replaced by the default.
10
+ */
11
+ export declare class UxConfigError extends Error {
12
+ readonly code: "E_UX_CONFIG";
13
+ }
14
+ export declare function loadUxMinConfidence(path?: string): number | undefined;
15
+ /**
16
+ * `ux.minConfidenceByAppClass` — per-`--app-class` cutoff defaults (issue #97), e.g.:
17
+ * `{ "ux": { "minConfidenceByAppClass": { "consumer": 0.3, "admin": 0.5 } } }`. Looked up
18
+ * case-insensitively by `appClass`; falls through to `resolveMinConfidence`'s next precedence
19
+ * level (`DEFAULT_MIN_CONFIDENCE`) when `appClass` has no entry — today's behavior is unchanged
20
+ * where no app-class-specific data exists.
21
+ */
22
+ export declare function loadUxMinConfidenceByAppClass(path?: string, appClass?: string): number | undefined;
23
+ /** `ux.show` — the quality grades a UX report shows (validated by `resolveQualityPolicy`). */
24
+ export declare function loadUxShow(path?: string): string[] | undefined;
25
+ /**
26
+ * `ux.maxFindingsPerPage` — the per-route finding cap (issue #198 interim, 0.2.0; validated by
27
+ * `resolveMaxFindingsPerRoute`).
28
+ */
29
+ export declare function loadUxMaxFindingsPerPage(path?: string): number | undefined;
@@ -0,0 +1,103 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { resolveDataDir } from "./data-dir.js";
3
+ /**
4
+ * The UX-review slice of `~/.jevitate/config.json`:
5
+ *
6
+ * ```json
7
+ * { "ux": { "minConfidence": 0.75, "show": ["actionable", "relevant-minor"] } }
8
+ * ```
9
+ *
10
+ * A missing file (or missing key) is "not configured"; a malformed file or a non-numeric value
11
+ * fails closed — it is never silently replaced by the default.
12
+ */
13
+ export class UxConfigError extends Error {
14
+ code = "E_UX_CONFIG";
15
+ }
16
+ /** The parsed `ux` object of the config file (undefined when the file or key is absent). */
17
+ function loadUxSection(path) {
18
+ let raw;
19
+ try {
20
+ raw = readFileSync(path, "utf8");
21
+ }
22
+ catch (e) {
23
+ if (typeof e === "object" && e !== null && "code" in e && e.code === "ENOENT")
24
+ return undefined;
25
+ throw new UxConfigError(`cannot read ${path}: ${e instanceof Error ? e.message : String(e)}`);
26
+ }
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(raw);
30
+ }
31
+ catch {
32
+ throw new UxConfigError(`${path} is not valid JSON`);
33
+ }
34
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
35
+ throw new UxConfigError(`${path} must be a JSON object`);
36
+ }
37
+ const ux = parsed.ux;
38
+ if (ux === undefined)
39
+ return undefined;
40
+ if (ux === null || typeof ux !== "object" || Array.isArray(ux))
41
+ throw new UxConfigError(`${path}: "ux" must be an object`);
42
+ return ux;
43
+ }
44
+ export function loadUxMinConfidence(path = resolveDataDir(["config.json"])) {
45
+ const v = loadUxSection(path)?.minConfidence;
46
+ if (v === undefined)
47
+ return undefined;
48
+ if (typeof v !== "number" || !Number.isFinite(v) || v < 0 || v > 1) {
49
+ throw new UxConfigError(`${path}: ux.minConfidence must be a number in [0,1]`);
50
+ }
51
+ return v;
52
+ }
53
+ /**
54
+ * `ux.minConfidenceByAppClass` — per-`--app-class` cutoff defaults (issue #97), e.g.:
55
+ * `{ "ux": { "minConfidenceByAppClass": { "consumer": 0.3, "admin": 0.5 } } }`. Looked up
56
+ * case-insensitively by `appClass`; falls through to `resolveMinConfidence`'s next precedence
57
+ * level (`DEFAULT_MIN_CONFIDENCE`) when `appClass` has no entry — today's behavior is unchanged
58
+ * where no app-class-specific data exists.
59
+ */
60
+ export function loadUxMinConfidenceByAppClass(path = resolveDataDir(["config.json"]), appClass) {
61
+ if (!appClass)
62
+ return undefined;
63
+ const v = loadUxSection(path)?.minConfidenceByAppClass;
64
+ if (v === undefined)
65
+ return undefined;
66
+ if (v === null || typeof v !== "object" || Array.isArray(v)) {
67
+ throw new UxConfigError(`${path}: ux.minConfidenceByAppClass must be an object keyed by app class`);
68
+ }
69
+ const rec = v;
70
+ const wanted = appClass.trim().toLowerCase();
71
+ const key = Object.keys(rec).find((k) => k.trim().toLowerCase() === wanted);
72
+ if (key === undefined)
73
+ return undefined;
74
+ const n = rec[key];
75
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 0 || n > 1) {
76
+ throw new UxConfigError(`${path}: ux.minConfidenceByAppClass.${key} must be a number in [0,1]`);
77
+ }
78
+ return n;
79
+ }
80
+ /** `ux.show` — the quality grades a UX report shows (validated by `resolveQualityPolicy`). */
81
+ export function loadUxShow(path = resolveDataDir(["config.json"])) {
82
+ const v = loadUxSection(path)?.show;
83
+ if (v === undefined)
84
+ return undefined;
85
+ if (!Array.isArray(v) || !v.every((x) => typeof x === "string")) {
86
+ throw new UxConfigError(`${path}: ux.show must be an array of quality labels`);
87
+ }
88
+ return v;
89
+ }
90
+ /**
91
+ * `ux.maxFindingsPerPage` — the per-route finding cap (issue #198 interim, 0.2.0; validated by
92
+ * `resolveMaxFindingsPerRoute`).
93
+ */
94
+ export function loadUxMaxFindingsPerPage(path = resolveDataDir(["config.json"])) {
95
+ const v = loadUxSection(path)?.maxFindingsPerPage;
96
+ if (v === undefined)
97
+ return undefined;
98
+ if (typeof v !== "number" || !Number.isInteger(v) || v < 1) {
99
+ throw new UxConfigError(`${path}: ux.maxFindingsPerPage must be a positive integer`);
100
+ }
101
+ return v;
102
+ }
103
+ //# sourceMappingURL=ux-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ux-config.js","sourceRoot":"","sources":["../src/ux-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { Recording, TargetDescriptor } from "@jevitate/recording";
2
+ import { type Snapshot } from "@jevitate/explore";
3
+ import { type AppContext, type RunSignalCapture, type ScreenRef, type UxEvidence } from "@jevitate/ux";
4
+ export declare const DEFAULT_JUDGMENT_BUDGET = 40;
5
+ /** A live Snapshot (+ extracted page text) → one screen's UxEvidence. */
6
+ export declare function snapshotToEvidence(snap: Snapshot, visibleText: string, appContext: AppContext, job: string | undefined, history: readonly ScreenRef[]): UxEvidence;
7
+ /**
8
+ * Values the run itself typed or selected — a Recording's own `fill`/`select` steps whose value
9
+ * was NOT redacted (a secret field's value is always `{redacted:true}` and never surfaces here).
10
+ * #85 item 1: feeds the vocabulary/jargon tier (nielsen-2) so a quote/label that is really the
11
+ * user's own content (e.g. a piece title echoed back onto a card) is not mistaken for app copy.
12
+ */
13
+ export declare function extractTypedValues(recording: Recording): string[];
14
+ /**
15
+ * The minimal shape of a mission transcript entry `recordingToEvidence` needs — duck-typed against
16
+ * `@jevitate/explore`'s `TranscriptEntry` (this file already imports plenty from there; kept
17
+ * separate so `recordingToEvidence` itself stays decoupled from the live explore-control shape).
18
+ */
19
+ export interface MissionTranscriptEntryLike {
20
+ readonly step?: number;
21
+ readonly op?: string | null;
22
+ readonly target?: string | null;
23
+ readonly actOk: boolean;
24
+ readonly reason?: string;
25
+ readonly url: string;
26
+ readonly signature?: string;
27
+ readonly descriptor?: TargetDescriptor;
28
+ readonly value?: string;
29
+ readonly message?: string;
30
+ readonly reply?: {
31
+ readonly received?: boolean;
32
+ readonly text?: string;
33
+ };
34
+ readonly screenshot?: string;
35
+ }
36
+ /**
37
+ * #134: the run-signal capture a transcript ALONE supports (no visible text, no requests) — enough
38
+ * for the journey friction (retries, dead ends, waits, backtracks, abandoned fields) and repeated
39
+ * replies, NOT for the oracles that need requests or page text (they would misfire on the blanks).
40
+ */
41
+ export declare function captureFromTranscript(transcript: readonly MissionTranscriptEntryLike[]): RunSignalCapture;
42
+ /**
43
+ * A saved Recording → per-page UxEvidence. A Recording is deterministic and
44
+ * thin: it carries the CONTROLS the user touched (via each step's descriptor)
45
+ * and the page url, but NOT the full visible text or a11y geometry. So offline
46
+ * analysis is honestly partial — items needing `visibleText`/`a11yFacts` Skip,
47
+ * and coverage reports it. (The live mode carries the rich per-screen snapshot.)
48
+ *
49
+ * `missionTranscript` (#85 item 2, optional) adds blocked/disabled-target controls the Recording
50
+ * itself cannot carry, on whichever screen(s) share the blocked action's url — the same evidence a
51
+ * live usability run gets from its snapshot. `typedValues` (every screen's own #85 item 1 input)
52
+ * is always derived from the Recording, with or without a transcript.
53
+ */
54
+ export declare function recordingToEvidence(recording: Recording, appContext: AppContext, job?: string, missionTranscript?: readonly MissionTranscriptEntryLike[]): UxEvidence[];