@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,36 @@
1
+ // The single filesystem boundary for the workspace layer (ADR-0005 D1). Every other module
2
+ // depends on the `WorkspaceFs` port, never on `node:fs` directly, so discovery/detection are
3
+ // testable with an in-memory fake and all real IO is auditable in one place. Synchronous, to
4
+ // mirror the existing `loadConfigFromFile`/`readFileSync` usage in the gateway.
5
+ import { lstatSync, readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
6
+ function isSymlink(absolutePath) {
7
+ return lstatSync(absolutePath, { throwIfNoEntry: false })?.isSymbolicLink() ?? false;
8
+ }
9
+ export const nodeWorkspaceFs = {
10
+ readFileUtf8: (absolutePath) => readFileSync(absolutePath, "utf8"),
11
+ stat: (absolutePath) => {
12
+ const stats = statSync(absolutePath, { throwIfNoEntry: true });
13
+ return {
14
+ size: stats.size,
15
+ isFile: stats.isFile(),
16
+ isDirectory: stats.isDirectory(),
17
+ isSymbolicLink: isSymlink(absolutePath),
18
+ hardLinkCount: stats.nlink,
19
+ };
20
+ },
21
+ readDir: (absolutePath) => readdirSync(absolutePath, { withFileTypes: true }).map((entry) => ({
22
+ name: entry.name,
23
+ isDirectory: entry.isDirectory(),
24
+ isFile: entry.isFile(),
25
+ isSymbolicLink: entry.isSymbolicLink(),
26
+ })),
27
+ realPath: (absolutePath) => realpathSync(absolutePath),
28
+ exists: (absolutePath) => {
29
+ try {
30
+ return statSync(absolutePath, { throwIfNoEntry: false }) !== undefined;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ },
36
+ };
@@ -0,0 +1,14 @@
1
+ export declare const DEFAULT_DENY_PATTERNS: readonly string[];
2
+ export declare function isDenied(relPath: string): boolean;
3
+ interface IgnoreRule {
4
+ readonly regex: RegExp;
5
+ readonly dirEntryRegex: RegExp | null;
6
+ readonly negated: boolean;
7
+ readonly dirOnly: boolean;
8
+ }
9
+ export interface IgnoreMatcher {
10
+ readonly rules: readonly IgnoreRule[];
11
+ }
12
+ export declare function compileIgnore(lines: readonly string[]): IgnoreMatcher;
13
+ export declare function isIgnored(matcher: IgnoreMatcher, relPath: string, isDir: boolean): boolean;
14
+ export {};
@@ -0,0 +1,176 @@
1
+ // PURE filtering. Two tiers (ADR-0005 D3):
2
+ // 1. isDenied() — ALWAYS-ON security deny list. Enforced before every read regardless
3
+ // of .gitignore. Secret/dep/build/cache/vcs/log/os files are never discovered or read.
4
+ // 2. compileIgnore()/isIgnored() — best-effort noise reduction over a DOCUMENTED, bounded
5
+ // .gitignore subset. Never relaxes the deny list.
6
+ // Glob translation produces only linear regex pieces (`[^/]*`, `.*`) so there is no
7
+ // catastrophic backtracking (no ReDoS).
8
+ export const DEFAULT_DENY_PATTERNS = Object.freeze([
9
+ // secrets
10
+ ".env",
11
+ ".env.*",
12
+ "*.pem",
13
+ "*.key",
14
+ "id_rsa",
15
+ "id_ed25519",
16
+ "id_ecdsa",
17
+ "id_dsa",
18
+ "*.p12",
19
+ "*.pfx",
20
+ ".npmrc",
21
+ // deps
22
+ "node_modules",
23
+ // build
24
+ "dist",
25
+ "build",
26
+ "out",
27
+ "coverage",
28
+ // caches
29
+ ".cache",
30
+ ".next",
31
+ ".turbo",
32
+ // vcs
33
+ ".git",
34
+ // logs
35
+ "*.log",
36
+ // os
37
+ ".DS_Store",
38
+ ]);
39
+ // Iterates from the end rather than using /\/+$/ to avoid quadratic ReDoS on
40
+ // inputs with many consecutive trailing slashes (CodeQL js/polynomial-redos).
41
+ function stripTrailingSlashes(value) {
42
+ let end = value.length;
43
+ while (end > 0 && value.charCodeAt(end - 1) === 47 /* "/" */) {
44
+ end -= 1;
45
+ }
46
+ return value.slice(0, end);
47
+ }
48
+ function normalize(relPath) {
49
+ return stripTrailingSlashes(relPath.replace(/\\/g, "/").replace(/^\.\//, ""));
50
+ }
51
+ function segments(relPath) {
52
+ return normalize(relPath)
53
+ .split("/")
54
+ .filter((part) => part.length > 0);
55
+ }
56
+ const EXAMPLE_ENV = ".env.example";
57
+ // Always-on security check. Denied if ANY path segment matches a deny pattern (a denied
58
+ // directory denies everything under it). `.env.example` is the single documented exception.
59
+ // Matching is CASE-INSENSITIVE: on case-insensitive filesystems (macOS, Windows) `.ENV` and
60
+ // `.env` name the same file, so a case-only variant must not bypass the deny list.
61
+ export function isDenied(relPath) {
62
+ for (const part of segments(relPath)) {
63
+ const lower = part.toLowerCase();
64
+ if (lower === EXAMPLE_ENV) {
65
+ continue;
66
+ }
67
+ for (const matcher of PRECOMPILED_DENY_MATCHERS) {
68
+ if (matcher.regex.test(lower)) {
69
+ return true;
70
+ }
71
+ }
72
+ }
73
+ return false;
74
+ }
75
+ function globBody(glob) {
76
+ let body = "";
77
+ let i = 0;
78
+ while (i < glob.length) {
79
+ // charAt returns "" past the end; the loop bound guarantees a real char here, so there is
80
+ // no dead nullish fallback. charAt(i + 1)/(i + 2) safely return "" at the boundary.
81
+ const char = glob.charAt(i);
82
+ if (char === "*" && glob.charAt(i + 1) === "*") {
83
+ body += ".*";
84
+ i += glob.charAt(i + 2) === "/" ? 3 : 2;
85
+ continue;
86
+ }
87
+ if (char === "*") {
88
+ body += "[^/]*";
89
+ }
90
+ else if (char === "?") {
91
+ body += "[^/]";
92
+ }
93
+ else {
94
+ body += escapeLiteral(char);
95
+ }
96
+ i += 1;
97
+ }
98
+ return body;
99
+ }
100
+ function globToRegExp(glob, anchored) {
101
+ const prefix = anchored ? "^" : "^(?:.*/)?";
102
+ return new RegExp(`${prefix}${globBody(glob)}(?:/.*)?$`);
103
+ }
104
+ const PRECOMPILED_DENY_MATCHERS = DEFAULT_DENY_PATTERNS.map((pattern) => ({
105
+ regex: globToRegExp(pattern.toLowerCase(), false),
106
+ }));
107
+ // Matches the path that names the directory itself (no nested suffix), used so a `dir/` rule
108
+ // can distinguish a real subdirectory from a same-named file at another depth.
109
+ function globToDirEntryRegExp(glob, anchored) {
110
+ const prefix = anchored ? "^" : "^(?:.*/)?";
111
+ return new RegExp(`${prefix}${globBody(glob)}$`);
112
+ }
113
+ function escapeLiteral(char) {
114
+ return /[.*+?^${}()|[\]\\]/.test(char) ? `\\${char}` : char;
115
+ }
116
+ function stripAnchors(value, anchored, dirOnly) {
117
+ let core = value;
118
+ if (anchored) {
119
+ core = core.slice(1);
120
+ }
121
+ if (dirOnly) {
122
+ core = core.slice(0, -1);
123
+ }
124
+ return core;
125
+ }
126
+ function buildRule(rawLine) {
127
+ const line = rawLine.trim();
128
+ if (line.length === 0 || line.startsWith("#")) {
129
+ return null;
130
+ }
131
+ const negated = line.startsWith("!");
132
+ const afterBang = negated ? line.slice(1) : line;
133
+ const anchored = afterBang.startsWith("/");
134
+ const dirOnly = afterBang.endsWith("/");
135
+ const core = stripAnchors(afterBang, anchored, dirOnly);
136
+ if (core.length === 0) {
137
+ return null;
138
+ }
139
+ return {
140
+ regex: globToRegExp(core, anchored),
141
+ dirEntryRegex: dirOnly ? globToDirEntryRegExp(core, anchored) : null,
142
+ negated,
143
+ dirOnly,
144
+ };
145
+ }
146
+ export function compileIgnore(lines) {
147
+ const rules = [];
148
+ for (const line of lines) {
149
+ const rule = buildRule(line);
150
+ if (rule !== null) {
151
+ rules.push(rule);
152
+ }
153
+ }
154
+ return { rules };
155
+ }
156
+ export function isIgnored(matcher, relPath, isDir) {
157
+ const target = normalize(relPath);
158
+ let ignored = false;
159
+ for (const rule of matcher.rules) {
160
+ if (ruleMatches(rule, target, isDir)) {
161
+ ignored = !rule.negated;
162
+ }
163
+ }
164
+ return ignored;
165
+ }
166
+ // A `dir/` rule ignores either the matching directory entry itself (only when it IS a
167
+ // directory), or any path genuinely nested under it. A same-named FILE is not ignored.
168
+ function ruleMatches(rule, target, isDir) {
169
+ if (!rule.dirOnly) {
170
+ return rule.regex.test(target);
171
+ }
172
+ if (rule.dirEntryRegex?.test(target) === true) {
173
+ return isDir;
174
+ }
175
+ return rule.regex.test(target);
176
+ }
@@ -0,0 +1,11 @@
1
+ export type { AuditEntry, AuditSummary, ContextEntry, ContextEntrySummary, ContextPack, ContextPackSummary, ContextRequest, DiscoveredFile, DiscoveryOptions, DiscoveryStats, FileContent, ReadOptions, SelectionReason, TestFramework, WorkspaceInfo, WorkspaceLanguage, WorkspaceSummary, } from "./types.js";
2
+ export { DEFAULT_CONTEXT_REQUEST, DEFAULT_DISCOVERY_OPTIONS, DEFAULT_READ_OPTIONS, SELECTION_REASON_PRIORITY, } from "./types.js";
3
+ export { FileTooLargeError, PathDeniedError, PathEscapeError, WORKSPACE_CODES, WorkspaceError, WorkspaceNotFoundError, WorkspaceReadError, type WorkspaceCode, } from "./errors.js";
4
+ export { type WorkspaceDirEntry, type WorkspaceFs, type WorkspaceStat } from "./fs.js";
5
+ export { isWithinWorkspace, resolveWithinWorkspace } from "./paths.js";
6
+ export { compileIgnore, DEFAULT_DENY_PATTERNS, isDenied, isIgnored, type IgnoreMatcher, } from "./ignore.js";
7
+ export { detectWorkspace } from "./detect.js";
8
+ export { discoverFiles, discoverWithStats, readWorkspaceFile, type DiscoveryResult, } from "./discovery.js";
9
+ export { lexicalRetrievalStrategy, type RankedFile, type RetrievalStrategy } from "./retrieval.js";
10
+ export { buildContextPack, buildContextPackFromFiles, type ContextPackDeps, } from "./contextPack.js";
11
+ export { buildWorkspaceSummary, summarizeForAudit } from "./summary.js";
@@ -0,0 +1,13 @@
1
+ // Public barrel for the repository-context & workspace-access layer (ADR-0005). The only
2
+ // file-read path exposed is the boundary-checked one; no export returns raw arbitrary file
3
+ // content. Explicit named re-exports, `type` keyword for type-only, double quotes, `.js`.
4
+ export { DEFAULT_CONTEXT_REQUEST, DEFAULT_DISCOVERY_OPTIONS, DEFAULT_READ_OPTIONS, SELECTION_REASON_PRIORITY, } from "./types.js";
5
+ export { FileTooLargeError, PathDeniedError, PathEscapeError, WORKSPACE_CODES, WorkspaceError, WorkspaceNotFoundError, WorkspaceReadError, } from "./errors.js";
6
+ export {} from "./fs.js";
7
+ export { isWithinWorkspace, resolveWithinWorkspace } from "./paths.js";
8
+ export { compileIgnore, DEFAULT_DENY_PATTERNS, isDenied, isIgnored, } from "./ignore.js";
9
+ export { detectWorkspace } from "./detect.js";
10
+ export { discoverFiles, discoverWithStats, readWorkspaceFile, } from "./discovery.js";
11
+ export { lexicalRetrievalStrategy } from "./retrieval.js";
12
+ export { buildContextPack, buildContextPackFromFiles, } from "./contextPack.js";
13
+ export { buildWorkspaceSummary, summarizeForAudit } from "./summary.js";
@@ -0,0 +1,2 @@
1
+ export declare function resolveWithinWorkspace(root: string, candidate: string): string;
2
+ export declare function isWithinWorkspace(root: string, candidate: string): boolean;
@@ -0,0 +1,38 @@
1
+ // PURE, security-critical lexical path containment. This module performs NO filesystem
2
+ // access: it decides whether a candidate path lexically resolves inside a workspace root.
3
+ // Symlink/realpath containment (which DOES touch the filesystem) is enforced separately at
4
+ // the IO edge in discovery.ts — see ADR-0005 D2 for the split.
5
+ import { isAbsolute, relative, resolve, sep } from "node:path";
6
+ import { PathEscapeError } from "./errors.js";
7
+ function hasNul(value) {
8
+ return value.includes("\u0000");
9
+ }
10
+ // Returns the normalized absolute path of `candidate` inside `root`, or throws
11
+ // PathEscapeError. The returned value is the ONLY path that downstream IO should read, so
12
+ // a static analyser's path sanitizer sits on this boundary.
13
+ export function resolveWithinWorkspace(root, candidate) {
14
+ if (hasNul(root) || hasNul(candidate)) {
15
+ throw new PathEscapeError("path contains a NUL byte", candidate);
16
+ }
17
+ const absoluteRoot = resolve(root);
18
+ const absoluteCandidate = isAbsolute(candidate)
19
+ ? resolve(candidate)
20
+ : resolve(absoluteRoot, candidate);
21
+ const rel = relative(absoluteRoot, absoluteCandidate);
22
+ if (rel === "") {
23
+ return absoluteRoot;
24
+ }
25
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
26
+ throw new PathEscapeError(`path escapes the workspace boundary: ${candidate}`, candidate);
27
+ }
28
+ return absoluteCandidate;
29
+ }
30
+ export function isWithinWorkspace(root, candidate) {
31
+ try {
32
+ resolveWithinWorkspace(root, candidate);
33
+ return true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
@@ -0,0 +1,7 @@
1
+ import type { WorkspaceFs } from "./fs.js";
2
+ export interface ContainedRealPathInfo {
3
+ readonly path: string;
4
+ readonly realRelative: string;
5
+ }
6
+ export declare function containedRealPathInfo(fs: WorkspaceFs, root: string, absolutePath: string): ContainedRealPathInfo;
7
+ export declare function assertContainedRealPath(fs: WorkspaceFs, root: string, absolutePath: string, _label: string): string;
@@ -0,0 +1,72 @@
1
+ // PURE-at-the-port symlink containment. After lexical resolveWithinWorkspace has proven a path is
2
+ // lexically inside the root, this gate defends against the symlink class of escape: a path whose
3
+ // real (symlink-followed) location is outside the root, or a not-yet-existing create target whose
4
+ // nearest existing parent escapes via a symlink. Every filesystem touch goes through the injected
5
+ // WorkspaceFs port (realPath only) so the logic stays testable with an in-memory fake and all real
6
+ // IO is auditable in one place (ADR-0005 D2, ADR-0006 D2). The read path (discovery.ts) and the
7
+ // write/cwd paths (tools/patch.ts, tools/exec.ts) share this single primitive — no duplicated logic.
8
+ import { dirname } from "node:path";
9
+ import { isWithinWorkspace } from "./paths.js";
10
+ import { PathEscapeError } from "./errors.js";
11
+ // Resolves `root` through any platform symlinks (e.g. macOS /var -> /private/var) so the
12
+ // containment comparison is symlink-consistent on both sides. Falls back to the lexical root.
13
+ function realRoot(fs, root) {
14
+ try {
15
+ return fs.realPath(root);
16
+ }
17
+ catch {
18
+ return root;
19
+ }
20
+ }
21
+ // Walks up from `absolutePath` to the nearest ancestor that exists on disk and returns its real
22
+ // path. A create target does not exist yet, so we must realpath the deepest existing parent to
23
+ // catch a symlinked parent directory (e.g. `link/evil` where `link` -> /outside). Bounded by the
24
+ // path depth; terminates at the filesystem root where dirname is a fixpoint.
25
+ function realNearestExisting(fs, absolutePath) {
26
+ let current = absolutePath;
27
+ for (;;) {
28
+ try {
29
+ return fs.realPath(current);
30
+ }
31
+ catch {
32
+ const parent = dirname(current);
33
+ if (parent === current) {
34
+ return absolutePath; // reached the root with nothing resolvable; lexical check stands
35
+ }
36
+ current = parent;
37
+ }
38
+ }
39
+ }
40
+ function toRelative(root, absolutePath) {
41
+ return absolutePath.slice(root.length).replace(/^[/\\]/, "");
42
+ }
43
+ export function containedRealPathInfo(fs, root, absolutePath) {
44
+ const realBase = realRoot(fs, root);
45
+ try {
46
+ const target = fs.realPath(absolutePath);
47
+ if (!isWithinWorkspace(realBase, target)) {
48
+ throw new PathEscapeError(`path escapes the workspace boundary via symlink: ${absolutePath}`, absolutePath);
49
+ }
50
+ return { path: target, realRelative: toRelative(realBase, target) };
51
+ }
52
+ catch (error) {
53
+ if (error instanceof PathEscapeError) {
54
+ throw error;
55
+ }
56
+ const parentReal = realNearestExisting(fs, absolutePath);
57
+ if (!isWithinWorkspace(realBase, parentReal)) {
58
+ throw new PathEscapeError(`path escapes the workspace boundary via symlink: ${absolutePath}`, absolutePath);
59
+ }
60
+ return { path: absolutePath, realRelative: toRelative(realBase, parentReal) };
61
+ }
62
+ }
63
+ // Asserts that `absolutePath` (already lexically contained) does not escape `root` via a symlink.
64
+ // For an existing target, the target's own realpath must stay within the real root. For a
65
+ // not-yet-existing target (create), the nearest existing ancestor's realpath must stay within it,
66
+ // which blocks `create through a symlinked directory` (the S-H1 .git/hooks escalation).
67
+ // Returns the canonical real path to hand to IO (existing case) or the lexically-resolved path
68
+ // (pure-create case where the target itself has no realpath yet).
69
+ export function assertContainedRealPath(fs, root, absolutePath, _label) {
70
+ const info = containedRealPathInfo(fs, root, absolutePath);
71
+ return info.path;
72
+ }
@@ -0,0 +1,9 @@
1
+ import { type DiscoveredFile, type SelectionReason } from "./types.js";
2
+ export interface RankedFile {
3
+ readonly file: DiscoveredFile;
4
+ readonly selectionReason: SelectionReason;
5
+ }
6
+ export interface RetrievalStrategy {
7
+ readonly rank: (files: readonly DiscoveredFile[], task: string | undefined) => readonly RankedFile[];
8
+ }
9
+ export declare const lexicalRetrievalStrategy: RetrievalStrategy;
@@ -0,0 +1,74 @@
1
+ // Retrieval seam (ADR-0005 D5). `RetrievalStrategy` is the typed extension point a future
2
+ // embedding ranker (e.g. `multilingual-e5-large`) plugs into. Wave-1 ships ONLY the seam and
3
+ // a deterministic lexical default — no embeddings, no vector DB, no new dependency. The
4
+ // default ranker is pure and clock/RNG-free so context packs are reproducible.
5
+ import { SELECTION_REASON_PRIORITY } from "./types.js";
6
+ const ENTRYPOINT_BASENAMES = new Set([
7
+ "index.ts",
8
+ "index.js",
9
+ "main.ts",
10
+ "main.js",
11
+ "cli.ts",
12
+ "cli.js",
13
+ ]);
14
+ const MANIFEST_BASENAMES = new Set([
15
+ "package.json",
16
+ "tsconfig.json",
17
+ "tsconfig.build.json",
18
+ ]);
19
+ const DOC_EXTENSIONS = new Set([".md", ".mdx", ".rst", ".txt"]);
20
+ const CONFIG_EXTENSIONS = new Set([".json", ".yml", ".yaml", ".toml"]);
21
+ const CONFIG_BASENAME_HINTS = [".config.", "eslint", "prettier", "vitest"];
22
+ function basename(path) {
23
+ const idx = path.lastIndexOf("/");
24
+ return idx === -1 ? path : path.slice(idx + 1);
25
+ }
26
+ function extension(name) {
27
+ const idx = name.lastIndexOf(".");
28
+ return idx <= 0 ? "" : name.slice(idx);
29
+ }
30
+ function isTest(name) {
31
+ return /\.(test|spec)\.[cm]?[jt]sx?$/.test(name);
32
+ }
33
+ function isConfig(name) {
34
+ return (CONFIG_EXTENSIONS.has(extension(name)) || CONFIG_BASENAME_HINTS.some((h) => name.includes(h)));
35
+ }
36
+ function classify(path) {
37
+ const name = basename(path);
38
+ if (isTest(name) || path.startsWith("tests/") || path.startsWith("test/")) {
39
+ return "test";
40
+ }
41
+ if (ENTRYPOINT_BASENAMES.has(name)) {
42
+ return "entrypoint";
43
+ }
44
+ if (MANIFEST_BASENAMES.has(name)) {
45
+ return "manifest";
46
+ }
47
+ if (DOC_EXTENSIONS.has(extension(name))) {
48
+ return "documentation";
49
+ }
50
+ if (isConfig(name)) {
51
+ return "config";
52
+ }
53
+ return "source";
54
+ }
55
+ function priorityIndex(reason) {
56
+ return SELECTION_REASON_PRIORITY.indexOf(reason);
57
+ }
58
+ // Deterministic lexical ranking: by selection-reason priority, then by path (ascending).
59
+ export const lexicalRetrievalStrategy = {
60
+ rank: (files) => {
61
+ const ranked = files.map((file) => ({ file, selectionReason: classify(file.relativePath) }));
62
+ return [...ranked].sort((a, b) => {
63
+ const byReason = priorityIndex(a.selectionReason) - priorityIndex(b.selectionReason);
64
+ if (byReason !== 0) {
65
+ return byReason;
66
+ }
67
+ if (a.file.relativePath < b.file.relativePath)
68
+ return -1;
69
+ if (a.file.relativePath > b.file.relativePath)
70
+ return 1;
71
+ return 0;
72
+ });
73
+ },
74
+ };
@@ -0,0 +1,3 @@
1
+ import type { AuditSummary, ContextPack, DiscoveryStats, WorkspaceInfo, WorkspaceSummary } from "./types.js";
2
+ export declare function buildWorkspaceSummary(workspace: WorkspaceInfo, pack?: ContextPack, stats?: DiscoveryStats): WorkspaceSummary;
3
+ export declare function summarizeForAudit(pack: ContextPack): AuditSummary;
@@ -0,0 +1,54 @@
1
+ // The structured, redacted view CLI/SDK/UI render WITHOUT touching the filesystem. Every
2
+ // string that could carry file content is already redacted upstream (context excerpts pass
3
+ // through redact() in discovery/contextPack). This module only reshapes already-safe data;
4
+ // it performs no IO and adds no raw file contents. Pure and deterministic.
5
+ function toContextSummary(pack) {
6
+ return {
7
+ totalCandidates: pack.totalCandidates,
8
+ usedBytes: pack.usedBytes,
9
+ budgetBytes: pack.budgetBytes,
10
+ droppedForBudget: pack.droppedForBudget,
11
+ entries: pack.selected.map((entry) => ({
12
+ path: entry.path,
13
+ sizeBytes: entry.sizeBytes,
14
+ excerptBytes: entry.excerptBytes,
15
+ selectionReason: entry.selectionReason,
16
+ truncated: entry.truncated,
17
+ excerpt: entry.excerpt,
18
+ })),
19
+ };
20
+ }
21
+ function statsFor(pack) {
22
+ return { discovered: pack?.totalCandidates ?? 0, denied: 0, ignored: 0 };
23
+ }
24
+ export function buildWorkspaceSummary(workspace, pack, stats) {
25
+ return {
26
+ root: workspace.root,
27
+ name: workspace.name,
28
+ version: workspace.version,
29
+ testFramework: workspace.testFramework,
30
+ sourceDirs: workspace.sourceDirs,
31
+ testDirs: workspace.testDirs,
32
+ languages: workspace.languages,
33
+ counts: stats ?? statsFor(pack),
34
+ context: pack === undefined ? undefined : toContextSummary(pack),
35
+ };
36
+ }
37
+ // Selected-context metadata for audit evidence: paths, sizes, reasons, and budget usage.
38
+ // Deliberately excludes excerpt TEXT so an audit record carries no file content at all.
39
+ export function summarizeForAudit(pack) {
40
+ return {
41
+ workspaceRoot: pack.workspaceRoot,
42
+ totalCandidates: pack.totalCandidates,
43
+ usedBytes: pack.usedBytes,
44
+ budgetBytes: pack.budgetBytes,
45
+ droppedForBudget: pack.droppedForBudget,
46
+ entries: pack.selected.map((entry) => ({
47
+ path: entry.path,
48
+ sizeBytes: entry.sizeBytes,
49
+ excerptBytes: entry.excerptBytes,
50
+ selectionReason: entry.selectionReason,
51
+ truncated: entry.truncated,
52
+ })),
53
+ };
54
+ }
@@ -0,0 +1,103 @@
1
+ export type WorkspaceLanguage = "typescript" | "javascript";
2
+ export type TestFramework = "vitest" | "jest" | "mocha" | "unknown";
3
+ export interface WorkspaceInfo {
4
+ readonly root: string;
5
+ readonly name: string | undefined;
6
+ readonly version: string | undefined;
7
+ readonly testFramework: TestFramework;
8
+ readonly sourceDirs: readonly string[];
9
+ readonly testDirs: readonly string[];
10
+ readonly languages: readonly WorkspaceLanguage[];
11
+ readonly ignoreLines: readonly string[];
12
+ }
13
+ export interface DiscoveredFile {
14
+ readonly relativePath: string;
15
+ readonly sizeBytes: number;
16
+ }
17
+ export interface DiscoveryOptions {
18
+ readonly maxDepth: number;
19
+ readonly maxFiles: number;
20
+ readonly applyGitignore: boolean;
21
+ }
22
+ export declare const DEFAULT_DISCOVERY_OPTIONS: DiscoveryOptions;
23
+ export interface DiscoveryStats {
24
+ readonly discovered: number;
25
+ readonly denied: number;
26
+ readonly ignored: number;
27
+ }
28
+ export interface ReadOptions {
29
+ readonly maxBytes: number;
30
+ }
31
+ export declare const DEFAULT_READ_OPTIONS: ReadOptions;
32
+ export interface FileContent {
33
+ readonly relativePath: string;
34
+ readonly sizeBytes: number;
35
+ readonly text: string;
36
+ readonly truncated: boolean;
37
+ }
38
+ export type SelectionReason = "entrypoint" | "manifest" | "documentation" | "config" | "source" | "test";
39
+ export declare const SELECTION_REASON_PRIORITY: readonly SelectionReason[];
40
+ export interface ContextRequest {
41
+ readonly task: string | undefined;
42
+ readonly budgetBytes: number;
43
+ readonly maxBytesPerFile: number;
44
+ readonly discovery: DiscoveryOptions;
45
+ }
46
+ export declare const DEFAULT_CONTEXT_REQUEST: ContextRequest;
47
+ export interface ContextEntry {
48
+ readonly path: string;
49
+ readonly sizeBytes: number;
50
+ readonly excerptBytes: number;
51
+ readonly selectionReason: SelectionReason;
52
+ readonly truncated: boolean;
53
+ readonly excerpt: string;
54
+ }
55
+ export interface ContextPack {
56
+ readonly workspaceRoot: string;
57
+ readonly totalCandidates: number;
58
+ readonly selected: readonly ContextEntry[];
59
+ readonly usedBytes: number;
60
+ readonly budgetBytes: number;
61
+ readonly droppedForBudget: number;
62
+ }
63
+ export interface ContextEntrySummary {
64
+ readonly path: string;
65
+ readonly sizeBytes: number;
66
+ readonly excerptBytes: number;
67
+ readonly selectionReason: SelectionReason;
68
+ readonly truncated: boolean;
69
+ readonly excerpt: string;
70
+ }
71
+ export interface ContextPackSummary {
72
+ readonly totalCandidates: number;
73
+ readonly usedBytes: number;
74
+ readonly budgetBytes: number;
75
+ readonly droppedForBudget: number;
76
+ readonly entries: readonly ContextEntrySummary[];
77
+ }
78
+ export interface WorkspaceSummary {
79
+ readonly root: string;
80
+ readonly name: string | undefined;
81
+ readonly version: string | undefined;
82
+ readonly testFramework: TestFramework;
83
+ readonly sourceDirs: readonly string[];
84
+ readonly testDirs: readonly string[];
85
+ readonly languages: readonly WorkspaceLanguage[];
86
+ readonly counts: DiscoveryStats;
87
+ readonly context: ContextPackSummary | undefined;
88
+ }
89
+ export interface AuditEntry {
90
+ readonly path: string;
91
+ readonly sizeBytes: number;
92
+ readonly excerptBytes: number;
93
+ readonly selectionReason: SelectionReason;
94
+ readonly truncated: boolean;
95
+ }
96
+ export interface AuditSummary {
97
+ readonly workspaceRoot: string;
98
+ readonly totalCandidates: number;
99
+ readonly usedBytes: number;
100
+ readonly budgetBytes: number;
101
+ readonly droppedForBudget: number;
102
+ readonly entries: readonly AuditEntry[];
103
+ }
@@ -0,0 +1,27 @@
1
+ // All workspace-layer interfaces and the frozen default tables. No runtime logic lives
2
+ // here beyond the frozen constant tables the type layer must expose as values, mirroring
3
+ // the ADR-0003/ADR-0004 `types.ts` precedent. `readonly` everywhere; optional props are
4
+ // `| undefined` because exactOptionalPropertyTypes is on.
5
+ export const DEFAULT_DISCOVERY_OPTIONS = {
6
+ maxDepth: 12,
7
+ maxFiles: 5_000,
8
+ applyGitignore: true,
9
+ };
10
+ export const DEFAULT_READ_OPTIONS = {
11
+ maxBytes: 262_144,
12
+ };
13
+ // Priority order used to rank candidates: lower index wins. Ties break on lexical path.
14
+ export const SELECTION_REASON_PRIORITY = [
15
+ "entrypoint",
16
+ "manifest",
17
+ "documentation",
18
+ "config",
19
+ "source",
20
+ "test",
21
+ ];
22
+ export const DEFAULT_CONTEXT_REQUEST = {
23
+ task: undefined,
24
+ budgetBytes: 65_536,
25
+ maxBytesPerFile: 8_192,
26
+ discovery: DEFAULT_DISCOVERY_OPTIONS,
27
+ };