@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,98 +0,0 @@
1
- import type { SchemaAlignmentConfig } from '../schema-alignment/types.ts';
2
-
3
- export interface AdapterReference {
4
- adapter: string;
5
- options?: Record<string, unknown>;
6
- }
7
-
8
- export type AdapterRef = string | AdapterReference;
9
-
10
- export type StaticRuleReference = string | { adapter: string; options?: Record<string, unknown> };
11
-
12
- export interface GuardrailConfig {
13
- configVersion: 1;
14
- preset?: string;
15
- reviewEngine?: AdapterRef;
16
- vcsHost?: AdapterRef;
17
- migrationRunner?: AdapterRef;
18
- reviewBot?: AdapterRef;
19
- adapterAllowlist?: string[];
20
- protectedPaths?: string[];
21
- staticRules?: StaticRuleReference[];
22
- staticRulesParallel?: boolean;
23
- stack?: string;
24
- testCommand?: string | null;
25
- thresholds?: {
26
- bugbotAutoFix?: number;
27
- bugbotProposePatch?: number;
28
- maxValidateRetries?: number;
29
- maxCodexRetries?: number;
30
- maxBugbotRounds?: number;
31
- };
32
- ignore?: Array<string | { rule?: string; path: string }>;
33
- reviewStrategy?: 'auto' | 'single-pass' | 'file-level' | 'diff' | 'auto-diff';
34
- chunking?: {
35
- smallTierMaxTokens?: number;
36
- partialReviewTokens?: number;
37
- perFileMaxTokens?: number;
38
- parallelism?: number;
39
- rateLimitBackoff?: 'exp' | 'linear' | 'none';
40
- };
41
- policy?: {
42
- /** Severity threshold for exit code 1. Default: 'critical'. Use 'none' to always pass. */
43
- failOn?: 'critical' | 'warning' | 'note' | 'none';
44
- /** Only report findings not present in the committed baseline. Default: false. */
45
- newOnly?: boolean;
46
- /** Path to baseline file relative to cwd. Default: .guardrail-baseline.json */
47
- baselinePath?: string;
48
- };
49
- pipeline?: {
50
- /**
51
- * When true, run the LLM review phase even if the static-rules phase reports `fail`
52
- * (i.e. finds a critical). Default: true. Set to false to skip only the review
53
- * phase on static-fail — the tests phase still runs regardless.
54
- *
55
- * Users that explicitly configure a review engine typically expect it to run — the
56
- * bugs the LLM is best at (IDOR, TOCTOU, CORS, off-by-one, rate limits) often sit
57
- * in the same commit as something a static rule already flagged. This flag only
58
- * gates the review phase, mirroring `runReviewOnTestFail`.
59
- */
60
- runReviewOnStaticFail?: boolean;
61
- /**
62
- * When true, run the LLM review phase even if the tests phase reports `fail`.
63
- * Default: false — failing tests usually indicate broken code, not code to review.
64
- * This flag only gates the review phase; the tests phase itself always runs.
65
- */
66
- runReviewOnTestFail?: boolean;
67
- };
68
- cost?: {
69
- /** Abort review phase if estimated spend exceeds this amount (USD). */
70
- maxPerRun?: number;
71
- /** Print token estimate before starting LLM review. Default: false. */
72
- estimateBeforeRun?: boolean;
73
- /** Per-model token price overrides (input/output per 1M tokens). */
74
- pricing?: Record<string, { inputPer1M: number; outputPer1M: number }>;
75
- };
76
- brand?: {
77
- /** Path to tailwind.config.{ts,js} — auto-extracts theme.colors as canonical palette */
78
- colorsFrom?: string;
79
- /** Explicit canonical color values (hex/rgb/hsl). Merged with colorsFrom. */
80
- colors?: string[];
81
- /** Canonical font family names */
82
- fonts?: string[];
83
- /** Path to design system component library (informational, for future LLM review) */
84
- componentLibrary?: string | { tokens?: string; guide?: string };
85
- };
86
- 'schema-alignment'?: SchemaAlignmentConfig;
87
- cache?: Record<string, unknown>;
88
- persistence?: Record<string, unknown>;
89
- concurrency?: Record<string, unknown>;
90
- council?: {
91
- models: Array<{ adapter: string; model: string; label: string }>;
92
- synthesizer: { adapter: string; model: string; label: string };
93
- timeout_ms?: number;
94
- min_successful_responses?: number;
95
- parallel_input_max_tokens?: number;
96
- synthesis_input_max_tokens?: number;
97
- };
98
- }
@@ -1,71 +0,0 @@
1
- // src/core/council/config.ts
2
- import { GuardrailError } from '../errors.ts';
3
- import type { CouncilConfig, CouncilModelEntry } from './types.ts';
4
-
5
- const SUPPORTED_ADAPTERS = new Set(['claude', 'openai']);
6
-
7
- export function parseCouncilConfig(raw: Record<string, unknown>): CouncilConfig {
8
- const models = raw['models'] as Array<Record<string, string>> | undefined;
9
- const synthRaw = raw['synthesizer'] as Record<string, string> | undefined;
10
- const timeoutMs = (raw['timeout_ms'] as number | undefined) ?? 30000;
11
- const minSuccessful = (raw['min_successful_responses'] as number | undefined) ?? 1;
12
- const parallelInputMaxTokens = (raw['parallel_input_max_tokens'] as number | undefined) ?? 8000;
13
- const synthesisInputMaxTokens = (raw['synthesis_input_max_tokens'] as number | undefined) ?? 12000;
14
-
15
- if (!Array.isArray(models) || models.length < 2) {
16
- throw new GuardrailError('council.models must have at least 2 entries', { code: 'invalid_config' });
17
- }
18
-
19
- if (!synthRaw?.['adapter'] || !synthRaw['model'] || !synthRaw['label']) {
20
- throw new GuardrailError('council.synthesizer requires adapter, model, and label', { code: 'invalid_config' });
21
- }
22
-
23
- if (timeoutMs < 5000) {
24
- throw new GuardrailError(`council.timeout_ms must be >= 5000, got ${timeoutMs}`, { code: 'invalid_config' });
25
- }
26
-
27
- if (minSuccessful < 1 || minSuccessful > models.length) {
28
- throw new GuardrailError(
29
- `council.min_successful_responses must be 1–${models.length}, got ${minSuccessful}`,
30
- { code: 'invalid_config' },
31
- );
32
- }
33
-
34
- for (const entry of [...models, synthRaw]) {
35
- if (!SUPPORTED_ADAPTERS.has(entry['adapter']!)) {
36
- throw new GuardrailError(
37
- `council: unknown adapter "${entry['adapter']}" — supported: ${[...SUPPORTED_ADAPTERS].join(', ')}`,
38
- { code: 'invalid_config' },
39
- );
40
- }
41
- }
42
-
43
- const seen = new Set<string>();
44
- for (const m of models) {
45
- if (seen.has(m['label']!)) {
46
- throw new GuardrailError(`council.models: duplicate label "${m['label']}"`, { code: 'invalid_config' });
47
- }
48
- seen.add(m['label']!);
49
- }
50
-
51
- const parsedModels: CouncilModelEntry[] = models.map(m => ({
52
- adapter: m['adapter'] as 'claude' | 'openai',
53
- model: m['model']!,
54
- label: m['label']!,
55
- }));
56
-
57
- const synthesizer: CouncilModelEntry = {
58
- adapter: synthRaw['adapter'] as 'claude' | 'openai',
59
- model: synthRaw['model']!,
60
- label: synthRaw['label']!,
61
- };
62
-
63
- return {
64
- models: parsedModels,
65
- synthesizer,
66
- timeoutMs,
67
- minSuccessfulResponses: minSuccessful,
68
- parallelInputMaxTokens,
69
- synthesisInputMaxTokens,
70
- };
71
- }
@@ -1,17 +0,0 @@
1
- const CHARS_PER_TOKEN = 4;
2
-
3
- export function windowContext(text: string, maxTokens: number): string {
4
- const estimated = Math.ceil(text.length / CHARS_PER_TOKEN);
5
- if (estimated <= maxTokens) return text;
6
-
7
- const maxChars = maxTokens * CHARS_PER_TOKEN;
8
- // Reserve budget for the marker so the final output stays within maxTokens.
9
- // Use a conservative upper bound of the formatted marker (the digit count of
10
- // charsDropped is computed from text length to avoid circular dependency).
11
- const markerOverhead = `<!-- [council: truncated ${text.length} chars] -->\n`.length;
12
- const effectiveMaxChars = Math.max(0, maxChars - markerOverhead);
13
- const charsDropped = text.length - effectiveMaxChars;
14
- const marker = `<!-- [council: truncated ${charsDropped} chars] -->\n`;
15
- process.stderr.write(`[council] context truncated: dropped ${charsDropped} chars to fit ${maxTokens} token budget\n`);
16
- return marker + text.slice(charsDropped);
17
- }
@@ -1,83 +0,0 @@
1
- import * as crypto from 'node:crypto';
2
- import { windowContext } from './context.ts';
3
- import type { CouncilConfig, CouncilResult, ModelResponse } from './types.ts';
4
- import type { CouncilAdapter } from '../../adapters/council/types.ts';
5
-
6
- async function consultWithTimeout(
7
- adapter: CouncilAdapter,
8
- prompt: string,
9
- context: string,
10
- timeoutMs: number,
11
- ): Promise<ModelResponse> {
12
- const start = Date.now();
13
- let timer: NodeJS.Timeout | undefined;
14
- try {
15
- const text = await Promise.race([
16
- adapter.consult(prompt, context),
17
- new Promise<never>((_, reject) => {
18
- timer = setTimeout(() => reject(new Error('timeout')), timeoutMs);
19
- }),
20
- ]);
21
- return { label: adapter.label, status: 'ok', text, latencyMs: Date.now() - start };
22
- } catch (err) {
23
- const message = err instanceof Error ? err.message : String(err);
24
- return message === 'timeout'
25
- ? { label: adapter.label, status: 'timeout', error: 'timed out', latencyMs: Date.now() - start }
26
- : { label: adapter.label, status: 'error', error: message, latencyMs: Date.now() - start };
27
- } finally {
28
- // Always clear the timer to avoid keeping the event loop alive after the
29
- // adapter resolves/rejects. Long-running hosts (MCP server) would accumulate
30
- // dangling timers for the full timeoutMs otherwise.
31
- if (timer) clearTimeout(timer);
32
- }
33
- }
34
-
35
- export async function runCouncil(
36
- config: CouncilConfig,
37
- adapters: CouncilAdapter[],
38
- synthesizer: CouncilAdapter,
39
- prompt: string,
40
- contextDoc: string,
41
- ): Promise<CouncilResult> {
42
- const run_id = crypto.randomUUID();
43
- const context = windowContext(contextDoc, config.parallelInputMaxTokens);
44
-
45
- const responses = await Promise.all(
46
- adapters.map(a => consultWithTimeout(a, prompt, context, config.timeoutMs))
47
- );
48
-
49
- const successful = responses.filter(r => r.status === 'ok');
50
-
51
- if (successful.length < config.minSuccessfulResponses) {
52
- return { schema_version: 1, run_id, status: 'failed', prompt, responses };
53
- }
54
-
55
- const responseSections = successful
56
- .map(r => `### ${r.label}\n${r.text}`)
57
- .join('\n\n');
58
-
59
- const synthesisDoc = `${contextDoc}\n\n---\n\n${responseSections}`;
60
- const synthesisCtx = windowContext(synthesisDoc, config.synthesisInputMaxTokens);
61
- const synthesisPrompt = [
62
- `You have received responses from multiple technical advisors on the following question:\n\n## Original Question\n\n${prompt}`,
63
- `## Advisor Responses\n\n${responseSections}`,
64
- 'Based on these responses, provide a synthesis: areas of agreement, key disagreements, and your final recommendation.',
65
- ].join('\n\n');
66
-
67
- // Synthesizer shares the same per-call timeout as model calls so a hung
68
- // synthesizer API doesn't block the whole command indefinitely.
69
- const synthResponse = await consultWithTimeout(
70
- synthesizer,
71
- synthesisPrompt,
72
- synthesisCtx,
73
- config.timeoutMs,
74
- );
75
- // status:'ok' means the synthesizer call itself completed without error.
76
- // Empty text is valid (e.g. the --no-synthesize stub that intentionally
77
- // returns ''); only treat actual failures/timeouts as partial.
78
- if (synthResponse.status === 'ok') {
79
- const synthesis = { label: synthesizer.label, text: synthResponse.text ?? '', latencyMs: synthResponse.latencyMs };
80
- return { schema_version: 1, run_id, status: 'success', prompt, responses, synthesis };
81
- }
82
- return { schema_version: 1, run_id, status: 'partial', prompt, responses };
83
- }
@@ -1,45 +0,0 @@
1
- // adapter is a closed union — extending to a new provider requires an intentional
2
- // code change in config.ts and cli/council.ts
3
- export interface CouncilModelEntry {
4
- adapter: 'claude' | 'openai';
5
- model: string;
6
- label: string;
7
- }
8
-
9
- export interface CouncilConfig {
10
- models: CouncilModelEntry[];
11
- synthesizer: CouncilModelEntry;
12
- timeoutMs: number;
13
- minSuccessfulResponses: number;
14
- parallelInputMaxTokens: number;
15
- synthesisInputMaxTokens: number;
16
- }
17
-
18
- export type ModelResponseStatus = 'ok' | 'timeout' | 'error';
19
-
20
- export interface ModelResponse {
21
- label: string;
22
- status: ModelResponseStatus;
23
- text?: string;
24
- error?: string;
25
- latencyMs: number;
26
- }
27
-
28
- export interface SynthesisResponse {
29
- label: string;
30
- text: string;
31
- latencyMs: number;
32
- }
33
-
34
- export type CouncilStatus = 'success' | 'partial' | 'failed';
35
-
36
- export interface CouncilResult {
37
- // snake_case: wire-format field, consistent with MCP handler schema_version convention
38
- schema_version: 1;
39
- // snake_case: wire-format field
40
- run_id: string;
41
- status: CouncilStatus;
42
- prompt: string;
43
- responses: ModelResponse[];
44
- synthesis?: SynthesisResponse;
45
- }
@@ -1,27 +0,0 @@
1
- import { runSafe } from '../shell.ts';
2
-
3
- export interface GitContext {
4
- branch: string | null;
5
- commitMessage: string | null;
6
- /** Short summary suitable for injecting into a review prompt */
7
- summary: string | null;
8
- }
9
-
10
- /**
11
- * Reads branch name and last commit message from git. Returns nulls gracefully
12
- * if git is unavailable or the repo has no commits.
13
- */
14
- export function detectGitContext(cwd: string): GitContext {
15
- const branch = runSafe('git', ['-C', cwd, 'rev-parse', '--abbrev-ref', 'HEAD'])?.trim() ?? null;
16
- const commitMessage = runSafe('git', ['-C', cwd, 'log', '-1', '--format=%s'])?.trim() ?? null;
17
-
18
- let summary: string | null = null;
19
- if (branch || commitMessage) {
20
- const parts: string[] = [];
21
- if (branch && branch !== 'HEAD') parts.push(`branch: ${branch}`);
22
- if (commitMessage) parts.push(`last commit: ${commitMessage}`);
23
- summary = parts.join(' | ');
24
- }
25
-
26
- return { branch, commitMessage, summary };
27
- }
@@ -1,89 +0,0 @@
1
- /**
2
- * Shared LLM API key detection. Used by setup, doctor/preflight, scan, and run so
3
- * every surface agrees on which env vars count as "have a key."
4
- *
5
- * Before this unified helper, doctor only checked ANTHROPIC_API_KEY + OPENAI_API_KEY
6
- * while setup/scan/run checked all 5 providers — producing contradictory messages
7
- * ("LLM API key: detected" from setup, "No LLM API key" from doctor moments later).
8
- */
9
-
10
- import * as fs from 'node:fs';
11
-
12
- /** All env var names guardrail recognizes as LLM API keys, ordered by preference. */
13
- export const LLM_KEY_NAMES = [
14
- 'ANTHROPIC_API_KEY',
15
- 'OPENAI_API_KEY',
16
- 'GEMINI_API_KEY',
17
- 'GOOGLE_API_KEY',
18
- 'GROQ_API_KEY',
19
- ] as const;
20
-
21
- export type LLMKeyName = typeof LLM_KEY_NAMES[number];
22
-
23
- export interface KeyDetectionOptions {
24
- /** Additional key→value map to check alongside process.env (e.g. parsed .env.local). */
25
- extraEnv?: Record<string, string | undefined>;
26
- }
27
-
28
- export interface KeyDetectionResult {
29
- /** True if any recognized LLM key is set to a non-empty value. */
30
- hasKey: boolean;
31
- /** Preferred key that was detected, or null. Follows LLM_KEY_NAMES order. */
32
- preferred: LLMKeyName | null;
33
- /** All keys that were detected, in LLM_KEY_NAMES order. */
34
- detected: LLMKeyName[];
35
- }
36
-
37
- function readEnvFileSync(filePath: string): Record<string, string> {
38
- const vars: Record<string, string> = {};
39
- try {
40
- const content = fs.readFileSync(filePath, 'utf-8');
41
- for (const line of content.split('\n')) {
42
- const trimmed = line.trim();
43
- if (!trimmed || trimmed.startsWith('#')) continue;
44
- const eq = trimmed.indexOf('=');
45
- if (eq < 0) continue;
46
- vars[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim().replace(/^['"]|['"]$/g, '');
47
- }
48
- } catch {
49
- /* ignore */
50
- }
51
- return vars;
52
- }
53
-
54
- /** Load an env file into a plain object without mutating process.env. */
55
- export function loadEnvFile(filePath: string): Record<string, string> {
56
- return readEnvFileSync(filePath);
57
- }
58
-
59
- /** Detect whether any recognized LLM API key is set. */
60
- export function detectLLMKey(options: KeyDetectionOptions = {}): KeyDetectionResult {
61
- const extra = options.extraEnv ?? {};
62
- const detected: LLMKeyName[] = [];
63
- for (const name of LLM_KEY_NAMES) {
64
- // Treat empty string as "not set" so an env file value can supply the key when
65
- // the shell has `FOO=` exported. `??` would shadow the env file here because it
66
- // only falls through on null/undefined — matching the old `!! || !!` semantics.
67
- const fromProcess = process.env[name];
68
- const value = (fromProcess && fromProcess.length > 0) ? fromProcess : extra[name];
69
- if (value && value.length > 0) detected.push(name);
70
- }
71
- return {
72
- hasKey: detected.length > 0,
73
- preferred: detected[0] ?? null,
74
- detected,
75
- };
76
- }
77
-
78
- /**
79
- * Human-readable list of providers and signup URLs, used by every "no key" message.
80
- * Must cover every entry in LLM_KEY_NAMES so users see the same set of options across
81
- * preflight, setup, scan, and run.
82
- */
83
- export const LLM_KEY_HINTS: Array<{ name: LLMKeyName; url: string; note?: string }> = [
84
- { name: 'ANTHROPIC_API_KEY', url: 'https://console.anthropic.com/' },
85
- { name: 'OPENAI_API_KEY', url: 'https://platform.openai.com/api-keys' },
86
- { name: 'GEMINI_API_KEY', url: 'https://aistudio.google.com/app/apikey' },
87
- { name: 'GOOGLE_API_KEY', url: 'https://aistudio.google.com/app/apikey', note: 'legacy alias for GEMINI_API_KEY' },
88
- { name: 'GROQ_API_KEY', url: 'https://console.groq.com/keys', note: 'fast free tier' },
89
- ];
@@ -1,63 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
-
4
- interface MigrationSignal {
5
- glob: string;
6
- check: (cwd: string) => boolean;
7
- }
8
-
9
- const MIGRATION_SIGNALS: MigrationSignal[] = [
10
- { glob: 'data/deltas/**', check: c => fs.existsSync(path.join(c, 'data', 'deltas')) },
11
- { glob: 'migrations/**', check: c => fs.existsSync(path.join(c, 'migrations')) },
12
- { glob: 'db/migrate/**', check: c => fs.existsSync(path.join(c, 'db', 'migrate')) },
13
- { glob: 'database/migrations/**', check: c => fs.existsSync(path.join(c, 'database', 'migrations')) },
14
- { glob: 'prisma/migrations/**', check: c => fs.existsSync(path.join(c, 'prisma', 'migrations')) },
15
- { glob: 'alembic/versions/**', check: c => fs.existsSync(path.join(c, 'alembic', 'versions')) },
16
- { glob: 'flyway/**', check: c => fs.existsSync(path.join(c, 'flyway')) },
17
- // *.sql is handled below via readdirSync
18
- ];
19
-
20
- const SCHEMA_FILES = [
21
- 'prisma/schema.prisma',
22
- 'schema.prisma',
23
- 'schema.sql',
24
- 'db/schema.rb',
25
- 'config/schema.xml',
26
- ];
27
-
28
- const INFRA_SIGNALS: Array<{ glob: string; check: (cwd: string) => boolean }> = [
29
- { glob: 'terraform/**', check: c => fs.existsSync(path.join(c, 'terraform')) },
30
- { glob: 'infra/**', check: c => fs.existsSync(path.join(c, 'infra')) },
31
- { glob: '.github/workflows/**', check: c => fs.existsSync(path.join(c, '.github', 'workflows')) },
32
- { glob: 'k8s/**', check: c => fs.existsSync(path.join(c, 'k8s')) },
33
- { glob: 'helm/**', check: c => fs.existsSync(path.join(c, 'helm')) },
34
- ];
35
-
36
- /**
37
- * Scans the project for migration directories, schema files, and infra configs
38
- * and returns glob patterns suitable for `protectedPaths`.
39
- */
40
- export function detectProtectedPaths(cwd: string): string[] {
41
- const found = new Set<string>();
42
-
43
- for (const sig of MIGRATION_SIGNALS) {
44
- if (sig.check(cwd)) found.add(sig.glob);
45
- }
46
-
47
- // Root-level .sql files
48
- try {
49
- if (fs.readdirSync(cwd).some(f => f.endsWith('.sql'))) found.add('*.sql');
50
- } catch { /* ignore */ }
51
-
52
- for (const rel of SCHEMA_FILES) {
53
- if (fs.existsSync(path.join(cwd, rel))) {
54
- found.add(rel.includes('/') ? rel.split('/')[0] + '/**' : rel);
55
- }
56
- }
57
-
58
- for (const sig of INFRA_SIGNALS) {
59
- if (sig.check(cwd)) found.add(sig.glob);
60
- }
61
-
62
- return Array.from(found).sort();
63
- }
@@ -1,74 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import * as path from 'node:path';
3
-
4
- export type Provider = 'anthropic' | 'gemini' | 'openai' | 'groq';
5
-
6
- const PROVIDER_PATTERNS: Record<Provider, RegExp> = {
7
- anthropic: /ANTHROPIC_API_KEY|@anthropic-ai\/sdk|anthropic\.com|claude-[a-z0-9]/gi,
8
- gemini: /GEMINI_API_KEY|GOOGLE_API_KEY|@google\/generative-ai|generativelanguage\.googleapis/gi,
9
- openai: /OPENAI_API_KEY|openai\.com|gpt-[0-9]/gi,
10
- groq: /GROQ_API_KEY|api\.groq\.com/gi,
11
- };
12
-
13
- const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rb']);
14
-
15
- const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'out',
16
- 'coverage', '__pycache__', '.venv', 'venv', 'target', '.gradle', '.cache', '.turbo']);
17
-
18
- function walkSync(dir: string, files: string[] = []): string[] {
19
- let entries: fs.Dirent[];
20
- try {
21
- entries = fs.readdirSync(dir, { withFileTypes: true });
22
- } catch {
23
- return files;
24
- }
25
- for (const entry of entries) {
26
- if (SKIP_DIRS.has(entry.name)) continue;
27
- const full = path.join(dir, entry.name);
28
- if (entry.isDirectory()) {
29
- walkSync(full, files);
30
- } else if (entry.isFile() && SOURCE_EXTENSIONS.has(path.extname(entry.name))) {
31
- files.push(full);
32
- }
33
- }
34
- return files;
35
- }
36
-
37
- export interface ProviderCounts {
38
- anthropic: number;
39
- gemini: number;
40
- openai: number;
41
- groq: number;
42
- }
43
-
44
- /**
45
- * Scans source files under `cwd` and returns per-provider match counts.
46
- * Counts are capped at 1 per file to avoid skewing on generated lock files.
47
- */
48
- export function detectProviderUsage(cwd: string): ProviderCounts {
49
- const counts: ProviderCounts = { anthropic: 0, gemini: 0, openai: 0, groq: 0 };
50
- const files = walkSync(cwd);
51
- for (const file of files) {
52
- let content: string;
53
- try {
54
- content = fs.readFileSync(file, 'utf8');
55
- } catch {
56
- continue;
57
- }
58
- for (const [provider, pattern] of Object.entries(PROVIDER_PATTERNS) as [Provider, RegExp][]) {
59
- pattern.lastIndex = 0;
60
- if (pattern.test(content)) counts[provider]++;
61
- }
62
- }
63
- return counts;
64
- }
65
-
66
- /**
67
- * Returns the provider with the highest usage count, or null if all zero.
68
- */
69
- export function dominantProvider(counts: ProviderCounts): Provider | null {
70
- const entries = Object.entries(counts) as [Provider, number][];
71
- const max = Math.max(...entries.map(([, v]) => v));
72
- if (max === 0) return null;
73
- return entries.find(([, v]) => v === max)![0];
74
- }