@delegance/claude-autopilot 5.0.1 → 5.0.3

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 (412) hide show
  1. package/dist/src/adapters/review-engine/codex.js +13 -1
  2. package/dist/src/cli/index.js +39 -1
  3. package/dist/src/cli/preflight.js +17 -4
  4. package/dist/src/cli/scan.js +12 -0
  5. package/package.json +4 -3
  6. package/dist/presets/go/rules/go-sql-injection.d.ts.map +0 -1
  7. package/dist/presets/go/rules/go-sql-injection.js.map +0 -1
  8. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.d.ts.map +0 -1
  9. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js.map +0 -1
  10. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.d.ts.map +0 -1
  11. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js.map +0 -1
  12. package/dist/presets/rails-postgres/rules/rails-sql-injection.d.ts.map +0 -1
  13. package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +0 -1
  14. package/dist/presets/t3/rules/t3-server-only.d.ts.map +0 -1
  15. package/dist/presets/t3/rules/t3-server-only.js.map +0 -1
  16. package/dist/src/adapters/base.d.ts.map +0 -1
  17. package/dist/src/adapters/base.js.map +0 -1
  18. package/dist/src/adapters/council/claude.d.ts.map +0 -1
  19. package/dist/src/adapters/council/claude.js.map +0 -1
  20. package/dist/src/adapters/council/openai.d.ts.map +0 -1
  21. package/dist/src/adapters/council/openai.js.map +0 -1
  22. package/dist/src/adapters/council/types.d.ts.map +0 -1
  23. package/dist/src/adapters/council/types.js.map +0 -1
  24. package/dist/src/adapters/loader.d.ts.map +0 -1
  25. package/dist/src/adapters/loader.js.map +0 -1
  26. package/dist/src/adapters/migration-runner/supabase.d.ts.map +0 -1
  27. package/dist/src/adapters/migration-runner/supabase.js.map +0 -1
  28. package/dist/src/adapters/migration-runner/types.d.ts.map +0 -1
  29. package/dist/src/adapters/migration-runner/types.js.map +0 -1
  30. package/dist/src/adapters/review-bot-parser/cursor.d.ts.map +0 -1
  31. package/dist/src/adapters/review-bot-parser/cursor.js.map +0 -1
  32. package/dist/src/adapters/review-bot-parser/declarative-base.d.ts.map +0 -1
  33. package/dist/src/adapters/review-bot-parser/declarative-base.js.map +0 -1
  34. package/dist/src/adapters/review-bot-parser/types.d.ts.map +0 -1
  35. package/dist/src/adapters/review-bot-parser/types.js.map +0 -1
  36. package/dist/src/adapters/review-engine/auto.d.ts.map +0 -1
  37. package/dist/src/adapters/review-engine/auto.js.map +0 -1
  38. package/dist/src/adapters/review-engine/claude.d.ts.map +0 -1
  39. package/dist/src/adapters/review-engine/claude.js.map +0 -1
  40. package/dist/src/adapters/review-engine/codex.d.ts.map +0 -1
  41. package/dist/src/adapters/review-engine/codex.js.map +0 -1
  42. package/dist/src/adapters/review-engine/gemini.d.ts.map +0 -1
  43. package/dist/src/adapters/review-engine/gemini.js.map +0 -1
  44. package/dist/src/adapters/review-engine/openai-compatible.d.ts.map +0 -1
  45. package/dist/src/adapters/review-engine/openai-compatible.js.map +0 -1
  46. package/dist/src/adapters/review-engine/parse-output.d.ts.map +0 -1
  47. package/dist/src/adapters/review-engine/parse-output.js.map +0 -1
  48. package/dist/src/adapters/review-engine/prompt-builder.d.ts.map +0 -1
  49. package/dist/src/adapters/review-engine/prompt-builder.js.map +0 -1
  50. package/dist/src/adapters/review-engine/types.d.ts.map +0 -1
  51. package/dist/src/adapters/review-engine/types.js.map +0 -1
  52. package/dist/src/adapters/vcs-host/commit-status.d.ts.map +0 -1
  53. package/dist/src/adapters/vcs-host/commit-status.js.map +0 -1
  54. package/dist/src/adapters/vcs-host/github.d.ts.map +0 -1
  55. package/dist/src/adapters/vcs-host/github.js.map +0 -1
  56. package/dist/src/adapters/vcs-host/types.d.ts.map +0 -1
  57. package/dist/src/adapters/vcs-host/types.js.map +0 -1
  58. package/dist/src/cli/_pkg-root.d.ts.map +0 -1
  59. package/dist/src/cli/_pkg-root.js.map +0 -1
  60. package/dist/src/cli/autoregress-bridge.d.ts.map +0 -1
  61. package/dist/src/cli/autoregress-bridge.js.map +0 -1
  62. package/dist/src/cli/baseline.d.ts.map +0 -1
  63. package/dist/src/cli/baseline.js.map +0 -1
  64. package/dist/src/cli/ci.d.ts.map +0 -1
  65. package/dist/src/cli/ci.js.map +0 -1
  66. package/dist/src/cli/costs.d.ts.map +0 -1
  67. package/dist/src/cli/costs.js.map +0 -1
  68. package/dist/src/cli/council.d.ts.map +0 -1
  69. package/dist/src/cli/council.js.map +0 -1
  70. package/dist/src/cli/detector.d.ts.map +0 -1
  71. package/dist/src/cli/detector.js.map +0 -1
  72. package/dist/src/cli/explain.d.ts.map +0 -1
  73. package/dist/src/cli/explain.js.map +0 -1
  74. package/dist/src/cli/fix.d.ts.map +0 -1
  75. package/dist/src/cli/fix.js.map +0 -1
  76. package/dist/src/cli/hook.d.ts.map +0 -1
  77. package/dist/src/cli/hook.js.map +0 -1
  78. package/dist/src/cli/ignore-helper.d.ts.map +0 -1
  79. package/dist/src/cli/ignore-helper.js.map +0 -1
  80. package/dist/src/cli/index.d.ts.map +0 -1
  81. package/dist/src/cli/index.js.map +0 -1
  82. package/dist/src/cli/lsp.d.ts.map +0 -1
  83. package/dist/src/cli/lsp.js.map +0 -1
  84. package/dist/src/cli/mcp.d.ts.map +0 -1
  85. package/dist/src/cli/mcp.js.map +0 -1
  86. package/dist/src/cli/migrate-v4.d.ts.map +0 -1
  87. package/dist/src/cli/migrate-v4.js.map +0 -1
  88. package/dist/src/cli/pr-comment.d.ts.map +0 -1
  89. package/dist/src/cli/pr-comment.js.map +0 -1
  90. package/dist/src/cli/pr-desc.d.ts.map +0 -1
  91. package/dist/src/cli/pr-desc.js.map +0 -1
  92. package/dist/src/cli/pr-review-comments.d.ts.map +0 -1
  93. package/dist/src/cli/pr-review-comments.js.map +0 -1
  94. package/dist/src/cli/pr.d.ts.map +0 -1
  95. package/dist/src/cli/pr.js.map +0 -1
  96. package/dist/src/cli/preflight.d.ts.map +0 -1
  97. package/dist/src/cli/preflight.js.map +0 -1
  98. package/dist/src/cli/report.d.ts.map +0 -1
  99. package/dist/src/cli/report.js.map +0 -1
  100. package/dist/src/cli/run.d.ts.map +0 -1
  101. package/dist/src/cli/run.js.map +0 -1
  102. package/dist/src/cli/scan.d.ts.map +0 -1
  103. package/dist/src/cli/scan.js.map +0 -1
  104. package/dist/src/cli/setup.d.ts.map +0 -1
  105. package/dist/src/cli/setup.js.map +0 -1
  106. package/dist/src/cli/test-gen.d.ts.map +0 -1
  107. package/dist/src/cli/test-gen.js.map +0 -1
  108. package/dist/src/cli/triage.d.ts.map +0 -1
  109. package/dist/src/cli/triage.js.map +0 -1
  110. package/dist/src/cli/watch.d.ts.map +0 -1
  111. package/dist/src/cli/watch.js.map +0 -1
  112. package/dist/src/cli/worker.d.ts.map +0 -1
  113. package/dist/src/cli/worker.js.map +0 -1
  114. package/dist/src/core/cache/cached-engine.d.ts.map +0 -1
  115. package/dist/src/core/cache/cached-engine.js.map +0 -1
  116. package/dist/src/core/cache/review-cache.d.ts.map +0 -1
  117. package/dist/src/core/cache/review-cache.js.map +0 -1
  118. package/dist/src/core/chunking/index.d.ts.map +0 -1
  119. package/dist/src/core/chunking/index.js.map +0 -1
  120. package/dist/src/core/chunking/risk-ranker.d.ts.map +0 -1
  121. package/dist/src/core/chunking/risk-ranker.js.map +0 -1
  122. package/dist/src/core/config/loader.d.ts.map +0 -1
  123. package/dist/src/core/config/loader.js.map +0 -1
  124. package/dist/src/core/config/preset-resolver.d.ts.map +0 -1
  125. package/dist/src/core/config/preset-resolver.js.map +0 -1
  126. package/dist/src/core/config/schema.d.ts.map +0 -1
  127. package/dist/src/core/config/schema.js.map +0 -1
  128. package/dist/src/core/config/types.d.ts.map +0 -1
  129. package/dist/src/core/config/types.js.map +0 -1
  130. package/dist/src/core/council/config.d.ts.map +0 -1
  131. package/dist/src/core/council/config.js.map +0 -1
  132. package/dist/src/core/council/context.d.ts.map +0 -1
  133. package/dist/src/core/council/context.js.map +0 -1
  134. package/dist/src/core/council/runner.d.ts.map +0 -1
  135. package/dist/src/core/council/runner.js.map +0 -1
  136. package/dist/src/core/council/types.d.ts.map +0 -1
  137. package/dist/src/core/council/types.js.map +0 -1
  138. package/dist/src/core/detect/git-context.d.ts.map +0 -1
  139. package/dist/src/core/detect/git-context.js.map +0 -1
  140. package/dist/src/core/detect/llm-key.d.ts.map +0 -1
  141. package/dist/src/core/detect/llm-key.js.map +0 -1
  142. package/dist/src/core/detect/protected-paths.d.ts.map +0 -1
  143. package/dist/src/core/detect/protected-paths.js.map +0 -1
  144. package/dist/src/core/detect/provider-usage.d.ts.map +0 -1
  145. package/dist/src/core/detect/provider-usage.js.map +0 -1
  146. package/dist/src/core/detect/stack.d.ts.map +0 -1
  147. package/dist/src/core/detect/stack.js.map +0 -1
  148. package/dist/src/core/detect/workspaces.d.ts.map +0 -1
  149. package/dist/src/core/detect/workspaces.js.map +0 -1
  150. package/dist/src/core/errors.d.ts.map +0 -1
  151. package/dist/src/core/errors.js.map +0 -1
  152. package/dist/src/core/findings/dedup.d.ts.map +0 -1
  153. package/dist/src/core/findings/dedup.js.map +0 -1
  154. package/dist/src/core/findings/types.d.ts.map +0 -1
  155. package/dist/src/core/findings/types.js.map +0 -1
  156. package/dist/src/core/fix/generator.d.ts.map +0 -1
  157. package/dist/src/core/fix/generator.js.map +0 -1
  158. package/dist/src/core/git/diff-hunks.d.ts.map +0 -1
  159. package/dist/src/core/git/diff-hunks.js.map +0 -1
  160. package/dist/src/core/git/touched-files.d.ts.map +0 -1
  161. package/dist/src/core/git/touched-files.js.map +0 -1
  162. package/dist/src/core/ignore/index.d.ts.map +0 -1
  163. package/dist/src/core/ignore/index.js.map +0 -1
  164. package/dist/src/core/index.d.ts.map +0 -1
  165. package/dist/src/core/index.js.map +0 -1
  166. package/dist/src/core/logging/ndjson-writer.d.ts.map +0 -1
  167. package/dist/src/core/logging/ndjson-writer.js.map +0 -1
  168. package/dist/src/core/logging/redaction.d.ts.map +0 -1
  169. package/dist/src/core/logging/redaction.js.map +0 -1
  170. package/dist/src/core/mcp/concurrency.d.ts.map +0 -1
  171. package/dist/src/core/mcp/concurrency.js.map +0 -1
  172. package/dist/src/core/mcp/handlers/fix-finding.d.ts.map +0 -1
  173. package/dist/src/core/mcp/handlers/fix-finding.js.map +0 -1
  174. package/dist/src/core/mcp/handlers/get-capabilities.d.ts.map +0 -1
  175. package/dist/src/core/mcp/handlers/get-capabilities.js.map +0 -1
  176. package/dist/src/core/mcp/handlers/get-findings.d.ts.map +0 -1
  177. package/dist/src/core/mcp/handlers/get-findings.js.map +0 -1
  178. package/dist/src/core/mcp/handlers/review-diff.d.ts.map +0 -1
  179. package/dist/src/core/mcp/handlers/review-diff.js.map +0 -1
  180. package/dist/src/core/mcp/handlers/scan-files.d.ts.map +0 -1
  181. package/dist/src/core/mcp/handlers/scan-files.js.map +0 -1
  182. package/dist/src/core/mcp/handlers/validate-fix.d.ts.map +0 -1
  183. package/dist/src/core/mcp/handlers/validate-fix.js.map +0 -1
  184. package/dist/src/core/mcp/run-store.d.ts.map +0 -1
  185. package/dist/src/core/mcp/run-store.js.map +0 -1
  186. package/dist/src/core/mcp/workspace.d.ts.map +0 -1
  187. package/dist/src/core/mcp/workspace.js.map +0 -1
  188. package/dist/src/core/persist/baseline.d.ts.map +0 -1
  189. package/dist/src/core/persist/baseline.js.map +0 -1
  190. package/dist/src/core/persist/cost-log.d.ts.map +0 -1
  191. package/dist/src/core/persist/cost-log.js.map +0 -1
  192. package/dist/src/core/persist/findings-cache.d.ts.map +0 -1
  193. package/dist/src/core/persist/findings-cache.js.map +0 -1
  194. package/dist/src/core/persist/triage.d.ts.map +0 -1
  195. package/dist/src/core/persist/triage.js.map +0 -1
  196. package/dist/src/core/phases/static-rules.d.ts.map +0 -1
  197. package/dist/src/core/phases/static-rules.js.map +0 -1
  198. package/dist/src/core/phases/tests.d.ts.map +0 -1
  199. package/dist/src/core/phases/tests.js.map +0 -1
  200. package/dist/src/core/pipeline/review-phase.d.ts.map +0 -1
  201. package/dist/src/core/pipeline/review-phase.js.map +0 -1
  202. package/dist/src/core/pipeline/run.d.ts.map +0 -1
  203. package/dist/src/core/pipeline/run.js.map +0 -1
  204. package/dist/src/core/runtime/idempotency.d.ts.map +0 -1
  205. package/dist/src/core/runtime/idempotency.js.map +0 -1
  206. package/dist/src/core/runtime/lock.d.ts.map +0 -1
  207. package/dist/src/core/runtime/lock.js.map +0 -1
  208. package/dist/src/core/runtime/state.d.ts.map +0 -1
  209. package/dist/src/core/runtime/state.js.map +0 -1
  210. package/dist/src/core/schema-alignment/detector.d.ts.map +0 -1
  211. package/dist/src/core/schema-alignment/detector.js.map +0 -1
  212. package/dist/src/core/schema-alignment/extractor/index.d.ts.map +0 -1
  213. package/dist/src/core/schema-alignment/extractor/index.js.map +0 -1
  214. package/dist/src/core/schema-alignment/extractor/prisma.d.ts.map +0 -1
  215. package/dist/src/core/schema-alignment/extractor/prisma.js.map +0 -1
  216. package/dist/src/core/schema-alignment/extractor/sql.d.ts.map +0 -1
  217. package/dist/src/core/schema-alignment/extractor/sql.js.map +0 -1
  218. package/dist/src/core/schema-alignment/llm-check.d.ts.map +0 -1
  219. package/dist/src/core/schema-alignment/llm-check.js.map +0 -1
  220. package/dist/src/core/schema-alignment/scanner.d.ts.map +0 -1
  221. package/dist/src/core/schema-alignment/scanner.js.map +0 -1
  222. package/dist/src/core/schema-alignment/types.d.ts.map +0 -1
  223. package/dist/src/core/schema-alignment/types.js.map +0 -1
  224. package/dist/src/core/shell.d.ts.map +0 -1
  225. package/dist/src/core/shell.js.map +0 -1
  226. package/dist/src/core/static-rules/registry.d.ts.map +0 -1
  227. package/dist/src/core/static-rules/registry.js.map +0 -1
  228. package/dist/src/core/static-rules/rules/brand-tokens.d.ts.map +0 -1
  229. package/dist/src/core/static-rules/rules/brand-tokens.js.map +0 -1
  230. package/dist/src/core/static-rules/rules/console-log.d.ts.map +0 -1
  231. package/dist/src/core/static-rules/rules/console-log.js.map +0 -1
  232. package/dist/src/core/static-rules/rules/hardcoded-secrets.d.ts.map +0 -1
  233. package/dist/src/core/static-rules/rules/hardcoded-secrets.js.map +0 -1
  234. package/dist/src/core/static-rules/rules/insecure-redirect.d.ts.map +0 -1
  235. package/dist/src/core/static-rules/rules/insecure-redirect.js.map +0 -1
  236. package/dist/src/core/static-rules/rules/large-file.d.ts.map +0 -1
  237. package/dist/src/core/static-rules/rules/large-file.js.map +0 -1
  238. package/dist/src/core/static-rules/rules/missing-auth.d.ts.map +0 -1
  239. package/dist/src/core/static-rules/rules/missing-auth.js.map +0 -1
  240. package/dist/src/core/static-rules/rules/missing-tests.d.ts.map +0 -1
  241. package/dist/src/core/static-rules/rules/missing-tests.js.map +0 -1
  242. package/dist/src/core/static-rules/rules/npm-audit.d.ts.map +0 -1
  243. package/dist/src/core/static-rules/rules/npm-audit.js.map +0 -1
  244. package/dist/src/core/static-rules/rules/package-lock-sync.d.ts.map +0 -1
  245. package/dist/src/core/static-rules/rules/package-lock-sync.js.map +0 -1
  246. package/dist/src/core/static-rules/rules/schema-alignment.d.ts.map +0 -1
  247. package/dist/src/core/static-rules/rules/schema-alignment.js.map +0 -1
  248. package/dist/src/core/static-rules/rules/sql-injection.d.ts.map +0 -1
  249. package/dist/src/core/static-rules/rules/sql-injection.js.map +0 -1
  250. package/dist/src/core/static-rules/rules/ssrf.d.ts.map +0 -1
  251. package/dist/src/core/static-rules/rules/ssrf.js.map +0 -1
  252. package/dist/src/core/static-rules/rules/todo-fixme.d.ts.map +0 -1
  253. package/dist/src/core/static-rules/rules/todo-fixme.js.map +0 -1
  254. package/dist/src/core/static-rules/tailwind-extractor.d.ts.map +0 -1
  255. package/dist/src/core/static-rules/tailwind-extractor.js.map +0 -1
  256. package/dist/src/core/test-gen/coverage-analyzer.d.ts.map +0 -1
  257. package/dist/src/core/test-gen/coverage-analyzer.js.map +0 -1
  258. package/dist/src/core/test-gen/framework-detector.d.ts.map +0 -1
  259. package/dist/src/core/test-gen/framework-detector.js.map +0 -1
  260. package/dist/src/core/test-gen/test-writer.d.ts.map +0 -1
  261. package/dist/src/core/test-gen/test-writer.js.map +0 -1
  262. package/dist/src/core/ui/design-context-loader.d.ts.map +0 -1
  263. package/dist/src/core/ui/design-context-loader.js.map +0 -1
  264. package/dist/src/core/worker/client.d.ts.map +0 -1
  265. package/dist/src/core/worker/client.js.map +0 -1
  266. package/dist/src/core/worker/lockfile.d.ts.map +0 -1
  267. package/dist/src/core/worker/lockfile.js.map +0 -1
  268. package/dist/src/core/worker/server.d.ts.map +0 -1
  269. package/dist/src/core/worker/server.js.map +0 -1
  270. package/dist/src/formatters/github-annotations.d.ts.map +0 -1
  271. package/dist/src/formatters/github-annotations.js.map +0 -1
  272. package/dist/src/formatters/index.d.ts.map +0 -1
  273. package/dist/src/formatters/index.js.map +0 -1
  274. package/dist/src/formatters/junit.d.ts.map +0 -1
  275. package/dist/src/formatters/junit.js.map +0 -1
  276. package/dist/src/formatters/sarif.d.ts.map +0 -1
  277. package/dist/src/formatters/sarif.js.map +0 -1
  278. package/dist/src/index.d.ts.map +0 -1
  279. package/dist/src/index.js.map +0 -1
  280. package/src/adapters/base.ts +0 -19
  281. package/src/adapters/council/claude.ts +0 -41
  282. package/src/adapters/council/openai.ts +0 -40
  283. package/src/adapters/council/types.ts +0 -7
  284. package/src/adapters/loader.ts +0 -108
  285. package/src/adapters/migration-runner/supabase.ts +0 -56
  286. package/src/adapters/migration-runner/types.ts +0 -36
  287. package/src/adapters/review-bot-parser/cursor.ts +0 -13
  288. package/src/adapters/review-bot-parser/declarative-base.ts +0 -64
  289. package/src/adapters/review-bot-parser/types.ts +0 -9
  290. package/src/adapters/review-engine/auto.ts +0 -94
  291. package/src/adapters/review-engine/claude.ts +0 -100
  292. package/src/adapters/review-engine/codex.ts +0 -82
  293. package/src/adapters/review-engine/gemini.ts +0 -105
  294. package/src/adapters/review-engine/openai-compatible.ts +0 -100
  295. package/src/adapters/review-engine/parse-output.ts +0 -74
  296. package/src/adapters/review-engine/prompt-builder.ts +0 -19
  297. package/src/adapters/review-engine/types.ts +0 -19
  298. package/src/adapters/vcs-host/commit-status.ts +0 -39
  299. package/src/adapters/vcs-host/github.ts +0 -77
  300. package/src/adapters/vcs-host/types.ts +0 -44
  301. package/src/cli/_pkg-root.ts +0 -85
  302. package/src/cli/autoregress-bridge.ts +0 -30
  303. package/src/cli/baseline.ts +0 -125
  304. package/src/cli/ci.ts +0 -45
  305. package/src/cli/costs.ts +0 -80
  306. package/src/cli/council.ts +0 -96
  307. package/src/cli/detector.ts +0 -92
  308. package/src/cli/explain.ts +0 -197
  309. package/src/cli/fix.ts +0 -249
  310. package/src/cli/hook.ts +0 -124
  311. package/src/cli/ignore-helper.ts +0 -116
  312. package/src/cli/index.ts +0 -612
  313. package/src/cli/lsp.ts +0 -200
  314. package/src/cli/mcp.ts +0 -206
  315. package/src/cli/migrate-v4.ts +0 -388
  316. package/src/cli/pr-comment.ts +0 -139
  317. package/src/cli/pr-desc.ts +0 -168
  318. package/src/cli/pr-review-comments.ts +0 -92
  319. package/src/cli/pr.ts +0 -76
  320. package/src/cli/preflight.ts +0 -235
  321. package/src/cli/report.ts +0 -186
  322. package/src/cli/run.ts +0 -425
  323. package/src/cli/scan.ts +0 -233
  324. package/src/cli/setup.ts +0 -191
  325. package/src/cli/test-gen.ts +0 -125
  326. package/src/cli/triage.ts +0 -137
  327. package/src/cli/watch.ts +0 -190
  328. package/src/cli/worker.ts +0 -109
  329. package/src/core/.gitkeep +0 -0
  330. package/src/core/cache/cached-engine.ts +0 -32
  331. package/src/core/cache/review-cache.ts +0 -70
  332. package/src/core/chunking/index.ts +0 -113
  333. package/src/core/chunking/risk-ranker.ts +0 -56
  334. package/src/core/config/loader.ts +0 -53
  335. package/src/core/config/preset-resolver.ts +0 -46
  336. package/src/core/config/schema.ts +0 -181
  337. package/src/core/config/types.ts +0 -98
  338. package/src/core/council/config.ts +0 -71
  339. package/src/core/council/context.ts +0 -17
  340. package/src/core/council/runner.ts +0 -83
  341. package/src/core/council/types.ts +0 -45
  342. package/src/core/detect/git-context.ts +0 -27
  343. package/src/core/detect/llm-key.ts +0 -89
  344. package/src/core/detect/protected-paths.ts +0 -63
  345. package/src/core/detect/provider-usage.ts +0 -74
  346. package/src/core/detect/stack.ts +0 -153
  347. package/src/core/detect/workspaces.ts +0 -103
  348. package/src/core/errors.ts +0 -37
  349. package/src/core/findings/dedup.ts +0 -14
  350. package/src/core/findings/types.ts +0 -39
  351. package/src/core/fix/generator.ts +0 -149
  352. package/src/core/git/diff-hunks.ts +0 -86
  353. package/src/core/git/touched-files.ts +0 -73
  354. package/src/core/ignore/index.ts +0 -54
  355. package/src/core/index.ts +0 -1
  356. package/src/core/logging/ndjson-writer.ts +0 -37
  357. package/src/core/logging/redaction.ts +0 -19
  358. package/src/core/mcp/concurrency.ts +0 -16
  359. package/src/core/mcp/handlers/fix-finding.ts +0 -126
  360. package/src/core/mcp/handlers/get-capabilities.ts +0 -62
  361. package/src/core/mcp/handlers/get-findings.ts +0 -36
  362. package/src/core/mcp/handlers/review-diff.ts +0 -65
  363. package/src/core/mcp/handlers/scan-files.ts +0 -65
  364. package/src/core/mcp/handlers/validate-fix.ts +0 -41
  365. package/src/core/mcp/run-store.ts +0 -85
  366. package/src/core/mcp/workspace.ts +0 -35
  367. package/src/core/persist/baseline.ts +0 -112
  368. package/src/core/persist/cost-log.ts +0 -30
  369. package/src/core/persist/findings-cache.ts +0 -43
  370. package/src/core/persist/triage.ts +0 -112
  371. package/src/core/phases/static-rules.ts +0 -93
  372. package/src/core/phases/tests.ts +0 -51
  373. package/src/core/pipeline/review-phase.ts +0 -182
  374. package/src/core/pipeline/run.ts +0 -116
  375. package/src/core/runtime/idempotency.ts +0 -6
  376. package/src/core/runtime/lock.ts +0 -29
  377. package/src/core/runtime/state.ts +0 -97
  378. package/src/core/schema-alignment/detector.ts +0 -59
  379. package/src/core/schema-alignment/extractor/index.ts +0 -24
  380. package/src/core/schema-alignment/extractor/prisma.ts +0 -21
  381. package/src/core/schema-alignment/extractor/sql.ts +0 -99
  382. package/src/core/schema-alignment/llm-check.ts +0 -91
  383. package/src/core/schema-alignment/scanner.ts +0 -107
  384. package/src/core/schema-alignment/types.ts +0 -43
  385. package/src/core/shell.ts +0 -48
  386. package/src/core/static-rules/registry.ts +0 -59
  387. package/src/core/static-rules/rules/brand-tokens.ts +0 -145
  388. package/src/core/static-rules/rules/console-log.ts +0 -42
  389. package/src/core/static-rules/rules/hardcoded-secrets.ts +0 -83
  390. package/src/core/static-rules/rules/insecure-redirect.ts +0 -67
  391. package/src/core/static-rules/rules/large-file.ts +0 -37
  392. package/src/core/static-rules/rules/missing-auth.ts +0 -70
  393. package/src/core/static-rules/rules/missing-tests.ts +0 -57
  394. package/src/core/static-rules/rules/npm-audit.ts +0 -38
  395. package/src/core/static-rules/rules/package-lock-sync.ts +0 -54
  396. package/src/core/static-rules/rules/schema-alignment.ts +0 -132
  397. package/src/core/static-rules/rules/sql-injection.ts +0 -71
  398. package/src/core/static-rules/rules/ssrf.ts +0 -63
  399. package/src/core/static-rules/rules/todo-fixme.ts +0 -40
  400. package/src/core/static-rules/tailwind-extractor.ts +0 -38
  401. package/src/core/test-gen/coverage-analyzer.ts +0 -93
  402. package/src/core/test-gen/framework-detector.ts +0 -21
  403. package/src/core/test-gen/test-writer.ts +0 -33
  404. package/src/core/ui/design-context-loader.ts +0 -87
  405. package/src/core/worker/client.ts +0 -46
  406. package/src/core/worker/lockfile.ts +0 -38
  407. package/src/core/worker/server.ts +0 -81
  408. package/src/formatters/github-annotations.ts +0 -36
  409. package/src/formatters/index.ts +0 -3
  410. package/src/formatters/junit.ts +0 -52
  411. package/src/formatters/sarif.ts +0 -103
  412. package/src/index.ts +0 -3
@@ -1,112 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { Finding } from '../findings/types.ts';
4
-
5
- const BASELINE_FILE = '.guardrail-baseline.json';
6
-
7
- export interface BaselineEntry {
8
- id: string;
9
- file: string;
10
- line?: number;
11
- severity: string;
12
- message: string;
13
- pinnedAt: string;
14
- note?: string;
15
- }
16
-
17
- export interface Baseline {
18
- version: 1;
19
- createdAt: string;
20
- updatedAt: string;
21
- note?: string;
22
- entries: BaselineEntry[];
23
- }
24
-
25
- /** Stable key for matching a finding against a baseline entry. */
26
- function baselineKey(f: { id: string; file: string; line?: number }): string {
27
- return `${f.id}::${f.file}::${f.line ?? ''}`;
28
- }
29
-
30
- export function baselineFilePath(cwd: string, overridePath?: string): string {
31
- return overridePath
32
- ? path.isAbsolute(overridePath) ? overridePath : path.join(cwd, overridePath)
33
- : path.join(cwd, BASELINE_FILE);
34
- }
35
-
36
- export function loadBaseline(cwd: string, overridePath?: string): Baseline | null {
37
- const p = baselineFilePath(cwd, overridePath);
38
- if (!fs.existsSync(p)) return null;
39
- try {
40
- return JSON.parse(fs.readFileSync(p, 'utf8')) as Baseline;
41
- } catch {
42
- return null;
43
- }
44
- }
45
-
46
- export function saveBaseline(cwd: string, findings: Finding[], options: { note?: string; overridePath?: string } = {}): Baseline {
47
- const existing = loadBaseline(cwd, options.overridePath);
48
- const now = new Date().toISOString();
49
- const baseline: Baseline = {
50
- version: 1,
51
- createdAt: existing?.createdAt ?? now,
52
- updatedAt: now,
53
- note: options.note ?? existing?.note,
54
- entries: findings.map(f => ({
55
- id: f.id,
56
- file: f.file,
57
- line: f.line,
58
- severity: f.severity,
59
- message: f.message,
60
- pinnedAt: now,
61
- })),
62
- };
63
- const p = baselineFilePath(cwd, options.overridePath);
64
- const tmp = p + '.tmp';
65
- fs.writeFileSync(tmp, JSON.stringify(baseline, null, 2), 'utf8');
66
- fs.renameSync(tmp, p);
67
- return baseline;
68
- }
69
-
70
- export function clearBaseline(cwd: string, overridePath?: string): void {
71
- const p = baselineFilePath(cwd, overridePath);
72
- if (fs.existsSync(p)) fs.unlinkSync(p);
73
- }
74
-
75
- export interface BaselineFilterResult {
76
- newFindings: Finding[];
77
- baselinedFindings: Finding[];
78
- baselinedCount: number;
79
- }
80
-
81
- /** Returns findings NOT present in the baseline (new findings only). */
82
- export function filterBaselined(findings: Finding[], baseline: Baseline): BaselineFilterResult {
83
- const pinned = new Set(baseline.entries.map(baselineKey));
84
- const newFindings: Finding[] = [];
85
- const baselinedFindings: Finding[] = [];
86
- for (const f of findings) {
87
- if (pinned.has(baselineKey(f))) {
88
- baselinedFindings.push(f);
89
- } else {
90
- newFindings.push(f);
91
- }
92
- }
93
- return { newFindings, baselinedFindings, baselinedCount: baselinedFindings.length };
94
- }
95
-
96
- export interface BaselineDiff {
97
- added: Finding[]; // in current but not in baseline
98
- resolved: BaselineEntry[]; // in baseline but not in current
99
- unchanged: Finding[]; // in both
100
- }
101
-
102
- /** Diff current findings against a baseline snapshot. */
103
- export function diffAgainstBaseline(current: Finding[], baseline: Baseline): BaselineDiff {
104
- const currentKeys = new Set(current.map(baselineKey));
105
- const baselineKeys = new Set(baseline.entries.map(baselineKey));
106
-
107
- return {
108
- added: current.filter(f => !baselineKeys.has(baselineKey(f))),
109
- resolved: baseline.entries.filter(e => !currentKeys.has(baselineKey(e))),
110
- unchanged: current.filter(f => baselineKeys.has(baselineKey(f))),
111
- };
112
- }
@@ -1,30 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
-
4
- const CACHE_DIR = '.guardrail-cache';
5
- const LOG_FILE = 'costs.jsonl';
6
-
7
- export interface CostLogEntry {
8
- timestamp: string;
9
- files: number;
10
- inputTokens: number;
11
- outputTokens: number;
12
- costUSD: number;
13
- durationMs: number;
14
- }
15
-
16
- export function appendCostLog(cwd: string, entry: CostLogEntry): void {
17
- const dir = path.join(cwd, CACHE_DIR);
18
- fs.mkdirSync(dir, { recursive: true });
19
- fs.appendFileSync(path.join(dir, LOG_FILE), JSON.stringify(entry) + '\n', 'utf8');
20
- }
21
-
22
- export function readCostLog(cwd: string): CostLogEntry[] {
23
- const p = path.join(cwd, CACHE_DIR, LOG_FILE);
24
- if (!fs.existsSync(p)) return [];
25
- return fs.readFileSync(p, 'utf8')
26
- .split('\n')
27
- .filter(Boolean)
28
- .map(line => { try { return JSON.parse(line) as CostLogEntry; } catch { return null; } })
29
- .filter((e): e is CostLogEntry => e !== null);
30
- }
@@ -1,43 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { Finding } from '../findings/types.ts';
4
-
5
- const CACHE_DIR = '.guardrail-cache';
6
- const CACHE_FILE = 'findings.json';
7
-
8
- function cacheFilePath(cwd: string): string {
9
- return path.join(cwd, CACHE_DIR, CACHE_FILE);
10
- }
11
-
12
- function findingKey(f: Finding): string {
13
- return `${f.id}::${f.file}::${f.line ?? ''}`;
14
- }
15
-
16
- export function loadCachedFindings(cwd: string): Finding[] {
17
- const p = cacheFilePath(cwd);
18
- if (!fs.existsSync(p)) return [];
19
- try {
20
- return JSON.parse(fs.readFileSync(p, 'utf8')) as Finding[];
21
- } catch {
22
- return [];
23
- }
24
- }
25
-
26
- export function saveCachedFindings(cwd: string, findings: Finding[]): void {
27
- const dir = path.join(cwd, CACHE_DIR);
28
- fs.mkdirSync(dir, { recursive: true });
29
- // atomic write
30
- const tmp = cacheFilePath(cwd) + '.tmp';
31
- fs.writeFileSync(tmp, JSON.stringify(findings, null, 2), 'utf8');
32
- fs.renameSync(tmp, cacheFilePath(cwd));
33
- }
34
-
35
- /**
36
- * Returns only findings not present in the cached baseline.
37
- * Two findings are considered the same when id + file + line all match.
38
- */
39
- export function filterNewFindings(current: Finding[], cached: Finding[]): Finding[] {
40
- if (cached.length === 0) return current;
41
- const seen = new Set(cached.map(findingKey));
42
- return current.filter(f => !seen.has(findingKey(f)));
43
- }
@@ -1,112 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
- import type { Finding } from '../findings/types.ts';
4
-
5
- const TRIAGE_FILE = '.guardrail-triage.json';
6
-
7
- export type TriageState = 'accepted-risk' | 'false-positive';
8
-
9
- export interface TriageEntry {
10
- id: string;
11
- file: string;
12
- line?: number;
13
- state: TriageState;
14
- reason?: string;
15
- triagedAt: string;
16
- expiresAt?: string;
17
- }
18
-
19
- export interface TriageStore {
20
- version: 1;
21
- entries: TriageEntry[];
22
- }
23
-
24
- function triageFilePath(cwd: string): string {
25
- return path.join(cwd, TRIAGE_FILE);
26
- }
27
-
28
- function entryKey(e: { id: string; file: string; line?: number }): string {
29
- return `${e.id}::${e.file}::${e.line ?? ''}`;
30
- }
31
-
32
- export function loadTriage(cwd: string): TriageStore {
33
- const p = triageFilePath(cwd);
34
- if (!fs.existsSync(p)) return { version: 1, entries: [] };
35
- try {
36
- return JSON.parse(fs.readFileSync(p, 'utf8')) as TriageStore;
37
- } catch {
38
- return { version: 1, entries: [] };
39
- }
40
- }
41
-
42
- export function saveTriage(cwd: string, store: TriageStore): void {
43
- const p = triageFilePath(cwd);
44
- const tmp = p + '.tmp';
45
- fs.writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf8');
46
- fs.renameSync(tmp, p);
47
- }
48
-
49
- export function addTriageEntry(
50
- cwd: string,
51
- finding: Finding,
52
- state: TriageState,
53
- options: { reason?: string; expiresInDays?: number } = {},
54
- ): void {
55
- const store = loadTriage(cwd);
56
- const key = entryKey(finding);
57
- store.entries = store.entries.filter(e => entryKey(e) !== key);
58
- const entry: TriageEntry = {
59
- id: finding.id,
60
- file: finding.file,
61
- line: finding.line,
62
- state,
63
- reason: options.reason,
64
- triagedAt: new Date().toISOString(),
65
- };
66
- if (options.expiresInDays !== undefined) {
67
- const exp = new Date();
68
- exp.setDate(exp.getDate() + options.expiresInDays);
69
- entry.expiresAt = exp.toISOString();
70
- }
71
- store.entries.push(entry);
72
- saveTriage(cwd, store);
73
- }
74
-
75
- export function removeTriageEntry(cwd: string, ids: string[]): number {
76
- const store = loadTriage(cwd);
77
- const before = store.entries.length;
78
- store.entries = store.entries.filter(e => !ids.some(id => e.id === id || e.id.startsWith(id)));
79
- saveTriage(cwd, store);
80
- return before - store.entries.length;
81
- }
82
-
83
- export function clearExpiredEntries(cwd: string): number {
84
- const store = loadTriage(cwd);
85
- const now = new Date().toISOString();
86
- const before = store.entries.length;
87
- store.entries = store.entries.filter(e => !e.expiresAt || e.expiresAt > now);
88
- saveTriage(cwd, store);
89
- return before - store.entries.length;
90
- }
91
-
92
- export interface TriageFilterResult {
93
- active: Finding[];
94
- triaged: Finding[];
95
- triageCount: number;
96
- }
97
-
98
- export function filterTriaged(findings: Finding[], store: TriageStore): TriageFilterResult {
99
- const now = new Date().toISOString();
100
- const activeKeys = new Set(
101
- store.entries
102
- .filter(e => !e.expiresAt || e.expiresAt > now)
103
- .map(entryKey),
104
- );
105
- const active: Finding[] = [];
106
- const triaged: Finding[] = [];
107
- for (const f of findings) {
108
- if (activeKeys.has(entryKey(f))) triaged.push(f);
109
- else active.push(f);
110
- }
111
- return { active, triaged, triageCount: triaged.length };
112
- }
@@ -1,93 +0,0 @@
1
- import type { Finding, FixAttempt, FixStatus } from '../findings/types.ts';
2
- import type { GuardrailConfig } from '../config/types.ts';
3
- import type { ReviewEngine } from '../../adapters/review-engine/types.ts';
4
- import { dedupFindings, findingContentKey } from '../findings/dedup.ts';
5
-
6
- export interface StaticRule {
7
- name: string;
8
- severity: 'critical' | 'warning' | 'note';
9
- check(touchedFiles: string[], config?: Record<string, unknown>): Promise<Finding[]>;
10
- autofix?(finding: Finding): Promise<FixStatus>;
11
- }
12
-
13
- export interface StaticRulesPhaseInput {
14
- touchedFiles: string[];
15
- rules: StaticRule[];
16
- config?: GuardrailConfig;
17
- engine?: ReviewEngine;
18
- }
19
-
20
- export interface StaticRulesPhaseResult {
21
- phase: 'static-rules';
22
- status: 'pass' | 'warn' | 'fail';
23
- findings: Finding[];
24
- fixAttempts: FixAttempt[];
25
- durationMs: number;
26
- }
27
-
28
- export async function runStaticRulesPhase(input: StaticRulesPhaseInput): Promise<StaticRulesPhaseResult> {
29
- const start = Date.now();
30
-
31
- const preFixFindings = dedupFindings(await runAllChecks(input.rules, input.touchedFiles, input.config, input.engine));
32
-
33
- const fixAttempts: FixAttempt[] = [];
34
- let anyFixApplied = false;
35
-
36
- for (const finding of preFixFindings) {
37
- const rule = findRuleForFinding(input.rules, finding);
38
- if (!rule?.autofix) continue;
39
-
40
- if (finding.protectedPath) {
41
- fixAttempts.push({
42
- findingId: finding.id,
43
- attemptedAt: new Date().toISOString(),
44
- status: 'skipped',
45
- notes: 'protected path',
46
- });
47
- continue;
48
- }
49
-
50
- const status = await rule.autofix(finding);
51
- if (status === 'fixed') anyFixApplied = true;
52
- fixAttempts.push({ findingId: finding.id, attemptedAt: new Date().toISOString(), status });
53
- }
54
-
55
- // Re-check is the source of truth for what persists after autofix.
56
- // findings always returns preFixFindings so callers have a complete record;
57
- // fixAttempts + re-check set-difference tells them what was resolved.
58
- const postFixFindings = anyFixApplied
59
- ? dedupFindings(await runAllChecks(input.rules, input.touchedFiles, input.config, input.engine))
60
- : preFixFindings;
61
-
62
- const postFixKeys = new Set(postFixFindings.map(findingContentKey));
63
- const isFixed = (f: Finding): boolean => !postFixKeys.has(findingContentKey(f));
64
-
65
- const unfixedCritical = preFixFindings.some(f => f.severity === 'critical' && !isFixed(f));
66
- const unfixedWarning = preFixFindings.some(f => f.severity === 'warning' && !isFixed(f));
67
-
68
- let status: StaticRulesPhaseResult['status'];
69
- if (unfixedCritical) status = 'fail';
70
- else if (unfixedWarning) status = 'warn';
71
- else status = 'pass';
72
-
73
- return { phase: 'static-rules', status, findings: preFixFindings, fixAttempts, durationMs: Date.now() - start };
74
- }
75
-
76
- async function runAllChecks(
77
- rules: StaticRule[],
78
- files: string[],
79
- config?: GuardrailConfig,
80
- engine?: ReviewEngine,
81
- ): Promise<Finding[]> {
82
- const ruleConfig: Record<string, unknown> = {
83
- ...(config ? (config as unknown as Record<string, unknown>) : {}),
84
- _engine: engine,
85
- };
86
- const all: Finding[] = [];
87
- for (const rule of rules) all.push(...(await rule.check(files, ruleConfig)));
88
- return all;
89
- }
90
-
91
- function findRuleForFinding(rules: StaticRule[], finding: Finding): StaticRule | undefined {
92
- return rules.find(r => r.name === finding.category) ?? rules.find(r => finding.category.includes(r.name));
93
- }
@@ -1,51 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import type { Finding } from '../findings/types.ts';
3
-
4
- export interface TestsPhaseInput {
5
- touchedFiles: string[];
6
- testCommand?: string | null;
7
- cwd?: string;
8
- }
9
-
10
- export interface TestsPhaseResult {
11
- phase: 'tests';
12
- status: 'pass' | 'fail' | 'skip';
13
- findings: Finding[];
14
- output?: string;
15
- durationMs: number;
16
- }
17
-
18
- export async function runTestsPhase(input: TestsPhaseInput): Promise<TestsPhaseResult> {
19
- const start = Date.now();
20
-
21
- if (!input.testCommand) {
22
- return { phase: 'tests', status: 'skip', findings: [], durationMs: Date.now() - start };
23
- }
24
-
25
- let output: string | undefined;
26
- try {
27
- // shell:true is intentional — testCommand is developer-supplied config, supports quoted args + pipes.
28
- output = execSync(input.testCommand, {
29
- encoding: 'utf8',
30
- cwd: input.cwd,
31
- timeout: 120000,
32
- shell: process.env.SHELL ?? "/bin/sh",
33
- stdio: ['ignore', 'pipe', 'pipe'],
34
- });
35
- } catch {
36
- const finding: Finding = {
37
- id: 'tests-phase-fail',
38
- source: 'static-rules',
39
- severity: 'critical',
40
- category: 'test-failure',
41
- file: '<tests>',
42
- message: `Test command failed: ${input.testCommand}`,
43
- suggestion: 'Fix failing tests before merging',
44
- protectedPath: false,
45
- createdAt: new Date().toISOString(),
46
- };
47
- return { phase: 'tests', status: 'fail', findings: [finding], output: undefined, durationMs: Date.now() - start };
48
- }
49
-
50
- return { phase: 'tests', status: 'pass', findings: [], output, durationMs: Date.now() - start };
51
- }
@@ -1,182 +0,0 @@
1
- import type { ReviewEngine } from '../../adapters/review-engine/types.ts';
2
- import type { Finding } from '../findings/types.ts';
3
- import type { GuardrailConfig } from '../config/types.ts';
4
- import { buildReviewChunks, type ReviewChunk } from '../chunking/index.ts';
5
- import { GuardrailError } from '../errors.ts';
6
- import { hasFrontendFiles, loadDesignContext } from '../ui/design-context-loader.ts';
7
-
8
- export interface ReviewPhaseResult {
9
- phase: 'review';
10
- status: 'pass' | 'warn' | 'fail' | 'skip';
11
- findings: Finding[];
12
- rawOutputs?: string[];
13
- costUSD?: number;
14
- usage?: { input: number; output: number };
15
- durationMs: number;
16
- }
17
-
18
- export interface ReviewPhaseInput {
19
- touchedFiles: string[];
20
- engine: ReviewEngine;
21
- config: GuardrailConfig;
22
- cwd?: string;
23
- gitSummary?: string;
24
- designSchema?: string;
25
- budgetRemainingUSD?: number;
26
- base?: string;
27
- }
28
-
29
- interface ChunkResult {
30
- findings: Finding[];
31
- rawOutput: string;
32
- inputTokens: number;
33
- outputTokens: number;
34
- costUSD: number;
35
- }
36
-
37
- function backoffMs(attempt: number, strategy: 'exp' | 'linear' | 'none'): number {
38
- if (strategy === 'none') return 0;
39
- if (strategy === 'linear') return attempt * 2000;
40
- return Math.min(Math.pow(2, attempt) * 1000, 32000); // exp: 1s, 2s, 4s, 8s … 32s cap
41
- }
42
-
43
- async function reviewChunkWithRetry(chunk: ReviewChunk, input: ReviewPhaseInput): Promise<ChunkResult> {
44
- const strategy = input.config.chunking?.rateLimitBackoff ?? 'exp';
45
- const maxAttempts = strategy === 'none' ? 1 : 4;
46
-
47
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
48
- try {
49
- const output = await input.engine.review({
50
- content: chunk.content,
51
- kind: chunk.kind,
52
- context: { stack: input.config.stack, cwd: input.cwd, gitSummary: input.gitSummary, designSchema: input.designSchema },
53
- });
54
- return {
55
- findings: output.findings,
56
- rawOutput: output.rawOutput,
57
- inputTokens: output.usage?.input ?? 0,
58
- outputTokens: output.usage?.output ?? 0,
59
- costUSD: output.usage?.costUSD ?? 0,
60
- };
61
- } catch (err) {
62
- const isRateLimit = err instanceof GuardrailError && err.code === 'rate_limit';
63
- const isLast = attempt === maxAttempts - 1;
64
- if (!isRateLimit || isLast) throw err;
65
- const delay = backoffMs(attempt + 1, strategy);
66
- await new Promise(r => setTimeout(r, delay));
67
- }
68
- }
69
- throw new Error('unreachable');
70
- }
71
-
72
- /** Run up to `limit` promises concurrently, preserving result order. */
73
- async function pMap<T, R>(
74
- items: T[],
75
- fn: (item: T, index: number) => Promise<R>,
76
- limit: number,
77
- ): Promise<R[]> {
78
- const results: R[] = new Array(items.length);
79
- let next = 0;
80
-
81
- async function worker(): Promise<void> {
82
- while (next < items.length) {
83
- const i = next++;
84
- results[i] = await fn(items[i]!, i);
85
- }
86
- }
87
-
88
- const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());
89
- await Promise.all(workers);
90
- return results;
91
- }
92
-
93
- export async function runReviewPhase(input: ReviewPhaseInput): Promise<ReviewPhaseResult> {
94
- const start = Date.now();
95
-
96
- if (input.touchedFiles.length === 0) {
97
- return { phase: 'review', status: 'skip', findings: [], durationMs: Date.now() - start };
98
- }
99
-
100
- let designSchema: string | undefined;
101
- if (hasFrontendFiles(input.touchedFiles) && input.config.brand?.componentLibrary) {
102
- const loaded = loadDesignContext(
103
- input.config.brand.componentLibrary,
104
- input.cwd ?? process.cwd(),
105
- );
106
- if (loaded) designSchema = loaded;
107
- }
108
- const enrichedInput: ReviewPhaseInput = designSchema ? { ...input, designSchema } : input;
109
-
110
- const chunks = await buildReviewChunks({
111
- touchedFiles: enrichedInput.touchedFiles,
112
- strategy: enrichedInput.config.reviewStrategy ?? 'auto',
113
- chunking: enrichedInput.config.chunking,
114
- engine: enrichedInput.engine,
115
- cwd: enrichedInput.cwd,
116
- protectedPaths: enrichedInput.config.protectedPaths,
117
- base: enrichedInput.base,
118
- });
119
-
120
- const parallelism = enrichedInput.config.chunking?.parallelism ?? 3;
121
- const budgetUSD = enrichedInput.budgetRemainingUSD;
122
-
123
- // For budget tracking we still need to enforce it — run serially if budget set,
124
- // parallel otherwise (budget check between serial chunks is the safe path).
125
- let chunkResults: ChunkResult[];
126
- if (budgetUSD !== undefined) {
127
- chunkResults = [];
128
- let spent = 0;
129
- let budgetExceeded = false;
130
- for (const chunk of chunks) {
131
- if (spent >= budgetUSD) { budgetExceeded = true; break; }
132
- const r = await reviewChunkWithRetry(chunk, enrichedInput);
133
- spent += r.costUSD;
134
- chunkResults.push(r);
135
- }
136
- if (budgetExceeded) {
137
- chunkResults.push({
138
- findings: [{
139
- id: 'budget-exceeded',
140
- source: 'pipeline',
141
- severity: 'warning',
142
- category: 'budget',
143
- file: '<pipeline>',
144
- message: `Review budget of $${budgetUSD} USD exceeded — remaining chunks skipped`,
145
- protectedPath: false,
146
- createdAt: new Date().toISOString(),
147
- }],
148
- rawOutput: '', inputTokens: 0, outputTokens: 0, costUSD: 0,
149
- });
150
- }
151
- } else {
152
- chunkResults = await pMap(chunks, chunk => reviewChunkWithRetry(chunk, enrichedInput), parallelism);
153
- }
154
-
155
- let totalInputTokens = 0;
156
- let totalOutputTokens = 0;
157
- let totalCostUSD = 0;
158
- const allFindings: Finding[] = [];
159
- const allRawOutputs: string[] = [];
160
-
161
- for (const r of chunkResults) {
162
- allFindings.push(...r.findings);
163
- if (r.rawOutput) allRawOutputs.push(r.rawOutput);
164
- totalInputTokens += r.inputTokens;
165
- totalOutputTokens += r.outputTokens;
166
- totalCostUSD += r.costUSD;
167
- }
168
-
169
- const hasCritical = allFindings.some(f => f.severity === 'critical');
170
- const hasWarning = allFindings.some(f => f.severity === 'warning');
171
- const status = hasCritical ? 'fail' : hasWarning ? 'warn' : 'pass';
172
-
173
- return {
174
- phase: 'review',
175
- status,
176
- findings: allFindings,
177
- rawOutputs: allRawOutputs.length > 0 ? allRawOutputs : undefined,
178
- costUSD: totalCostUSD > 0 ? totalCostUSD : undefined,
179
- usage: totalInputTokens > 0 ? { input: totalInputTokens, output: totalOutputTokens } : undefined,
180
- durationMs: Date.now() - start,
181
- };
182
- }