@delegance/claude-autopilot 5.0.1 → 5.0.2

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 (410) hide show
  1. package/dist/src/cli/index.js +39 -1
  2. package/dist/src/cli/preflight.js +17 -4
  3. package/package.json +4 -3
  4. package/dist/presets/go/rules/go-sql-injection.d.ts.map +0 -1
  5. package/dist/presets/go/rules/go-sql-injection.js.map +0 -1
  6. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.d.ts.map +0 -1
  7. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js.map +0 -1
  8. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.d.ts.map +0 -1
  9. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js.map +0 -1
  10. package/dist/presets/rails-postgres/rules/rails-sql-injection.d.ts.map +0 -1
  11. package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +0 -1
  12. package/dist/presets/t3/rules/t3-server-only.d.ts.map +0 -1
  13. package/dist/presets/t3/rules/t3-server-only.js.map +0 -1
  14. package/dist/src/adapters/base.d.ts.map +0 -1
  15. package/dist/src/adapters/base.js.map +0 -1
  16. package/dist/src/adapters/council/claude.d.ts.map +0 -1
  17. package/dist/src/adapters/council/claude.js.map +0 -1
  18. package/dist/src/adapters/council/openai.d.ts.map +0 -1
  19. package/dist/src/adapters/council/openai.js.map +0 -1
  20. package/dist/src/adapters/council/types.d.ts.map +0 -1
  21. package/dist/src/adapters/council/types.js.map +0 -1
  22. package/dist/src/adapters/loader.d.ts.map +0 -1
  23. package/dist/src/adapters/loader.js.map +0 -1
  24. package/dist/src/adapters/migration-runner/supabase.d.ts.map +0 -1
  25. package/dist/src/adapters/migration-runner/supabase.js.map +0 -1
  26. package/dist/src/adapters/migration-runner/types.d.ts.map +0 -1
  27. package/dist/src/adapters/migration-runner/types.js.map +0 -1
  28. package/dist/src/adapters/review-bot-parser/cursor.d.ts.map +0 -1
  29. package/dist/src/adapters/review-bot-parser/cursor.js.map +0 -1
  30. package/dist/src/adapters/review-bot-parser/declarative-base.d.ts.map +0 -1
  31. package/dist/src/adapters/review-bot-parser/declarative-base.js.map +0 -1
  32. package/dist/src/adapters/review-bot-parser/types.d.ts.map +0 -1
  33. package/dist/src/adapters/review-bot-parser/types.js.map +0 -1
  34. package/dist/src/adapters/review-engine/auto.d.ts.map +0 -1
  35. package/dist/src/adapters/review-engine/auto.js.map +0 -1
  36. package/dist/src/adapters/review-engine/claude.d.ts.map +0 -1
  37. package/dist/src/adapters/review-engine/claude.js.map +0 -1
  38. package/dist/src/adapters/review-engine/codex.d.ts.map +0 -1
  39. package/dist/src/adapters/review-engine/codex.js.map +0 -1
  40. package/dist/src/adapters/review-engine/gemini.d.ts.map +0 -1
  41. package/dist/src/adapters/review-engine/gemini.js.map +0 -1
  42. package/dist/src/adapters/review-engine/openai-compatible.d.ts.map +0 -1
  43. package/dist/src/adapters/review-engine/openai-compatible.js.map +0 -1
  44. package/dist/src/adapters/review-engine/parse-output.d.ts.map +0 -1
  45. package/dist/src/adapters/review-engine/parse-output.js.map +0 -1
  46. package/dist/src/adapters/review-engine/prompt-builder.d.ts.map +0 -1
  47. package/dist/src/adapters/review-engine/prompt-builder.js.map +0 -1
  48. package/dist/src/adapters/review-engine/types.d.ts.map +0 -1
  49. package/dist/src/adapters/review-engine/types.js.map +0 -1
  50. package/dist/src/adapters/vcs-host/commit-status.d.ts.map +0 -1
  51. package/dist/src/adapters/vcs-host/commit-status.js.map +0 -1
  52. package/dist/src/adapters/vcs-host/github.d.ts.map +0 -1
  53. package/dist/src/adapters/vcs-host/github.js.map +0 -1
  54. package/dist/src/adapters/vcs-host/types.d.ts.map +0 -1
  55. package/dist/src/adapters/vcs-host/types.js.map +0 -1
  56. package/dist/src/cli/_pkg-root.d.ts.map +0 -1
  57. package/dist/src/cli/_pkg-root.js.map +0 -1
  58. package/dist/src/cli/autoregress-bridge.d.ts.map +0 -1
  59. package/dist/src/cli/autoregress-bridge.js.map +0 -1
  60. package/dist/src/cli/baseline.d.ts.map +0 -1
  61. package/dist/src/cli/baseline.js.map +0 -1
  62. package/dist/src/cli/ci.d.ts.map +0 -1
  63. package/dist/src/cli/ci.js.map +0 -1
  64. package/dist/src/cli/costs.d.ts.map +0 -1
  65. package/dist/src/cli/costs.js.map +0 -1
  66. package/dist/src/cli/council.d.ts.map +0 -1
  67. package/dist/src/cli/council.js.map +0 -1
  68. package/dist/src/cli/detector.d.ts.map +0 -1
  69. package/dist/src/cli/detector.js.map +0 -1
  70. package/dist/src/cli/explain.d.ts.map +0 -1
  71. package/dist/src/cli/explain.js.map +0 -1
  72. package/dist/src/cli/fix.d.ts.map +0 -1
  73. package/dist/src/cli/fix.js.map +0 -1
  74. package/dist/src/cli/hook.d.ts.map +0 -1
  75. package/dist/src/cli/hook.js.map +0 -1
  76. package/dist/src/cli/ignore-helper.d.ts.map +0 -1
  77. package/dist/src/cli/ignore-helper.js.map +0 -1
  78. package/dist/src/cli/index.d.ts.map +0 -1
  79. package/dist/src/cli/index.js.map +0 -1
  80. package/dist/src/cli/lsp.d.ts.map +0 -1
  81. package/dist/src/cli/lsp.js.map +0 -1
  82. package/dist/src/cli/mcp.d.ts.map +0 -1
  83. package/dist/src/cli/mcp.js.map +0 -1
  84. package/dist/src/cli/migrate-v4.d.ts.map +0 -1
  85. package/dist/src/cli/migrate-v4.js.map +0 -1
  86. package/dist/src/cli/pr-comment.d.ts.map +0 -1
  87. package/dist/src/cli/pr-comment.js.map +0 -1
  88. package/dist/src/cli/pr-desc.d.ts.map +0 -1
  89. package/dist/src/cli/pr-desc.js.map +0 -1
  90. package/dist/src/cli/pr-review-comments.d.ts.map +0 -1
  91. package/dist/src/cli/pr-review-comments.js.map +0 -1
  92. package/dist/src/cli/pr.d.ts.map +0 -1
  93. package/dist/src/cli/pr.js.map +0 -1
  94. package/dist/src/cli/preflight.d.ts.map +0 -1
  95. package/dist/src/cli/preflight.js.map +0 -1
  96. package/dist/src/cli/report.d.ts.map +0 -1
  97. package/dist/src/cli/report.js.map +0 -1
  98. package/dist/src/cli/run.d.ts.map +0 -1
  99. package/dist/src/cli/run.js.map +0 -1
  100. package/dist/src/cli/scan.d.ts.map +0 -1
  101. package/dist/src/cli/scan.js.map +0 -1
  102. package/dist/src/cli/setup.d.ts.map +0 -1
  103. package/dist/src/cli/setup.js.map +0 -1
  104. package/dist/src/cli/test-gen.d.ts.map +0 -1
  105. package/dist/src/cli/test-gen.js.map +0 -1
  106. package/dist/src/cli/triage.d.ts.map +0 -1
  107. package/dist/src/cli/triage.js.map +0 -1
  108. package/dist/src/cli/watch.d.ts.map +0 -1
  109. package/dist/src/cli/watch.js.map +0 -1
  110. package/dist/src/cli/worker.d.ts.map +0 -1
  111. package/dist/src/cli/worker.js.map +0 -1
  112. package/dist/src/core/cache/cached-engine.d.ts.map +0 -1
  113. package/dist/src/core/cache/cached-engine.js.map +0 -1
  114. package/dist/src/core/cache/review-cache.d.ts.map +0 -1
  115. package/dist/src/core/cache/review-cache.js.map +0 -1
  116. package/dist/src/core/chunking/index.d.ts.map +0 -1
  117. package/dist/src/core/chunking/index.js.map +0 -1
  118. package/dist/src/core/chunking/risk-ranker.d.ts.map +0 -1
  119. package/dist/src/core/chunking/risk-ranker.js.map +0 -1
  120. package/dist/src/core/config/loader.d.ts.map +0 -1
  121. package/dist/src/core/config/loader.js.map +0 -1
  122. package/dist/src/core/config/preset-resolver.d.ts.map +0 -1
  123. package/dist/src/core/config/preset-resolver.js.map +0 -1
  124. package/dist/src/core/config/schema.d.ts.map +0 -1
  125. package/dist/src/core/config/schema.js.map +0 -1
  126. package/dist/src/core/config/types.d.ts.map +0 -1
  127. package/dist/src/core/config/types.js.map +0 -1
  128. package/dist/src/core/council/config.d.ts.map +0 -1
  129. package/dist/src/core/council/config.js.map +0 -1
  130. package/dist/src/core/council/context.d.ts.map +0 -1
  131. package/dist/src/core/council/context.js.map +0 -1
  132. package/dist/src/core/council/runner.d.ts.map +0 -1
  133. package/dist/src/core/council/runner.js.map +0 -1
  134. package/dist/src/core/council/types.d.ts.map +0 -1
  135. package/dist/src/core/council/types.js.map +0 -1
  136. package/dist/src/core/detect/git-context.d.ts.map +0 -1
  137. package/dist/src/core/detect/git-context.js.map +0 -1
  138. package/dist/src/core/detect/llm-key.d.ts.map +0 -1
  139. package/dist/src/core/detect/llm-key.js.map +0 -1
  140. package/dist/src/core/detect/protected-paths.d.ts.map +0 -1
  141. package/dist/src/core/detect/protected-paths.js.map +0 -1
  142. package/dist/src/core/detect/provider-usage.d.ts.map +0 -1
  143. package/dist/src/core/detect/provider-usage.js.map +0 -1
  144. package/dist/src/core/detect/stack.d.ts.map +0 -1
  145. package/dist/src/core/detect/stack.js.map +0 -1
  146. package/dist/src/core/detect/workspaces.d.ts.map +0 -1
  147. package/dist/src/core/detect/workspaces.js.map +0 -1
  148. package/dist/src/core/errors.d.ts.map +0 -1
  149. package/dist/src/core/errors.js.map +0 -1
  150. package/dist/src/core/findings/dedup.d.ts.map +0 -1
  151. package/dist/src/core/findings/dedup.js.map +0 -1
  152. package/dist/src/core/findings/types.d.ts.map +0 -1
  153. package/dist/src/core/findings/types.js.map +0 -1
  154. package/dist/src/core/fix/generator.d.ts.map +0 -1
  155. package/dist/src/core/fix/generator.js.map +0 -1
  156. package/dist/src/core/git/diff-hunks.d.ts.map +0 -1
  157. package/dist/src/core/git/diff-hunks.js.map +0 -1
  158. package/dist/src/core/git/touched-files.d.ts.map +0 -1
  159. package/dist/src/core/git/touched-files.js.map +0 -1
  160. package/dist/src/core/ignore/index.d.ts.map +0 -1
  161. package/dist/src/core/ignore/index.js.map +0 -1
  162. package/dist/src/core/index.d.ts.map +0 -1
  163. package/dist/src/core/index.js.map +0 -1
  164. package/dist/src/core/logging/ndjson-writer.d.ts.map +0 -1
  165. package/dist/src/core/logging/ndjson-writer.js.map +0 -1
  166. package/dist/src/core/logging/redaction.d.ts.map +0 -1
  167. package/dist/src/core/logging/redaction.js.map +0 -1
  168. package/dist/src/core/mcp/concurrency.d.ts.map +0 -1
  169. package/dist/src/core/mcp/concurrency.js.map +0 -1
  170. package/dist/src/core/mcp/handlers/fix-finding.d.ts.map +0 -1
  171. package/dist/src/core/mcp/handlers/fix-finding.js.map +0 -1
  172. package/dist/src/core/mcp/handlers/get-capabilities.d.ts.map +0 -1
  173. package/dist/src/core/mcp/handlers/get-capabilities.js.map +0 -1
  174. package/dist/src/core/mcp/handlers/get-findings.d.ts.map +0 -1
  175. package/dist/src/core/mcp/handlers/get-findings.js.map +0 -1
  176. package/dist/src/core/mcp/handlers/review-diff.d.ts.map +0 -1
  177. package/dist/src/core/mcp/handlers/review-diff.js.map +0 -1
  178. package/dist/src/core/mcp/handlers/scan-files.d.ts.map +0 -1
  179. package/dist/src/core/mcp/handlers/scan-files.js.map +0 -1
  180. package/dist/src/core/mcp/handlers/validate-fix.d.ts.map +0 -1
  181. package/dist/src/core/mcp/handlers/validate-fix.js.map +0 -1
  182. package/dist/src/core/mcp/run-store.d.ts.map +0 -1
  183. package/dist/src/core/mcp/run-store.js.map +0 -1
  184. package/dist/src/core/mcp/workspace.d.ts.map +0 -1
  185. package/dist/src/core/mcp/workspace.js.map +0 -1
  186. package/dist/src/core/persist/baseline.d.ts.map +0 -1
  187. package/dist/src/core/persist/baseline.js.map +0 -1
  188. package/dist/src/core/persist/cost-log.d.ts.map +0 -1
  189. package/dist/src/core/persist/cost-log.js.map +0 -1
  190. package/dist/src/core/persist/findings-cache.d.ts.map +0 -1
  191. package/dist/src/core/persist/findings-cache.js.map +0 -1
  192. package/dist/src/core/persist/triage.d.ts.map +0 -1
  193. package/dist/src/core/persist/triage.js.map +0 -1
  194. package/dist/src/core/phases/static-rules.d.ts.map +0 -1
  195. package/dist/src/core/phases/static-rules.js.map +0 -1
  196. package/dist/src/core/phases/tests.d.ts.map +0 -1
  197. package/dist/src/core/phases/tests.js.map +0 -1
  198. package/dist/src/core/pipeline/review-phase.d.ts.map +0 -1
  199. package/dist/src/core/pipeline/review-phase.js.map +0 -1
  200. package/dist/src/core/pipeline/run.d.ts.map +0 -1
  201. package/dist/src/core/pipeline/run.js.map +0 -1
  202. package/dist/src/core/runtime/idempotency.d.ts.map +0 -1
  203. package/dist/src/core/runtime/idempotency.js.map +0 -1
  204. package/dist/src/core/runtime/lock.d.ts.map +0 -1
  205. package/dist/src/core/runtime/lock.js.map +0 -1
  206. package/dist/src/core/runtime/state.d.ts.map +0 -1
  207. package/dist/src/core/runtime/state.js.map +0 -1
  208. package/dist/src/core/schema-alignment/detector.d.ts.map +0 -1
  209. package/dist/src/core/schema-alignment/detector.js.map +0 -1
  210. package/dist/src/core/schema-alignment/extractor/index.d.ts.map +0 -1
  211. package/dist/src/core/schema-alignment/extractor/index.js.map +0 -1
  212. package/dist/src/core/schema-alignment/extractor/prisma.d.ts.map +0 -1
  213. package/dist/src/core/schema-alignment/extractor/prisma.js.map +0 -1
  214. package/dist/src/core/schema-alignment/extractor/sql.d.ts.map +0 -1
  215. package/dist/src/core/schema-alignment/extractor/sql.js.map +0 -1
  216. package/dist/src/core/schema-alignment/llm-check.d.ts.map +0 -1
  217. package/dist/src/core/schema-alignment/llm-check.js.map +0 -1
  218. package/dist/src/core/schema-alignment/scanner.d.ts.map +0 -1
  219. package/dist/src/core/schema-alignment/scanner.js.map +0 -1
  220. package/dist/src/core/schema-alignment/types.d.ts.map +0 -1
  221. package/dist/src/core/schema-alignment/types.js.map +0 -1
  222. package/dist/src/core/shell.d.ts.map +0 -1
  223. package/dist/src/core/shell.js.map +0 -1
  224. package/dist/src/core/static-rules/registry.d.ts.map +0 -1
  225. package/dist/src/core/static-rules/registry.js.map +0 -1
  226. package/dist/src/core/static-rules/rules/brand-tokens.d.ts.map +0 -1
  227. package/dist/src/core/static-rules/rules/brand-tokens.js.map +0 -1
  228. package/dist/src/core/static-rules/rules/console-log.d.ts.map +0 -1
  229. package/dist/src/core/static-rules/rules/console-log.js.map +0 -1
  230. package/dist/src/core/static-rules/rules/hardcoded-secrets.d.ts.map +0 -1
  231. package/dist/src/core/static-rules/rules/hardcoded-secrets.js.map +0 -1
  232. package/dist/src/core/static-rules/rules/insecure-redirect.d.ts.map +0 -1
  233. package/dist/src/core/static-rules/rules/insecure-redirect.js.map +0 -1
  234. package/dist/src/core/static-rules/rules/large-file.d.ts.map +0 -1
  235. package/dist/src/core/static-rules/rules/large-file.js.map +0 -1
  236. package/dist/src/core/static-rules/rules/missing-auth.d.ts.map +0 -1
  237. package/dist/src/core/static-rules/rules/missing-auth.js.map +0 -1
  238. package/dist/src/core/static-rules/rules/missing-tests.d.ts.map +0 -1
  239. package/dist/src/core/static-rules/rules/missing-tests.js.map +0 -1
  240. package/dist/src/core/static-rules/rules/npm-audit.d.ts.map +0 -1
  241. package/dist/src/core/static-rules/rules/npm-audit.js.map +0 -1
  242. package/dist/src/core/static-rules/rules/package-lock-sync.d.ts.map +0 -1
  243. package/dist/src/core/static-rules/rules/package-lock-sync.js.map +0 -1
  244. package/dist/src/core/static-rules/rules/schema-alignment.d.ts.map +0 -1
  245. package/dist/src/core/static-rules/rules/schema-alignment.js.map +0 -1
  246. package/dist/src/core/static-rules/rules/sql-injection.d.ts.map +0 -1
  247. package/dist/src/core/static-rules/rules/sql-injection.js.map +0 -1
  248. package/dist/src/core/static-rules/rules/ssrf.d.ts.map +0 -1
  249. package/dist/src/core/static-rules/rules/ssrf.js.map +0 -1
  250. package/dist/src/core/static-rules/rules/todo-fixme.d.ts.map +0 -1
  251. package/dist/src/core/static-rules/rules/todo-fixme.js.map +0 -1
  252. package/dist/src/core/static-rules/tailwind-extractor.d.ts.map +0 -1
  253. package/dist/src/core/static-rules/tailwind-extractor.js.map +0 -1
  254. package/dist/src/core/test-gen/coverage-analyzer.d.ts.map +0 -1
  255. package/dist/src/core/test-gen/coverage-analyzer.js.map +0 -1
  256. package/dist/src/core/test-gen/framework-detector.d.ts.map +0 -1
  257. package/dist/src/core/test-gen/framework-detector.js.map +0 -1
  258. package/dist/src/core/test-gen/test-writer.d.ts.map +0 -1
  259. package/dist/src/core/test-gen/test-writer.js.map +0 -1
  260. package/dist/src/core/ui/design-context-loader.d.ts.map +0 -1
  261. package/dist/src/core/ui/design-context-loader.js.map +0 -1
  262. package/dist/src/core/worker/client.d.ts.map +0 -1
  263. package/dist/src/core/worker/client.js.map +0 -1
  264. package/dist/src/core/worker/lockfile.d.ts.map +0 -1
  265. package/dist/src/core/worker/lockfile.js.map +0 -1
  266. package/dist/src/core/worker/server.d.ts.map +0 -1
  267. package/dist/src/core/worker/server.js.map +0 -1
  268. package/dist/src/formatters/github-annotations.d.ts.map +0 -1
  269. package/dist/src/formatters/github-annotations.js.map +0 -1
  270. package/dist/src/formatters/index.d.ts.map +0 -1
  271. package/dist/src/formatters/index.js.map +0 -1
  272. package/dist/src/formatters/junit.d.ts.map +0 -1
  273. package/dist/src/formatters/junit.js.map +0 -1
  274. package/dist/src/formatters/sarif.d.ts.map +0 -1
  275. package/dist/src/formatters/sarif.js.map +0 -1
  276. package/dist/src/index.d.ts.map +0 -1
  277. package/dist/src/index.js.map +0 -1
  278. package/src/adapters/base.ts +0 -19
  279. package/src/adapters/council/claude.ts +0 -41
  280. package/src/adapters/council/openai.ts +0 -40
  281. package/src/adapters/council/types.ts +0 -7
  282. package/src/adapters/loader.ts +0 -108
  283. package/src/adapters/migration-runner/supabase.ts +0 -56
  284. package/src/adapters/migration-runner/types.ts +0 -36
  285. package/src/adapters/review-bot-parser/cursor.ts +0 -13
  286. package/src/adapters/review-bot-parser/declarative-base.ts +0 -64
  287. package/src/adapters/review-bot-parser/types.ts +0 -9
  288. package/src/adapters/review-engine/auto.ts +0 -94
  289. package/src/adapters/review-engine/claude.ts +0 -100
  290. package/src/adapters/review-engine/codex.ts +0 -82
  291. package/src/adapters/review-engine/gemini.ts +0 -105
  292. package/src/adapters/review-engine/openai-compatible.ts +0 -100
  293. package/src/adapters/review-engine/parse-output.ts +0 -74
  294. package/src/adapters/review-engine/prompt-builder.ts +0 -19
  295. package/src/adapters/review-engine/types.ts +0 -19
  296. package/src/adapters/vcs-host/commit-status.ts +0 -39
  297. package/src/adapters/vcs-host/github.ts +0 -77
  298. package/src/adapters/vcs-host/types.ts +0 -44
  299. package/src/cli/_pkg-root.ts +0 -85
  300. package/src/cli/autoregress-bridge.ts +0 -30
  301. package/src/cli/baseline.ts +0 -125
  302. package/src/cli/ci.ts +0 -45
  303. package/src/cli/costs.ts +0 -80
  304. package/src/cli/council.ts +0 -96
  305. package/src/cli/detector.ts +0 -92
  306. package/src/cli/explain.ts +0 -197
  307. package/src/cli/fix.ts +0 -249
  308. package/src/cli/hook.ts +0 -124
  309. package/src/cli/ignore-helper.ts +0 -116
  310. package/src/cli/index.ts +0 -612
  311. package/src/cli/lsp.ts +0 -200
  312. package/src/cli/mcp.ts +0 -206
  313. package/src/cli/migrate-v4.ts +0 -388
  314. package/src/cli/pr-comment.ts +0 -139
  315. package/src/cli/pr-desc.ts +0 -168
  316. package/src/cli/pr-review-comments.ts +0 -92
  317. package/src/cli/pr.ts +0 -76
  318. package/src/cli/preflight.ts +0 -235
  319. package/src/cli/report.ts +0 -186
  320. package/src/cli/run.ts +0 -425
  321. package/src/cli/scan.ts +0 -233
  322. package/src/cli/setup.ts +0 -191
  323. package/src/cli/test-gen.ts +0 -125
  324. package/src/cli/triage.ts +0 -137
  325. package/src/cli/watch.ts +0 -190
  326. package/src/cli/worker.ts +0 -109
  327. package/src/core/.gitkeep +0 -0
  328. package/src/core/cache/cached-engine.ts +0 -32
  329. package/src/core/cache/review-cache.ts +0 -70
  330. package/src/core/chunking/index.ts +0 -113
  331. package/src/core/chunking/risk-ranker.ts +0 -56
  332. package/src/core/config/loader.ts +0 -53
  333. package/src/core/config/preset-resolver.ts +0 -46
  334. package/src/core/config/schema.ts +0 -181
  335. package/src/core/config/types.ts +0 -98
  336. package/src/core/council/config.ts +0 -71
  337. package/src/core/council/context.ts +0 -17
  338. package/src/core/council/runner.ts +0 -83
  339. package/src/core/council/types.ts +0 -45
  340. package/src/core/detect/git-context.ts +0 -27
  341. package/src/core/detect/llm-key.ts +0 -89
  342. package/src/core/detect/protected-paths.ts +0 -63
  343. package/src/core/detect/provider-usage.ts +0 -74
  344. package/src/core/detect/stack.ts +0 -153
  345. package/src/core/detect/workspaces.ts +0 -103
  346. package/src/core/errors.ts +0 -37
  347. package/src/core/findings/dedup.ts +0 -14
  348. package/src/core/findings/types.ts +0 -39
  349. package/src/core/fix/generator.ts +0 -149
  350. package/src/core/git/diff-hunks.ts +0 -86
  351. package/src/core/git/touched-files.ts +0 -73
  352. package/src/core/ignore/index.ts +0 -54
  353. package/src/core/index.ts +0 -1
  354. package/src/core/logging/ndjson-writer.ts +0 -37
  355. package/src/core/logging/redaction.ts +0 -19
  356. package/src/core/mcp/concurrency.ts +0 -16
  357. package/src/core/mcp/handlers/fix-finding.ts +0 -126
  358. package/src/core/mcp/handlers/get-capabilities.ts +0 -62
  359. package/src/core/mcp/handlers/get-findings.ts +0 -36
  360. package/src/core/mcp/handlers/review-diff.ts +0 -65
  361. package/src/core/mcp/handlers/scan-files.ts +0 -65
  362. package/src/core/mcp/handlers/validate-fix.ts +0 -41
  363. package/src/core/mcp/run-store.ts +0 -85
  364. package/src/core/mcp/workspace.ts +0 -35
  365. package/src/core/persist/baseline.ts +0 -112
  366. package/src/core/persist/cost-log.ts +0 -30
  367. package/src/core/persist/findings-cache.ts +0 -43
  368. package/src/core/persist/triage.ts +0 -112
  369. package/src/core/phases/static-rules.ts +0 -93
  370. package/src/core/phases/tests.ts +0 -51
  371. package/src/core/pipeline/review-phase.ts +0 -182
  372. package/src/core/pipeline/run.ts +0 -116
  373. package/src/core/runtime/idempotency.ts +0 -6
  374. package/src/core/runtime/lock.ts +0 -29
  375. package/src/core/runtime/state.ts +0 -97
  376. package/src/core/schema-alignment/detector.ts +0 -59
  377. package/src/core/schema-alignment/extractor/index.ts +0 -24
  378. package/src/core/schema-alignment/extractor/prisma.ts +0 -21
  379. package/src/core/schema-alignment/extractor/sql.ts +0 -99
  380. package/src/core/schema-alignment/llm-check.ts +0 -91
  381. package/src/core/schema-alignment/scanner.ts +0 -107
  382. package/src/core/schema-alignment/types.ts +0 -43
  383. package/src/core/shell.ts +0 -48
  384. package/src/core/static-rules/registry.ts +0 -59
  385. package/src/core/static-rules/rules/brand-tokens.ts +0 -145
  386. package/src/core/static-rules/rules/console-log.ts +0 -42
  387. package/src/core/static-rules/rules/hardcoded-secrets.ts +0 -83
  388. package/src/core/static-rules/rules/insecure-redirect.ts +0 -67
  389. package/src/core/static-rules/rules/large-file.ts +0 -37
  390. package/src/core/static-rules/rules/missing-auth.ts +0 -70
  391. package/src/core/static-rules/rules/missing-tests.ts +0 -57
  392. package/src/core/static-rules/rules/npm-audit.ts +0 -38
  393. package/src/core/static-rules/rules/package-lock-sync.ts +0 -54
  394. package/src/core/static-rules/rules/schema-alignment.ts +0 -132
  395. package/src/core/static-rules/rules/sql-injection.ts +0 -71
  396. package/src/core/static-rules/rules/ssrf.ts +0 -63
  397. package/src/core/static-rules/rules/todo-fixme.ts +0 -40
  398. package/src/core/static-rules/tailwind-extractor.ts +0 -38
  399. package/src/core/test-gen/coverage-analyzer.ts +0 -93
  400. package/src/core/test-gen/framework-detector.ts +0 -21
  401. package/src/core/test-gen/test-writer.ts +0 -33
  402. package/src/core/ui/design-context-loader.ts +0 -87
  403. package/src/core/worker/client.ts +0 -46
  404. package/src/core/worker/lockfile.ts +0 -38
  405. package/src/core/worker/server.ts +0 -81
  406. package/src/formatters/github-annotations.ts +0 -36
  407. package/src/formatters/index.ts +0 -3
  408. package/src/formatters/junit.ts +0 -52
  409. package/src/formatters/sarif.ts +0 -103
  410. package/src/index.ts +0 -3
@@ -1,153 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
-
4
- function readJson(p: string): Record<string, unknown> | null {
5
- try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; }
6
- }
7
-
8
- function fileContains(p: string, needle: string): boolean {
9
- try { return fs.readFileSync(p, 'utf8').includes(needle); } catch { return false; }
10
- }
11
-
12
- function readFile(p: string): string {
13
- try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }
14
- }
15
-
16
- function version(deps: Record<string, string>, name: string): string | null {
17
- const v = deps[name];
18
- if (!v) return null;
19
- return v.replace(/^[\^~>=<\s]+/, '').split('.')[0] ?? null;
20
- }
21
-
22
- /**
23
- * Infers a human-readable stack description from project files.
24
- * Returns null if nothing definitive is found (caller should omit from prompt).
25
- */
26
- export function detectStack(cwd: string): string | null {
27
- // Go
28
- const goMod = path.join(cwd, 'go.mod');
29
- if (fs.existsSync(goMod)) {
30
- const content = readFile(goMod);
31
- const parts = ['Go'];
32
- if (content.includes('gin-gonic/gin')) parts.push('Gin');
33
- else if (content.includes('labstack/echo')) parts.push('Echo');
34
- else if (content.includes('gofiber/fiber')) parts.push('Fiber');
35
- else if (content.includes('go-chi/chi')) parts.push('Chi');
36
- if (content.includes('database/sql') || content.includes('sqlx') || content.includes('pgx')) parts.push('PostgreSQL');
37
- if (content.includes('gorm.io')) parts.push('GORM');
38
- if (content.includes('redis')) parts.push('Redis');
39
- return parts.join(' + ');
40
- }
41
-
42
- // Rust
43
- const cargoToml = path.join(cwd, 'Cargo.toml');
44
- if (fs.existsSync(cargoToml)) {
45
- const content = readFile(cargoToml);
46
- const parts = ['Rust'];
47
- if (content.includes('actix-web')) parts.push('Actix-Web');
48
- else if (content.includes('axum')) parts.push('Axum');
49
- else if (content.includes('warp')) parts.push('Warp');
50
- if (content.includes('sqlx') || content.includes('diesel')) parts.push('PostgreSQL');
51
- if (content.includes('serde')) parts.push('Serde');
52
- if (content.includes('tokio')) parts.push('Tokio async');
53
- return parts.join(' + ');
54
- }
55
-
56
- // Ruby / Rails
57
- const gemfile = path.join(cwd, 'Gemfile');
58
- if (fs.existsSync(gemfile)) {
59
- const content = readFile(gemfile);
60
- const parts: string[] = [];
61
- if (content.includes("'rails'") || content.includes('"rails"')) parts.push('Ruby on Rails');
62
- else if (content.includes("'sinatra'") || content.includes('"sinatra"')) parts.push('Sinatra');
63
- else parts.push('Ruby');
64
- if (content.includes('pg') || content.includes('postgresql')) parts.push('PostgreSQL');
65
- else if (content.includes('mysql')) parts.push('MySQL');
66
- else if (content.includes('sqlite')) parts.push('SQLite');
67
- if (content.includes('rspec')) parts.push('RSpec');
68
- if (content.includes('sidekiq')) parts.push('Sidekiq');
69
- return parts.join(' + ');
70
- }
71
-
72
- // Python
73
- const reqTxt = path.join(cwd, 'requirements.txt');
74
- const pyproject = path.join(cwd, 'pyproject.toml');
75
- const hasFastapi = fileContains(reqTxt, 'fastapi') || fileContains(pyproject, 'fastapi');
76
- const hasDjango = fileContains(reqTxt, 'django') || fileContains(pyproject, 'django');
77
- const hasFlask = fileContains(reqTxt, 'flask') || fileContains(pyproject, 'flask');
78
- if (hasFastapi || hasDjango || hasFlask || fs.existsSync(reqTxt) || fs.existsSync(pyproject)) {
79
- const parts: string[] = [];
80
- if (hasFastapi) parts.push('FastAPI');
81
- else if (hasDjango) parts.push('Django');
82
- else if (hasFlask) parts.push('Flask');
83
- else parts.push('Python');
84
- const combined = readFile(reqTxt) + readFile(pyproject);
85
- if (combined.includes('sqlalchemy') || combined.includes('SQLAlchemy')) parts.push('SQLAlchemy');
86
- if (combined.includes('postgresql') || combined.includes('psycopg')) parts.push('PostgreSQL');
87
- if (combined.includes('pydantic')) parts.push('Pydantic');
88
- if (combined.includes('celery')) parts.push('Celery');
89
- return parts.join(' + ');
90
- }
91
-
92
- // Node / JS / TS
93
- const pkgPath = path.join(cwd, 'package.json');
94
- if (!fs.existsSync(pkgPath)) return null;
95
- const pkg = readJson(pkgPath);
96
- if (!pkg) return null;
97
-
98
- const deps: Record<string, string> = {
99
- ...(pkg['dependencies'] as Record<string, string> ?? {}),
100
- ...(pkg['devDependencies'] as Record<string, string> ?? {}),
101
- };
102
-
103
- const parts: string[] = [];
104
- const isTs = 'typescript' in deps || fs.existsSync(path.join(cwd, 'tsconfig.json'));
105
-
106
- // Framework
107
- if ('next' in deps) {
108
- const v = version(deps, 'next');
109
- parts.push(v ? `Next.js ${v}` : 'Next.js');
110
- } else if ('nuxt' in deps || 'nuxt3' in deps) {
111
- parts.push('Nuxt');
112
- } else if ('remix' in deps || '@remix-run/react' in deps) {
113
- parts.push('Remix');
114
- } else if ('astro' in deps) {
115
- parts.push('Astro');
116
- } else if ('express' in deps) {
117
- parts.push('Express');
118
- } else if ('fastify' in deps) {
119
- parts.push('Fastify');
120
- } else if ('hono' in deps) {
121
- parts.push('Hono');
122
- } else if ('react' in deps) {
123
- parts.push('React');
124
- } else if ('vue' in deps) {
125
- parts.push('Vue');
126
- } else if ('svelte' in deps || '@sveltejs/kit' in deps) {
127
- parts.push('SvelteKit');
128
- }
129
-
130
- // Database / ORM
131
- if ('@supabase/supabase-js' in deps) parts.push('Supabase');
132
- if ('prisma' in deps || '@prisma/client' in deps) parts.push('Prisma');
133
- if ('drizzle-orm' in deps) parts.push('Drizzle');
134
- if ('typeorm' in deps) parts.push('TypeORM');
135
- if ('mongoose' in deps) parts.push('MongoDB');
136
-
137
- // Meta-frameworks / routers
138
- if ('@trpc/server' in deps) parts.push('tRPC');
139
- if ('graphql' in deps && ('apollo-server' in deps || '@apollo/server' in deps)) parts.push('GraphQL/Apollo');
140
-
141
- // Auth
142
- if ('next-auth' in deps || '@auth/core' in deps) parts.push('NextAuth');
143
- if ('clerk' in deps || '@clerk/nextjs' in deps) parts.push('Clerk');
144
-
145
- // UI
146
- if ('tailwindcss' in deps) parts.push('Tailwind CSS');
147
-
148
- // Language suffix
149
- if (isTs) parts.push('TypeScript');
150
-
151
- if (parts.length === 0) return null;
152
- return parts.join(' + ');
153
- }
@@ -1,103 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
-
4
- export interface Workspace {
5
- name: string;
6
- dir: string; // absolute path
7
- rel: string; // relative to root
8
- testCommand?: string;
9
- }
10
-
11
- function readJson(p: string): Record<string, unknown> | null {
12
- try { return JSON.parse(fs.readFileSync(p, 'utf8')) as Record<string, unknown>; } catch { return null; }
13
- }
14
-
15
- function globDirs(root: string, patterns: string[]): string[] {
16
- const results: string[] = [];
17
- for (const pattern of patterns) {
18
- // Support "packages/*" and "apps/*" style globs (one level deep only)
19
- const parts = pattern.split('/');
20
- if (parts.length === 2 && parts[1] === '*') {
21
- const base = path.join(root, parts[0]!);
22
- if (!fs.existsSync(base)) continue;
23
- for (const entry of fs.readdirSync(base, { withFileTypes: true })) {
24
- if (entry.isDirectory()) results.push(path.join(base, entry.name));
25
- }
26
- } else {
27
- const abs = path.join(root, pattern);
28
- if (fs.existsSync(abs) && fs.statSync(abs).isDirectory()) results.push(abs);
29
- }
30
- }
31
- return results;
32
- }
33
-
34
- function detectTestCommand(dir: string): string | undefined {
35
- const pkg = readJson(path.join(dir, 'package.json'));
36
- if (pkg?.scripts && typeof (pkg.scripts as Record<string, unknown>).test === 'string') {
37
- return `npm test --prefix ${dir}`;
38
- }
39
- if (fs.existsSync(path.join(dir, 'go.mod'))) return `go test ./... -C ${dir}`;
40
- if (fs.existsSync(path.join(dir, 'Cargo.toml'))) return `cargo test --manifest-path ${path.join(dir, 'Cargo.toml')}`;
41
- return undefined;
42
- }
43
-
44
- /** Detect npm/yarn/pnpm workspaces, Turborepo, Nx, Go multi-module. */
45
- export function detectWorkspaces(cwd: string): Workspace[] | null {
46
- const pkg = readJson(path.join(cwd, 'package.json')) as { workspaces?: string[] | { packages?: string[] }; name?: string } | null;
47
-
48
- // npm/yarn workspaces
49
- let wsDirs: string[] = [];
50
- if (pkg?.workspaces) {
51
- const patterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : (pkg.workspaces.packages ?? []);
52
- wsDirs = globDirs(cwd, patterns);
53
- }
54
-
55
- // Turborepo — pnpm-workspace.yaml or turbo.json
56
- if (wsDirs.length === 0 && fs.existsSync(path.join(cwd, 'pnpm-workspace.yaml'))) {
57
- try {
58
- const raw = fs.readFileSync(path.join(cwd, 'pnpm-workspace.yaml'), 'utf8');
59
- const matches = raw.match(/^\s*-\s*['"]?([^'"#\n]+)['"]?/gm) ?? [];
60
- const patterns = matches.map(m => m.replace(/^\s*-\s*['"]?/, '').replace(/['"]?\s*$/, '').trim());
61
- wsDirs = globDirs(cwd, patterns);
62
- } catch { /* ignore */ }
63
- }
64
-
65
- // Turborepo fallback: packages/ and apps/ dirs
66
- if (wsDirs.length === 0 && fs.existsSync(path.join(cwd, 'turbo.json'))) {
67
- wsDirs = globDirs(cwd, ['packages/*', 'apps/*']);
68
- }
69
-
70
- // Nx: check nx.json + libs/ + apps/
71
- if (wsDirs.length === 0 && fs.existsSync(path.join(cwd, 'nx.json'))) {
72
- wsDirs = globDirs(cwd, ['libs/*', 'apps/*', 'packages/*']);
73
- }
74
-
75
- if (wsDirs.length === 0) return null;
76
-
77
- return wsDirs
78
- .filter(d => fs.existsSync(d))
79
- .map(d => {
80
- const rel = path.relative(cwd, d);
81
- const pkgJson = readJson(path.join(d, 'package.json')) as { name?: string } | null;
82
- return {
83
- name: pkgJson?.name ?? rel,
84
- dir: d,
85
- rel,
86
- testCommand: detectTestCommand(d),
87
- };
88
- });
89
- }
90
-
91
- /** Given a list of touched files, return which workspaces they belong to. */
92
- export function mapFilesToWorkspaces(files: string[], workspaces: Workspace[], cwd: string): Map<Workspace, string[]> {
93
- const result = new Map<Workspace, string[]>();
94
- for (const file of files) {
95
- const abs = path.isAbsolute(file) ? file : path.resolve(cwd, file);
96
- const ws = workspaces.find(w => abs.startsWith(w.dir + path.sep) || abs === w.dir);
97
- if (ws) {
98
- if (!result.has(ws)) result.set(ws, []);
99
- result.get(ws)!.push(file);
100
- }
101
- }
102
- return result;
103
- }
@@ -1,37 +0,0 @@
1
- // src/core/errors.ts
2
-
3
- export type ErrorCode =
4
- | 'auth' | 'rate_limit' | 'transient_network' | 'invalid_config'
5
- | 'adapter_bug' | 'user_input' | 'budget_exceeded' | 'concurrency_lock' | 'superseded';
6
-
7
- export interface GuardrailErrorOptions {
8
- code: ErrorCode;
9
- retryable?: boolean;
10
- provider?: string;
11
- step?: string;
12
- details?: Record<string, unknown>;
13
- }
14
-
15
- const DEFAULT_RETRYABLE: Record<ErrorCode, boolean> = {
16
- auth: false, rate_limit: true, transient_network: true, invalid_config: false,
17
- adapter_bug: false, user_input: false, budget_exceeded: false,
18
- concurrency_lock: false, superseded: false,
19
- };
20
-
21
- export class GuardrailError extends Error {
22
- code: ErrorCode;
23
- retryable: boolean;
24
- provider?: string;
25
- step?: string;
26
- details: Record<string, unknown>;
27
-
28
- constructor(message: string, options: GuardrailErrorOptions) {
29
- super(message);
30
- this.name = 'GuardrailError';
31
- this.code = options.code;
32
- this.retryable = options.retryable ?? DEFAULT_RETRYABLE[options.code];
33
- this.provider = options.provider;
34
- this.step = options.step;
35
- this.details = options.details ?? {};
36
- }
37
- }
@@ -1,14 +0,0 @@
1
- import type { Finding } from './types.ts';
2
-
3
- export function findingContentKey(f: Finding): string {
4
- return `${f.file}|${f.line ?? ''}|${f.severity}|${f.message.slice(0, 40)}`;
5
- }
6
-
7
- export function dedupFindings(findings: Finding[]): Finding[] {
8
- const seen = new Map<string, Finding>();
9
- for (const f of findings) {
10
- const key = findingContentKey(f);
11
- if (!seen.has(key)) seen.set(key, f);
12
- }
13
- return Array.from(seen.values());
14
- }
@@ -1,39 +0,0 @@
1
- // src/core/findings/types.ts
2
-
3
- export type FindingSource = 'static-rules' | 'review-engine' | 'pipeline' | `review-bot:${string}`;
4
- export type Severity = 'critical' | 'warning' | 'note';
5
-
6
- export interface Finding {
7
- id: string;
8
- source: FindingSource;
9
- severity: Severity;
10
- category: string;
11
- file: string;
12
- line?: number;
13
- message: string;
14
- suggestion?: string;
15
- protectedPath: boolean;
16
- createdAt: string;
17
- }
18
-
19
- export type TriageVerdict = 'real_bug' | 'false_positive' | 'low_value';
20
- export type TriageAction = 'auto_fix' | 'propose_patch' | 'ask_question' | 'dismiss' | 'needs_human';
21
-
22
- export interface TriageRecord {
23
- findingId: string;
24
- verdict: TriageVerdict;
25
- confidence: number;
26
- reason: string;
27
- action: TriageAction;
28
- recordedAt: string;
29
- }
30
-
31
- export type FixStatus = 'fixed' | 'reverted' | 'human_required' | 'skipped';
32
-
33
- export interface FixAttempt {
34
- findingId: string;
35
- attemptedAt: string;
36
- status: FixStatus;
37
- commitSha?: string;
38
- notes?: string;
39
- }
@@ -1,149 +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
- import type { ReviewEngine } from '../../adapters/review-engine/types.ts';
5
-
6
- export const CONTEXT_LINES = 20;
7
-
8
- // LLM error / refusal phrases that indicate a bad output
9
- const REFUSAL_PHRASES = [
10
- 'i cannot', "i can't", 'i am unable', 'as an ai', 'as a language model',
11
- 'i apologize', "i'm sorry", 'cannot safely', 'would require', 'error:',
12
- ];
13
-
14
- export interface GenerateResult {
15
- status: 'ok' | 'cannot_fix' | 'rejected' | 'error';
16
- reason?: string;
17
- originalLines?: string[];
18
- replacementLines?: string[];
19
- startLine?: number;
20
- endLine?: number;
21
- }
22
-
23
- export function validateReplacement(original: string[], replacement: string[], _finding: Finding): string | null {
24
- if (replacement.length === 0) return 'LLM returned empty output';
25
-
26
- // Reject obvious LLM refusals
27
- const joined = replacement.join(' ').toLowerCase();
28
- for (const phrase of REFUSAL_PHRASES) {
29
- if (joined.includes(phrase)) return `LLM refused: "${replacement[0]?.slice(0, 60)}"`;
30
- }
31
-
32
- // Reject if line count ballooned more than 3x (likely hallucination)
33
- if (replacement.length > original.length * 3 + 10) {
34
- return `Suspicious: replacement is ${replacement.length} lines vs original ${original.length}`;
35
- }
36
-
37
- // Reject if the replacement is identical (LLM made no change)
38
- if (replacement.join('\n') === original.join('\n')) {
39
- return 'LLM returned identical code — no change made';
40
- }
41
-
42
- return null;
43
- }
44
-
45
- export function buildUnifiedDiff(
46
- original: string[],
47
- replacement: string[],
48
- filePath: string,
49
- startLine: number,
50
- opts: { color?: boolean } = {},
51
- ): string {
52
- // Colors default on for CLI ergonomics; MCP callers pass color:false so ANSI
53
- // escapes don't leak into JSON responses that machine clients must parse.
54
- const useColor = opts.color !== false;
55
- const C = {
56
- reset: '\x1b[0m', green: '\x1b[32m', red: '\x1b[31m',
57
- };
58
- const fmt = (c: keyof typeof C, t: string) => useColor ? `${C[c]}${t}${C.reset}` : t;
59
- const lines: string[] = [`--- ${filePath}`, `+++ ${filePath} (proposed fix)`, `@@ -${startLine},${original.length} +${startLine},${replacement.length} @@`];
60
- for (const l of original) lines.push(fmt('red', `- ${l}`));
61
- for (const l of replacement) lines.push(fmt('green', `+ ${l}`));
62
- return lines.join('\n');
63
- }
64
-
65
- export async function generateFix(finding: Finding, engine: ReviewEngine, cwd: string): Promise<GenerateResult> {
66
- // MCP handlers can pass through findings loaded from disk — validate required
67
- // fields rather than trusting the CLI pre-filter path.
68
- if (!finding.file || typeof finding.file !== 'string') {
69
- return { status: 'cannot_fix', reason: 'finding.file missing' };
70
- }
71
- if (typeof finding.line !== 'number' || !Number.isFinite(finding.line) || finding.line < 1) {
72
- return { status: 'cannot_fix', reason: 'finding.line missing or invalid' };
73
- }
74
-
75
- const absPath = path.resolve(cwd, finding.file);
76
- let fileLines: string[];
77
- try {
78
- fileLines = fs.readFileSync(absPath, 'utf8').split('\n');
79
- } catch {
80
- return { status: 'cannot_fix', reason: 'file not readable' };
81
- }
82
-
83
- const lineIdx = finding.line - 1;
84
- if (lineIdx < 0 || lineIdx >= fileLines.length) {
85
- return { status: 'cannot_fix', reason: 'line out of range' };
86
- }
87
-
88
- const startIdx = Math.max(0, lineIdx - CONTEXT_LINES);
89
- const endIdx = Math.min(fileLines.length - 1, lineIdx + CONTEXT_LINES);
90
- const contextLines = fileLines.slice(startIdx, endIdx + 1);
91
- const startLine = startIdx + 1;
92
-
93
- const numbered = contextLines.map((l, i) => {
94
- const n = startLine + i;
95
- return `${n === finding.line ? '>>>' : ' '} ${String(n).padStart(4)}: ${l}`;
96
- }).join('\n');
97
-
98
- const prompt = [
99
- `File: ${finding.file}`,
100
- `Finding (line ${finding.line}): [${finding.severity.toUpperCase()}] ${finding.message}`,
101
- finding.suggestion ? `Suggestion: ${finding.suggestion}` : '',
102
- '',
103
- 'Relevant lines (>>> marks the finding):',
104
- '```',
105
- numbered,
106
- '```',
107
- '',
108
- `Rewrite ONLY lines ${startLine}–${endIdx + 1} to fix this finding.`,
109
- 'Rules:',
110
- '- Output ONLY the replacement lines with no explanation, no markdown fences, no line numbers',
111
- '- Preserve indentation exactly',
112
- '- Make the minimal change needed — do not refactor unrelated code',
113
- '- If the fix cannot be done safely in this context, output exactly: CANNOT_FIX',
114
- ].filter(Boolean).join('\n');
115
-
116
- let rawOutput: string;
117
- try {
118
- const output = await engine.review({ content: prompt, kind: 'file-batch' });
119
- rawOutput = output.rawOutput.trim();
120
- } catch (err) {
121
- return { status: 'error', reason: `LLM error: ${err instanceof Error ? err.message : String(err)}` };
122
- }
123
-
124
- if (rawOutput === 'CANNOT_FIX' || rawOutput.startsWith('CANNOT_FIX')) {
125
- return { status: 'cannot_fix', reason: 'LLM: cannot fix safely in this context' };
126
- }
127
-
128
- // Strip markdown fences if the model added them despite instructions
129
- const cleaned = rawOutput
130
- .replace(/^```[a-zA-Z]*\n?/, '')
131
- .replace(/\n?```$/, '')
132
- .trimEnd();
133
-
134
- const replacementLines = cleaned.split('\n');
135
- const originalLines = contextLines;
136
-
137
- const validationError = validateReplacement(originalLines, replacementLines, finding);
138
- if (validationError) {
139
- return { status: 'rejected', reason: validationError };
140
- }
141
-
142
- return {
143
- status: 'ok',
144
- originalLines,
145
- replacementLines,
146
- startLine,
147
- endLine: endIdx + 1,
148
- };
149
- }
@@ -1,86 +0,0 @@
1
- import { runSafe } from '../shell.ts';
2
-
3
- export interface FileDiff {
4
- file: string;
5
- hunks: string; // unified diff content for this file (header + hunks)
6
- additions: number;
7
- deletions: number;
8
- }
9
-
10
- /**
11
- * Returns per-file unified diffs for the given files between base and HEAD.
12
- * Falls back to working-tree diff (unstaged) when base diff is empty for a file.
13
- */
14
- export function getFileDiffs(cwd: string, base: string, files: string[]): FileDiff[] {
15
- if (files.length === 0) return [];
16
-
17
- // Get full diff in one shot — more efficient than per-file calls
18
- const raw = runSafe('git', ['diff', base, 'HEAD', '--unified=3', '--', ...files], { cwd })
19
- ?? runSafe('git', ['diff', 'HEAD', '--unified=3', '--', ...files], { cwd })
20
- ?? '';
21
-
22
- return parseUnifiedDiff(raw, files);
23
- }
24
-
25
- /**
26
- * Parses unified diff output into per-file FileDiff entries.
27
- * Only returns files that actually have diff content.
28
- */
29
- export function parseUnifiedDiff(raw: string, requestedFiles: string[]): FileDiff[] {
30
- if (!raw.trim()) return [];
31
-
32
- const results: FileDiff[] = [];
33
- const sections = raw.split(/^(?=diff --git )/m).filter(Boolean);
34
-
35
- const requested = new Set(requestedFiles.map(f => f.replace(/\\/g, '/')));
36
-
37
- for (const section of sections) {
38
- // Extract b/ filename from diff header: diff --git a/src/foo.ts b/src/foo.ts
39
- const headerMatch = section.match(/^diff --git a\/.+ b\/(.+)$/m);
40
- if (!headerMatch) continue;
41
- const file = headerMatch[1]!.trim();
42
- if (!requested.has(file)) continue;
43
-
44
- // Strip the git binary/index header lines, keep hunk content
45
- const hunkStart = section.indexOf('@@');
46
- const hunks = hunkStart >= 0 ? section.slice(hunkStart) : '';
47
- if (!hunks.trim()) continue;
48
-
49
- let additions = 0;
50
- let deletions = 0;
51
- for (const line of hunks.split('\n')) {
52
- if (line.startsWith('+') && !line.startsWith('+++')) additions++;
53
- if (line.startsWith('-') && !line.startsWith('---')) deletions++;
54
- }
55
-
56
- results.push({ file, hunks: hunks.trimEnd(), additions, deletions });
57
- }
58
-
59
- return results;
60
- }
61
-
62
- /**
63
- * Formats FileDiff entries into a review-ready string.
64
- * Total size is bounded by maxChars (default 120K chars ≈ 30K tokens).
65
- */
66
- export function formatDiffContent(diffs: FileDiff[], maxChars = 120_000): string {
67
- const parts: string[] = [];
68
- let total = 0;
69
- let skipped = 0;
70
-
71
- for (const d of diffs) {
72
- const section = `## ${d.file} (+${d.additions}/-${d.deletions})\n\`\`\`diff\n${d.hunks}\n\`\`\``;
73
- if (total + section.length > maxChars) {
74
- skipped++;
75
- continue;
76
- }
77
- parts.push(section);
78
- total += section.length;
79
- }
80
-
81
- if (skipped > 0) {
82
- parts.push(`[${skipped} file${skipped !== 1 ? 's' : ''} omitted — diff exceeded size limit]`);
83
- }
84
-
85
- return parts.join('\n\n');
86
- }
@@ -1,73 +0,0 @@
1
- import { runSafe } from '../shell.ts';
2
-
3
- const IGNORE_PREFIXES = [
4
- 'node_modules/',
5
- 'dist/',
6
- 'build/',
7
- '.next/',
8
- '.nuxt/',
9
- 'out/',
10
- 'coverage/',
11
- '.turbo/',
12
- '.cache/',
13
- 'vendor/',
14
- '__pycache__/',
15
- '.venv/',
16
- 'venv/',
17
- 'target/', // Rust/Java
18
- '.gradle/',
19
- ];
20
-
21
- function isIgnored(file: string): boolean {
22
- return IGNORE_PREFIXES.some(p => file.startsWith(p));
23
- }
24
-
25
- export interface TouchedFilesOptions {
26
- cwd?: string;
27
- base?: string; // e.g. 'HEAD~1', 'main', a SHA — defaults to HEAD~1
28
- }
29
-
30
- /**
31
- * Returns the list of files changed relative to `base` (default HEAD~1).
32
- * Falls back to `git status --short` unstaged/staged files if the diff fails
33
- * (e.g. first commit, no parent).
34
- */
35
- export function resolveGitTouchedFiles(options: TouchedFilesOptions = {}): string[] {
36
- const cwd = options.cwd ?? process.cwd();
37
- const base = options.base ?? 'HEAD~1';
38
-
39
- // Primary: diff against base
40
- const diffOut = runSafe('git', ['diff', '--name-only', base, 'HEAD'], { cwd });
41
- if (diffOut !== null && diffOut.trim().length > 0) {
42
- return parseFileList(diffOut);
43
- }
44
-
45
- // Fallback: staged + unstaged working tree changes
46
- const statusOut = runSafe('git', ['status', '--short'], { cwd });
47
- if (statusOut !== null && statusOut.trim().length > 0) {
48
- return parseStatusOutput(statusOut);
49
- }
50
-
51
- return [];
52
- }
53
-
54
- function parseFileList(output: string): string[] {
55
- return [...new Set(output.split('\n').map(l => l.trim()).filter(Boolean).filter(f => !isIgnored(f)))];
56
- }
57
-
58
- function parseStatusOutput(output: string): string[] {
59
- const files = new Set<string>();
60
- for (const line of output.split('\n')) {
61
- const trimmed = line.trim();
62
- if (!trimmed) continue;
63
- // format: XY filename (or XY old -> new for renames)
64
- const parts = trimmed.replace(/^\S+\s+/, '');
65
- const renamed = parts.match(/^(.+)\s+->\s+(.+)$/);
66
- if (renamed) {
67
- files.add(renamed[2]!.trim());
68
- } else {
69
- files.add(parts.trim());
70
- }
71
- }
72
- return [...files].filter(f => !isIgnored(f));
73
- }