@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
package/src/cli/run.ts DELETED
@@ -1,425 +0,0 @@
1
- #!/usr/bin/env node
2
- import * as path from 'node:path';
3
- import * as fs from 'node:fs';
4
-
5
- // Load .env.local / .env so OPENAI_API_KEY etc. are available without shell export
6
- const ENV_FILES = ['.env.local', '.env.dev', '.env.development', '.env'];
7
- for (const f of ENV_FILES) {
8
- const p = path.join(process.cwd(), f);
9
- if (!fs.existsSync(p)) continue;
10
- for (const line of fs.readFileSync(p, 'utf8').split('\n')) {
11
- const t = line.trim();
12
- if (!t || t.startsWith('#')) continue;
13
- const eq = t.indexOf('=');
14
- if (eq < 0) continue;
15
- const key = t.slice(0, eq).trim();
16
- if (!process.env[key]) {
17
- process.env[key] = t.slice(eq + 1).trim().replace(/^['"]|['"]$/g, '');
18
- }
19
- }
20
- break;
21
- }
22
-
23
- import { loadConfig } from '../core/config/loader.ts';
24
- import { loadRulesFromConfig } from '../core/static-rules/registry.ts';
25
- import { resolvePreset } from '../core/config/preset-resolver.ts';
26
- import { mergeConfigs } from '../core/config/preset-resolver.ts';
27
- import { loadAdapter } from '../adapters/loader.ts';
28
- import { runGuardrail } from '../core/pipeline/run.ts';
29
- import { resolveGitTouchedFiles } from '../core/git/touched-files.ts';
30
- import type { RunInput } from '../core/pipeline/run.ts';
31
- import type { ReviewEngine } from '../adapters/review-engine/types.ts';
32
- import type { GuardrailConfig } from '../core/config/types.ts';
33
- import { findPackageRoot } from './_pkg-root.ts';
34
- import { toSarif } from '../formatters/sarif.ts';
35
- import { toJUnit } from '../formatters/junit.ts';
36
- import { loadTriage, filterTriaged } from '../core/persist/triage.ts';
37
- import { emitAnnotations } from '../formatters/github-annotations.ts';
38
- import { detectStack } from '../core/detect/stack.ts';
39
- import { detectProtectedPaths } from '../core/detect/protected-paths.ts';
40
- import { detectGitContext } from '../core/detect/git-context.ts';
41
- import { detectWorkspaces, mapFilesToWorkspaces } from '../core/detect/workspaces.ts';
42
- import { detectProject } from './detector.ts';
43
- import { detectPrNumber, formatComment, postPrComment } from './pr-comment.ts';
44
- import { postReviewComments } from './pr-review-comments.ts';
45
- import { loadIgnoreRules, parseConfigIgnore, applyIgnoreRules } from '../core/ignore/index.ts';
46
- import { detectLLMKey, LLM_KEY_HINTS } from '../core/detect/llm-key.ts';
47
- import { loadCachedFindings, saveCachedFindings, filterNewFindings } from '../core/persist/findings-cache.ts';
48
- import { loadBaseline, filterBaselined } from '../core/persist/baseline.ts';
49
- import { appendCostLog } from '../core/persist/cost-log.ts';
50
- import { postCommitStatus, resolveCommitSha } from '../adapters/vcs-host/commit-status.ts';
51
-
52
- function computeExitCode(findings: { severity: string }[], failOn: string): number {
53
- if (failOn === 'none') return 0;
54
- const fail = failOn === 'warning' ? ['critical', 'warning']
55
- : failOn === 'note' ? ['critical', 'warning', 'note']
56
- : ['critical'];
57
- return findings.some(f => fail.includes(f.severity)) ? 1 : 0;
58
- }
59
-
60
- function readToolVersion(): string {
61
- const root = findPackageRoot(import.meta.url);
62
- if (!root) return 'unknown';
63
- const pkgPath = path.join(root, 'package.json');
64
- return (JSON.parse(fs.readFileSync(pkgPath, 'utf8')) as { version: string }).version;
65
- }
66
-
67
- const C = {
68
- reset: '\x1b[0m',
69
- bold: '\x1b[1m',
70
- dim: '\x1b[2m',
71
- green: '\x1b[32m',
72
- yellow: '\x1b[33m',
73
- red: '\x1b[31m',
74
- cyan: '\x1b[36m',
75
- };
76
-
77
- function fmt(color: keyof typeof C, text: string): string {
78
- return `${C[color]}${text}${C.reset}`;
79
- }
80
-
81
- export interface RunCommandOptions {
82
- cwd?: string;
83
- configPath?: string;
84
- base?: string; // git base ref (default HEAD~1)
85
- files?: string[]; // explicit file list (skips git detection)
86
- dryRun?: boolean; // skip review, print what would run
87
- diff?: boolean; // use diff strategy (send git hunks instead of full files)
88
- delta?: boolean; // only report findings not present in last run's baseline
89
- newOnly?: boolean; // only report findings not in committed .guardrail-baseline.json
90
- failOn?: 'critical' | 'warning' | 'note' | 'none'; // severity threshold for exit 1
91
- inlineComments?: boolean; // post per-line review comments on the PR diff
92
- format?: 'text' | 'sarif' | 'junit';
93
- outputPath?: string;
94
- postComments?: boolean; // post/update summary comment on the open PR
95
- skipReview?: boolean; // skip tests and review phases (static rules only)
96
- }
97
-
98
- /**
99
- * Returns an exit code (0 = pass/warn, 1 = fail/error).
100
- * Never calls process.exit directly — caller decides when to exit.
101
- */
102
- export async function runCommand(options: RunCommandOptions = {}): Promise<number> {
103
- const cwd = options.cwd ?? process.cwd();
104
- const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
105
-
106
- // Load + merge config (graceful zero-config fallback)
107
- let config: GuardrailConfig;
108
- if (!fs.existsSync(configPath)) {
109
- console.log(fmt('dim', `[run] No guardrail.config.yaml found — using defaults. Run \`npx guardrail setup\` to configure.`));
110
- config = { configVersion: 1, reviewEngine: { adapter: 'auto' }, testCommand: null };
111
- } else {
112
- try {
113
- const userConfig = await loadConfig(configPath);
114
- if (userConfig.preset) {
115
- const preset = await resolvePreset(userConfig.preset);
116
- config = mergeConfigs(preset.config, userConfig);
117
- } else {
118
- config = userConfig;
119
- }
120
- } catch (err) {
121
- console.error(fmt('red', `[run] Config error: ${err instanceof Error ? err.message : String(err)}`));
122
- return 1;
123
- }
124
- }
125
-
126
- // Fill in missing config fields from auto-detection (track what was auto-detected for logging)
127
- const autoDetected: string[] = [];
128
-
129
- if (!config.stack) {
130
- const detected = detectStack(cwd);
131
- if (detected) { config = { ...config, stack: detected }; autoDetected.push(`stack: ${detected}`); }
132
- }
133
- if (!config.protectedPaths || config.protectedPaths.length === 0) {
134
- const detected = detectProtectedPaths(cwd);
135
- if (detected.length > 0) {
136
- config = { ...config, protectedPaths: detected };
137
- autoDetected.push(`protected: ${detected.slice(0, 3).join(', ')}${detected.length > 3 ? ` +${detected.length - 3} more` : ''}`);
138
- }
139
- }
140
- if (config.testCommand === undefined) {
141
- const detected = detectProject(cwd).testCommand;
142
- config = { ...config, testCommand: detected };
143
- autoDetected.push(`test: ${detected}`);
144
- }
145
-
146
- // Monorepo workspace detection
147
- const workspaces = detectWorkspaces(cwd);
148
- if (workspaces && workspaces.length > 0) {
149
- autoDetected.push(`workspaces: ${workspaces.length} (${workspaces.map(w => w.name).slice(0, 3).join(', ')}${workspaces.length > 3 ? ` +${workspaces.length - 3} more` : ''})`);
150
- }
151
-
152
- const gitCtx = detectGitContext(cwd);
153
-
154
- // Resolve touched files
155
- const touchedFiles = options.files ?? resolveGitTouchedFiles({ cwd, base: options.base });
156
- if (touchedFiles.length === 0) {
157
- console.log(fmt('yellow', '[run] No changed files detected — nothing to review.'));
158
- console.log(fmt('dim', ' Pass --base <ref> to compare against a different branch/commit.'));
159
- return 0;
160
- }
161
-
162
- console.log(`\n${fmt('bold', '[run]')} ${fmt('dim', configPath)}`);
163
- console.log(`${fmt('dim', ` ${touchedFiles.length} changed file(s):`)} ${touchedFiles.slice(0, 5).join(', ')}${touchedFiles.length > 5 ? ` … +${touchedFiles.length - 5} more` : ''}`);
164
- if (gitCtx.summary) {
165
- console.log(fmt('dim', ` ${gitCtx.summary}`));
166
- }
167
- if (autoDetected.length > 0) {
168
- console.log(fmt('dim', ` auto-detected: ${autoDetected.join(' | ')}`));
169
- }
170
-
171
- if (options.dryRun) {
172
- console.log(fmt('yellow', '\n[run] Dry run — skipping pipeline execution.\n'));
173
- return 0;
174
- }
175
-
176
- // Load review engine (optional — skip gracefully if no API key configured)
177
- let reviewEngine: ReviewEngine | undefined;
178
- if (config.reviewEngine) {
179
- const ref = typeof config.reviewEngine === 'string' ? config.reviewEngine : config.reviewEngine.adapter;
180
- if (!detectLLMKey().hasKey && ['auto', 'claude', 'gemini', 'codex', 'openai-compatible'].includes(ref)) {
181
- console.log(fmt('yellow', '\n [run] No LLM API key — set one of:'));
182
- for (const { name, url, note } of LLM_KEY_HINTS) {
183
- const suffix = note ? ` (${note})` : '';
184
- console.log(fmt('dim', ` ${name.padEnd(18)} ${url}${suffix}`));
185
- }
186
- console.log('');
187
- } else {
188
- try {
189
- reviewEngine = await loadAdapter<ReviewEngine>({
190
- point: 'review-engine',
191
- ref,
192
- options: typeof config.reviewEngine === 'string' ? undefined : config.reviewEngine.options,
193
- });
194
- } catch (err) {
195
- console.error(fmt('yellow', ` [run] Could not load review engine (${ref}): ${err instanceof Error ? err.message : String(err)} — skipping`));
196
- }
197
- }
198
- }
199
-
200
- // Load static rules from config
201
- const staticRules = config.staticRules && config.staticRules.length > 0
202
- ? await loadRulesFromConfig(config.staticRules)
203
- : [];
204
-
205
- // Apply --diff flag: override reviewStrategy to 'diff'
206
- if (options.diff && config.reviewStrategy !== 'diff') {
207
- config = { ...config, reviewStrategy: 'diff' };
208
- }
209
-
210
- // Pre-run cost estimate
211
- if (config.cost?.estimateBeforeRun) {
212
- const totalChars = touchedFiles.reduce((sum, f) => {
213
- try { return sum + fs.statSync(f).size; } catch { return sum; }
214
- }, 0);
215
- const estTokens = Math.round(totalChars / 4);
216
- const estCost = estTokens / 1_000_000 * 3.0; // rough: $3/M tokens (Sonnet)
217
- const cap = config.cost?.maxPerRun;
218
- console.log(fmt('dim', ` [run] estimated: ~${estTokens.toLocaleString()} tokens, ~$${estCost.toFixed(4)}`
219
- + (cap ? ` (cap: $${cap})` : '')));
220
- }
221
-
222
- // Execute pipeline
223
- const input: RunInput = {
224
- touchedFiles,
225
- config,
226
- reviewEngine,
227
- staticRules,
228
- cwd,
229
- gitSummary: gitCtx.summary ?? undefined,
230
- base: options.base,
231
- skipReview: options.skipReview,
232
- };
233
-
234
- // Post pending commit status (best-effort — never fatal)
235
- const commitSha = resolveCommitSha(cwd);
236
- if (commitSha) {
237
- postCommitStatus({ sha: commitSha, state: 'pending', description: `Reviewing ${touchedFiles.length} file(s)…`, cwd });
238
- }
239
-
240
- console.log('');
241
- const result = await runGuardrail(input);
242
-
243
- // Apply .guardrail-ignore + config ignore: rules
244
- const ignoreRules = [...loadIgnoreRules(cwd), ...parseConfigIgnore(config.ignore)];
245
- if (ignoreRules.length > 0) {
246
- const before = result.allFindings.length;
247
- result.allFindings = applyIgnoreRules(result.allFindings, ignoreRules);
248
- for (const phase of result.phases) {
249
- phase.findings = applyIgnoreRules(phase.findings, ignoreRules);
250
- }
251
- const suppressed = before - result.allFindings.length;
252
- if (suppressed > 0) {
253
- console.log(fmt('dim', ` [run] ${suppressed} finding${suppressed !== 1 ? 's' : ''} suppressed by .guardrail-ignore`));
254
- }
255
- }
256
-
257
- // Delta mode: filter to only new findings vs last run's cache, then persist
258
- if (options.delta) {
259
- const cached = loadCachedFindings(cwd);
260
- const before = result.allFindings.length;
261
- result.allFindings = filterNewFindings(result.allFindings, cached);
262
- for (const phase of result.phases) {
263
- phase.findings = filterNewFindings(phase.findings, cached);
264
- }
265
- const existing = before - result.allFindings.length;
266
- if (existing > 0) {
267
- console.log(fmt('dim', ` [run] ${existing} pre-existing finding${existing !== 1 ? 's' : ''} hidden (--delta mode)`));
268
- }
269
- }
270
-
271
- // --new-only / policy.newOnly: filter against committed .guardrail-baseline.json
272
- const policy = config.policy ?? {};
273
- const newOnly = options.newOnly ?? policy.newOnly ?? false;
274
- if (newOnly) {
275
- const baseline = loadBaseline(cwd, policy.baselinePath);
276
- if (baseline) {
277
- const { newFindings, baselinedCount } = filterBaselined(result.allFindings, baseline);
278
- result.allFindings = newFindings;
279
- for (const phase of result.phases) {
280
- phase.findings = filterBaselined(phase.findings, baseline).newFindings;
281
- }
282
- if (baselinedCount > 0) {
283
- console.log(fmt('dim', ` [run] ${baselinedCount} baselined finding${baselinedCount !== 1 ? 's' : ''} suppressed (--new-only)`));
284
- }
285
- } else {
286
- console.log(fmt('yellow', ' [run] --new-only: no .guardrail-baseline.json found — showing all findings'));
287
- console.log(fmt('dim', ' Run `guardrail baseline create` after first scan to pin the baseline'));
288
- }
289
- }
290
-
291
- // Triage filter: suppress accepted-risk / false-positive findings
292
- const triageStore = loadTriage(cwd);
293
- if (triageStore.entries.length > 0) {
294
- const { active, triageCount } = filterTriaged(result.allFindings, triageStore);
295
- if (triageCount > 0) {
296
- result.allFindings = active;
297
- for (const phase of result.phases) {
298
- phase.findings = filterTriaged(phase.findings, triageStore).active;
299
- }
300
- console.log(fmt('dim', ` [run] ${triageCount} triaged finding${triageCount !== 1 ? 's' : ''} suppressed (accepted-risk / false-positive)`));
301
- }
302
- }
303
-
304
- // Always persist the unfiltered findings as the run cache
305
- saveCachedFindings(cwd, result.allFindings);
306
-
307
- // Append to per-run cost log
308
- const reviewPhase = result.phases.find(p => p.phase === 'review') as { usage?: { input: number; output: number } } | undefined;
309
- appendCostLog(cwd, {
310
- timestamp: new Date().toISOString(),
311
- files: touchedFiles.length,
312
- inputTokens: reviewPhase?.usage?.input ?? 0,
313
- outputTokens: reviewPhase?.usage?.output ?? 0,
314
- costUSD: result.totalCostUSD ?? 0,
315
- durationMs: result.durationMs,
316
- });
317
-
318
- // emitAnnotations is a no-op unless GITHUB_ACTIONS=true
319
- emitAnnotations(result.allFindings);
320
-
321
- // Write SARIF output if requested
322
- if (options.format === 'sarif' && options.outputPath) {
323
- const sarif = toSarif(result, { toolVersion: readToolVersion(), cwd });
324
- fs.mkdirSync(path.dirname(path.resolve(options.outputPath)), { recursive: true });
325
- fs.writeFileSync(options.outputPath, JSON.stringify(sarif, null, 2), 'utf8');
326
- console.log(fmt('dim', `[run] SARIF written to ${options.outputPath}`));
327
- }
328
-
329
- // Write JUnit XML output if requested
330
- if (options.format === 'junit' && options.outputPath) {
331
- const junit = toJUnit(result);
332
- fs.mkdirSync(path.dirname(path.resolve(options.outputPath)), { recursive: true });
333
- fs.writeFileSync(options.outputPath, junit, 'utf8');
334
- console.log(fmt('dim', `[run] JUnit XML written to ${options.outputPath}`));
335
- }
336
-
337
- // Post inline PR review comments if requested
338
- if (options.inlineComments) {
339
- const pr = detectPrNumber(cwd);
340
- if (!pr) {
341
- console.log(fmt('yellow', ' [run] --inline-comments: no open PR found — skipping'));
342
- } else {
343
- try {
344
- const { posted, skipped } = await postReviewComments(pr, result.allFindings, cwd);
345
- console.log(fmt('dim', ` [run] PR #${pr} inline review: ${posted} comment${posted !== 1 ? 's' : ''} posted${skipped > 0 ? `, ${skipped} skipped (no line number)` : ''}`));
346
- } catch (err) {
347
- console.error(fmt('yellow', ` [run] Failed to post inline comments: ${err instanceof Error ? err.message : String(err)}`));
348
- }
349
- }
350
- }
351
-
352
- // Post PR comment if requested
353
- if (options.postComments) {
354
- const pr = detectPrNumber(cwd);
355
- if (!pr) {
356
- console.log(fmt('yellow', ' [run] --post-comments: no open PR found — skipping comment'));
357
- } else {
358
- try {
359
- const body = formatComment(result, config, gitCtx, touchedFiles.length);
360
- const { action } = await postPrComment(pr, body, cwd);
361
- console.log(fmt('dim', ` [run] PR #${pr} comment ${action}`));
362
- } catch (err) {
363
- console.error(fmt('yellow', ` [run] Failed to post PR comment: ${err instanceof Error ? err.message : String(err)}`));
364
- }
365
- }
366
- }
367
-
368
- // Print phase summaries
369
- for (const phase of result.phases) {
370
- const icon = phase.status === 'pass' ? fmt('green', '✓') :
371
- phase.status === 'skip' ? fmt('dim', '–') :
372
- phase.status === 'warn' ? fmt('yellow', '!') : fmt('red', '✗');
373
- const phaseLabel = phase.phase.padEnd(14);
374
- const findingCount = phase.findings.length;
375
- const extra = findingCount > 0 ? fmt('dim', ` (${findingCount} finding${findingCount !== 1 ? 's' : ''})`) : '';
376
- const dur = 'durationMs' in phase ? fmt('dim', ` ${phase.durationMs}ms`) : '';
377
- console.log(` ${icon} ${phaseLabel}${extra}${dur}`);
378
-
379
- // Print critical/warning findings inline
380
- for (const f of phase.findings) {
381
- if (f.severity === 'critical' || f.severity === 'warning') {
382
- const sev = f.severity === 'critical' ? fmt('red', 'CRITICAL') : fmt('yellow', 'WARNING ');
383
- console.log(` ${sev} ${f.file}${f.line ? `:${f.line}` : ''} — ${f.message}`);
384
- if (f.suggestion) console.log(fmt('dim', ` ${f.suggestion}`));
385
- }
386
- }
387
- }
388
-
389
- // Cost summary
390
- if (result.totalCostUSD !== undefined) {
391
- console.log(`\n ${fmt('dim', `cost: $${result.totalCostUSD.toFixed(4)}`)} ${fmt('dim', `${result.durationMs}ms total`)}`);
392
- } else {
393
- console.log(`\n ${fmt('dim', `${result.durationMs}ms total`)}`);
394
- }
395
-
396
- // Post final commit status
397
- if (commitSha) {
398
- const critical = result.allFindings.filter(f => f.severity === 'critical').length;
399
- const warnings = result.allFindings.filter(f => f.severity === 'warning').length;
400
- const state = result.status === 'fail' ? 'failure' : 'success';
401
- const desc = result.status === 'pass'
402
- ? 'All checks passed'
403
- : result.status === 'warn'
404
- ? `Passed with ${warnings} warning${warnings !== 1 ? 's' : ''}`
405
- : `${critical} critical finding${critical !== 1 ? 's' : ''}`;
406
- postCommitStatus({ sha: commitSha, state, description: desc, cwd });
407
- }
408
-
409
- // Final verdict — apply policy.failOn threshold
410
- const failOn = options.failOn ?? policy.failOn ?? 'critical';
411
- const exitCode = computeExitCode(result.allFindings, failOn);
412
-
413
- console.log('');
414
- if (exitCode === 0 && result.status !== 'pass') {
415
- const reason = failOn === 'none' ? ' (policy: fail-on=none)' : ` (policy: fail-on=${failOn})`;
416
- console.log(fmt('yellow', `[run] ! Passed with findings${reason}\n`));
417
- } else if (result.status === 'pass') {
418
- console.log(fmt('green', '[run] ✓ All phases passed\n'));
419
- } else if (result.status === 'warn') {
420
- console.log(fmt('yellow', '[run] ! Passed with warnings\n'));
421
- } else {
422
- console.log(fmt('red', '[run] ✗ Pipeline failed — see findings above\n'));
423
- }
424
- return exitCode;
425
- }
package/src/cli/scan.ts DELETED
@@ -1,233 +0,0 @@
1
- import * as path from 'node:path';
2
- import * as fs from 'node:fs';
3
- import { loadConfig } from '../core/config/loader.ts';
4
- import { loadAdapter } from '../adapters/loader.ts';
5
- import type { ReviewEngine } from '../adapters/review-engine/types.ts';
6
- import { runReviewPhase } from '../core/pipeline/review-phase.ts';
7
- import { detectStack } from '../core/detect/stack.ts';
8
- import { loadIgnoreRules, parseConfigIgnore, applyIgnoreRules } from '../core/ignore/index.ts';
9
- import { saveCachedFindings } from '../core/persist/findings-cache.ts';
10
- import type { GuardrailConfig } from '../core/config/types.ts';
11
- import { detectLLMKey, LLM_KEY_HINTS } from '../core/detect/llm-key.ts';
12
-
13
- const C = {
14
- reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
15
- green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m',
16
- };
17
- const fmt = (c: keyof typeof C, t: string) => `${C[c]}${t}${C.reset}`;
18
-
19
- const IGNORED_DIRS = new Set([
20
- 'node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'coverage',
21
- '.guardrail-cache', '.autopilot', '__pycache__', '.venv', 'vendor',
22
- ]);
23
-
24
- const CODE_EXTS = new Set([
25
- '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
26
- '.py', '.go', '.rb', '.rs', '.java', '.kt', '.swift',
27
- '.c', '.cpp', '.h', '.cs', '.php',
28
- '.sql', '.sh', '.bash', '.yaml', '.yml', '.json', '.toml',
29
- ]);
30
-
31
- function collectFiles(target: string, cwd: string): string[] {
32
- const abs = path.isAbsolute(target) ? target : path.resolve(cwd, target);
33
- if (!fs.existsSync(abs)) return [];
34
-
35
- const stat = fs.statSync(abs);
36
- if (stat.isFile()) return [abs];
37
-
38
- const results: string[] = [];
39
- function walk(dir: string) {
40
- for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
41
- if (IGNORED_DIRS.has(entry.name)) continue;
42
- const full = path.join(dir, entry.name);
43
- if (entry.isDirectory()) {
44
- walk(full);
45
- } else if (entry.isFile() && CODE_EXTS.has(path.extname(entry.name))) {
46
- results.push(full);
47
- }
48
- }
49
- }
50
- walk(abs);
51
- return results;
52
- }
53
-
54
- function collectAllFiles(cwd: string): string[] {
55
- return collectFiles(cwd, cwd);
56
- }
57
-
58
- export interface ScanCommandOptions {
59
- cwd?: string;
60
- configPath?: string;
61
- targets?: string[]; // explicit paths/dirs to scan
62
- all?: boolean; // scan entire codebase
63
- ask?: string; // targeted question to inject into review prompt
64
- focus?: 'security' | 'logic' | 'performance' | 'brand' | 'all';
65
- dryRun?: boolean;
66
- }
67
-
68
- export async function runScan(options: ScanCommandOptions = {}): Promise<number> {
69
- const cwd = options.cwd ?? process.cwd();
70
- const configPath = options.configPath ?? path.join(cwd, 'guardrail.config.yaml');
71
-
72
- let config: GuardrailConfig = { configVersion: 1 };
73
- if (fs.existsSync(configPath)) {
74
- const loaded = await loadConfig(configPath);
75
- if (loaded) config = loaded;
76
- }
77
-
78
- // Collect files
79
- let files: string[];
80
- if (options.all) {
81
- files = collectAllFiles(cwd);
82
- } else if (options.targets && options.targets.length > 0) {
83
- files = options.targets.flatMap(t => collectFiles(t, cwd));
84
- } else {
85
- console.error(fmt('red', '[scan] Specify a path, --all, or use `guardrail run` for git-changed files'));
86
- console.error(fmt('dim', ' Examples:'));
87
- console.error(fmt('dim', ' guardrail scan src/auth/'));
88
- console.error(fmt('dim', ' guardrail scan --all'));
89
- console.error(fmt('dim', ' guardrail scan --ask "is there SQL injection?" src/db/'));
90
- return 1;
91
- }
92
-
93
- // Deduplicate
94
- files = [...new Set(files)];
95
-
96
- if (files.length === 0) {
97
- console.log(fmt('yellow', '[scan] No code files found at the specified path(s)'));
98
- return 0;
99
- }
100
-
101
- if (options.dryRun) {
102
- console.log(fmt('bold', `[scan] Would scan ${files.length} file(s):`));
103
- for (const f of files) console.log(fmt('dim', ` ${path.relative(cwd, f)}`));
104
- return 0;
105
- }
106
-
107
- // Auto-detect stack if not in config
108
- if (!config.stack) {
109
- config = { ...config, stack: detectStack(cwd) ?? undefined };
110
- }
111
-
112
- // Build review engine
113
- if (!detectLLMKey().hasKey) {
114
- console.error(fmt('red', '[scan] No LLM API key — set one of:'));
115
- for (const { name, url, note } of LLM_KEY_HINTS) {
116
- const suffix = note ? ` (${note})` : '';
117
- console.error(fmt('dim', ` ${name.padEnd(18)} ${url}${suffix}`));
118
- }
119
- return 1;
120
- }
121
- const engineRef = typeof config.reviewEngine === 'string' ? config.reviewEngine
122
- : (config.reviewEngine?.adapter ?? 'auto');
123
- let engine: ReviewEngine;
124
- try {
125
- engine = await loadAdapter<ReviewEngine>({
126
- point: 'review-engine',
127
- ref: engineRef,
128
- options: typeof config.reviewEngine === 'object' ? config.reviewEngine.options as Record<string, unknown> : undefined,
129
- });
130
- } catch (err) {
131
- console.error(fmt('red', `[scan] Could not load review engine: ${err instanceof Error ? err.message : String(err)}`));
132
- return 1;
133
- }
134
-
135
- const focusLabel = options.focus && options.focus !== 'all' ? options.focus : null;
136
- const relFiles = files.map(f => path.relative(cwd, f));
137
-
138
- console.log('');
139
- const scopeDesc = options.all ? 'entire codebase' : relFiles.slice(0, 3).join(', ') + (relFiles.length > 3 ? ` +${relFiles.length - 3} more` : '');
140
- console.log(fmt('bold', `[scan]`) + fmt('dim', ` ${files.length} file(s) — ${scopeDesc}`));
141
- if (options.ask) console.log(fmt('dim', ` question: ${options.ask}`));
142
- if (focusLabel) console.log(fmt('dim', ` focus: ${focusLabel}`));
143
- console.log('');
144
-
145
- // Build a focused git summary / prompt context
146
- const focusHint = buildFocusHint(options.ask, focusLabel);
147
-
148
- const result = await runReviewPhase({
149
- touchedFiles: relFiles,
150
- engine,
151
- config,
152
- cwd,
153
- gitSummary: focusHint,
154
- });
155
-
156
- // Apply ignore rules
157
- const ignoreRules = [...loadIgnoreRules(cwd), ...parseConfigIgnore(config.ignore)];
158
- const findings = applyIgnoreRules(result.findings, ignoreRules);
159
-
160
- // Print results
161
- if (findings.length === 0 && options.ask && result.rawOutputs && result.rawOutputs.length > 0) {
162
- // --ask returned prose rather than structured findings — surface raw response
163
- console.log(fmt('cyan', `Answer:`));
164
- for (const raw of result.rawOutputs) {
165
- // Strip markdown fences and the ## Findings / ## Review Summary headers if present
166
- const cleaned = raw.replace(/^##\s+Review Summary\s*\n/gm, '').replace(/^##\s+Findings\s*\n/gm, '').trim();
167
- console.log(cleaned);
168
- }
169
- console.log('');
170
- } else if (findings.length === 0) {
171
- console.log(fmt('green', '✓ No findings'));
172
- } else {
173
- const critical = findings.filter(f => f.severity === 'critical');
174
- const warnings = findings.filter(f => f.severity === 'warning');
175
- const notes = findings.filter(f => f.severity === 'note');
176
-
177
- if (critical.length > 0) {
178
- console.log(fmt('red', `🚨 ${critical.length} critical`));
179
- for (const f of critical) {
180
- const loc = f.file && f.file !== '<unspecified>' ? fmt('dim', `${f.file}${f.line ? `:${f.line}` : ''}`) + ' ' : '';
181
- console.log(` ${loc}${f.message}`);
182
- if (f.suggestion) console.log(fmt('dim', ` → ${f.suggestion}`));
183
- }
184
- console.log('');
185
- }
186
- if (warnings.length > 0) {
187
- console.log(fmt('yellow', `⚠ ${warnings.length} warning${warnings.length !== 1 ? 's' : ''}`));
188
- for (const f of warnings) {
189
- const loc = f.file && f.file !== '<unspecified>' ? fmt('dim', `${f.file}${f.line ? `:${f.line}` : ''}`) + ' ' : '';
190
- console.log(` ${loc}${f.message}`);
191
- if (f.suggestion) console.log(fmt('dim', ` → ${f.suggestion}`));
192
- }
193
- console.log('');
194
- }
195
- if (notes.length > 0) {
196
- console.log(fmt('dim', `ℹ ${notes.length} note${notes.length !== 1 ? 's' : ''}`));
197
- for (const f of notes) {
198
- const loc = f.file && f.file !== '<unspecified>' ? `${f.file}${f.line ? `:${f.line}` : ''} ` : '';
199
- console.log(fmt('dim', ` ${loc}${f.message}`));
200
- }
201
- console.log('');
202
- }
203
- }
204
-
205
- // Persist findings so `guardrail fix` can read them
206
- saveCachedFindings(cwd, findings);
207
-
208
- if (result.costUSD !== undefined) {
209
- console.log(fmt('dim', ` $${result.costUSD.toFixed(4)} · ${result.durationMs}ms`));
210
- }
211
-
212
- const fixable = findings.filter(f => f.severity === 'critical' || f.severity === 'warning');
213
- if (fixable.length > 0) {
214
- console.log(fmt('dim', ` → run \`guardrail fix\` to auto-fix ${fixable.length} finding${fixable.length !== 1 ? 's' : ''}`));
215
- }
216
-
217
- return findings.some(f => f.severity === 'critical') ? 1 : 0;
218
- }
219
-
220
- function buildFocusHint(ask: string | undefined, focus: string | null): string {
221
- const parts: string[] = [];
222
- if (ask) {
223
- parts.push(
224
- `TARGETED QUESTION (required): The reviewer specifically wants to know: "${ask}". ` +
225
- `You MUST answer this question using the structured findings format. ` +
226
- `Even if no issues are found, output at least one ### [NOTE] finding that directly answers the question.`,
227
- );
228
- }
229
- if (focus === 'security') parts.push('Focus: security vulnerabilities, auth issues, injection risks, data exposure');
230
- if (focus === 'logic') parts.push('Focus: logic bugs, incorrect behavior, edge cases, null handling, async errors');
231
- if (focus === 'performance') parts.push('Focus: performance issues, N+1 queries, blocking I/O, memory leaks');
232
- return parts.join(' | ');
233
- }