@plune-ai/cairn 0.2.1

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 (323) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +181 -0
  3. package/dist/agent/graph.d.ts +538 -0
  4. package/dist/agent/graph.d.ts.map +1 -0
  5. package/dist/agent/graph.js +0 -0
  6. package/dist/agent/graph.js.map +1 -0
  7. package/dist/agent/index.d.ts +83 -0
  8. package/dist/agent/index.d.ts.map +1 -0
  9. package/dist/agent/index.js +407 -0
  10. package/dist/agent/index.js.map +1 -0
  11. package/dist/analyze/index.d.ts +22 -0
  12. package/dist/analyze/index.d.ts.map +1 -0
  13. package/dist/analyze/index.js +39 -0
  14. package/dist/analyze/index.js.map +1 -0
  15. package/dist/artifacts/index.d.ts +29 -0
  16. package/dist/artifacts/index.d.ts.map +1 -0
  17. package/dist/artifacts/index.js +68 -0
  18. package/dist/artifacts/index.js.map +1 -0
  19. package/dist/artifacts/report.d.ts +21 -0
  20. package/dist/artifacts/report.d.ts.map +1 -0
  21. package/dist/artifacts/report.js +56 -0
  22. package/dist/artifacts/report.js.map +1 -0
  23. package/dist/artifacts/testcase-md.d.ts +37 -0
  24. package/dist/artifacts/testcase-md.d.ts.map +1 -0
  25. package/dist/artifacts/testcase-md.js +91 -0
  26. package/dist/artifacts/testcase-md.js.map +1 -0
  27. package/dist/browser/backends/playwright-cli.d.ts +23 -0
  28. package/dist/browser/backends/playwright-cli.d.ts.map +1 -0
  29. package/dist/browser/backends/playwright-cli.js +85 -0
  30. package/dist/browser/backends/playwright-cli.js.map +1 -0
  31. package/dist/browser/backends/playwright-lib.d.ts +32 -0
  32. package/dist/browser/backends/playwright-lib.d.ts.map +1 -0
  33. package/dist/browser/backends/playwright-lib.js +157 -0
  34. package/dist/browser/backends/playwright-lib.js.map +1 -0
  35. package/dist/browser/gateway.d.ts +33 -0
  36. package/dist/browser/gateway.d.ts.map +1 -0
  37. package/dist/browser/gateway.js +2 -0
  38. package/dist/browser/gateway.js.map +1 -0
  39. package/dist/browser/index.d.ts +15 -0
  40. package/dist/browser/index.d.ts.map +1 -0
  41. package/dist/browser/index.js +59 -0
  42. package/dist/browser/index.js.map +1 -0
  43. package/dist/browser/types.d.ts +99 -0
  44. package/dist/browser/types.d.ts.map +1 -0
  45. package/dist/browser/types.js +6 -0
  46. package/dist/browser/types.js.map +1 -0
  47. package/dist/checklist/index.d.ts +24 -0
  48. package/dist/checklist/index.d.ts.map +1 -0
  49. package/dist/checklist/index.js +65 -0
  50. package/dist/checklist/index.js.map +1 -0
  51. package/dist/cli/branding.d.ts +14 -0
  52. package/dist/cli/branding.d.ts.map +1 -0
  53. package/dist/cli/branding.js +14 -0
  54. package/dist/cli/branding.js.map +1 -0
  55. package/dist/cli/index.d.ts +12 -0
  56. package/dist/cli/index.d.ts.map +1 -0
  57. package/dist/cli/index.js +322 -0
  58. package/dist/cli/index.js.map +1 -0
  59. package/dist/cli/lex-bot.d.ts +3 -0
  60. package/dist/cli/lex-bot.d.ts.map +1 -0
  61. package/dist/cli/lex-bot.js +11 -0
  62. package/dist/cli/lex-bot.js.map +1 -0
  63. package/dist/codegen/index.d.ts +36 -0
  64. package/dist/codegen/index.d.ts.map +1 -0
  65. package/dist/codegen/index.js +63 -0
  66. package/dist/codegen/index.js.map +1 -0
  67. package/dist/codegen/schema.d.ts +14 -0
  68. package/dist/codegen/schema.d.ts.map +1 -0
  69. package/dist/codegen/schema.js +9 -0
  70. package/dist/codegen/schema.js.map +1 -0
  71. package/dist/config/env.d.ts +18 -0
  72. package/dist/config/env.d.ts.map +1 -0
  73. package/dist/config/env.js +42 -0
  74. package/dist/config/env.js.map +1 -0
  75. package/dist/config/index.d.ts +11 -0
  76. package/dist/config/index.d.ts.map +1 -0
  77. package/dist/config/index.js +74 -0
  78. package/dist/config/index.js.map +1 -0
  79. package/dist/config/profiles.d.ts +7 -0
  80. package/dist/config/profiles.d.ts.map +1 -0
  81. package/dist/config/profiles.js +28 -0
  82. package/dist/config/profiles.js.map +1 -0
  83. package/dist/config/schema.d.ts +91 -0
  84. package/dist/config/schema.d.ts.map +1 -0
  85. package/dist/config/schema.js +20 -0
  86. package/dist/config/schema.js.map +1 -0
  87. package/dist/design/index.d.ts +36 -0
  88. package/dist/design/index.d.ts.map +1 -0
  89. package/dist/design/index.js +35 -0
  90. package/dist/design/index.js.map +1 -0
  91. package/dist/design/schema.d.ts +109 -0
  92. package/dist/design/schema.d.ts.map +1 -0
  93. package/dist/design/schema.js +35 -0
  94. package/dist/design/schema.js.map +1 -0
  95. package/dist/eval/collect.d.ts +18 -0
  96. package/dist/eval/collect.d.ts.map +1 -0
  97. package/dist/eval/collect.js +53 -0
  98. package/dist/eval/collect.js.map +1 -0
  99. package/dist/eval/experiment.d.ts +49 -0
  100. package/dist/eval/experiment.d.ts.map +1 -0
  101. package/dist/eval/experiment.js +66 -0
  102. package/dist/eval/experiment.js.map +1 -0
  103. package/dist/eval/judge.d.ts +30 -0
  104. package/dist/eval/judge.d.ts.map +1 -0
  105. package/dist/eval/judge.js +47 -0
  106. package/dist/eval/judge.js.map +1 -0
  107. package/dist/eval/pilot.d.ts +21 -0
  108. package/dist/eval/pilot.d.ts.map +1 -0
  109. package/dist/eval/pilot.js +24 -0
  110. package/dist/eval/pilot.js.map +1 -0
  111. package/dist/eval/scorers.d.ts +23 -0
  112. package/dist/eval/scorers.d.ts.map +1 -0
  113. package/dist/eval/scorers.js +38 -0
  114. package/dist/eval/scorers.js.map +1 -0
  115. package/dist/index.d.ts +21 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +13 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/knowledge/index.d.ts +7 -0
  120. package/dist/knowledge/index.d.ts.map +1 -0
  121. package/dist/knowledge/index.js +39 -0
  122. package/dist/knowledge/index.js.map +1 -0
  123. package/dist/llm/factory.d.ts +31 -0
  124. package/dist/llm/factory.d.ts.map +1 -0
  125. package/dist/llm/factory.js +48 -0
  126. package/dist/llm/factory.js.map +1 -0
  127. package/dist/llm/index.d.ts +5 -0
  128. package/dist/llm/index.d.ts.map +1 -0
  129. package/dist/llm/index.js +3 -0
  130. package/dist/llm/index.js.map +1 -0
  131. package/dist/llm/structured.d.ts +30 -0
  132. package/dist/llm/structured.d.ts.map +1 -0
  133. package/dist/llm/structured.js +58 -0
  134. package/dist/llm/structured.js.map +1 -0
  135. package/dist/llm/vision.d.ts +16 -0
  136. package/dist/llm/vision.d.ts.map +1 -0
  137. package/dist/llm/vision.js +4 -0
  138. package/dist/llm/vision.js.map +1 -0
  139. package/dist/observe/index.d.ts +21 -0
  140. package/dist/observe/index.d.ts.map +1 -0
  141. package/dist/observe/index.js +18 -0
  142. package/dist/observe/index.js.map +1 -0
  143. package/dist/observe/parse-aria.d.ts +8 -0
  144. package/dist/observe/parse-aria.d.ts.map +1 -0
  145. package/dist/observe/parse-aria.js +71 -0
  146. package/dist/observe/parse-aria.js.map +1 -0
  147. package/dist/probe/index.d.ts +19 -0
  148. package/dist/probe/index.d.ts.map +1 -0
  149. package/dist/probe/index.js +38 -0
  150. package/dist/probe/index.js.map +1 -0
  151. package/dist/promote/index.d.ts +6 -0
  152. package/dist/promote/index.d.ts.map +1 -0
  153. package/dist/promote/index.js +4 -0
  154. package/dist/promote/index.js.map +1 -0
  155. package/dist/promote/promote-case.d.ts +12 -0
  156. package/dist/promote/promote-case.d.ts.map +1 -0
  157. package/dist/promote/promote-case.js +103 -0
  158. package/dist/promote/promote-case.js.map +1 -0
  159. package/dist/promote/selectors.d.ts +29 -0
  160. package/dist/promote/selectors.d.ts.map +1 -0
  161. package/dist/promote/selectors.js +58 -0
  162. package/dist/promote/selectors.js.map +1 -0
  163. package/dist/prompts/index.d.ts +32 -0
  164. package/dist/prompts/index.d.ts.map +1 -0
  165. package/dist/prompts/index.js +55 -0
  166. package/dist/prompts/index.js.map +1 -0
  167. package/dist/prompts/local/identify-elements.d.ts +6 -0
  168. package/dist/prompts/local/identify-elements.d.ts.map +1 -0
  169. package/dist/prompts/local/identify-elements.js +21 -0
  170. package/dist/prompts/local/identify-elements.js.map +1 -0
  171. package/dist/prompts/local/index.d.ts +3 -0
  172. package/dist/prompts/local/index.d.ts.map +1 -0
  173. package/dist/prompts/local/index.js +18 -0
  174. package/dist/prompts/local/index.js.map +1 -0
  175. package/dist/prompts/local/judge-checklist-coverage.d.ts +3 -0
  176. package/dist/prompts/local/judge-checklist-coverage.d.ts.map +1 -0
  177. package/dist/prompts/local/judge-checklist-coverage.js +11 -0
  178. package/dist/prompts/local/judge-checklist-coverage.js.map +1 -0
  179. package/dist/prompts/local/judge-test-cases.d.ts +3 -0
  180. package/dist/prompts/local/judge-test-cases.d.ts.map +1 -0
  181. package/dist/prompts/local/judge-test-cases.js +11 -0
  182. package/dist/prompts/local/judge-test-cases.js.map +1 -0
  183. package/dist/prompts/local/pilot-review.d.ts +3 -0
  184. package/dist/prompts/local/pilot-review.d.ts.map +1 -0
  185. package/dist/prompts/local/pilot-review.js +13 -0
  186. package/dist/prompts/local/pilot-review.js.map +1 -0
  187. package/dist/prompts/local/qa-manual-test-designer.d.ts +7 -0
  188. package/dist/prompts/local/qa-manual-test-designer.d.ts.map +1 -0
  189. package/dist/prompts/local/qa-manual-test-designer.js +13 -0
  190. package/dist/prompts/local/qa-manual-test-designer.js.map +1 -0
  191. package/dist/prompts/local/qa-playwright-ts-writer.d.ts +6 -0
  192. package/dist/prompts/local/qa-playwright-ts-writer.d.ts.map +1 -0
  193. package/dist/prompts/local/qa-playwright-ts-writer.js +40 -0
  194. package/dist/prompts/local/qa-playwright-ts-writer.js.map +1 -0
  195. package/dist/prompts/local/qa-testcase-from-ui.d.ts +6 -0
  196. package/dist/prompts/local/qa-testcase-from-ui.d.ts.map +1 -0
  197. package/dist/prompts/local/qa-testcase-from-ui.js +52 -0
  198. package/dist/prompts/local/qa-testcase-from-ui.js.map +1 -0
  199. package/dist/session/index.d.ts +27 -0
  200. package/dist/session/index.d.ts.map +1 -0
  201. package/dist/session/index.js +74 -0
  202. package/dist/session/index.js.map +1 -0
  203. package/dist/telemetry/index.d.ts +21 -0
  204. package/dist/telemetry/index.d.ts.map +1 -0
  205. package/dist/telemetry/index.js +26 -0
  206. package/dist/telemetry/index.js.map +1 -0
  207. package/dist/tui/App.d.ts +6 -0
  208. package/dist/tui/App.d.ts.map +1 -0
  209. package/dist/tui/App.js +61 -0
  210. package/dist/tui/App.js.map +1 -0
  211. package/dist/tui/components/error-boundary.d.ts +17 -0
  212. package/dist/tui/components/error-boundary.d.ts.map +1 -0
  213. package/dist/tui/components/error-boundary.js +20 -0
  214. package/dist/tui/components/error-boundary.js.map +1 -0
  215. package/dist/tui/components/field.d.ts +10 -0
  216. package/dist/tui/components/field.d.ts.map +1 -0
  217. package/dist/tui/components/field.js +8 -0
  218. package/dist/tui/components/field.js.map +1 -0
  219. package/dist/tui/components/help.d.ts +5 -0
  220. package/dist/tui/components/help.d.ts.map +1 -0
  221. package/dist/tui/components/help.js +7 -0
  222. package/dist/tui/components/help.js.map +1 -0
  223. package/dist/tui/components/log-pane.d.ts +6 -0
  224. package/dist/tui/components/log-pane.d.ts.map +1 -0
  225. package/dist/tui/components/log-pane.js +10 -0
  226. package/dist/tui/components/log-pane.js.map +1 -0
  227. package/dist/tui/components/node-checklist.d.ts +6 -0
  228. package/dist/tui/components/node-checklist.d.ts.map +1 -0
  229. package/dist/tui/components/node-checklist.js +9 -0
  230. package/dist/tui/components/node-checklist.js.map +1 -0
  231. package/dist/tui/components/pilot-badge.d.ts +6 -0
  232. package/dist/tui/components/pilot-badge.d.ts.map +1 -0
  233. package/dist/tui/components/pilot-badge.js +12 -0
  234. package/dist/tui/components/pilot-badge.js.map +1 -0
  235. package/dist/tui/components/scores-table.d.ts +6 -0
  236. package/dist/tui/components/scores-table.d.ts.map +1 -0
  237. package/dist/tui/components/scores-table.js +9 -0
  238. package/dist/tui/components/scores-table.js.map +1 -0
  239. package/dist/tui/components/scrollable-text.d.ts +6 -0
  240. package/dist/tui/components/scrollable-text.d.ts.map +1 -0
  241. package/dist/tui/components/scrollable-text.js +22 -0
  242. package/dist/tui/components/scrollable-text.js.map +1 -0
  243. package/dist/tui/components/session-picker.d.ts +5 -0
  244. package/dist/tui/components/session-picker.d.ts.map +1 -0
  245. package/dist/tui/components/session-picker.js +16 -0
  246. package/dist/tui/components/session-picker.js.map +1 -0
  247. package/dist/tui/components/test-case-list.d.ts +7 -0
  248. package/dist/tui/components/test-case-list.d.ts.map +1 -0
  249. package/dist/tui/components/test-case-list.js +10 -0
  250. package/dist/tui/components/test-case-list.js.map +1 -0
  251. package/dist/tui/hooks/use-run-artifacts.d.ts +14 -0
  252. package/dist/tui/hooks/use-run-artifacts.d.ts.map +1 -0
  253. package/dist/tui/hooks/use-run-artifacts.js +37 -0
  254. package/dist/tui/hooks/use-run-artifacts.js.map +1 -0
  255. package/dist/tui/hooks/use-runner.d.ts +25 -0
  256. package/dist/tui/hooks/use-runner.d.ts.map +1 -0
  257. package/dist/tui/hooks/use-runner.js +116 -0
  258. package/dist/tui/hooks/use-runner.js.map +1 -0
  259. package/dist/tui/hooks/use-runs.d.ts +14 -0
  260. package/dist/tui/hooks/use-runs.d.ts.map +1 -0
  261. package/dist/tui/hooks/use-runs.js +57 -0
  262. package/dist/tui/hooks/use-runs.js.map +1 -0
  263. package/dist/tui/hooks/use-sessions.d.ts +10 -0
  264. package/dist/tui/hooks/use-sessions.d.ts.map +1 -0
  265. package/dist/tui/hooks/use-sessions.js +32 -0
  266. package/dist/tui/hooks/use-sessions.js.map +1 -0
  267. package/dist/tui/hooks/use-stdout-dimensions.d.ts +3 -0
  268. package/dist/tui/hooks/use-stdout-dimensions.d.ts.map +1 -0
  269. package/dist/tui/hooks/use-stdout-dimensions.js +18 -0
  270. package/dist/tui/hooks/use-stdout-dimensions.js.map +1 -0
  271. package/dist/tui/index.d.ts +7 -0
  272. package/dist/tui/index.d.ts.map +1 -0
  273. package/dist/tui/index.js +13 -0
  274. package/dist/tui/index.js.map +1 -0
  275. package/dist/tui/router-context.d.ts +12 -0
  276. package/dist/tui/router-context.d.ts.map +1 -0
  277. package/dist/tui/router-context.js +14 -0
  278. package/dist/tui/router-context.js.map +1 -0
  279. package/dist/tui/router.d.ts +44 -0
  280. package/dist/tui/router.d.ts.map +1 -0
  281. package/dist/tui/router.js +22 -0
  282. package/dist/tui/router.js.map +1 -0
  283. package/dist/tui/screens/form-screen.d.ts +7 -0
  284. package/dist/tui/screens/form-screen.d.ts.map +1 -0
  285. package/dist/tui/screens/form-screen.js +104 -0
  286. package/dist/tui/screens/form-screen.js.map +1 -0
  287. package/dist/tui/screens/launcher-screen.d.ts +2 -0
  288. package/dist/tui/screens/launcher-screen.d.ts.map +1 -0
  289. package/dist/tui/screens/launcher-screen.js +28 -0
  290. package/dist/tui/screens/launcher-screen.js.map +1 -0
  291. package/dist/tui/screens/run-dashboard-screen.d.ts +7 -0
  292. package/dist/tui/screens/run-dashboard-screen.d.ts.map +1 -0
  293. package/dist/tui/screens/run-dashboard-screen.js +32 -0
  294. package/dist/tui/screens/run-dashboard-screen.js.map +1 -0
  295. package/dist/tui/screens/run-detail-screen.d.ts +5 -0
  296. package/dist/tui/screens/run-detail-screen.d.ts.map +1 -0
  297. package/dist/tui/screens/run-detail-screen.js +67 -0
  298. package/dist/tui/screens/run-detail-screen.js.map +1 -0
  299. package/dist/tui/screens/runs-list-screen.d.ts +2 -0
  300. package/dist/tui/screens/runs-list-screen.d.ts.map +1 -0
  301. package/dist/tui/screens/runs-list-screen.js +22 -0
  302. package/dist/tui/screens/runs-list-screen.js.map +1 -0
  303. package/dist/tui/screens/summary-screen.d.ts +6 -0
  304. package/dist/tui/screens/summary-screen.d.ts.map +1 -0
  305. package/dist/tui/screens/summary-screen.js +53 -0
  306. package/dist/tui/screens/summary-screen.js.map +1 -0
  307. package/dist/tui/theme.d.ts +31 -0
  308. package/dist/tui/theme.d.ts.map +1 -0
  309. package/dist/tui/theme.js +70 -0
  310. package/dist/tui/theme.js.map +1 -0
  311. package/dist/tui/types.d.ts +38 -0
  312. package/dist/tui/types.d.ts.map +1 -0
  313. package/dist/tui/types.js +2 -0
  314. package/dist/tui/types.js.map +1 -0
  315. package/dist/validate/index.d.ts +30 -0
  316. package/dist/validate/index.d.ts.map +1 -0
  317. package/dist/validate/index.js +39 -0
  318. package/dist/validate/index.js.map +1 -0
  319. package/dist/validate/runner.d.ts +15 -0
  320. package/dist/validate/runner.d.ts.map +1 -0
  321. package/dist/validate/runner.js +74 -0
  322. package/dist/validate/runner.js.map +1 -0
  323. package/package.json +97 -0
@@ -0,0 +1,322 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI `cairn`. Commands: observe · explore · design · automate · dataset-add · experiment.
4
+ * `lex-bot` stays as a hidden, deprecated alias (see ./lex-bot.ts) → same code path.
5
+ */
6
+ import "dotenv/config";
7
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
8
+ import { dirname, join, resolve } from "node:path";
9
+ import { pathToFileURL } from "node:url";
10
+ import { Command } from "commander";
11
+ import { BOT_NAME, BOT_VERSION } from "../index.js";
12
+ import { makeGateway } from "../browser/index.js";
13
+ import { capture } from "../observe/index.js";
14
+ import { SessionStore } from "../session/index.js";
15
+ import { loadConfig } from "../config/index.js";
16
+ import { runExploration, runDesign, runAutomate } from "../agent/index.js";
17
+ import { promoteCase, locatorFor } from "../promote/index.js";
18
+ import { makeModel } from "../llm/index.js";
19
+ import { structuredInvoker } from "../llm/structured.js";
20
+ import { PromptRegistry, LOCAL_PROMPTS } from "../prompts/index.js";
21
+ import { runExperiment } from "../eval/experiment.js";
22
+ const program = new Command();
23
+ program
24
+ .name("cairn")
25
+ .description(`${BOT_NAME} — autonomous UI test generator`)
26
+ .version(BOT_VERSION);
27
+ program
28
+ .command("observe")
29
+ .description("Explore a page: ARIA snapshot + interactive elements + screenshot")
30
+ .requiredOption("--url <url>", "page URL")
31
+ .option("--backend <kind>", "lib | cli", "lib")
32
+ .option("--session <name>", "name of the saved session (.auth/<name>.storageState.json)")
33
+ .option("--out <file>", "where to save the screenshot", "observe-screenshot.png")
34
+ .action(async (opts) => {
35
+ const backend = opts.backend === "cli" ? "cli" : "lib";
36
+ const config = loadConfig(process.env);
37
+ let storageState;
38
+ if (opts.session) {
39
+ storageState = await new SessionStore(resolve(".auth")).load(opts.session);
40
+ }
41
+ const gateway = makeGateway({ backend, storageState, channel: config.browser.channel });
42
+ try {
43
+ const study = await capture(gateway, opts.url);
44
+ const interactive = study.elements.filter((e) => e.interactive);
45
+ process.stdout.write(`URL: ${study.url} (backend: ${study.capturedBy})\n`);
46
+ process.stdout.write(`Elements: ${study.elements.length}, interactive: ${interactive.length}\n\n`);
47
+ process.stdout.write(`${study.ariaYaml}\n\nInteractive:\n`);
48
+ for (const e of interactive) {
49
+ process.stdout.write(` [${e.ref}] ${e.role}${e.name ? ` "${e.name}"` : ""}\n`);
50
+ }
51
+ await mkdir(dirname(opts.out), { recursive: true });
52
+ await writeFile(opts.out, Buffer.from(study.screenshotB64, "base64"));
53
+ process.stdout.write(`\nScreenshot → ${opts.out}\n`);
54
+ }
55
+ finally {
56
+ await gateway.close();
57
+ }
58
+ });
59
+ program
60
+ .command("explore")
61
+ .description("Explore a page and generate methodology-based test cases (Sprint 2: no code)")
62
+ .requiredOption("--url <url>", "page URL")
63
+ .option("--backend <kind>", "lib | cli (overrides BROWSER_BACKEND)")
64
+ .option("--session <name>", "name of the saved session (.auth/<name>.storageState.json)")
65
+ .option("--session-file <path>", "direct path to a storageState file (any name)")
66
+ .option("--headed", "visible browser (debug)")
67
+ .option("--checklist <file>", "checklist file (md/text) — guides what to test")
68
+ .option("--style <s>", "planning style: happy | negative | coverage | all")
69
+ .action(async (opts) => {
70
+ const env = { ...process.env };
71
+ if (opts.backend)
72
+ env.BROWSER_BACKEND = opts.backend;
73
+ const config = loadConfig(env);
74
+ const checklistText = opts.checklist ? await readFile(opts.checklist, "utf8") : undefined;
75
+ process.stderr.write(`▸ Exploring ${opts.url}${opts.session ? ` (session: ${opts.session})` : ""}${opts.checklist ? ` (checklist: ${opts.checklist})` : ""}…\n`);
76
+ const result = await runExploration({
77
+ url: opts.url,
78
+ config,
79
+ sessionName: opts.session,
80
+ sessionFile: opts.sessionFile,
81
+ headed: opts.headed,
82
+ checklistText,
83
+ style: opts.style,
84
+ onProgress: (e) => process.stderr.write(` ▸ ${e}\n`),
85
+ });
86
+ process.stdout.write(`\n=== Exploration of ${result.study.url} (run ${result.runId}) ===\n`);
87
+ process.stdout.write(`Purpose: ${result.analysis.pageSemantics}\n`);
88
+ process.stdout.write(`LLM profile: ${config.llmProfile} · test cases: ${result.testCases.length}\n\n`);
89
+ for (const tc of result.testCases) {
90
+ process.stdout.write(`[${tc.id}] (${tc.priority} · ${tc.technique}) ${tc.title}\n`);
91
+ for (const step of tc.steps)
92
+ process.stdout.write(` - ${step}\n`);
93
+ process.stdout.write(` ⇒ ${tc.expected}\n`);
94
+ if (tc.elementRefs.length)
95
+ process.stdout.write(` refs: ${tc.elementRefs.join(", ")}\n`);
96
+ process.stdout.write("\n");
97
+ }
98
+ if (result.validation) {
99
+ const v = result.validation;
100
+ process.stdout.write(`=== Validation: ${Math.round(v.greenRatio * 100)}% green (flaky: ${v.flakyCount}) ===\n`);
101
+ for (const r of v.results) {
102
+ const mark = r.status === "passed" ? "✓" : r.status === "flaky" ? "~" : "✗";
103
+ process.stdout.write(` ${mark} ${r.test}\n`);
104
+ }
105
+ }
106
+ if (result.scores.length > 0) {
107
+ process.stdout.write("\n=== Metrics ===\n");
108
+ for (const s of result.scores) {
109
+ process.stdout.write(` ${s.name}: ${s.value.toFixed(2)}${s.comment ? ` — ${s.comment}` : ""}\n`);
110
+ }
111
+ }
112
+ if (result.pilot) {
113
+ process.stdout.write(`\n=== Pilot: ${result.pilot.verdict.toUpperCase()} ===\n ${result.pilot.reason}\n → ${result.pilot.guidance}\n`);
114
+ }
115
+ process.stdout.write(`\nArtifacts: ${result.runDir}\n`);
116
+ });
117
+ program
118
+ .command("dataset-add")
119
+ .description("Add a run (study.json) to an experiment dataset")
120
+ .requiredOption("--from-run <dir>", "runs/<id> folder")
121
+ .requiredOption("--to <file>", "dataset file (JSON)")
122
+ .action(async (opts) => {
123
+ const study = JSON.parse(await readFile(join(opts.fromRun, "study.json"), "utf8"));
124
+ let pageSemantics = "";
125
+ try {
126
+ const rep = JSON.parse(await readFile(join(opts.fromRun, "report.json"), "utf8"));
127
+ pageSemantics = rep.pageSemantics ?? "";
128
+ }
129
+ catch {
130
+ // report.json is optional
131
+ }
132
+ let ds = { items: [] };
133
+ try {
134
+ ds = JSON.parse(await readFile(opts.to, "utf8"));
135
+ }
136
+ catch {
137
+ // new dataset
138
+ }
139
+ const id = `item-${ds.items.length + 1}`;
140
+ ds.items.push({ id, study, pageSemantics });
141
+ await mkdir(dirname(opts.to) || ".", { recursive: true });
142
+ await writeFile(opts.to, JSON.stringify(ds, null, 2), "utf8");
143
+ process.stdout.write(`Added ${id} → ${opts.to} (total items: ${ds.items.length})\n`);
144
+ });
145
+ program
146
+ .command("experiment")
147
+ .description("Compare prompt versions on a dataset (B2 self-improvement)")
148
+ .requiredOption("--dataset <file>", "dataset file (JSON)")
149
+ .option("--candidate <spec>", "promptName=file.md — candidate prompt vs production")
150
+ .option("--target <metric>", "target verdict metric", "grounding")
151
+ .action(async (opts) => {
152
+ const config = loadConfig(process.env);
153
+ const keys = {
154
+ anthropicApiKey: config.anthropicApiKey,
155
+ openrouterApiKey: config.openrouterApiKey,
156
+ };
157
+ const ds = JSON.parse(await readFile(opts.dataset, "utf8"));
158
+ const variants = [{ label: "production", prompts: new PromptRegistry() }];
159
+ if (opts.candidate) {
160
+ const eq = opts.candidate.indexOf("=");
161
+ const name = opts.candidate.slice(0, eq);
162
+ const text = await readFile(opts.candidate.slice(eq + 1), "utf8");
163
+ variants.push({
164
+ label: "candidate",
165
+ prompts: new PromptRegistry({ local: { ...LOCAL_PROMPTS, [name]: text } }),
166
+ });
167
+ }
168
+ process.stderr.write(`▸ Experiment: ${ds.items.length} items × ${variants.length} versions…\n`);
169
+ const result = await runExperiment(ds.items, variants, {
170
+ designInvoke: structuredInvoker(makeModel(config.models.reasoning, keys)),
171
+ judgeInvoke: structuredInvoker(makeModel(config.models.judge, keys)),
172
+ }, { target: opts.target });
173
+ process.stdout.write(`\n=== Experiment (${ds.items.length} items) ===\n`);
174
+ for (const v of result.perVariant) {
175
+ process.stdout.write(`\n[${v.label}]\n`);
176
+ for (const [name, val] of Object.entries(v.meanScores)) {
177
+ process.stdout.write(` ${name}: ${val.toFixed(3)}\n`);
178
+ }
179
+ }
180
+ if (result.verdict) {
181
+ const vd = result.verdict;
182
+ const reg = vd.guardrailRegressions.length ? `; regressions: ${vd.guardrailRegressions.join(", ")}` : "";
183
+ process.stdout.write(`\n=== Verdict: candidate ${vd.improved ? "BETTER ✓" : "NOT better ✗"} (${vd.target} Δ=${vd.delta.toFixed(3)})${reg} ===\n`);
184
+ process.stdout.write(vd.improved
185
+ ? " → the version can be promoted (Langfuse label=production) — runbook promote-prompt.\n"
186
+ : " → reject/iterate the prompt.\n");
187
+ }
188
+ });
189
+ program
190
+ .command("design")
191
+ .description("Explore a page and WRITE test cases in ATC format (.md, with selectors), WITHOUT code")
192
+ .requiredOption("--url <url>", "page URL")
193
+ .option("--session <name>", "name of the saved session")
194
+ .option("--session-file <path>", "path to a storageState file")
195
+ .option("--checklist <file>", "checklist file — guides what to test")
196
+ .option("--style <s>", "planning style: happy | negative | coverage | all")
197
+ .option("--headed", "visible browser (debug)")
198
+ .action(async (opts) => {
199
+ const config = loadConfig(process.env);
200
+ const checklistText = opts.checklist ? await readFile(opts.checklist, "utf8") : undefined;
201
+ process.stderr.write(`▸ Designing test cases for ${opts.url}${opts.session ? ` (session: ${opts.session})` : ""}…\n`);
202
+ const result = await runDesign({
203
+ url: opts.url,
204
+ config,
205
+ sessionName: opts.session,
206
+ sessionFile: opts.sessionFile,
207
+ checklistText,
208
+ style: opts.style,
209
+ headed: opts.headed,
210
+ onProgress: (e) => process.stderr.write(` ▸ ${e}\n`),
211
+ });
212
+ process.stdout.write(`\n=== ${result.testCases.length} test cases → ${result.runDir}\\testcases\\ ===\n`);
213
+ for (const tc of result.testCases) {
214
+ const exec = tc.execution === "manual" ? "MTC/manual" : "ATC/auto";
215
+ process.stdout.write(`[${exec} · ${tc.priority}/${tc.type}] ${tc.title}\n`);
216
+ }
217
+ for (const f of result.testCaseFiles)
218
+ process.stdout.write(` ${f}\n`);
219
+ if (result.scores.length > 0) {
220
+ process.stdout.write("\n=== Metrics ===\n");
221
+ for (const s of result.scores) {
222
+ process.stdout.write(` ${s.name}: ${s.value.toFixed(2)}${s.comment ? ` — ${s.comment}` : ""}\n`);
223
+ }
224
+ }
225
+ });
226
+ program
227
+ .command("automate")
228
+ .description("Generate @playwright/test from ready cases (runs/<id>/testcases/*.md)")
229
+ .requiredOption("--run <dir>", "design run folder (runs/<id>)")
230
+ .option("--validate", "run the generated tests (a session is required)")
231
+ .option("--session <name>", "session name for validation")
232
+ .option("--session-file <path>", "path to storageState for validation")
233
+ .action(async (opts) => {
234
+ const config = loadConfig(process.env);
235
+ process.stderr.write(`▸ Automating cases from ${opts.run}…\n`);
236
+ const result = await runAutomate({
237
+ runDir: opts.run,
238
+ config,
239
+ validate: opts.validate,
240
+ sessionName: opts.session,
241
+ sessionFile: opts.sessionFile,
242
+ onProgress: (e) => process.stderr.write(` ▸ ${e}\n`),
243
+ });
244
+ process.stdout.write(`\n=== ${result.specFiles.length} spec files → ${result.runDir}\\tests\\ ===\n`);
245
+ for (const f of result.specFiles)
246
+ process.stdout.write(` ${f}\n`);
247
+ if (result.validation) {
248
+ process.stdout.write(`\nValidation: ${Math.round(result.validation.greenRatio * 100)}% green out of ${result.validation.results.length} tests\n`);
249
+ }
250
+ });
251
+ program
252
+ .command("promote")
253
+ .description("Promote manual MTC case(s) to automatable ATC (.md only; run `automate` to generate code)")
254
+ .requiredOption("--run <dir>", "run folder (runs/<id>)")
255
+ .requiredOption("--cases <ids>", "comma-separated MTC ids, e.g. MTC-DEMO-001,MTC-DEMO-003")
256
+ .option("--session <name>", "session for the live selector fallback")
257
+ .option("--session-file <path>", "storageState path for the live selector fallback")
258
+ .action(async (opts) => {
259
+ const config = loadConfig(process.env);
260
+ const runDir = resolve(opts.run);
261
+ const ids = opts.cases.split(",").map((s) => s.trim()).filter(Boolean);
262
+ // Live fallback only when a session is provided (best-effort — see note).
263
+ let collectLive;
264
+ let storageState;
265
+ if (opts.sessionFile)
266
+ storageState = await new SessionStore(resolve(".auth")).loadFile(resolve(opts.sessionFile));
267
+ else if (opts.session)
268
+ storageState = await new SessionStore(resolve(".auth")).load(opts.session);
269
+ if (storageState) {
270
+ collectLive = async (url, refs) => {
271
+ const gateway = makeGateway({ backend: config.browser.backend, storageState, channel: config.browser.channel });
272
+ try {
273
+ await gateway.observe({ url });
274
+ const verified = await gateway.verify(refs.map((ref) => ({ ref, role: "", name: undefined, interactive: true, rank: 0 })));
275
+ const out = new Map();
276
+ for (const v of verified)
277
+ if (v.verified)
278
+ out.set(v.ref, locatorFor(v));
279
+ return out;
280
+ }
281
+ finally {
282
+ await gateway.close();
283
+ }
284
+ };
285
+ }
286
+ process.stderr.write(`▸ Promoting ${String(ids.length)} case(s) from ${opts.run}…\n`);
287
+ for (const id of ids) {
288
+ const res = await promoteCase(runDir, id, { collectLive });
289
+ process.stdout.write(`${res.oldId} → ${res.newId}${res.warning ? ` (⚠ ${res.warning})` : ""}\n`);
290
+ }
291
+ process.stdout.write(`\nDone. Run \`cairn automate --run ${opts.run}\` to generate code for the new ATC case(s).\n`);
292
+ });
293
+ /**
294
+ * Run the CLI. Shared by the primary `cairn` entry (this file) and the deprecated
295
+ * `lex-bot` alias shim (./lex-bot.ts), so both go through the exact same code path.
296
+ */
297
+ export async function runCli() {
298
+ const cliArgs = process.argv.slice(2);
299
+ if (cliArgs.length === 0 && process.stdin.isTTY && process.stdout.isTTY) {
300
+ // No command in an interactive terminal → launch the TUI (lazy: keeps React/Ink
301
+ // out of every other code path, incl. library embedders).
302
+ const { mountTui } = await import("../tui/index.js");
303
+ await mountTui();
304
+ }
305
+ else if (cliArgs.length === 0) {
306
+ // No command but non-TTY (pipe/CI) → print usage instead of crashing Ink raw-mode.
307
+ program.outputHelp();
308
+ }
309
+ else {
310
+ await program.parseAsync(process.argv).catch((e) => {
311
+ process.stderr.write(`${e.message}\n`);
312
+ process.exitCode = 1;
313
+ });
314
+ }
315
+ }
316
+ // Auto-run only when invoked directly as the `cairn` bin — NOT when imported by the
317
+ // `lex-bot` alias shim (which calls runCli() itself after printing the deprecation notice).
318
+ const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
319
+ if (invokedDirectly) {
320
+ await runCli();
321
+ }
322
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=lex-bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lex-bot.d.ts","sourceRoot":"","sources":["../../src/cli/lex-bot.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Deprecated `lex-bot` CLI alias (C0-03). Prints a one-line deprecation notice to
4
+ * stderr, then runs the exact same code path as `cairn`. Kept for 1–2 releases so
5
+ * existing scripts/aliases keep working; will be removed once users have migrated.
6
+ */
7
+ import { LEXBOT_CLI_NOTICE } from "./branding.js";
8
+ import { runCli } from "./index.js";
9
+ process.stderr.write(`${LEXBOT_CLI_NOTICE}\n`);
10
+ await runCli();
11
+ //# sourceMappingURL=lex-bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lex-bot.js","sourceRoot":"","sources":["../../src/cli/lex-bot.ts"],"names":[],"mappings":";AACA;;;;GAIG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,iBAAiB,IAAI,CAAC,CAAC;AAC/C,MAAM,MAAM,EAAE,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { StructuredInvoke } from "../llm/structured.js";
2
+ import type { PromptRegistry } from "../prompts/index.js";
3
+ import type { PageStudy } from "../observe/index.js";
4
+ import type { TestCase } from "../design/index.js";
5
+ import type { VerifiedElement } from "../browser/types.js";
6
+ import { type Transition } from "../probe/index.js";
7
+ import type { ParsedTestCase } from "../artifacts/testcase-md.js";
8
+ import { type GeneratedSuite } from "./schema.js";
9
+ export type { GeneratedSuite, FileBlob } from "./schema.js";
10
+ export { GeneratedSuiteSchema, FileBlobSchema } from "./schema.js";
11
+ export interface CodegenInput {
12
+ study: PageStudy;
13
+ pageSemantics: string;
14
+ testCases: TestCase[];
15
+ /** Repair context: which tests failed (repair node). */
16
+ repairHint?: string;
17
+ /** Discovered elements (count≥1) from verify; fallback — study.elements. */
18
+ elements?: VerifiedElement[];
19
+ /** Observed state transitions (act→observe, Stage B). */
20
+ transitions?: Transition[];
21
+ }
22
+ export interface CodegenDeps {
23
+ invoke: StructuredInvoke;
24
+ prompts: PromptRegistry;
25
+ }
26
+ /** Generate a runnable `@playwright/test` suite from test cases (ADR-0005). */
27
+ export declare function generateSuite(input: CodegenInput, deps: CodegenDeps): Promise<GeneratedSuite>;
28
+ /**
29
+ * `automate` command: generate @playwright/test from PARSED test cases (.md).
30
+ * Locators are taken directly from the cases (Selectors section) — those are what we use in the code.
31
+ */
32
+ export declare function automateCases(cases: ParsedTestCase[], ctx: {
33
+ baseUrl: string;
34
+ pageSemantics: string;
35
+ }, deps: CodegenDeps): Promise<GeneratedSuite>;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/codegen/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAExE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,yDAAyD;IACzD,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;CACzB;AAYD,+EAA+E;AAC/E,wBAAsB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CA8BnG;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,cAAc,EAAE,EACvB,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC/C,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,cAAc,CAAC,CAqBzB"}
@@ -0,0 +1,63 @@
1
+ import { HumanMessage } from "@langchain/core/messages";
2
+ import { formatTransitions } from "../probe/index.js";
3
+ import { detectLanguage } from "../checklist/index.js";
4
+ import { GeneratedSuiteSchema } from "./schema.js";
5
+ export { GeneratedSuiteSchema, FileBlobSchema } from "./schema.js";
6
+ /** Safe relative path inside runs/<id>/tests (no traversal/absolute paths). */
7
+ function sanitizePath(p) {
8
+ const cleaned = p
9
+ .replace(/\\/g, "/")
10
+ .replace(/\.\.+/g, "")
11
+ .replace(/^\/+/, "")
12
+ .trim();
13
+ return cleaned.length > 0 ? cleaned : "test.spec.ts";
14
+ }
15
+ /** Generate a runnable `@playwright/test` suite from test cases (ADR-0005). */
16
+ export async function generateSuite(input, deps) {
17
+ const els = input.elements ?? input.study.elements.map((e) => ({ ...e, count: 1, verified: true }));
18
+ const elements = els
19
+ .filter((e) => e.interactive)
20
+ .map((e) => `${e.ref} · ${e.role}${e.name ? ` "${e.name}"` : ""}${e.count > 1 ? ` (×${e.count} — repeated, .first())` : ""}${e.viaSwitcher ? ` [first click tab "${e.viaSwitcher.name ?? ""}"]` : ""}`)
21
+ .join("\n");
22
+ const testCases = input.testCases
23
+ .map((tc) => `${tc.id} [${tc.kind}/${tc.priority}/${tc.technique}] ${tc.title}: ${tc.steps.join("; ")} ⇒ ${tc.expected} (refs: ${tc.elementRefs.join(", ")})`)
24
+ .join("\n");
25
+ const prompt = await deps.prompts.getPrompt("qa-playwright-ts-writer", {
26
+ baseUrl: input.study.url,
27
+ pageSemantics: input.pageSemantics,
28
+ elements,
29
+ testCases,
30
+ transitions: formatTransitions(input.transitions ?? []),
31
+ });
32
+ const text = input.repairHint
33
+ ? `${prompt.text}\n\nREPAIR: the previous generation failed the tests: ${input.repairHint}\nFix the locators/navigation/assertions so the tests pass.`
34
+ : prompt.text;
35
+ const suite = await deps.invoke(GeneratedSuiteSchema, [new HumanMessage(text)]);
36
+ return { files: suite.files.map((f) => ({ path: sanitizePath(f.path), content: f.content })) };
37
+ }
38
+ /**
39
+ * `automate` command: generate @playwright/test from PARSED test cases (.md).
40
+ * Locators are taken directly from the cases (Selectors section) — those are what we use in the code.
41
+ */
42
+ export async function automateCases(cases, ctx, deps) {
43
+ const seen = new Map();
44
+ for (const c of cases)
45
+ for (const s of c.selectors)
46
+ if (!seen.has(s.locator))
47
+ seen.set(s.locator, s.label);
48
+ const elements = [...seen.entries()].map(([locator, label]) => `${label}: ${locator}`).join("\n");
49
+ const testCases = cases
50
+ .map((c, i) => `TC-${i + 1}: ${c.title}\n Steps: ${c.steps.join("; ")}\n Expected: ${c.expected.join("; ")}`)
51
+ .join("\n\n");
52
+ const prompt = await deps.prompts.getPrompt("qa-playwright-ts-writer", {
53
+ baseUrl: ctx.baseUrl,
54
+ pageSemantics: ctx.pageSemantics,
55
+ elements,
56
+ testCases,
57
+ transitions: "(from the case steps)",
58
+ language: detectLanguage(testCases),
59
+ });
60
+ const suite = await deps.invoke(GeneratedSuiteSchema, [new HumanMessage(prompt.text)]);
61
+ return { files: suite.files.map((f) => ({ path: sanitizePath(f.path), content: f.content })) };
62
+ }
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/codegen/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ export declare const FileBlobSchema: z.ZodObject<{
3
+ path: z.ZodString;
4
+ content: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export type FileBlob = z.infer<typeof FileBlobSchema>;
7
+ export declare const GeneratedSuiteSchema: z.ZodObject<{
8
+ files: z.ZodArray<z.ZodObject<{
9
+ path: z.ZodString;
10
+ content: z.ZodString;
11
+ }, z.core.$strip>>;
12
+ }, z.core.$strip>;
13
+ export type GeneratedSuite = z.infer<typeof GeneratedSuiteSchema>;
14
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/codegen/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,cAAc;;;iBAGzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,oBAAoB;;;;;iBAE/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ export const FileBlobSchema = z.object({
3
+ path: z.string(),
4
+ content: z.string(),
5
+ });
6
+ export const GeneratedSuiteSchema = z.object({
7
+ files: z.array(FileBlobSchema).min(1),
8
+ });
9
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/codegen/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACtC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Env-var resolution with the CAIRN_ prefix and backward-compatible fallbacks (C0-06).
3
+ *
4
+ * For each logical name, resolution order is:
5
+ * CAIRN_<name> → LEXBOT_<name> → LEX_<name> → <name> (bare/current)
6
+ *
7
+ * The new `CAIRN_` prefix and the current bare names are first-class; the legacy
8
+ * `LEXBOT_`/`LEX_` forms keep working but emit a one-time deprecation warning so
9
+ * users can migrate. Nothing is removed — this is purely additive back-compat.
10
+ */
11
+ export type EnvRecord = Record<string, string | undefined>;
12
+ /**
13
+ * Build an env reader bound to a raw env record. Returns `read(name)` which applies
14
+ * the CAIRN_ → legacy → bare resolution above. Legacy hits warn once per variable
15
+ * (deduped for the lifetime of this reader, i.e. once per process in the CLI).
16
+ */
17
+ export declare function createEnvReader(raw: EnvRecord, warn?: (msg: string) => void): (name: string) => string | undefined;
18
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAS3D;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,SAAS,EACd,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAkB,GACxC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAuBtC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Env-var resolution with the CAIRN_ prefix and backward-compatible fallbacks (C0-06).
3
+ *
4
+ * For each logical name, resolution order is:
5
+ * CAIRN_<name> → LEXBOT_<name> → LEX_<name> → <name> (bare/current)
6
+ *
7
+ * The new `CAIRN_` prefix and the current bare names are first-class; the legacy
8
+ * `LEXBOT_`/`LEX_` forms keep working but emit a one-time deprecation warning so
9
+ * users can migrate. Nothing is removed — this is purely additive back-compat.
10
+ */
11
+ /** Legacy product prefixes, in precedence order (newer legacy form first). */
12
+ const LEGACY_PREFIXES = ["LEXBOT_", "LEX_"];
13
+ const defaultWarn = (msg) => {
14
+ process.stderr.write(`${msg}\n`);
15
+ };
16
+ /**
17
+ * Build an env reader bound to a raw env record. Returns `read(name)` which applies
18
+ * the CAIRN_ → legacy → bare resolution above. Legacy hits warn once per variable
19
+ * (deduped for the lifetime of this reader, i.e. once per process in the CLI).
20
+ */
21
+ export function createEnvReader(raw, warn = defaultWarn) {
22
+ const warned = new Set();
23
+ return (name) => {
24
+ const preferred = raw[`CAIRN_${name}`];
25
+ if (preferred !== undefined)
26
+ return preferred;
27
+ for (const prefix of LEGACY_PREFIXES) {
28
+ const key = `${prefix}${name}`;
29
+ const value = raw[key];
30
+ if (value !== undefined) {
31
+ if (!warned.has(key)) {
32
+ warned.add(key);
33
+ warn(`[cairn] env ${key} is deprecated — use CAIRN_${name} instead ` +
34
+ `(old name still works; removal planned in 1–2 releases).`);
35
+ }
36
+ return value;
37
+ }
38
+ }
39
+ return raw[name];
40
+ };
41
+ }
42
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,8EAA8E;AAC9E,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,CAAU,CAAC;AAErD,MAAM,WAAW,GAAG,CAAC,GAAW,EAAQ,EAAE;IACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAc,EACd,OAA8B,WAAW;IAEzC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,OAAO,CAAC,IAAY,EAAsB,EAAE;QAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,SAAS,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAE9C,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACrC,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;YAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACrB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAChB,IAAI,CACF,eAAe,GAAG,8BAA8B,IAAI,WAAW;wBAC7D,0DAA0D,CAC7D,CAAC;gBACJ,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { AppConfig } from "./schema.js";
2
+ export type { AppConfig, ModelsConfig, ModelTier, Provider, LlmProfile, BrowserBackend } from "./schema.js";
3
+ type Env = Record<string, string | undefined>;
4
+ /**
5
+ * Read and validate configuration from env. Pure function (env is injected for tests).
6
+ * Throws a clear error on an invalid profile/backend or a missing key for a required provider.
7
+ */
8
+ export declare function loadConfig(env?: Env, opts?: {
9
+ warn?: (msg: string) => void;
10
+ }): AppConfig;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,aAAa,CAAC;AAIvD,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5G,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C;;;GAGG;AACH,wBAAgB,UAAU,CACxB,GAAG,GAAE,GAAiB,EACtB,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GAC1C,SAAS,CA6EX"}