@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,7 @@
1
+ import { type ContextPack, type WorkspaceInfo } from "../../workspace/index.js";
2
+ import { type WorkspaceFs } from "../../workspace/fs.js";
3
+ import type { BugWorkflowLimits, FailureEvidence } from "./types.js";
4
+ export interface BugContextDeps {
5
+ readonly fs?: WorkspaceFs | undefined;
6
+ }
7
+ export declare function buildBugContext(workspace: WorkspaceInfo, description: string | undefined, evidence: FailureEvidence, limits: BugWorkflowLimits, deps?: BugContextDeps): ContextPack;
@@ -0,0 +1,119 @@
1
+ // Context assembly for the investigation call (ADR-0009 D8). Delegates to #5 buildContextPack so
2
+ // the implicated source, nearby tests, manifests/config, and type definitions are selected, ranked,
3
+ // and excerpted under a byte budget — every excerpt already redacted by #5 at the IO boundary. The
4
+ // failure-frame files and developer-provided targetFiles are folded into the lexical `task` hint so
5
+ // the Wave-1 lexical strategy ranks them up (the #5 ContextRequest is reused unchanged; we do not
6
+ // add a new "seed files" field to #5). Pure except for the WorkspaceFs seam threaded into #5.
7
+ import { buildContextPack, DEFAULT_DISCOVERY_OPTIONS, lexicalRetrievalStrategy, SELECTION_REASON_PRIORITY, } from "../../workspace/index.js";
8
+ import { nodeWorkspaceFs } from "../../workspace/fs.js";
9
+ // The lexical task hint: the bug description (or a generic fallback) plus the implicated file paths
10
+ // so the lexical ranker pulls those files into the pack. Deduped; bounded by the frame cap upstream.
11
+ function taskHint(description, evidence) {
12
+ const base = description !== undefined && description.trim().length > 0
13
+ ? description.trim()
14
+ : "investigate failing test and locate the root cause";
15
+ const files = Array.from(new Set(evidence.frames.map((frame) => frame.file)));
16
+ return files.length === 0 ? base : `${base} ${files.join(" ")}`;
17
+ }
18
+ function toPosix(path) {
19
+ return path.split("\\").join("/");
20
+ }
21
+ function basename(path) {
22
+ const normalized = toPosix(path);
23
+ const idx = normalized.lastIndexOf("/");
24
+ return idx === -1 ? normalized : normalized.slice(idx + 1);
25
+ }
26
+ function stem(path) {
27
+ const base = basename(path);
28
+ const idx = base.lastIndexOf(".");
29
+ return idx <= 0 ? base : base.slice(0, idx);
30
+ }
31
+ function testStem(path) {
32
+ const parts = stem(path).split(".");
33
+ const marker = parts.findIndex((part) => part === "test" || part === "spec");
34
+ return marker === -1 ? parts.join(".") : parts.slice(0, marker).join(".");
35
+ }
36
+ function underDir(path, dir) {
37
+ const normalized = toPosix(dir);
38
+ return path === normalized || path.startsWith(`${normalized}/`);
39
+ }
40
+ function toWorkspaceRelative(path, workspace) {
41
+ const normalized = toPosix(path);
42
+ const root = toPosix(workspace.root);
43
+ return normalized.startsWith(`${root}/`) ? normalized.slice(root.length + 1) : normalized;
44
+ }
45
+ function buildEvidenceIndex(evidence, workspace) {
46
+ const paths = new Set(evidence.frames.map((frame) => toWorkspaceRelative(frame.file, workspace)));
47
+ return { paths, stems: new Set([...paths].map(stem)) };
48
+ }
49
+ function isEvidenceTarget(path, evidence) {
50
+ return evidence.paths.has(toPosix(path));
51
+ }
52
+ function isTestCandidate(path, workspace, selectionReason) {
53
+ return (selectionReason === "test" ||
54
+ workspace.testDirs.some((testDir) => underDir(path, testDir)) ||
55
+ stem(path)
56
+ .split(".")
57
+ .some((part) => part === "test" || part === "spec"));
58
+ }
59
+ function isNearbyEvidenceTest(path, workspace, evidence, selectionReason) {
60
+ if (!isTestCandidate(path, workspace, selectionReason)) {
61
+ return false;
62
+ }
63
+ const candidateStem = testStem(path);
64
+ return evidence.stems.has(candidateStem);
65
+ }
66
+ function priorityIndex(reason) {
67
+ return SELECTION_REASON_PRIORITY.indexOf(reason);
68
+ }
69
+ function evidencePriority(ranked, workspace, evidence) {
70
+ const path = toPosix(ranked.file.relativePath);
71
+ if (isEvidenceTarget(path, evidence)) {
72
+ return 0;
73
+ }
74
+ if (isNearbyEvidenceTest(path, workspace, evidence, ranked.selectionReason)) {
75
+ return 1;
76
+ }
77
+ return 2;
78
+ }
79
+ function isSupportContext(ranked) {
80
+ return ranked.selectionReason === "manifest" || ranked.selectionReason === "config";
81
+ }
82
+ function focusedContext(ranked, workspace, evidence) {
83
+ const focused = ranked.filter((item) => evidencePriority(item, workspace, evidence) < 2 || isSupportContext(item));
84
+ return focused.length === 0 ? ranked : focused;
85
+ }
86
+ function createBugRetrievalStrategy(workspace, evidence) {
87
+ const index = buildEvidenceIndex(evidence, workspace);
88
+ return {
89
+ rank: (files, task) => {
90
+ const ranked = focusedContext(lexicalRetrievalStrategy.rank(files, task), workspace, index);
91
+ return [...ranked].sort((a, b) => {
92
+ const byEvidence = evidencePriority(a, workspace, index) - evidencePriority(b, workspace, index);
93
+ if (byEvidence !== 0) {
94
+ return byEvidence;
95
+ }
96
+ const byReason = priorityIndex(a.selectionReason) - priorityIndex(b.selectionReason);
97
+ if (byReason !== 0) {
98
+ return byReason;
99
+ }
100
+ return a.file.relativePath.localeCompare(b.file.relativePath);
101
+ });
102
+ },
103
+ };
104
+ }
105
+ export function buildBugContext(workspace, description, evidence, limits, deps = {}) {
106
+ const request = {
107
+ task: taskHint(description, evidence),
108
+ budgetBytes: limits.contextBudgetBytes,
109
+ maxBytesPerFile: limits.maxBytesPerFile,
110
+ discovery: DEFAULT_DISCOVERY_OPTIONS,
111
+ };
112
+ // buildContextPack defaults to the lexical strategy, but ContextPackDeps requires the field; pass
113
+ // the #5 barrel default explicitly so we hand a complete deps object without reaching past #5.
114
+ const packDeps = {
115
+ fs: deps.fs ?? nodeWorkspaceFs,
116
+ strategy: createBugRetrievalStrategy(workspace, evidence),
117
+ };
118
+ return buildContextPack(workspace, request, packDeps);
119
+ }
@@ -0,0 +1,3 @@
1
+ import { type BugWorkflowLimits } from "./types.js";
2
+ import type { WorkflowDescriptor } from "../descriptor.js";
3
+ export declare const BUG_INVESTIGATION_WORKFLOW_DESCRIPTOR: WorkflowDescriptor<BugWorkflowLimits>;
@@ -0,0 +1,46 @@
1
+ // The static UI workflow descriptor (ADR-0009 D12). Issue #13 reads this to render the
2
+ // bug-investigation workflow UI without knowing the implementation. Frozen and JSON-serializable.
3
+ // Imports the shared WorkflowDescriptor base from ../descriptor.js (NOT from the unit-test
4
+ // workflow) so the two sibling workflows do not depend on each other. preferredCostClass is "high"
5
+ // because root-cause analysis benefits from a stronger model than test generation.
6
+ import { DEFAULT_BUG_WORKFLOW_LIMITS } from "./types.js";
7
+ export const BUG_INVESTIGATION_WORKFLOW_DESCRIPTOR = {
8
+ workflowId: "bug-investigation",
9
+ name: "Bug Investigation and Regression Test",
10
+ description: "Investigates a bounded bug report (description, failing output, stack trace, and/or " +
11
+ "suspected files), proposes a root-cause hypothesis with a minimal fix and a regression " +
12
+ "test, and separates verified facts from model hypotheses. Dry-run by default; pass " +
13
+ "apply:true to write the fix and run verification. When evidence is insufficient it returns " +
14
+ "a scoped investigation report with no patch rather than an invented fix.",
15
+ inputs: [
16
+ {
17
+ name: "report",
18
+ type: "object",
19
+ required: true,
20
+ description: "Bug report: { description?, failingOutput?, stackTrace?, targetFiles? } — at least one present",
21
+ },
22
+ {
23
+ name: "apply",
24
+ type: "boolean",
25
+ required: false,
26
+ description: "Write the fix to disk and run verification",
27
+ defaultValue: false,
28
+ },
29
+ {
30
+ name: "modelId",
31
+ type: "string",
32
+ required: true,
33
+ description: "Model ID registered in gateway config",
34
+ },
35
+ {
36
+ name: "limits",
37
+ type: "object",
38
+ required: false,
39
+ description: "Partial<BugWorkflowLimits> overrides (incl. the bug-fix change budget)",
40
+ },
41
+ ],
42
+ defaultLimits: DEFAULT_BUG_WORKFLOW_LIMITS,
43
+ modelSelectionOptions: { arbitrary: true, preferredCostClass: "high" },
44
+ supportsDryRun: true,
45
+ supportsApply: true,
46
+ };
@@ -0,0 +1,12 @@
1
+ import type { BugReportInput } from "./types.js";
2
+ import type { BugInvestigationEvent, BugWorkflowEventSink } from "./events.js";
3
+ export declare function computeBugFingerprint(report: BugReportInput, modelId: string): string;
4
+ type EnvelopeFields = "schemaVersion" | "runId" | "fingerprint" | "seq" | "ts";
5
+ export type BugEventBody = {
6
+ [E in BugInvestigationEvent as E["type"]]: Omit<E, EnvelopeFields>;
7
+ }[BugInvestigationEvent["type"]];
8
+ export interface BugEventEmitter {
9
+ readonly emit: (body: BugEventBody) => void;
10
+ }
11
+ export declare function createBugEventEmitter(sink: BugWorkflowEventSink, runId: string, fingerprint: string, now: () => number): BugEventEmitter;
12
+ export {};
@@ -0,0 +1,35 @@
1
+ // Event emission helper for the bug-investigation workflow (ADR-0009 D5). Owns the monotonic seq
2
+ // counter and stamps every event with the shared envelope ({ schemaVersion, runId, fingerprint,
3
+ // seq, ts }). The fingerprint is SHA-256(workflowId + canonical(report) + modelId) truncated to 16
4
+ // hex chars — the same shape as the harness fingerprinter — reusing `canonicalise` from the harness
5
+ // barrel so two structurally equal reports fingerprint identically regardless of key order.
6
+ // Sensitive fields are redacted by the CALLER before handing the event here.
7
+ import { createHash } from "node:crypto";
8
+ import { canonicalise } from "../../harness/index.js";
9
+ const FINGERPRINT_HEX_CHARS = 16;
10
+ export function computeBugFingerprint(report, modelId) {
11
+ const canonical = canonicalise({ workflowId: "bug-investigation", report, modelId });
12
+ return createHash("sha256")
13
+ .update(canonical, "utf8")
14
+ .digest("hex")
15
+ .slice(0, FINGERPRINT_HEX_CHARS);
16
+ }
17
+ export function createBugEventEmitter(sink, runId, fingerprint, now) {
18
+ let seq = 0;
19
+ return {
20
+ emit: (body) => {
21
+ seq += 1;
22
+ // The body is a complete discriminated-union member minus the envelope; re-attaching the
23
+ // envelope yields a valid BugInvestigationEvent. The cast is over the union, not a widening.
24
+ const event = {
25
+ schemaVersion: "1",
26
+ runId,
27
+ fingerprint,
28
+ seq,
29
+ ts: now(),
30
+ ...body,
31
+ };
32
+ sink.emit(event);
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,81 @@
1
+ import type { VerificationStatus } from "../../verification/index.js";
2
+ import type { BugWorkflowLimits, BugWorkflowStatus } from "./types.js";
3
+ interface BaseBugEvent {
4
+ readonly schemaVersion: "1";
5
+ readonly runId: string;
6
+ readonly fingerprint: string;
7
+ readonly seq: number;
8
+ readonly ts: number;
9
+ }
10
+ export interface BugInvestigationStartedEvent extends BaseBugEvent {
11
+ readonly type: "bug:started";
12
+ readonly workflowId: "bug-investigation";
13
+ readonly modelId: string;
14
+ readonly applyEnabled: boolean;
15
+ readonly limits: BugWorkflowLimits;
16
+ }
17
+ export interface FailureParsedEvent extends BaseBugEvent {
18
+ readonly type: "bug:failure:parsed";
19
+ readonly frameCount: number;
20
+ readonly messageCount: number;
21
+ }
22
+ export interface BugContextSelectedEvent extends BaseBugEvent {
23
+ readonly type: "bug:context:selected";
24
+ readonly entryCount: number;
25
+ readonly usedBytes: number;
26
+ readonly budgetBytes: number;
27
+ readonly droppedForBudget: number;
28
+ }
29
+ export interface BugModelCallStartedEvent extends BaseBugEvent {
30
+ readonly type: "bug:model:call:started";
31
+ readonly attempt: number;
32
+ readonly contextBytes: number;
33
+ }
34
+ export interface BugModelCallCompletedEvent extends BaseBugEvent {
35
+ readonly type: "bug:model:call:completed";
36
+ readonly attempt: number;
37
+ readonly finishReason: string;
38
+ readonly promptTokens: number;
39
+ readonly completionTokens: number;
40
+ readonly latencyMs: number;
41
+ }
42
+ export interface RootCauseProposedEvent extends BaseBugEvent {
43
+ readonly type: "bug:rootcause:proposed";
44
+ readonly hasPatch: boolean;
45
+ readonly confidence?: "low" | "medium" | "high" | undefined;
46
+ }
47
+ export interface BugPatchValidatedEvent extends BaseBugEvent {
48
+ readonly type: "bug:patch:validated";
49
+ readonly ok: boolean;
50
+ readonly patchBytes: number;
51
+ readonly filesChanged: number;
52
+ readonly rejectionCode?: string | undefined;
53
+ }
54
+ export interface BugPatchAppliedEvent extends BaseBugEvent {
55
+ readonly type: "bug:patch:applied";
56
+ readonly changedFiles: number;
57
+ readonly created: number;
58
+ readonly deleted: number;
59
+ }
60
+ export interface BugVerificationResultEvent extends BaseBugEvent {
61
+ readonly type: "bug:verification:result";
62
+ readonly overallStatus: VerificationStatus;
63
+ readonly stepCount: number;
64
+ readonly passedCount: number;
65
+ readonly durationMs: number;
66
+ }
67
+ export interface BugInvestigationCompletedEvent extends BaseBugEvent {
68
+ readonly type: "bug:completed";
69
+ readonly status: BugWorkflowStatus;
70
+ readonly durationMs: number;
71
+ }
72
+ export interface BugInvestigationFailedEvent extends BaseBugEvent {
73
+ readonly type: "bug:failed";
74
+ readonly errorCode: string;
75
+ readonly message: string;
76
+ }
77
+ export type BugInvestigationEvent = BugInvestigationStartedEvent | FailureParsedEvent | BugContextSelectedEvent | BugModelCallStartedEvent | BugModelCallCompletedEvent | RootCauseProposedEvent | BugPatchValidatedEvent | BugPatchAppliedEvent | BugVerificationResultEvent | BugInvestigationCompletedEvent | BugInvestigationFailedEvent;
78
+ export interface BugWorkflowEventSink {
79
+ readonly emit: (event: BugInvestigationEvent) => void;
80
+ }
81
+ export {};
@@ -0,0 +1,9 @@
1
+ // The BugInvestigationEvent discriminated union and its BugWorkflowEventSink (ADR-0009 D5). The
2
+ // envelope reuses the harness BaseEvent field shape ({ schemaVersion, runId, fingerprint, seq,
3
+ // ts }) by STRUCTURAL convention — NOT a TypeScript import — so the #10 audit ledger and #13 UI can
4
+ // narrow these events with the same envelope logic they apply to HarnessEvent. This union is
5
+ // SEPARATE from both HarnessEvent and the unit-test WorkflowEvent. Every member name is DISTINCT
6
+ // from the unit-test workflow's (ADR-0009 D5) so the package-root re-export does not collide. No
7
+ // runtime logic lives here. Members carry COUNTS/FLAGS only — never prose, diff, or raw paths;
8
+ // the one SENSITIVE field (failure message) is redacted before emit.
9
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { BugReportInput, FailureEvidence } from "./types.js";
2
+ export declare const MAX_FRAMES = 25;
3
+ export declare function parseFailureEvidence(report: BugReportInput): FailureEvidence;
@@ -0,0 +1,154 @@
1
+ // Failure-output parsing (ADR-0009 D7, NEW seam). Extracts candidate source frames and short
2
+ // error/assertion messages from a bug report's failingOutput + stackTrace, and merges the
3
+ // developer-provided targetFiles as line-less seed frames. The extracted frames are VERIFIED FACTS
4
+ // (what the tool parsed, not a model claim) and seed both context selection (D8) and the report.
5
+ //
6
+ // SECURITY (CodeQL js/polynomial-redos, steering note F): failure output is attacker-influenceable
7
+ // (a failing test can print arbitrary text), so this parser uses ONLY bounded, line-oriented string
8
+ // ops — split('\n'), indexOf/lastIndexOf, slice, a right-split on ':', and an all-digit check. The
9
+ // single regex used (ALL_DIGITS) is a bounded character class with NO nested quantifiers and NO
10
+ // `.*` alternation, so there is no super-linear backtracking surface. Line count and per-line work
11
+ // are both capped. Pure: no IO, no clock, no RNG.
12
+ // Caps that bound total work regardless of input size.
13
+ const MAX_LINES_SCANNED = 2_000;
14
+ export const MAX_FRAMES = 25;
15
+ const MAX_MESSAGES = 10;
16
+ const MAX_MESSAGE_LENGTH = 200;
17
+ const ALL_DIGITS = /^[0-9]+$/;
18
+ const FILE_URL_PREFIX = "file://";
19
+ const MESSAGE_MARKERS = [
20
+ "assertionerror",
21
+ "error:",
22
+ "expected",
23
+ "typeerror",
24
+ "referenceerror",
25
+ "✕",
26
+ "×",
27
+ "fail",
28
+ "●",
29
+ ];
30
+ function toPosix(value) {
31
+ return value.split("\\").join("/");
32
+ }
33
+ // Parses a numeric line number from a token, or undefined when the token is not all-digits.
34
+ function toLine(token) {
35
+ if (token === undefined || token.length === 0 || !ALL_DIGITS.test(token)) {
36
+ return undefined;
37
+ }
38
+ return Number(token);
39
+ }
40
+ // Strips a leading `file://` URL prefix from a location token. `file:///repo/x.ts` -> `/repo/x.ts`.
41
+ function stripFileUrl(location) {
42
+ if (!location.startsWith(FILE_URL_PREFIX)) {
43
+ return location;
44
+ }
45
+ const afterScheme = location.slice(FILE_URL_PREFIX.length);
46
+ // file:///path keeps the leading slash of the absolute path; file://host/path is not expected
47
+ // from runtimes here, so we keep everything after the scheme verbatim.
48
+ return afterScheme;
49
+ }
50
+ // Peels `:line:col` off the END of a location token using a right-split, returning the file path
51
+ // and the numeric line (when present). `src/x.ts:3:10` -> { file: "src/x.ts", line: 3 }. A token
52
+ // with no numeric `:line` segment yields no frame.
53
+ function peelLocation(rawLocation) {
54
+ const location = stripFileUrl(rawLocation.trim());
55
+ const lastColon = location.lastIndexOf(":");
56
+ if (lastColon <= 0) {
57
+ return undefined;
58
+ }
59
+ const beforeCol = location.slice(0, lastColon);
60
+ const lineColon = beforeCol.lastIndexOf(":");
61
+ // Case `file:line:col`: peel col then line.
62
+ const lineToken = lineColon <= 0 ? undefined : beforeCol.slice(lineColon + 1);
63
+ const line = toLine(lineToken);
64
+ if (line !== undefined) {
65
+ const file = toPosix(beforeCol.slice(0, lineColon));
66
+ return file.length === 0 ? undefined : { file, line };
67
+ }
68
+ // Case `file:line` (no col): the token after the last colon is the line.
69
+ const lineOnly = toLine(location.slice(lastColon + 1));
70
+ if (lineOnly !== undefined) {
71
+ const file = toPosix(beforeCol);
72
+ return file.length === 0 ? undefined : { file, line: lineOnly };
73
+ }
74
+ return undefined;
75
+ }
76
+ // Extracts the location token from a stack-frame line. Handles `at fn (loc)`, `at loc`, and a bare
77
+ // `loc` line, all via plain indexOf/slice (no regex).
78
+ function locationToken(line) {
79
+ const trimmed = line.trim();
80
+ const open = trimmed.lastIndexOf("(");
81
+ if (open !== -1) {
82
+ const close = trimmed.indexOf(")", open + 1);
83
+ if (close !== -1) {
84
+ return trimmed.slice(open + 1, close);
85
+ }
86
+ }
87
+ const at = "at ";
88
+ if (trimmed.startsWith(at)) {
89
+ return trimmed.slice(at.length).trim();
90
+ }
91
+ return trimmed;
92
+ }
93
+ function isMessageLine(lower) {
94
+ return MESSAGE_MARKERS.some((marker) => lower.includes(marker));
95
+ }
96
+ function pushFrame(acc, frame) {
97
+ const key = `${frame.file}:${frame.line === undefined ? "" : String(frame.line)}`;
98
+ if (acc.seen.has(key) || acc.frames.length >= MAX_FRAMES) {
99
+ return;
100
+ }
101
+ acc.seen.add(key);
102
+ acc.frames.push(frame);
103
+ }
104
+ function pushMessage(acc, line) {
105
+ if (acc.messages.length >= MAX_MESSAGES) {
106
+ return;
107
+ }
108
+ acc.messages.push(line.trim().slice(0, MAX_MESSAGE_LENGTH));
109
+ }
110
+ function scanLine(acc, line) {
111
+ const token = locationToken(line);
112
+ const frame = token === undefined ? undefined : peelLocation(token);
113
+ if (frame !== undefined) {
114
+ pushFrame(acc, frame);
115
+ }
116
+ if (isMessageLine(line.toLowerCase())) {
117
+ pushMessage(acc, line);
118
+ }
119
+ }
120
+ function scanText(acc, text) {
121
+ if (text === undefined) {
122
+ return;
123
+ }
124
+ let start = 0;
125
+ let scanned = 0;
126
+ while (scanned < MAX_LINES_SCANNED && start <= text.length) {
127
+ const newline = text.indexOf("\n", start);
128
+ const end = newline === -1 ? text.length : newline;
129
+ scanLine(acc, text.slice(start, end));
130
+ scanned += 1;
131
+ if (newline === -1) {
132
+ break;
133
+ }
134
+ start = newline + 1;
135
+ }
136
+ }
137
+ function mergeTargetFiles(acc, targetFiles) {
138
+ if (targetFiles === undefined) {
139
+ return;
140
+ }
141
+ for (const raw of targetFiles) {
142
+ const file = toPosix(raw.trim());
143
+ if (file.length > 0) {
144
+ pushFrame(acc, { file, line: undefined });
145
+ }
146
+ }
147
+ }
148
+ export function parseFailureEvidence(report) {
149
+ const acc = { frames: [], messages: [], seen: new Set() };
150
+ scanText(acc, report.failingOutput);
151
+ scanText(acc, report.stackTrace);
152
+ mergeTargetFiles(acc, report.targetFiles);
153
+ return { frames: acc.frames, messages: acc.messages };
154
+ }
@@ -0,0 +1,2 @@
1
+ export declare function isSensitivePath(relPath: string): boolean;
2
+ export declare function isElevatedReviewPath(relPath: string): boolean;
@@ -0,0 +1,69 @@
1
+ // The bug-fix scope guard's path predicates (ADR-0009 D6). A bug fix legitimately edits production
2
+ // source, so #8's test-files-only guard does NOT apply. Instead this module provides two pure
3
+ // predicates that bound prompt-injection blast radius WITHOUT modifying #6:
4
+ // - isSensitivePath: reject traversal/absolute (fail-closed), .github/, .husky/, and lockfiles —
5
+ // paths #6's deny-list does NOT cover but that a prompt-injected "fix" must never touch.
6
+ // - isElevatedReviewPath: manifest/config edits are ALLOWED but surfaced for elevated review.
7
+ // The change-budget half of D6 is enforced via the #6 PatchLimits override seam (in model-loop.ts).
8
+ //
9
+ // SECURITY (CodeQL js/polynomial-redos): ALL checks use plain string ops (split, startsWith,
10
+ // equality, toLowerCase) — ZERO regex — so there is no ReDoS surface. Checks 2-4 are case-
11
+ // insensitive (matching #6 isDenied) so a case-only variant cannot bypass the guard on
12
+ // case-insensitive filesystems (macOS/Windows); the traversal check is case-invariant by nature.
13
+ const LOCKFILE_BASENAMES = [
14
+ "package-lock.json",
15
+ "npm-shrinkwrap.json",
16
+ "yarn.lock",
17
+ "pnpm-lock.yaml",
18
+ ];
19
+ const SENSITIVE_DIRS = [".github", ".husky"];
20
+ function toPosix(relPath) {
21
+ return relPath.split("\\").join("/");
22
+ }
23
+ // Copies #8's isTraversal logic EXACTLY: an absolute leading slash or any `..` segment can resolve
24
+ // to a file OUTSIDE the apparent location after #6 resolveWithinWorkspace collapses it. Rejected
25
+ // fail-closed BEFORE the case-folded checks so the guarded path matches what #6 would write.
26
+ function isTraversal(posixPath) {
27
+ return posixPath.startsWith("/") || posixPath.split("/").includes("..");
28
+ }
29
+ function basename(posixPath) {
30
+ const slash = posixPath.lastIndexOf("/");
31
+ return slash === -1 ? posixPath : posixPath.slice(slash + 1);
32
+ }
33
+ function underSensitiveDir(lower) {
34
+ return SENSITIVE_DIRS.some((dir) => lower === dir || lower.startsWith(`${dir}/`));
35
+ }
36
+ // Drops `.` and empty ("//") segments so the guard sees the SAME form #6 resolveWithinWorkspace
37
+ // collapses to. Without this, `./.husky/pre-commit` and `.//.github/x` slip past the dir/basename
38
+ // checks (they don't literally start with `.github/`/`.husky/`) yet #6 writes the real protected
39
+ // file (security fix C1). Run only AFTER isTraversal has fail-closed `..`/leading-`/` on the raw
40
+ // path. Pure string ops — no regex.
41
+ function normalizePosix(posixPath) {
42
+ return posixPath
43
+ .split("/")
44
+ .filter((segment) => segment !== "" && segment !== ".")
45
+ .join("/");
46
+ }
47
+ // The sensitive-path guard (D6 bound 2). Returns true when the path must be rejected as
48
+ // out-of-scope. Manifest/config edits are NOT sensitive (see isElevatedReviewPath).
49
+ export function isSensitivePath(relPath) {
50
+ const posixPath = toPosix(relPath);
51
+ if (isTraversal(posixPath)) {
52
+ return true;
53
+ }
54
+ const lower = normalizePosix(posixPath).toLowerCase();
55
+ if (underSensitiveDir(lower)) {
56
+ return true;
57
+ }
58
+ return LOCKFILE_BASENAMES.includes(basename(lower));
59
+ }
60
+ // Manifest/config edits a fix may legitimately need. ALLOWED, but flagged so the report surfaces
61
+ // them as an elevated-review item. A pure basename predicate (case-insensitive). Normalizes `./`
62
+ // and `//` segments first so a `./package.json` form is flagged identically to `package.json`.
63
+ export function isElevatedReviewPath(relPath) {
64
+ const base = basename(normalizePosix(toPosix(relPath)).toLowerCase());
65
+ if (base === "package.json") {
66
+ return true;
67
+ }
68
+ return base.startsWith("tsconfig") && base.endsWith(".json");
69
+ }
@@ -0,0 +1,7 @@
1
+ export { investigateBug } from "./workflow.js";
2
+ export { assembleBugReport, renderBugMarkdownReport, type BugReportParts } from "./report.js";
3
+ export { BUG_INVESTIGATION_WORKFLOW_DESCRIPTOR } from "./descriptor.js";
4
+ export { isSensitivePath, isElevatedReviewPath } from "./guard.js";
5
+ export { parseFailureEvidence, MAX_FRAMES } from "./failure-parse.js";
6
+ export { DEFAULT_BUG_WORKFLOW_LIMITS, type BugInvestigationInput, type BugInvestigationDeps, type BugInvestigationReport, type BugReportInput, type BugWorkflowLimits, type BugWorkflowStatus, type ChangedFile, type FailureEvidence, type FailureFrame, type Hypothesis, type ParsedBugOutput, type VerifiedFindings, } from "./types.js";
7
+ export type { BugContextSelectedEvent, BugInvestigationCompletedEvent, BugInvestigationEvent, BugInvestigationFailedEvent, BugInvestigationStartedEvent, BugModelCallCompletedEvent, BugModelCallStartedEvent, BugPatchAppliedEvent, BugPatchValidatedEvent, BugVerificationResultEvent, BugWorkflowEventSink, FailureParsedEvent, RootCauseProposedEvent, } from "./events.js";
@@ -0,0 +1,13 @@
1
+ // Public barrel for the bug-investigation workflow (ADR-0009 D1). Re-exports the single entry
2
+ // (investigateBug), the static UI descriptor, the Markdown renderer, the BugInvestigationEvent
3
+ // family, and all public types. Internal pipeline modules (internal, model-loop, verify-stage,
4
+ // stages, emit, parse, context, prompt) are NOT re-exported — they are implementation detail. The
5
+ // shared WorkflowDescriptor/WorkflowInputSpec types are intentionally NOT re-exported here (the top
6
+ // workflows barrel exposes them exactly once from ./descriptor.js, ADR-0009 D12). Explicit named
7
+ // re-exports, `type` keyword for type-only, double quotes, `.js`.
8
+ export { investigateBug } from "./workflow.js";
9
+ export { assembleBugReport, renderBugMarkdownReport } from "./report.js";
10
+ export { BUG_INVESTIGATION_WORKFLOW_DESCRIPTOR } from "./descriptor.js";
11
+ export { isSensitivePath, isElevatedReviewPath } from "./guard.js";
12
+ export { parseFailureEvidence, MAX_FRAMES } from "./failure-parse.js";
13
+ export { DEFAULT_BUG_WORKFLOW_LIMITS, } from "./types.js";
@@ -0,0 +1,37 @@
1
+ import type { PatchLimits, PatchValidation } from "../../tools/index.js";
2
+ import { type BugEventEmitter } from "./emit.js";
3
+ import { type BugInvestigationDeps, type BugInvestigationInput, type BugWorkflowLimits, type Hypothesis } from "./types.js";
4
+ import type { BugWorkflowEventSink } from "./events.js";
5
+ export declare const NO_OP_SINK: BugWorkflowEventSink;
6
+ export interface BugWorkflowProgress {
7
+ modelCallCount: number;
8
+ patchRetryCount: number;
9
+ }
10
+ export interface BugRunState {
11
+ readonly input: BugInvestigationInput;
12
+ readonly deps: BugInvestigationDeps;
13
+ readonly limits: BugWorkflowLimits;
14
+ readonly signal: AbortSignal;
15
+ readonly now: () => number;
16
+ readonly emitter: BugEventEmitter;
17
+ readonly startedAt: number;
18
+ readonly progress: BugWorkflowProgress;
19
+ }
20
+ export interface AcceptedBugPatch {
21
+ readonly diff: string;
22
+ readonly validation: PatchValidation;
23
+ readonly hypothesis: Hypothesis;
24
+ }
25
+ export interface BugModelLoopResult {
26
+ readonly accepted: AcceptedBugPatch | undefined;
27
+ readonly investigationOnly: Hypothesis | undefined;
28
+ readonly modelCallCount: number;
29
+ readonly patchRetryCount: number;
30
+ readonly lastRejectionCode: string | undefined;
31
+ }
32
+ export declare const EMPTY_BUG_LOOP: BugModelLoopResult;
33
+ export declare function resolveBugLimits(input: BugInvestigationInput): BugWorkflowLimits;
34
+ export declare function patchLimitsFrom(limits: BugWorkflowLimits): PatchLimits;
35
+ export declare function buildBugRunState(input: BugInvestigationInput, deps: BugInvestigationDeps, fingerprint: string): BugRunState;
36
+ export declare function nextActionsFor(applied: boolean, files: readonly string[], elevated: readonly string[]): readonly string[];
37
+ export declare function investigationNextActions(): readonly string[];