@oscharko-dev/keiko 0.1.0-beta.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 (450) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +7 -0
  3. package/README.md +621 -0
  4. package/TRADEMARKS.md +41 -0
  5. package/dist/audit/aggregate.d.ts +5 -0
  6. package/dist/audit/aggregate.js +25 -0
  7. package/dist/audit/build.d.ts +2 -0
  8. package/dist/audit/build.js +224 -0
  9. package/dist/audit/errors.d.ts +25 -0
  10. package/dist/audit/errors.js +39 -0
  11. package/dist/audit/index-api.d.ts +14 -0
  12. package/dist/audit/index-api.js +131 -0
  13. package/dist/audit/index.d.ts +12 -0
  14. package/dist/audit/index.js +17 -0
  15. package/dist/audit/persist.d.ts +8 -0
  16. package/dist/audit/persist.js +40 -0
  17. package/dist/audit/redaction.d.ts +3 -0
  18. package/dist/audit/redaction.js +61 -0
  19. package/dist/audit/report.d.ts +18 -0
  20. package/dist/audit/report.js +50 -0
  21. package/dist/audit/retention.d.ts +3 -0
  22. package/dist/audit/retention.js +95 -0
  23. package/dist/audit/runid.d.ts +1 -0
  24. package/dist/audit/runid.js +29 -0
  25. package/dist/audit/side-file.d.ts +12 -0
  26. package/dist/audit/side-file.js +82 -0
  27. package/dist/audit/store.d.ts +12 -0
  28. package/dist/audit/store.js +198 -0
  29. package/dist/audit/types.d.ts +188 -0
  30. package/dist/audit/types.js +8 -0
  31. package/dist/audit/workflow-evidence.d.ts +27 -0
  32. package/dist/audit/workflow-evidence.js +145 -0
  33. package/dist/cli/context.d.ts +2 -0
  34. package/dist/cli/context.js +102 -0
  35. package/dist/cli/evaluate.d.ts +7 -0
  36. package/dist/cli/evaluate.js +207 -0
  37. package/dist/cli/evidence.d.ts +8 -0
  38. package/dist/cli/evidence.js +88 -0
  39. package/dist/cli/gateway-config.d.ts +10 -0
  40. package/dist/cli/gateway-config.js +12 -0
  41. package/dist/cli/gen-tests.d.ts +7 -0
  42. package/dist/cli/gen-tests.js +208 -0
  43. package/dist/cli/index.d.ts +2 -0
  44. package/dist/cli/index.js +14 -0
  45. package/dist/cli/investigate.d.ts +8 -0
  46. package/dist/cli/investigate.js +242 -0
  47. package/dist/cli/models.d.ts +3 -0
  48. package/dist/cli/models.js +64 -0
  49. package/dist/cli/run.d.ts +7 -0
  50. package/dist/cli/run.js +187 -0
  51. package/dist/cli/runner.d.ts +6 -0
  52. package/dist/cli/runner.js +83 -0
  53. package/dist/cli/ui.d.ts +31 -0
  54. package/dist/cli/ui.js +240 -0
  55. package/dist/cli/verify.d.ts +2 -0
  56. package/dist/cli/verify.js +103 -0
  57. package/dist/evaluations/fixtures/bug-investigation/happy-path.d.ts +2 -0
  58. package/dist/evaluations/fixtures/bug-investigation/happy-path.js +66 -0
  59. package/dist/evaluations/fixtures/bug-investigation/investigation-only.d.ts +2 -0
  60. package/dist/evaluations/fixtures/bug-investigation/investigation-only.js +39 -0
  61. package/dist/evaluations/fixtures/bug-investigation/unsafe-action.d.ts +2 -0
  62. package/dist/evaluations/fixtures/bug-investigation/unsafe-action.js +37 -0
  63. package/dist/evaluations/fixtures/index.d.ts +7 -0
  64. package/dist/evaluations/fixtures/index.js +35 -0
  65. package/dist/evaluations/fixtures/support.d.ts +5 -0
  66. package/dist/evaluations/fixtures/support.js +42 -0
  67. package/dist/evaluations/fixtures/unit-tests/happy-path.d.ts +2 -0
  68. package/dist/evaluations/fixtures/unit-tests/happy-path.js +40 -0
  69. package/dist/evaluations/fixtures/unit-tests/retry-then-accept.d.ts +2 -0
  70. package/dist/evaluations/fixtures/unit-tests/retry-then-accept.js +39 -0
  71. package/dist/evaluations/fixtures/unit-tests/unsafe-action.d.ts +2 -0
  72. package/dist/evaluations/fixtures/unit-tests/unsafe-action.js +32 -0
  73. package/dist/evaluations/index.d.ts +12 -0
  74. package/dist/evaluations/index.js +12 -0
  75. package/dist/evaluations/manifest-check.d.ts +1 -0
  76. package/dist/evaluations/manifest-check.js +48 -0
  77. package/dist/evaluations/model-provider.d.ts +12 -0
  78. package/dist/evaluations/model-provider.js +26 -0
  79. package/dist/evaluations/render.d.ts +2 -0
  80. package/dist/evaluations/render.js +59 -0
  81. package/dist/evaluations/runner-support.d.ts +27 -0
  82. package/dist/evaluations/runner-support.js +163 -0
  83. package/dist/evaluations/runner.d.ts +20 -0
  84. package/dist/evaluations/runner.js +174 -0
  85. package/dist/evaluations/scorer.d.ts +14 -0
  86. package/dist/evaluations/scorer.js +131 -0
  87. package/dist/evaluations/scripted-model.d.ts +6 -0
  88. package/dist/evaluations/scripted-model.js +26 -0
  89. package/dist/evaluations/surface-parity.d.ts +2 -0
  90. package/dist/evaluations/surface-parity.js +184 -0
  91. package/dist/evaluations/types.d.ts +74 -0
  92. package/dist/evaluations/types.js +16 -0
  93. package/dist/gateway/capabilities.d.ts +11 -0
  94. package/dist/gateway/capabilities.data.d.ts +2 -0
  95. package/dist/gateway/capabilities.data.js +203 -0
  96. package/dist/gateway/capabilities.js +41 -0
  97. package/dist/gateway/config.d.ts +15 -0
  98. package/dist/gateway/config.js +154 -0
  99. package/dist/gateway/errors.d.ts +72 -0
  100. package/dist/gateway/errors.js +82 -0
  101. package/dist/gateway/gateway.d.ts +19 -0
  102. package/dist/gateway/gateway.js +94 -0
  103. package/dist/gateway/index.d.ts +10 -0
  104. package/dist/gateway/index.js +11 -0
  105. package/dist/gateway/model-selection.d.ts +9 -0
  106. package/dist/gateway/model-selection.js +36 -0
  107. package/dist/gateway/normalize.d.ts +7 -0
  108. package/dist/gateway/normalize.js +93 -0
  109. package/dist/gateway/openai-adapter.d.ts +20 -0
  110. package/dist/gateway/openai-adapter.js +263 -0
  111. package/dist/gateway/redaction.d.ts +1 -0
  112. package/dist/gateway/redaction.js +51 -0
  113. package/dist/gateway/resilience.d.ts +24 -0
  114. package/dist/gateway/resilience.js +166 -0
  115. package/dist/gateway/types.d.ts +108 -0
  116. package/dist/gateway/types.js +2 -0
  117. package/dist/harness/adapters.d.ts +23 -0
  118. package/dist/harness/adapters.js +38 -0
  119. package/dist/harness/context.d.ts +33 -0
  120. package/dist/harness/context.js +21 -0
  121. package/dist/harness/emitter.d.ts +15 -0
  122. package/dist/harness/emitter.js +72 -0
  123. package/dist/harness/errors.d.ts +21 -0
  124. package/dist/harness/errors.js +39 -0
  125. package/dist/harness/executor.d.ts +3 -0
  126. package/dist/harness/executor.js +211 -0
  127. package/dist/harness/fingerprint.d.ts +6 -0
  128. package/dist/harness/fingerprint.js +43 -0
  129. package/dist/harness/index.d.ts +9 -0
  130. package/dist/harness/index.js +13 -0
  131. package/dist/harness/loop.d.ts +3 -0
  132. package/dist/harness/loop.js +159 -0
  133. package/dist/harness/patcher.d.ts +4 -0
  134. package/dist/harness/patcher.js +49 -0
  135. package/dist/harness/planner.d.ts +3 -0
  136. package/dist/harness/planner.js +21 -0
  137. package/dist/harness/ports.d.ts +61 -0
  138. package/dist/harness/ports.js +4 -0
  139. package/dist/harness/session.d.ts +25 -0
  140. package/dist/harness/session.js +116 -0
  141. package/dist/harness/sinks.d.ts +30 -0
  142. package/dist/harness/sinks.js +72 -0
  143. package/dist/harness/tasks/explain-plan.d.ts +3 -0
  144. package/dist/harness/tasks/explain-plan.js +29 -0
  145. package/dist/harness/tasks/generate-unit-tests.d.ts +3 -0
  146. package/dist/harness/tasks/generate-unit-tests.js +28 -0
  147. package/dist/harness/tasks/investigate-bug.d.ts +3 -0
  148. package/dist/harness/tasks/investigate-bug.js +31 -0
  149. package/dist/harness/tasks/policy.d.ts +11 -0
  150. package/dist/harness/tasks/policy.js +22 -0
  151. package/dist/harness/tasks/verify.d.ts +3 -0
  152. package/dist/harness/tasks/verify.js +16 -0
  153. package/dist/harness/types.d.ts +270 -0
  154. package/dist/harness/types.js +33 -0
  155. package/dist/index.d.ts +11 -0
  156. package/dist/index.js +36 -0
  157. package/dist/sdk/index.d.ts +9 -0
  158. package/dist/sdk/index.js +37 -0
  159. package/dist/sdk/run-agent.d.ts +16 -0
  160. package/dist/sdk/run-agent.js +56 -0
  161. package/dist/tools/browser/cdp-client.d.ts +35 -0
  162. package/dist/tools/browser/cdp-client.js +218 -0
  163. package/dist/tools/browser/errors.d.ts +25 -0
  164. package/dist/tools/browser/errors.js +55 -0
  165. package/dist/tools/browser/index.d.ts +5 -0
  166. package/dist/tools/browser/index.js +6 -0
  167. package/dist/tools/browser/session.d.ts +44 -0
  168. package/dist/tools/browser/session.js +748 -0
  169. package/dist/tools/browser/types.d.ts +48 -0
  170. package/dist/tools/browser/types.js +2 -0
  171. package/dist/tools/browser/validators.d.ts +5 -0
  172. package/dist/tools/browser/validators.js +97 -0
  173. package/dist/tools/errors.d.ts +59 -0
  174. package/dist/tools/errors.js +94 -0
  175. package/dist/tools/exec.d.ts +42 -0
  176. package/dist/tools/exec.js +327 -0
  177. package/dist/tools/index.d.ts +11 -0
  178. package/dist/tools/index.js +14 -0
  179. package/dist/tools/patch-content.d.ts +10 -0
  180. package/dist/tools/patch-content.js +126 -0
  181. package/dist/tools/patch-normalize.d.ts +1 -0
  182. package/dist/tools/patch-normalize.js +80 -0
  183. package/dist/tools/patch-parse.d.ts +8 -0
  184. package/dist/tools/patch-parse.js +201 -0
  185. package/dist/tools/patch.d.ts +18 -0
  186. package/dist/tools/patch.js +403 -0
  187. package/dist/tools/registry.d.ts +36 -0
  188. package/dist/tools/registry.js +231 -0
  189. package/dist/tools/sandbox.d.ts +8 -0
  190. package/dist/tools/sandbox.js +121 -0
  191. package/dist/tools/schemas.d.ts +2 -0
  192. package/dist/tools/schemas.js +51 -0
  193. package/dist/tools/terminal-policy.d.ts +9 -0
  194. package/dist/tools/terminal-policy.js +313 -0
  195. package/dist/tools/types.d.ts +99 -0
  196. package/dist/tools/types.js +103 -0
  197. package/dist/tools/writer.d.ts +7 -0
  198. package/dist/tools/writer.js +20 -0
  199. package/dist/ui/browser.d.ts +10 -0
  200. package/dist/ui/browser.js +231 -0
  201. package/dist/ui/chat-handlers.d.ts +4 -0
  202. package/dist/ui/chat-handlers.js +281 -0
  203. package/dist/ui/csp-hashes.json +17 -0
  204. package/dist/ui/csp.d.ts +2 -0
  205. package/dist/ui/csp.js +66 -0
  206. package/dist/ui/deps.d.ts +34 -0
  207. package/dist/ui/deps.js +137 -0
  208. package/dist/ui/evidence.d.ts +27 -0
  209. package/dist/ui/evidence.js +142 -0
  210. package/dist/ui/files-deny.d.ts +2 -0
  211. package/dist/ui/files-deny.js +12 -0
  212. package/dist/ui/files.d.ts +65 -0
  213. package/dist/ui/files.js +492 -0
  214. package/dist/ui/headers.d.ts +2 -0
  215. package/dist/ui/headers.js +21 -0
  216. package/dist/ui/host-check.d.ts +2 -0
  217. package/dist/ui/host-check.js +58 -0
  218. package/dist/ui/index.d.ts +20 -0
  219. package/dist/ui/index.js +23 -0
  220. package/dist/ui/load-csp.d.ts +1 -0
  221. package/dist/ui/load-csp.js +28 -0
  222. package/dist/ui/read-handlers.d.ts +8 -0
  223. package/dist/ui/read-handlers.js +247 -0
  224. package/dist/ui/routes.d.ts +36 -0
  225. package/dist/ui/routes.js +129 -0
  226. package/dist/ui/run-engine.d.ts +20 -0
  227. package/dist/ui/run-engine.js +345 -0
  228. package/dist/ui/run-handlers.d.ts +8 -0
  229. package/dist/ui/run-handlers.js +431 -0
  230. package/dist/ui/run-request.d.ts +13 -0
  231. package/dist/ui/run-request.js +219 -0
  232. package/dist/ui/runs.d.ts +43 -0
  233. package/dist/ui/runs.js +92 -0
  234. package/dist/ui/server.d.ts +11 -0
  235. package/dist/ui/server.js +143 -0
  236. package/dist/ui/sink.d.ts +27 -0
  237. package/dist/ui/sink.js +80 -0
  238. package/dist/ui/sse.d.ts +7 -0
  239. package/dist/ui/sse.js +27 -0
  240. package/dist/ui/static/404.html +1 -0
  241. package/dist/ui/static/_next/static/ca-A01hy9W98aRvMZKdAw/_buildManifest.js +1 -0
  242. package/dist/ui/static/_next/static/ca-A01hy9W98aRvMZKdAw/_ssgManifest.js +1 -0
  243. package/dist/ui/static/_next/static/chunks/255-d47fd57964443afe.js +1 -0
  244. package/dist/ui/static/_next/static/chunks/4-be1fef693af8e088.js +1 -0
  245. package/dist/ui/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
  246. package/dist/ui/static/_next/static/chunks/app/_not-found/page-75825b09bcecad97.js +1 -0
  247. package/dist/ui/static/_next/static/chunks/app/launch/page-9c86a13c29884245.js +1 -0
  248. package/dist/ui/static/_next/static/chunks/app/layout-bdea63fe87947d50.js +1 -0
  249. package/dist/ui/static/_next/static/chunks/app/page-4168c12c68b7a853.js +1 -0
  250. package/dist/ui/static/_next/static/chunks/framework-a6e0b7e30f98059a.js +1 -0
  251. package/dist/ui/static/_next/static/chunks/main-778a50aebff02192.js +1 -0
  252. package/dist/ui/static/_next/static/chunks/main-app-30679af7240d63e9.js +1 -0
  253. package/dist/ui/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
  254. package/dist/ui/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
  255. package/dist/ui/static/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  256. package/dist/ui/static/_next/static/chunks/webpack-4a462cecab786e93.js +1 -0
  257. package/dist/ui/static/_next/static/css/be7cb54d5c5673b6.css +1 -0
  258. package/dist/ui/static/assets/editors/goland.svg +35 -0
  259. package/dist/ui/static/assets/editors/intellij.svg +39 -0
  260. package/dist/ui/static/assets/editors/pycharm.svg +58 -0
  261. package/dist/ui/static/assets/editors/rustrover.svg +19 -0
  262. package/dist/ui/static/assets/editors/vscode.svg +1 -0
  263. package/dist/ui/static/assets/editors/webstorm.svg +21 -0
  264. package/dist/ui/static/assets/icons/anthropic.svg +1 -0
  265. package/dist/ui/static/assets/icons/brave.svg +1 -0
  266. package/dist/ui/static/assets/icons/css3.svg +1 -0
  267. package/dist/ui/static/assets/icons/docker.svg +1 -0
  268. package/dist/ui/static/assets/icons/git.svg +1 -0
  269. package/dist/ui/static/assets/icons/github.svg +1 -0
  270. package/dist/ui/static/assets/icons/go.svg +1 -0
  271. package/dist/ui/static/assets/icons/gradle.svg +1 -0
  272. package/dist/ui/static/assets/icons/grafana.svg +1 -0
  273. package/dist/ui/static/assets/icons/graphql.svg +1 -0
  274. package/dist/ui/static/assets/icons/html5.svg +1 -0
  275. package/dist/ui/static/assets/icons/image.svg +1 -0
  276. package/dist/ui/static/assets/icons/java.svg +1 -0
  277. package/dist/ui/static/assets/icons/javascript.svg +1 -0
  278. package/dist/ui/static/assets/icons/json.svg +1 -0
  279. package/dist/ui/static/assets/icons/kafka.svg +1 -0
  280. package/dist/ui/static/assets/icons/kubernetes.svg +1 -0
  281. package/dist/ui/static/assets/icons/linear.svg +1 -0
  282. package/dist/ui/static/assets/icons/markdown.svg +1 -0
  283. package/dist/ui/static/assets/icons/nginx.svg +1 -0
  284. package/dist/ui/static/assets/icons/nodejs.svg +1 -0
  285. package/dist/ui/static/assets/icons/notion.svg +1 -0
  286. package/dist/ui/static/assets/icons/openai.svg +1 -0
  287. package/dist/ui/static/assets/icons/playwright.svg +1 -0
  288. package/dist/ui/static/assets/icons/postgresql.svg +1 -0
  289. package/dist/ui/static/assets/icons/prometheus.svg +1 -0
  290. package/dist/ui/static/assets/icons/properties.svg +1 -0
  291. package/dist/ui/static/assets/icons/puppeteer.svg +1 -0
  292. package/dist/ui/static/assets/icons/python.svg +1 -0
  293. package/dist/ui/static/assets/icons/react.svg +1 -0
  294. package/dist/ui/static/assets/icons/redis.svg +1 -0
  295. package/dist/ui/static/assets/icons/rust.svg +1 -0
  296. package/dist/ui/static/assets/icons/sentry.svg +1 -0
  297. package/dist/ui/static/assets/icons/slack.svg +1 -0
  298. package/dist/ui/static/assets/icons/spring.svg +1 -0
  299. package/dist/ui/static/assets/icons/typescript.svg +1 -0
  300. package/dist/ui/static/assets/icons/upstash.svg +1 -0
  301. package/dist/ui/static/assets/icons/yaml.svg +1 -0
  302. package/dist/ui/static/assets/keiko-logo.svg +10 -0
  303. package/dist/ui/static/index.html +1 -0
  304. package/dist/ui/static/index.txt +19 -0
  305. package/dist/ui/static/keiko-logo.svg +10 -0
  306. package/dist/ui/static/launch.html +1 -0
  307. package/dist/ui/static/launch.txt +19 -0
  308. package/dist/ui/static.d.ts +3 -0
  309. package/dist/ui/static.js +72 -0
  310. package/dist/ui/store/chats.d.ts +14 -0
  311. package/dist/ui/store/chats.js +110 -0
  312. package/dist/ui/store/db.d.ts +6 -0
  313. package/dist/ui/store/db.js +182 -0
  314. package/dist/ui/store/errors.d.ts +12 -0
  315. package/dist/ui/store/errors.js +30 -0
  316. package/dist/ui/store/index.d.ts +6 -0
  317. package/dist/ui/store/index.js +6 -0
  318. package/dist/ui/store/messages.d.ts +5 -0
  319. package/dist/ui/store/messages.js +137 -0
  320. package/dist/ui/store/paths.d.ts +4 -0
  321. package/dist/ui/store/paths.js +69 -0
  322. package/dist/ui/store/projects.d.ts +7 -0
  323. package/dist/ui/store/projects.js +61 -0
  324. package/dist/ui/store/schema.d.ts +3 -0
  325. package/dist/ui/store/schema.js +77 -0
  326. package/dist/ui/store/types.d.ts +80 -0
  327. package/dist/ui/store/types.js +3 -0
  328. package/dist/ui/store/validation.d.ts +4 -0
  329. package/dist/ui/store/validation.js +72 -0
  330. package/dist/ui/store-handlers.d.ts +16 -0
  331. package/dist/ui/store-handlers.js +465 -0
  332. package/dist/ui/terminal-errors.d.ts +21 -0
  333. package/dist/ui/terminal-errors.js +45 -0
  334. package/dist/ui/terminal-evidence.d.ts +20 -0
  335. package/dist/ui/terminal-evidence.js +65 -0
  336. package/dist/ui/terminal-routes.d.ts +9 -0
  337. package/dist/ui/terminal-routes.js +219 -0
  338. package/dist/ui/terminal.d.ts +67 -0
  339. package/dist/ui/terminal.js +835 -0
  340. package/dist/verification/classify.d.ts +10 -0
  341. package/dist/verification/classify.js +53 -0
  342. package/dist/verification/detect.d.ts +4 -0
  343. package/dist/verification/detect.js +81 -0
  344. package/dist/verification/errors.d.ts +11 -0
  345. package/dist/verification/errors.js +21 -0
  346. package/dist/verification/index.d.ts +17 -0
  347. package/dist/verification/index.js +13 -0
  348. package/dist/verification/limits.d.ts +3 -0
  349. package/dist/verification/limits.js +40 -0
  350. package/dist/verification/monitor.d.ts +4 -0
  351. package/dist/verification/monitor.js +58 -0
  352. package/dist/verification/orchestrator.d.ts +16 -0
  353. package/dist/verification/orchestrator.js +363 -0
  354. package/dist/verification/plan.d.ts +9 -0
  355. package/dist/verification/plan.js +125 -0
  356. package/dist/verification/summary.d.ts +40 -0
  357. package/dist/verification/summary.js +67 -0
  358. package/dist/verification/types.d.ts +63 -0
  359. package/dist/verification/types.js +13 -0
  360. package/dist/workflows/bug-investigation/context.d.ts +7 -0
  361. package/dist/workflows/bug-investigation/context.js +119 -0
  362. package/dist/workflows/bug-investigation/descriptor.d.ts +3 -0
  363. package/dist/workflows/bug-investigation/descriptor.js +46 -0
  364. package/dist/workflows/bug-investigation/emit.d.ts +12 -0
  365. package/dist/workflows/bug-investigation/emit.js +35 -0
  366. package/dist/workflows/bug-investigation/events.d.ts +81 -0
  367. package/dist/workflows/bug-investigation/events.js +9 -0
  368. package/dist/workflows/bug-investigation/failure-parse.d.ts +3 -0
  369. package/dist/workflows/bug-investigation/failure-parse.js +154 -0
  370. package/dist/workflows/bug-investigation/guard.d.ts +2 -0
  371. package/dist/workflows/bug-investigation/guard.js +69 -0
  372. package/dist/workflows/bug-investigation/index.d.ts +7 -0
  373. package/dist/workflows/bug-investigation/index.js +13 -0
  374. package/dist/workflows/bug-investigation/internal.d.ts +37 -0
  375. package/dist/workflows/bug-investigation/internal.js +64 -0
  376. package/dist/workflows/bug-investigation/model-loop.d.ts +4 -0
  377. package/dist/workflows/bug-investigation/model-loop.js +223 -0
  378. package/dist/workflows/bug-investigation/parse.d.ts +3 -0
  379. package/dist/workflows/bug-investigation/parse.js +123 -0
  380. package/dist/workflows/bug-investigation/prompt.d.ts +4 -0
  381. package/dist/workflows/bug-investigation/prompt.js +107 -0
  382. package/dist/workflows/bug-investigation/report.d.ts +23 -0
  383. package/dist/workflows/bug-investigation/report.js +151 -0
  384. package/dist/workflows/bug-investigation/stages.d.ts +13 -0
  385. package/dist/workflows/bug-investigation/stages.js +242 -0
  386. package/dist/workflows/bug-investigation/types.d.ts +91 -0
  387. package/dist/workflows/bug-investigation/types.js +14 -0
  388. package/dist/workflows/bug-investigation/verify-stage.d.ts +10 -0
  389. package/dist/workflows/bug-investigation/verify-stage.js +91 -0
  390. package/dist/workflows/bug-investigation/workflow.d.ts +2 -0
  391. package/dist/workflows/bug-investigation/workflow.js +74 -0
  392. package/dist/workflows/descriptor.d.ts +20 -0
  393. package/dist/workflows/descriptor.js +8 -0
  394. package/dist/workflows/index.d.ts +3 -0
  395. package/dist/workflows/index.js +2 -0
  396. package/dist/workflows/unit-tests/context.d.ts +7 -0
  397. package/dist/workflows/unit-tests/context.js +129 -0
  398. package/dist/workflows/unit-tests/conventions.d.ts +4 -0
  399. package/dist/workflows/unit-tests/conventions.js +87 -0
  400. package/dist/workflows/unit-tests/descriptor.d.ts +4 -0
  401. package/dist/workflows/unit-tests/descriptor.js +43 -0
  402. package/dist/workflows/unit-tests/emit.d.ts +12 -0
  403. package/dist/workflows/unit-tests/emit.js +35 -0
  404. package/dist/workflows/unit-tests/events.d.ts +78 -0
  405. package/dist/workflows/unit-tests/events.js +7 -0
  406. package/dist/workflows/unit-tests/index.d.ts +6 -0
  407. package/dist/workflows/unit-tests/index.js +10 -0
  408. package/dist/workflows/unit-tests/internal.d.ts +35 -0
  409. package/dist/workflows/unit-tests/internal.js +43 -0
  410. package/dist/workflows/unit-tests/model-loop.d.ts +4 -0
  411. package/dist/workflows/unit-tests/model-loop.js +95 -0
  412. package/dist/workflows/unit-tests/parse.d.ts +6 -0
  413. package/dist/workflows/unit-tests/parse.js +68 -0
  414. package/dist/workflows/unit-tests/prompt.d.ts +4 -0
  415. package/dist/workflows/unit-tests/prompt.js +71 -0
  416. package/dist/workflows/unit-tests/report.d.ts +21 -0
  417. package/dist/workflows/unit-tests/report.js +90 -0
  418. package/dist/workflows/unit-tests/stages.d.ts +9 -0
  419. package/dist/workflows/unit-tests/stages.js +155 -0
  420. package/dist/workflows/unit-tests/types.d.ts +70 -0
  421. package/dist/workflows/unit-tests/types.js +11 -0
  422. package/dist/workflows/unit-tests/verify-stage.d.ts +9 -0
  423. package/dist/workflows/unit-tests/verify-stage.js +56 -0
  424. package/dist/workflows/unit-tests/workflow.d.ts +2 -0
  425. package/dist/workflows/unit-tests/workflow.js +58 -0
  426. package/dist/workspace/contextPack.d.ts +9 -0
  427. package/dist/workspace/contextPack.js +94 -0
  428. package/dist/workspace/detect.d.ts +3 -0
  429. package/dist/workspace/detect.js +135 -0
  430. package/dist/workspace/discovery.d.ts +9 -0
  431. package/dist/workspace/discovery.js +167 -0
  432. package/dist/workspace/errors.d.ts +39 -0
  433. package/dist/workspace/errors.js +66 -0
  434. package/dist/workspace/fs.d.ts +21 -0
  435. package/dist/workspace/fs.js +36 -0
  436. package/dist/workspace/ignore.d.ts +14 -0
  437. package/dist/workspace/ignore.js +176 -0
  438. package/dist/workspace/index.d.ts +11 -0
  439. package/dist/workspace/index.js +13 -0
  440. package/dist/workspace/paths.d.ts +2 -0
  441. package/dist/workspace/paths.js +38 -0
  442. package/dist/workspace/realpath.d.ts +7 -0
  443. package/dist/workspace/realpath.js +72 -0
  444. package/dist/workspace/retrieval.d.ts +9 -0
  445. package/dist/workspace/retrieval.js +74 -0
  446. package/dist/workspace/summary.d.ts +3 -0
  447. package/dist/workspace/summary.js +54 -0
  448. package/dist/workspace/types.d.ts +103 -0
  449. package/dist/workspace/types.js +27 -0
  450. package/package.json +58 -0
@@ -0,0 +1,465 @@
1
+ // ADR-0013 D7 — Route handlers for UI-local store routes. All inputs are validated;
2
+ // every error path uses the redacted `{ error: { code, message } }` envelope; SECURITY_HEADERS are
3
+ // applied uniformly by the server layer. JSON body reading is bounded by MAX_STORE_BODY_BYTES.
4
+ import { errorBody } from "./routes.js";
5
+ import { findCapability } from "../gateway/index.js";
6
+ import { UiStoreError, assertUiDbOutsideProject, isProjectAvailable, validateProjectPath, } from "./store/index.js";
7
+ const MAX_STORE_BODY_BYTES = 256_000;
8
+ class BodyTooLargeError extends Error {
9
+ constructor() {
10
+ super("body too large");
11
+ this.name = "BodyTooLargeError";
12
+ }
13
+ }
14
+ // ──────────────────────────────────────────────────────────────────────────
15
+ // Body parsing helpers
16
+ // ──────────────────────────────────────────────────────────────────────────
17
+ function readBody(req) {
18
+ return new Promise((resolve, reject) => {
19
+ const chunks = [];
20
+ let total = 0;
21
+ let capped = false;
22
+ req.on("data", (chunk) => {
23
+ total += chunk.length;
24
+ if (total > MAX_STORE_BODY_BYTES) {
25
+ if (!capped) {
26
+ capped = true;
27
+ chunks.length = 0;
28
+ reject(new BodyTooLargeError());
29
+ req.resume();
30
+ }
31
+ return;
32
+ }
33
+ chunks.push(chunk);
34
+ });
35
+ req.on("end", () => {
36
+ if (!capped)
37
+ resolve(Buffer.concat(chunks).toString("utf8"));
38
+ });
39
+ req.on("error", reject);
40
+ });
41
+ }
42
+ async function readJsonObject(req) {
43
+ let raw;
44
+ try {
45
+ raw = await readBody(req);
46
+ }
47
+ catch (error) {
48
+ if (error instanceof BodyTooLargeError)
49
+ throw error;
50
+ throw new InvalidRequest("Failed to read request body.");
51
+ }
52
+ let parsed;
53
+ try {
54
+ parsed = JSON.parse(raw);
55
+ }
56
+ catch {
57
+ throw new InvalidRequest("Request body is not valid JSON.");
58
+ }
59
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
60
+ throw new InvalidRequest("Request body must be a JSON object.");
61
+ }
62
+ return parsed;
63
+ }
64
+ class InvalidRequest extends Error {
65
+ constructor(message) {
66
+ super(message);
67
+ this.name = "InvalidRequest";
68
+ }
69
+ }
70
+ // ──────────────────────────────────────────────────────────────────────────
71
+ // Error mapping
72
+ // ──────────────────────────────────────────────────────────────────────────
73
+ function uiStoreErrorResult(error) {
74
+ return { status: error.status, body: errorBody(error.code, error.message) };
75
+ }
76
+ function badRequest(code, message) {
77
+ return { status: 400, body: errorBody(code, message) };
78
+ }
79
+ function notFoundResult(message) {
80
+ return { status: 404, body: errorBody("not_found", message) };
81
+ }
82
+ function payloadTooLarge() {
83
+ return {
84
+ status: 413,
85
+ body: errorBody("payload_too_large", "Request body exceeds the size limit."),
86
+ };
87
+ }
88
+ async function runHandler(worker) {
89
+ try {
90
+ return await worker();
91
+ }
92
+ catch (error) {
93
+ if (error instanceof BodyTooLargeError)
94
+ return payloadTooLarge();
95
+ if (error instanceof InvalidRequest)
96
+ return badRequest("invalid_request", error.message);
97
+ if (error instanceof UiStoreError)
98
+ return uiStoreErrorResult(error);
99
+ throw error;
100
+ }
101
+ }
102
+ // ──────────────────────────────────────────────────────────────────────────
103
+ // Field validators (typed narrowing from JSON)
104
+ // ──────────────────────────────────────────────────────────────────────────
105
+ function requireString(body, name) {
106
+ const v = body[name];
107
+ if (typeof v !== "string" || v.length === 0) {
108
+ throw new InvalidRequest(`Field "${name}" is required.`);
109
+ }
110
+ return v;
111
+ }
112
+ function optionalString(body, name) {
113
+ const v = body[name];
114
+ if (v === undefined)
115
+ return undefined;
116
+ if (typeof v !== "string")
117
+ throw new InvalidRequest(`Field "${name}" must be a string.`);
118
+ return v;
119
+ }
120
+ function assertChatModelRegistryId(modelId) {
121
+ const capability = findCapability(modelId);
122
+ if (capability?.kind !== "chat") {
123
+ throw new InvalidRequest('Field "selectedModel" must be a chat model registry id.');
124
+ }
125
+ }
126
+ function requireChatModelId(body, name) {
127
+ const modelId = requireString(body, name);
128
+ assertChatModelRegistryId(modelId);
129
+ return modelId;
130
+ }
131
+ function optionalChatModelId(body, name) {
132
+ const modelId = optionalString(body, name);
133
+ if (modelId !== undefined)
134
+ assertChatModelRegistryId(modelId);
135
+ return modelId;
136
+ }
137
+ function optionalBoolean(body, name) {
138
+ const v = body[name];
139
+ if (v === undefined)
140
+ return undefined;
141
+ if (typeof v !== "boolean")
142
+ throw new InvalidRequest(`Field "${name}" must be a boolean.`);
143
+ return v;
144
+ }
145
+ function requireNumber(body, name) {
146
+ const v = body[name];
147
+ if (typeof v !== "number" || !Number.isFinite(v)) {
148
+ throw new InvalidRequest(`Field "${name}" must be a finite number.`);
149
+ }
150
+ return v;
151
+ }
152
+ function requireObject(body, name) {
153
+ const v = body[name];
154
+ if (typeof v !== "object" || v === null || Array.isArray(v)) {
155
+ throw new InvalidRequest(`Field "${name}" must be a JSON object.`);
156
+ }
157
+ return v;
158
+ }
159
+ const ROLES = new Set(["user", "assistant", "system"]);
160
+ const WORKFLOW_STATUSES = new Set([
161
+ "pending",
162
+ "running",
163
+ "completed",
164
+ "failed",
165
+ "cancelled",
166
+ ]);
167
+ // Issue #66 — taskType labels non-workflow harness runs (verify, explain-plan) so the chat can
168
+ // render a non-ambiguous label. Constrained to a-z/0-9/`-` so the value stays URL-safe and
169
+ // matches the BFF descriptor taskType identifiers (verify, explain-plan).
170
+ const MAX_TASK_TYPE = 64;
171
+ const TASK_TYPE_RE = /^[a-z][a-z0-9-]*$/;
172
+ function optionalTaskType(body) {
173
+ const v = body.taskType;
174
+ if (v === undefined)
175
+ return undefined;
176
+ if (typeof v !== "string" || v.length === 0 || v.length > MAX_TASK_TYPE || !TASK_TYPE_RE.test(v)) {
177
+ throw new InvalidRequest('Field "taskType" must match [a-z][a-z0-9-]* (≤ 64 chars).');
178
+ }
179
+ return v;
180
+ }
181
+ function requireRole(body) {
182
+ const v = body.role;
183
+ if (typeof v !== "string" || !ROLES.has(v)) {
184
+ throw new InvalidRequest('Field "role" must be one of user, assistant, system.');
185
+ }
186
+ return v;
187
+ }
188
+ function optionalWorkflowStatus(body) {
189
+ const v = body.workflowStatus;
190
+ if (v === undefined)
191
+ return undefined;
192
+ if (typeof v !== "string" || !WORKFLOW_STATUSES.has(v)) {
193
+ throw new InvalidRequest('Field "workflowStatus" is not a recognized value.');
194
+ }
195
+ return v;
196
+ }
197
+ function requireQuery(ctx, name) {
198
+ const v = ctx.url.searchParams.get(name);
199
+ if (v === null || v.length === 0)
200
+ throw new InvalidRequest(`Query "${name}" is required.`);
201
+ return v;
202
+ }
203
+ function projectWithAvailability(p) {
204
+ return { ...p, available: isProjectAvailable(p) };
205
+ }
206
+ function chatBelongsToProject(deps, projectPath, chatId) {
207
+ return deps.store.listChats(projectPath).some((chat) => chat.id === chatId);
208
+ }
209
+ function messageBelongsToChat(deps, chatId, messageId) {
210
+ return deps.store.listMessages(chatId).some((message) => message.id === messageId);
211
+ }
212
+ // ──────────────────────────────────────────────────────────────────────────
213
+ // Route 13 — GET /api/projects
214
+ // ──────────────────────────────────────────────────────────────────────────
215
+ export function handleListProjects(_ctx, deps) {
216
+ const projects = deps.store.listProjects().map(projectWithAvailability);
217
+ return { status: 200, body: { projects } };
218
+ }
219
+ // ──────────────────────────────────────────────────────────────────────────
220
+ // Route 14 — POST /api/projects
221
+ // ──────────────────────────────────────────────────────────────────────────
222
+ export async function handleCreateProject(ctx, deps) {
223
+ return runHandler(async () => {
224
+ const body = await readJsonObject(ctx.req);
225
+ const path = requireString(body, "path");
226
+ const name = optionalString(body, "name");
227
+ const normalizedPath = validateProjectPath(path, { mustExist: true });
228
+ assertUiDbOutsideProject(deps.uiDbPath, normalizedPath);
229
+ const project = deps.store.createProject(normalizedPath, name);
230
+ return { status: 201, body: { project: projectWithAvailability(project) } };
231
+ });
232
+ }
233
+ // ──────────────────────────────────────────────────────────────────────────
234
+ // Route 15 — PATCH /api/projects?path=...
235
+ // ──────────────────────────────────────────────────────────────────────────
236
+ function buildProjectPatch(body) {
237
+ const name = optionalString(body, "name");
238
+ const favorite = optionalBoolean(body, "favorite");
239
+ return {
240
+ ...(name !== undefined ? { name } : {}),
241
+ ...(favorite !== undefined ? { favorite } : {}),
242
+ };
243
+ }
244
+ export async function handleUpdateProject(ctx, deps) {
245
+ return runHandler(async () => {
246
+ const targetPath = requireQuery(ctx, "path");
247
+ const body = await readJsonObject(ctx.req);
248
+ const patch = buildProjectPatch(body);
249
+ const project = deps.store.updateProject(targetPath, patch);
250
+ return { status: 200, body: { project: projectWithAvailability(project) } };
251
+ });
252
+ }
253
+ // ──────────────────────────────────────────────────────────────────────────
254
+ // Route 16 — DELETE /api/projects?path=...
255
+ // ──────────────────────────────────────────────────────────────────────────
256
+ export function handleDeleteProject(ctx, deps) {
257
+ return runHandlerSync(() => {
258
+ const targetPath = requireQuery(ctx, "path");
259
+ deps.store.deleteProject(targetPath);
260
+ return { status: 204, body: null };
261
+ });
262
+ }
263
+ function runHandlerSync(worker) {
264
+ try {
265
+ return worker();
266
+ }
267
+ catch (error) {
268
+ if (error instanceof InvalidRequest)
269
+ return badRequest("invalid_request", error.message);
270
+ if (error instanceof UiStoreError)
271
+ return uiStoreErrorResult(error);
272
+ throw error;
273
+ }
274
+ }
275
+ // ──────────────────────────────────────────────────────────────────────────
276
+ // Route 17 — GET /api/chats?projectPath=...
277
+ // ──────────────────────────────────────────────────────────────────────────
278
+ export function handleListChats(ctx, deps) {
279
+ return runHandlerSync(() => {
280
+ const projectPath = requireQuery(ctx, "projectPath");
281
+ const chats = deps.store.listChats(projectPath);
282
+ return { status: 200, body: { chats } };
283
+ });
284
+ }
285
+ // ──────────────────────────────────────────────────────────────────────────
286
+ // Route 18 — POST /api/chats
287
+ // ──────────────────────────────────────────────────────────────────────────
288
+ export async function handleCreateChat(ctx, deps) {
289
+ return runHandler(async () => {
290
+ const body = await readJsonObject(ctx.req);
291
+ const projectPath = requireString(body, "projectPath");
292
+ const title = requireString(body, "title");
293
+ const selectedModel = requireChatModelId(body, "selectedModel");
294
+ const branchLabel = optionalString(body, "branchLabel");
295
+ const chat = deps.store.createChat(projectPath, title, selectedModel, branchLabel === undefined ? undefined : { branchLabel });
296
+ return { status: 201, body: { chat } };
297
+ });
298
+ }
299
+ // ──────────────────────────────────────────────────────────────────────────
300
+ // Route 19 — PATCH /api/chats?id=...
301
+ // ──────────────────────────────────────────────────────────────────────────
302
+ function buildChatPatch(body) {
303
+ const title = optionalString(body, "title");
304
+ const selectedModel = optionalChatModelId(body, "selectedModel");
305
+ const branchLabel = optionalString(body, "branchLabel");
306
+ const statusRaw = body.status;
307
+ const patch = {
308
+ ...(title !== undefined ? { title } : {}),
309
+ ...(selectedModel !== undefined ? { selectedModel } : {}),
310
+ ...(branchLabel !== undefined ? { branchLabel } : {}),
311
+ };
312
+ if (statusRaw === undefined)
313
+ return patch;
314
+ if (statusRaw !== "open" && statusRaw !== "closed") {
315
+ throw new InvalidRequest('Field "status" must be "open" or "closed".');
316
+ }
317
+ return { ...patch, status: statusRaw };
318
+ }
319
+ export async function handleUpdateChat(ctx, deps) {
320
+ return runHandler(async () => {
321
+ const id = requireQuery(ctx, "id");
322
+ const body = await readJsonObject(ctx.req);
323
+ const patch = buildChatPatch(body);
324
+ const chat = deps.store.updateChat(id, patch);
325
+ return { status: 200, body: { chat } };
326
+ });
327
+ }
328
+ // ──────────────────────────────────────────────────────────────────────────
329
+ // Route 20 — DELETE /api/chats?id=...
330
+ // ──────────────────────────────────────────────────────────────────────────
331
+ export function handleDeleteChat(ctx, deps) {
332
+ return runHandlerSync(() => {
333
+ const id = requireQuery(ctx, "id");
334
+ deps.store.deleteChat(id);
335
+ return { status: 204, body: null };
336
+ });
337
+ }
338
+ // ──────────────────────────────────────────────────────────────────────────
339
+ // Route 21 — GET /api/chats/messages?chatId=...
340
+ // ──────────────────────────────────────────────────────────────────────────
341
+ export function handleListMessages(ctx, deps) {
342
+ return runHandlerSync(() => {
343
+ const chatId = requireQuery(ctx, "chatId");
344
+ const projectPath = requireQuery(ctx, "projectPath");
345
+ if (!chatBelongsToProject(deps, projectPath, chatId)) {
346
+ return notFoundResult("Chat not found.");
347
+ }
348
+ const messages = deps.store.listMessages(chatId);
349
+ return { status: 200, body: { messages } };
350
+ });
351
+ }
352
+ // ──────────────────────────────────────────────────────────────────────────
353
+ // Route 22 — POST /api/chats/messages
354
+ // ──────────────────────────────────────────────────────────────────────────
355
+ export async function handleCreateMessage(ctx, deps) {
356
+ return runHandler(async () => {
357
+ const body = await readJsonObject(ctx.req);
358
+ const chatId = requireString(body, "chatId");
359
+ const projectPath = requireString(body, "projectPath");
360
+ if (!chatBelongsToProject(deps, projectPath, chatId)) {
361
+ return notFoundResult("Chat not found.");
362
+ }
363
+ const role = requireRole(body);
364
+ const content = requireString(body, "content");
365
+ const timestamp = requireNumber(body, "timestamp");
366
+ const message = deps.store.createMessage({
367
+ chatId,
368
+ role,
369
+ content,
370
+ timestamp,
371
+ runId: optionalString(body, "runId"),
372
+ workflowId: optionalString(body, "workflowId"),
373
+ workflowStatus: optionalWorkflowStatus(body),
374
+ shortResult: optionalString(body, "shortResult"),
375
+ taskType: optionalTaskType(body),
376
+ });
377
+ return { status: 201, body: { message } };
378
+ });
379
+ }
380
+ // ──────────────────────────────────────────────────────────────────────────
381
+ // Route 23 — POST /api/chats/messages/run-summary-pair (issue #66)
382
+ // ──────────────────────────────────────────────────────────────────────────
383
+ function buildRunSummaryPair(body) {
384
+ const chatId = requireString(body, "chatId");
385
+ const user = requireObject(body, "user");
386
+ const summary = requireObject(body, "summary");
387
+ const workflowId = optionalString(summary, "workflowId");
388
+ const taskType = optionalTaskType(summary);
389
+ if ((workflowId === undefined) === (taskType === undefined)) {
390
+ throw new InvalidRequest('Run summary requires exactly one of "workflowId" or "taskType".');
391
+ }
392
+ const userMessage = {
393
+ chatId,
394
+ role: "user",
395
+ content: requireString(user, "content"),
396
+ timestamp: requireNumber(user, "timestamp"),
397
+ runId: undefined,
398
+ workflowId: undefined,
399
+ workflowStatus: undefined,
400
+ shortResult: undefined,
401
+ taskType: undefined,
402
+ };
403
+ const summaryMessage = {
404
+ chatId,
405
+ role: "system",
406
+ content: requireString(summary, "content"),
407
+ timestamp: requireNumber(summary, "timestamp"),
408
+ runId: requireString(summary, "runId"),
409
+ workflowId,
410
+ workflowStatus: optionalWorkflowStatus(summary),
411
+ shortResult: optionalString(summary, "shortResult"),
412
+ taskType,
413
+ };
414
+ if (summaryMessage.workflowStatus === undefined) {
415
+ throw new InvalidRequest('Field "summary.workflowStatus" is required.');
416
+ }
417
+ return [userMessage, summaryMessage];
418
+ }
419
+ export async function handleCreateRunSummaryPair(ctx, deps) {
420
+ return runHandler(async () => {
421
+ const body = await readJsonObject(ctx.req);
422
+ const chatId = requireString(body, "chatId");
423
+ const projectPath = requireString(body, "projectPath");
424
+ if (!chatBelongsToProject(deps, projectPath, chatId)) {
425
+ return notFoundResult("Chat not found.");
426
+ }
427
+ const messages = deps.store.createMessages(buildRunSummaryPair(body));
428
+ return { status: 201, body: { messages } };
429
+ });
430
+ }
431
+ // ──────────────────────────────────────────────────────────────────────────
432
+ // Route 24 — PATCH /api/chats/messages?id=... (issue #66)
433
+ // ──────────────────────────────────────────────────────────────────────────
434
+ // Builds a typed UpdateChatMessagePatch from the JSON body. At least one updatable field must
435
+ // appear; the store layer also fails-closed on this, but throwing here surfaces the friendlier
436
+ // INVALID_REQUEST envelope without spending a SQL prepare.
437
+ function buildMessagePatch(body) {
438
+ const workflowStatus = optionalWorkflowStatus(body);
439
+ const shortResult = optionalString(body, "shortResult");
440
+ const taskType = optionalTaskType(body);
441
+ if (workflowStatus === undefined && shortResult === undefined && taskType === undefined) {
442
+ throw new InvalidRequest("PATCH body must include at least one updatable field.");
443
+ }
444
+ return {
445
+ ...(workflowStatus !== undefined ? { workflowStatus } : {}),
446
+ ...(shortResult !== undefined ? { shortResult } : {}),
447
+ ...(taskType !== undefined ? { taskType } : {}),
448
+ };
449
+ }
450
+ export async function handleUpdateMessage(ctx, deps) {
451
+ return runHandler(async () => {
452
+ const id = requireQuery(ctx, "id");
453
+ const chatId = requireQuery(ctx, "chatId");
454
+ const projectPath = requireQuery(ctx, "projectPath");
455
+ if (!chatBelongsToProject(deps, projectPath, chatId) || !messageBelongsToChat(deps, chatId, id)) {
456
+ return notFoundResult("Message not found.");
457
+ }
458
+ const body = await readJsonObject(ctx.req);
459
+ const patch = buildMessagePatch(body);
460
+ const message = deps.store.updateMessage(id, patch);
461
+ return { status: 200, body: { message } };
462
+ });
463
+ }
464
+ // barrel-level NOT_FOUND helper used by future delete-missing paths
465
+ export { notFoundResult };
@@ -0,0 +1,21 @@
1
+ export declare const TERMINAL_ERROR_CODES: {
2
+ readonly PROJECT_NOT_FOUND: "PROJECT_NOT_FOUND";
3
+ readonly COMMAND_DENIED: "COMMAND_DENIED";
4
+ readonly CWD_OUTSIDE_PROJECT: "CWD_OUTSIDE_PROJECT";
5
+ readonly CWD_DENIED: "CWD_DENIED";
6
+ readonly EXECUTION_NOT_FOUND: "EXECUTION_NOT_FOUND";
7
+ readonly EXECUTION_LIMIT_EXCEEDED: "EXECUTION_LIMIT_EXCEEDED";
8
+ readonly TIMEOUT: "TIMEOUT";
9
+ readonly CANCELLED: "CANCELLED";
10
+ readonly EXECUTABLE_NOT_FOUND: "EXECUTABLE_NOT_FOUND";
11
+ readonly EVIDENCE_WRITE_FAILED: "EVIDENCE_WRITE_FAILED";
12
+ readonly BAD_REQUEST: "BAD_REQUEST";
13
+ readonly PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE";
14
+ readonly INTERNAL: "INTERNAL";
15
+ };
16
+ export type TerminalErrorCode = (typeof TERMINAL_ERROR_CODES)[keyof typeof TERMINAL_ERROR_CODES];
17
+ export declare class TerminalToolError extends Error {
18
+ readonly code: TerminalErrorCode;
19
+ readonly status: number;
20
+ constructor(code: TerminalErrorCode, message: string);
21
+ }
@@ -0,0 +1,45 @@
1
+ // ADR-0018 D10 — typed failure modes for the UI terminal tool. Callers switch on `code`; messages
2
+ // are static strings that never leak filesystem paths or raw Node/OS error text into the HTTP
3
+ // response or SSE event payload.
4
+ export const TERMINAL_ERROR_CODES = {
5
+ PROJECT_NOT_FOUND: "PROJECT_NOT_FOUND",
6
+ COMMAND_DENIED: "COMMAND_DENIED",
7
+ CWD_OUTSIDE_PROJECT: "CWD_OUTSIDE_PROJECT",
8
+ CWD_DENIED: "CWD_DENIED",
9
+ EXECUTION_NOT_FOUND: "EXECUTION_NOT_FOUND",
10
+ EXECUTION_LIMIT_EXCEEDED: "EXECUTION_LIMIT_EXCEEDED",
11
+ TIMEOUT: "TIMEOUT",
12
+ CANCELLED: "CANCELLED",
13
+ EXECUTABLE_NOT_FOUND: "EXECUTABLE_NOT_FOUND",
14
+ EVIDENCE_WRITE_FAILED: "EVIDENCE_WRITE_FAILED",
15
+ BAD_REQUEST: "BAD_REQUEST",
16
+ PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE",
17
+ INTERNAL: "INTERNAL",
18
+ };
19
+ // HTTP status mapping per ADR-0018 D10. CANCELLED uses 499 ("Client Closed Request"), the
20
+ // Nginx-popularised convention also used by the harness for abort-driven cancellation.
21
+ const STATUS_MAP = {
22
+ PROJECT_NOT_FOUND: 404,
23
+ COMMAND_DENIED: 403,
24
+ CWD_OUTSIDE_PROJECT: 403,
25
+ CWD_DENIED: 403,
26
+ EXECUTION_NOT_FOUND: 404,
27
+ EXECUTION_LIMIT_EXCEEDED: 429,
28
+ TIMEOUT: 408,
29
+ CANCELLED: 499,
30
+ EXECUTABLE_NOT_FOUND: 404,
31
+ EVIDENCE_WRITE_FAILED: 500,
32
+ BAD_REQUEST: 400,
33
+ PAYLOAD_TOO_LARGE: 413,
34
+ INTERNAL: 500,
35
+ };
36
+ export class TerminalToolError extends Error {
37
+ code;
38
+ status;
39
+ constructor(code, message) {
40
+ super(message);
41
+ this.name = "TerminalToolError";
42
+ this.code = code;
43
+ this.status = STATUS_MAP[code];
44
+ }
45
+ }
@@ -0,0 +1,20 @@
1
+ import type { EvidenceStore } from "../audit/store.js";
2
+ import type { EvidenceManifest } from "../audit/types.js";
3
+ export declare const TERMINAL_EVIDENCE_KIND: "terminal-execution";
4
+ export type TerminalEvidenceEntry = EvidenceManifest;
5
+ export interface TerminalEvidenceInput {
6
+ readonly executionId: string;
7
+ readonly projectId: string;
8
+ readonly command: string;
9
+ readonly argCount: number;
10
+ readonly exitCode: number | null;
11
+ readonly signal: string | null;
12
+ readonly durationMs: number;
13
+ readonly timedOut: boolean;
14
+ readonly truncated: boolean;
15
+ readonly stdoutBytes: number;
16
+ readonly stderrBytes: number;
17
+ readonly startedAt: number;
18
+ }
19
+ export declare function buildTerminalEvidenceEntry(input: TerminalEvidenceInput): TerminalEvidenceEntry;
20
+ export declare function appendTerminalEvidence(store: EvidenceStore, entry: TerminalEvidenceEntry, redact: (input: string) => string): string;
@@ -0,0 +1,65 @@
1
+ // ADR-0018 D6/D11 — terminal-execution evidence. Each execution writes a normal
2
+ // EvidenceManifest via the existing EvidenceStore.put port, so the shared evidence list/detail
3
+ // APIs can parse it. The terminal-specific data lives in the standard run/task identity plus one
4
+ // commandExecutions record. It carries counts only — never command args, never output bytes.
5
+ import { deepRedactStrings } from "../audit/redaction.js";
6
+ import { EVIDENCE_SCHEMA_VERSION } from "../audit/types.js";
7
+ import { HARNESS_VERSION } from "../harness/session.js";
8
+ export const TERMINAL_EVIDENCE_KIND = "terminal-execution";
9
+ function terminalOutcome(input) {
10
+ if (input.signal !== null)
11
+ return "cancelled";
12
+ if (input.timedOut)
13
+ return "limit-exceeded";
14
+ if (input.exitCode === null)
15
+ return "failed";
16
+ return "completed";
17
+ }
18
+ // PURE. Builds the on-disk manifest from a finished execution. The executionId and projectId carry
19
+ // only identifiers; args and output are deliberately excluded.
20
+ export function buildTerminalEvidenceEntry(input) {
21
+ const runId = input.executionId;
22
+ return {
23
+ evidenceSchemaVersion: EVIDENCE_SCHEMA_VERSION,
24
+ run: {
25
+ runId,
26
+ fingerprint: runId,
27
+ harnessVersion: HARNESS_VERSION,
28
+ taskType: TERMINAL_EVIDENCE_KIND,
29
+ outcome: terminalOutcome(input),
30
+ startedAt: input.startedAt,
31
+ finishedAt: input.startedAt + input.durationMs,
32
+ durationMs: input.durationMs,
33
+ },
34
+ model: { modelId: "terminal-tool", costClass: "unknown" },
35
+ usageTotals: { promptTokens: 0, completionTokens: 0, requestCount: 0, totalLatencyMs: 0 },
36
+ context: {
37
+ workspaceRoot: input.projectId,
38
+ totalCandidates: 0,
39
+ usedBytes: 0,
40
+ budgetBytes: 0,
41
+ droppedForBudget: 0,
42
+ entries: [],
43
+ },
44
+ stateTransitions: [],
45
+ toolCalls: [],
46
+ commandExecutions: [
47
+ {
48
+ seq: 1,
49
+ ts: input.startedAt,
50
+ executable: input.command,
51
+ argCount: input.argCount,
52
+ exitCode: input.exitCode,
53
+ timedOut: input.timedOut,
54
+ durationMs: input.durationMs,
55
+ },
56
+ ],
57
+ };
58
+ }
59
+ // Defense in depth: applies the live redactor to every string leaf of the entry before serializing.
60
+ // All known leaves (command, projectId, executionId) are structurally safe today, but a future
61
+ // schema addition would inherit the redaction automatically. Mirrors the persistEvidence pattern.
62
+ export function appendTerminalEvidence(store, entry, redact) {
63
+ const safe = deepRedactStrings(entry, redact);
64
+ return store.put(safe.run.runId, JSON.stringify(safe, null, 2));
65
+ }
@@ -0,0 +1,9 @@
1
+ import { type TerminalErrorCode } from "./terminal-errors.js";
2
+ import type { UiHandlerDeps } from "./deps.js";
3
+ import { type HandlerOutcome, type RouteContext, type RouteResult } from "./routes.js";
4
+ export declare function handleTerminalPolicy(_ctx: RouteContext, _deps: UiHandlerDeps): RouteResult;
5
+ export declare function handleTerminalDirectories(ctx: RouteContext, deps: UiHandlerDeps): Promise<RouteResult>;
6
+ export declare function handleCreateTerminalExecution(ctx: RouteContext, deps: UiHandlerDeps): Promise<RouteResult>;
7
+ export declare function handleDeleteTerminalExecution(ctx: RouteContext, deps: UiHandlerDeps): RouteResult;
8
+ export declare function handleTerminalEvents(ctx: RouteContext, deps: UiHandlerDeps): HandlerOutcome;
9
+ export type { TerminalErrorCode };