@delegance/claude-autopilot 5.0.0-alpha.2 → 5.0.0-alpha.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 (294) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/bin/_launcher.js +45 -2
  3. package/dist/presets/go/rules/go-sql-injection.js +60 -0
  4. package/dist/presets/go/rules/go-sql-injection.js.map +1 -0
  5. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js +37 -0
  6. package/dist/presets/nextjs-supabase/rules/supabase-rls-bypass.js.map +1 -0
  7. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js +49 -0
  8. package/dist/presets/python-fastapi/rules/fastapi-missing-auth.js.map +1 -0
  9. package/dist/presets/rails-postgres/rules/rails-sql-injection.js +39 -0
  10. package/dist/presets/rails-postgres/rules/rails-sql-injection.js.map +1 -0
  11. package/dist/presets/t3/rules/t3-server-only.js +34 -0
  12. package/dist/presets/t3/rules/t3-server-only.js.map +1 -0
  13. package/dist/src/adapters/base.js +8 -0
  14. package/dist/src/adapters/base.js.map +1 -0
  15. package/dist/src/adapters/council/claude.js +40 -0
  16. package/dist/src/adapters/council/claude.js.map +1 -0
  17. package/dist/src/adapters/council/openai.js +39 -0
  18. package/dist/src/adapters/council/openai.js.map +1 -0
  19. package/dist/src/adapters/council/types.js +2 -0
  20. package/dist/src/adapters/council/types.js.map +1 -0
  21. package/dist/src/adapters/loader.js +92 -0
  22. package/dist/src/adapters/loader.js.map +1 -0
  23. package/dist/src/adapters/migration-runner/supabase.js +50 -0
  24. package/dist/src/adapters/migration-runner/supabase.js.map +1 -0
  25. package/dist/src/adapters/migration-runner/types.js +2 -0
  26. package/dist/src/adapters/migration-runner/types.js.map +1 -0
  27. package/dist/src/adapters/review-bot-parser/cursor.js +12 -0
  28. package/dist/src/adapters/review-bot-parser/cursor.js.map +1 -0
  29. package/dist/src/adapters/review-bot-parser/declarative-base.js +46 -0
  30. package/dist/src/adapters/review-bot-parser/declarative-base.js.map +1 -0
  31. package/dist/src/adapters/review-bot-parser/types.js +2 -0
  32. package/dist/src/adapters/review-bot-parser/types.js.map +1 -0
  33. package/dist/src/adapters/review-engine/auto.js +75 -0
  34. package/dist/src/adapters/review-engine/auto.js.map +1 -0
  35. package/dist/src/adapters/review-engine/claude.js +87 -0
  36. package/dist/src/adapters/review-engine/claude.js.map +1 -0
  37. package/dist/src/adapters/review-engine/codex.js +73 -0
  38. package/dist/src/adapters/review-engine/codex.js.map +1 -0
  39. package/dist/src/adapters/review-engine/gemini.js +92 -0
  40. package/dist/src/adapters/review-engine/gemini.js.map +1 -0
  41. package/dist/src/adapters/review-engine/openai-compatible.js +84 -0
  42. package/dist/src/adapters/review-engine/openai-compatible.js.map +1 -0
  43. package/dist/src/adapters/review-engine/parse-output.js +65 -0
  44. package/dist/src/adapters/review-engine/parse-output.js.map +1 -0
  45. package/dist/src/adapters/review-engine/prompt-builder.js +18 -0
  46. package/dist/src/adapters/review-engine/prompt-builder.js.map +1 -0
  47. package/dist/src/adapters/review-engine/types.js +2 -0
  48. package/dist/src/adapters/review-engine/types.js.map +1 -0
  49. package/dist/src/adapters/vcs-host/commit-status.js +24 -0
  50. package/dist/src/adapters/vcs-host/commit-status.js.map +1 -0
  51. package/dist/src/adapters/vcs-host/github.js +73 -0
  52. package/dist/src/adapters/vcs-host/github.js.map +1 -0
  53. package/dist/src/adapters/vcs-host/types.js +2 -0
  54. package/dist/src/adapters/vcs-host/types.js.map +1 -0
  55. package/dist/src/cli/autoregress-bridge.js +23 -0
  56. package/dist/src/cli/autoregress-bridge.js.map +1 -0
  57. package/dist/src/cli/baseline.js +110 -0
  58. package/dist/src/cli/baseline.js.map +1 -0
  59. package/dist/src/cli/ci.js +31 -0
  60. package/dist/src/cli/ci.js.map +1 -0
  61. package/dist/src/cli/costs.js +70 -0
  62. package/dist/src/cli/costs.js.map +1 -0
  63. package/dist/src/cli/council.js +75 -0
  64. package/dist/src/cli/council.js.map +1 -0
  65. package/dist/src/cli/detector.js +83 -0
  66. package/dist/src/cli/detector.js.map +1 -0
  67. package/dist/src/cli/explain.js +177 -0
  68. package/dist/src/cli/explain.js.map +1 -0
  69. package/dist/src/cli/fix.js +215 -0
  70. package/dist/src/cli/fix.js.map +1 -0
  71. package/dist/src/cli/hook.js +122 -0
  72. package/dist/src/cli/hook.js.map +1 -0
  73. package/dist/src/cli/ignore-helper.js +98 -0
  74. package/dist/src/cli/ignore-helper.js.map +1 -0
  75. package/dist/src/cli/index.js +594 -0
  76. package/dist/src/cli/index.js.map +1 -0
  77. package/dist/src/cli/init.js +88 -0
  78. package/dist/src/cli/init.js.map +1 -0
  79. package/dist/src/cli/lsp.js +177 -0
  80. package/dist/src/cli/lsp.js.map +1 -0
  81. package/dist/src/cli/mcp.js +174 -0
  82. package/dist/src/cli/mcp.js.map +1 -0
  83. package/dist/src/cli/migrate-v4.js +336 -0
  84. package/dist/src/cli/migrate-v4.js.map +1 -0
  85. package/dist/src/cli/pr-comment.js +120 -0
  86. package/dist/src/cli/pr-comment.js.map +1 -0
  87. package/dist/src/cli/pr-desc.js +136 -0
  88. package/dist/src/cli/pr-desc.js.map +1 -0
  89. package/dist/src/cli/pr-review-comments.js +73 -0
  90. package/dist/src/cli/pr-review-comments.js.map +1 -0
  91. package/dist/src/cli/pr.js +63 -0
  92. package/dist/src/cli/pr.js.map +1 -0
  93. package/dist/src/cli/preflight.js +209 -0
  94. package/dist/src/cli/preflight.js.map +1 -0
  95. package/dist/src/cli/report.js +162 -0
  96. package/dist/src/cli/report.js.map +1 -0
  97. package/dist/src/cli/run.js +392 -0
  98. package/dist/src/cli/run.js.map +1 -0
  99. package/dist/src/cli/scan.js +211 -0
  100. package/dist/src/cli/scan.js.map +1 -0
  101. package/dist/src/cli/setup.js +169 -0
  102. package/dist/src/cli/setup.js.map +1 -0
  103. package/dist/src/cli/test-gen.js +112 -0
  104. package/dist/src/cli/test-gen.js.map +1 -0
  105. package/dist/src/cli/triage.js +119 -0
  106. package/dist/src/cli/triage.js.map +1 -0
  107. package/dist/src/cli/watch.js +160 -0
  108. package/dist/src/cli/watch.js.map +1 -0
  109. package/dist/src/cli/worker.js +112 -0
  110. package/dist/src/cli/worker.js.map +1 -0
  111. package/dist/src/core/cache/cached-engine.js +30 -0
  112. package/dist/src/core/cache/cached-engine.js.map +1 -0
  113. package/dist/src/core/cache/review-cache.js +52 -0
  114. package/dist/src/core/cache/review-cache.js.map +1 -0
  115. package/dist/src/core/chunking/index.js +88 -0
  116. package/dist/src/core/chunking/index.js.map +1 -0
  117. package/dist/src/core/chunking/risk-ranker.js +49 -0
  118. package/dist/src/core/chunking/risk-ranker.js.map +1 -0
  119. package/dist/src/core/config/loader.js +47 -0
  120. package/dist/src/core/config/loader.js.map +1 -0
  121. package/dist/src/core/config/preset-resolver.js +38 -0
  122. package/dist/src/core/config/preset-resolver.js.map +1 -0
  123. package/dist/src/core/config/schema.js +182 -0
  124. package/dist/src/core/config/schema.js.map +1 -0
  125. package/dist/src/core/config/types.js +2 -0
  126. package/dist/src/core/config/types.js.map +1 -0
  127. package/dist/src/core/council/config.js +54 -0
  128. package/dist/src/core/council/config.js.map +1 -0
  129. package/dist/src/core/council/context.js +17 -0
  130. package/dist/src/core/council/context.js.map +1 -0
  131. package/dist/src/core/council/runner.js +59 -0
  132. package/dist/src/core/council/runner.js.map +1 -0
  133. package/dist/src/core/council/types.js +2 -0
  134. package/dist/src/core/council/types.js.map +1 -0
  135. package/dist/src/core/detect/git-context.js +20 -0
  136. package/dist/src/core/detect/git-context.js.map +1 -0
  137. package/dist/src/core/detect/llm-key.js +72 -0
  138. package/dist/src/core/detect/llm-key.js.map +1 -0
  139. package/dist/src/core/detect/protected-paths.js +54 -0
  140. package/dist/src/core/detect/protected-paths.js.map +1 -0
  141. package/dist/src/core/detect/provider-usage.js +66 -0
  142. package/dist/src/core/detect/provider-usage.js.map +1 -0
  143. package/dist/src/core/detect/stack.js +204 -0
  144. package/dist/src/core/detect/stack.js.map +1 -0
  145. package/dist/src/core/detect/workspaces.js +100 -0
  146. package/dist/src/core/detect/workspaces.js.map +1 -0
  147. package/dist/src/core/errors.js +23 -0
  148. package/dist/src/core/errors.js.map +1 -0
  149. package/dist/src/core/findings/dedup.js +13 -0
  150. package/dist/src/core/findings/dedup.js.map +1 -0
  151. package/dist/src/core/findings/types.js +3 -0
  152. package/dist/src/core/findings/types.js.map +1 -0
  153. package/dist/src/core/fix/generator.js +119 -0
  154. package/dist/src/core/fix/generator.js.map +1 -0
  155. package/dist/src/core/git/diff-hunks.js +72 -0
  156. package/dist/src/core/git/diff-hunks.js.map +1 -0
  157. package/dist/src/core/git/touched-files.js +63 -0
  158. package/dist/src/core/git/touched-files.js.map +1 -0
  159. package/dist/src/core/ignore/index.js +49 -0
  160. package/dist/src/core/ignore/index.js.map +1 -0
  161. package/dist/src/core/index.js +2 -0
  162. package/dist/src/core/index.js.map +1 -0
  163. package/dist/src/core/logging/ndjson-writer.js +27 -0
  164. package/dist/src/core/logging/ndjson-writer.js.map +1 -0
  165. package/dist/src/core/logging/redaction.js +18 -0
  166. package/dist/src/core/logging/redaction.js.map +1 -0
  167. package/dist/src/core/mcp/concurrency.js +17 -0
  168. package/dist/src/core/mcp/concurrency.js.map +1 -0
  169. package/dist/src/core/mcp/handlers/fix-finding.js +80 -0
  170. package/dist/src/core/mcp/handlers/fix-finding.js.map +1 -0
  171. package/dist/src/core/mcp/handlers/get-capabilities.js +45 -0
  172. package/dist/src/core/mcp/handlers/get-capabilities.js.map +1 -0
  173. package/dist/src/core/mcp/handlers/get-findings.js +18 -0
  174. package/dist/src/core/mcp/handlers/get-findings.js.map +1 -0
  175. package/dist/src/core/mcp/handlers/review-diff.js +45 -0
  176. package/dist/src/core/mcp/handlers/review-diff.js.map +1 -0
  177. package/dist/src/core/mcp/handlers/scan-files.js +46 -0
  178. package/dist/src/core/mcp/handlers/scan-files.js.map +1 -0
  179. package/dist/src/core/mcp/handlers/validate-fix.js +27 -0
  180. package/dist/src/core/mcp/handlers/validate-fix.js.map +1 -0
  181. package/dist/src/core/mcp/run-store.js +68 -0
  182. package/dist/src/core/mcp/run-store.js.map +1 -0
  183. package/dist/src/core/mcp/workspace.js +34 -0
  184. package/dist/src/core/mcp/workspace.js.map +1 -0
  185. package/dist/src/core/persist/baseline.js +77 -0
  186. package/dist/src/core/persist/baseline.js.map +1 -0
  187. package/dist/src/core/persist/cost-log.js +25 -0
  188. package/dist/src/core/persist/cost-log.js.map +1 -0
  189. package/dist/src/core/persist/findings-cache.js +40 -0
  190. package/dist/src/core/persist/findings-cache.js.map +1 -0
  191. package/dist/src/core/persist/triage.js +77 -0
  192. package/dist/src/core/persist/triage.js.map +1 -0
  193. package/dist/src/core/phases/static-rules.js +57 -0
  194. package/dist/src/core/phases/static-rules.js.map +1 -0
  195. package/dist/src/core/phases/tests.js +34 -0
  196. package/dist/src/core/phases/tests.js.map +1 -0
  197. package/dist/src/core/pipeline/review-phase.js +138 -0
  198. package/dist/src/core/pipeline/review-phase.js.map +1 -0
  199. package/dist/src/core/pipeline/run.js +81 -0
  200. package/dist/src/core/pipeline/run.js.map +1 -0
  201. package/dist/src/core/runtime/idempotency.js +6 -0
  202. package/dist/src/core/runtime/idempotency.js.map +1 -0
  203. package/dist/src/core/runtime/lock.js +25 -0
  204. package/dist/src/core/runtime/lock.js.map +1 -0
  205. package/dist/src/core/runtime/state.js +53 -0
  206. package/dist/src/core/runtime/state.js.map +1 -0
  207. package/dist/src/core/schema-alignment/detector.js +44 -0
  208. package/dist/src/core/schema-alignment/detector.js.map +1 -0
  209. package/dist/src/core/schema-alignment/extractor/index.js +23 -0
  210. package/dist/src/core/schema-alignment/extractor/index.js.map +1 -0
  211. package/dist/src/core/schema-alignment/extractor/prisma.js +20 -0
  212. package/dist/src/core/schema-alignment/extractor/prisma.js.map +1 -0
  213. package/dist/src/core/schema-alignment/extractor/sql.js +77 -0
  214. package/dist/src/core/schema-alignment/extractor/sql.js.map +1 -0
  215. package/dist/src/core/schema-alignment/llm-check.js +83 -0
  216. package/dist/src/core/schema-alignment/llm-check.js.map +1 -0
  217. package/dist/src/core/schema-alignment/scanner.js +96 -0
  218. package/dist/src/core/schema-alignment/scanner.js.map +1 -0
  219. package/dist/src/core/schema-alignment/types.js +3 -0
  220. package/dist/src/core/schema-alignment/types.js.map +1 -0
  221. package/dist/src/core/shell.js +41 -0
  222. package/dist/src/core/shell.js.map +1 -0
  223. package/dist/src/core/static-rules/registry.js +46 -0
  224. package/dist/src/core/static-rules/registry.js.map +1 -0
  225. package/dist/src/core/static-rules/rules/brand-tokens.js +135 -0
  226. package/dist/src/core/static-rules/rules/brand-tokens.js.map +1 -0
  227. package/dist/src/core/static-rules/rules/console-log.js +45 -0
  228. package/dist/src/core/static-rules/rules/console-log.js.map +1 -0
  229. package/dist/src/core/static-rules/rules/hardcoded-secrets.js +79 -0
  230. package/dist/src/core/static-rules/rules/hardcoded-secrets.js.map +1 -0
  231. package/dist/src/core/static-rules/rules/insecure-redirect.js +65 -0
  232. package/dist/src/core/static-rules/rules/insecure-redirect.js.map +1 -0
  233. package/dist/src/core/static-rules/rules/large-file.js +39 -0
  234. package/dist/src/core/static-rules/rules/large-file.js.map +1 -0
  235. package/dist/src/core/static-rules/rules/missing-auth.js +69 -0
  236. package/dist/src/core/static-rules/rules/missing-auth.js.map +1 -0
  237. package/dist/src/core/static-rules/rules/missing-tests.js +48 -0
  238. package/dist/src/core/static-rules/rules/missing-tests.js.map +1 -0
  239. package/dist/src/core/static-rules/rules/npm-audit.js +40 -0
  240. package/dist/src/core/static-rules/rules/npm-audit.js.map +1 -0
  241. package/dist/src/core/static-rules/rules/package-lock-sync.js +47 -0
  242. package/dist/src/core/static-rules/rules/package-lock-sync.js.map +1 -0
  243. package/dist/src/core/static-rules/rules/schema-alignment.js +116 -0
  244. package/dist/src/core/static-rules/rules/schema-alignment.js.map +1 -0
  245. package/dist/src/core/static-rules/rules/sql-injection.js +69 -0
  246. package/dist/src/core/static-rules/rules/sql-injection.js.map +1 -0
  247. package/dist/src/core/static-rules/rules/ssrf.js +61 -0
  248. package/dist/src/core/static-rules/rules/ssrf.js.map +1 -0
  249. package/dist/src/core/static-rules/rules/todo-fixme.js +42 -0
  250. package/dist/src/core/static-rules/rules/todo-fixme.js.map +1 -0
  251. package/dist/src/core/static-rules/tailwind-extractor.js +37 -0
  252. package/dist/src/core/static-rules/tailwind-extractor.js.map +1 -0
  253. package/dist/src/core/test-gen/coverage-analyzer.js +85 -0
  254. package/dist/src/core/test-gen/coverage-analyzer.js.map +1 -0
  255. package/dist/src/core/test-gen/framework-detector.js +20 -0
  256. package/dist/src/core/test-gen/framework-detector.js.map +1 -0
  257. package/dist/src/core/test-gen/test-writer.js +31 -0
  258. package/dist/src/core/test-gen/test-writer.js.map +1 -0
  259. package/dist/src/core/ui/design-context-loader.js +109 -0
  260. package/dist/src/core/ui/design-context-loader.js.map +1 -0
  261. package/dist/src/core/worker/client.js +29 -0
  262. package/dist/src/core/worker/client.js.map +1 -0
  263. package/dist/src/core/worker/lockfile.js +38 -0
  264. package/dist/src/core/worker/lockfile.js.map +1 -0
  265. package/dist/src/core/worker/server.js +63 -0
  266. package/dist/src/core/worker/server.js.map +1 -0
  267. package/dist/src/formatters/github-annotations.js +35 -0
  268. package/dist/src/formatters/github-annotations.js.map +1 -0
  269. package/dist/src/formatters/index.js +3 -0
  270. package/dist/src/formatters/index.js.map +1 -0
  271. package/dist/src/formatters/junit.js +38 -0
  272. package/dist/src/formatters/junit.js.map +1 -0
  273. package/dist/src/formatters/sarif.js +62 -0
  274. package/dist/src/formatters/sarif.js.map +1 -0
  275. package/dist/src/index.js +2 -0
  276. package/dist/src/index.js.map +1 -0
  277. package/package.json +11 -4
  278. package/scripts/post-build-rewrite-imports.mjs +66 -0
  279. package/src/cli/baseline.ts +1 -1
  280. package/src/cli/costs.ts +1 -1
  281. package/src/cli/explain.ts +2 -2
  282. package/src/cli/fix.ts +1 -1
  283. package/src/cli/ignore-helper.ts +1 -1
  284. package/src/cli/index.ts +95 -25
  285. package/src/cli/init.ts +1 -1
  286. package/src/cli/migrate-v4.ts +388 -0
  287. package/src/cli/pr.ts +1 -1
  288. package/src/cli/preflight.ts +2 -2
  289. package/src/cli/run.ts +1 -1
  290. package/src/cli/scan.ts +1 -1
  291. package/src/cli/setup.ts +1 -1
  292. package/src/cli/triage.ts +1 -1
  293. package/src/cli/watch.ts +1 -1
  294. package/src/cli/worker.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.0.0-alpha.3] — 2026-04-24
4
+
5
+ Final alpha before v5.0.0 GA. Closes every remaining GA blocker from the alpha cycle.
6
+
7
+ ### Added
8
+ - **Compiled JS entrypoint** — `npm run build` emits `dist/src/**/*.js` via `tsc -p tsconfig.build.json`. The launcher at `bin/_launcher.js` prefers the compiled output when present (global installs), falls back to `src/` + `tsx` for dev workflows. Drops `tsx` from the runtime hot path for published installs. Uses TypeScript 6's `rewriteRelativeImportExtensions: true` to rewrite `.ts` → `.js` specifiers at emit time; includes a defensive post-build rewriter script that no-ops when tsc already did the work.
9
+ - **`claude-autopilot migrate-v4` codemod** — `src/cli/migrate-v4.ts`. Scans a target repo for `@delegance/guardrail` and `guardrail <verb>` references, proposes replacements, applies with `--write` (creates `.v4-backup.<timestamp>` files and writes a restore manifest). `--undo` reads the manifest and restores by sha256 match — refuses to overwrite files modified after the migrate. Covers `package.json` (dependency sections with operator preservation), shell scripts, Makefiles, GitHub Actions yaml, Dockerfiles (including CMD-array `["guardrail", "verb"]` form). Skips `node_modules/`, `dist/`, and the tool's own `.claude-autopilot/` state dir.
10
+ - **Tombstone `@delegance/guardrail@5.0.0`** package at `packages/guardrail-tombstone/`. Thin CLI wrapper that forwards argv / stdio / exit code / signal to `@delegance/claude-autopilot`. Resolves the child via `createRequire().resolve()` (works under npm / pnpm / yarn / PnP) with two relative-probe fallbacks and a last-resort PATH lookup. Emits a one-line deprecation notice on stderr (silenceable via `CLAUDE_AUTOPILOT_DEPRECATION=never`). Maps ENOENT to exit 127 with an actionable install hint.
11
+ - **CI bin-parity workflow** at `.github/workflows/bin-parity.yml`. On every push to master + PR, runs matrix (ubuntu + macos × node 22 + 24) that packs a tarball, globally installs, then asserts: (a) both bins return semver, (b) deprecation notice is on stderr under `always`, (c) deprecation does not leak onto stdout, (d) exit codes match between `claude-autopilot` and `guardrail` on a non-zero-exit invocation. A second job installs from the published `@alpha` tag on push to master for real-world parity.
12
+ - **Prefix-hygiene test** at `tests/no-legacy-prefix.test.ts` — asserts that `src/cli/**` uses `[claude-autopilot]` not `[guardrail]`, with an explicit allowlist for legitimate legacy references (bin wrappers, launcher).
13
+ - `tsconfig.build.json` — separate build config with `rewriteRelativeImportExtensions: true` and explicit emit settings.
14
+ - `scripts/post-build-rewrite-imports.mjs` — defensive rewriter for `.ts` → `.js` import specifiers in emitted JS. No-op when tsc emits correctly.
15
+ - `prepublishOnly` script — runs `build && test` before any `npm publish`.
16
+ - 14 new tests (migrate-v4: 7, tombstone-bin: 3, no-legacy-prefix: 1, others: 3).
17
+
18
+ ### Changed
19
+ - **Error prefixes normalized** — every `[guardrail] ...` error message in `src/cli/index.ts` and `src/cli/preflight.ts` now uses `[claude-autopilot]` or the phase name (`[run]`, `[doctor]`). Legacy `[guardrail]` retained only in the bin-wrapper deprecation notice, `bin/_launcher.js`, and the tombstone package (where it legitimately refers to the deprecated package name).
20
+ - **Welcome screen rewritten** — bare `claude-autopilot` invocation now leads with the pipeline pitch (`claude-autopilot brainstorm "..."`) and frames the review subcommands as the v4-compatible alternative. Previously sold the package as "LLM code review."
21
+ - **Version resolution in `src/cli/index.ts`** — walks up from `import.meta.url` for the nearest `@delegance/claude-autopilot` `package.json` instead of a hardcoded `../../package.json`. Necessary because the compiled entrypoint lives at `dist/src/cli/index.js` where the old relative path resolved to `dist/package.json` (which doesn't exist).
22
+ - **`package.json` `files` field** now includes `dist/` (new) and `scripts/post-build-rewrite-imports.mjs`.
23
+ - `preflight.ts`: "Guardrail prerequisite check" heading → "claude-autopilot prerequisite check".
24
+
25
+ ### Fixed
26
+ - (None — alpha.3 is feature work; no regressions surfaced by the compat matrix.)
27
+
28
+ ### Still manual for GA
29
+ - Alex to publish `@delegance/guardrail@5.0.0` tombstone from `packages/guardrail-tombstone/`.
30
+ - Alex to run `npm dist-tag add @delegance/claude-autopilot@5.0.0 latest` once 5.0.0 GA ships.
31
+ - Alex to run `npm deprecate @delegance/claude-autopilot@"<5.0.0" "Use @delegance/claude-autopilot@alpha during alpha cycle, or @latest after GA"` to flag pre-rename versions.
32
+
3
33
  ## [5.0.0-alpha.2] — 2026-04-24
4
34
 
5
35
  ### Added
package/bin/_launcher.js CHANGED
@@ -9,7 +9,19 @@ import * as path from 'node:path';
9
9
  import * as os from 'node:os';
10
10
 
11
11
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
- const ENTRYPOINT = path.resolve(__dirname, '..', 'src', 'cli', 'index.ts');
12
+ const COMPILED = path.resolve(__dirname, '..', 'dist', 'src', 'cli', 'index.js');
13
+ const SOURCE = path.resolve(__dirname, '..', 'src', 'cli', 'index.ts');
14
+
15
+ /**
16
+ * Pick the best available entrypoint. Compiled (dist/) is preferred for global
17
+ * installs — no tsx dependency, faster startup. Source+tsx is used in dev from the
18
+ * repo itself. Result determines the spawn strategy below.
19
+ */
20
+ function resolveEntry() {
21
+ if (fs.existsSync(COMPILED)) return { kind: 'compiled', path: COMPILED };
22
+ if (fs.existsSync(SOURCE)) return { kind: 'source', path: SOURCE };
23
+ return null;
24
+ }
13
25
 
14
26
  function findTsx() {
15
27
  const own = path.resolve(__dirname, '..', 'node_modules', '.bin', 'tsx');
@@ -72,6 +84,37 @@ export function launch(opts) {
72
84
  'Silence: set CLAUDE_AUTOPILOT_DEPRECATION=never\n',
73
85
  );
74
86
  }
75
- const result = spawnSync(findTsx(), [ENTRYPOINT, ...process.argv.slice(2)], { stdio: 'inherit' });
87
+
88
+ const entry = resolveEntry();
89
+ if (!entry) {
90
+ process.stderr.write(
91
+ '[claude-autopilot] Could not find CLI entrypoint. Expected either\n' +
92
+ ` ${COMPILED} (compiled) or\n` +
93
+ ` ${SOURCE} (source)\n` +
94
+ 'Reinstall: npm install -g @delegance/claude-autopilot@alpha\n',
95
+ );
96
+ process.exit(127);
97
+ }
98
+
99
+ let result;
100
+ if (entry.kind === 'compiled') {
101
+ // Fast path — plain node, no tsx dep. Used by global installs (ships dist/).
102
+ result = spawnSync(process.execPath, [entry.path, ...process.argv.slice(2)], { stdio: 'inherit' });
103
+ } else {
104
+ // Dev path — run source via tsx. Used from the repo itself, or by users who
105
+ // installed from git or linked a local copy.
106
+ result = spawnSync(findTsx(), [entry.path, ...process.argv.slice(2)], { stdio: 'inherit' });
107
+ }
108
+
109
+ if (result.error) {
110
+ // ENOENT or similar spawn failure — surface cleanly instead of hanging.
111
+ process.stderr.write(`[claude-autopilot] Failed to launch CLI: ${result.error.message}\n`);
112
+ process.exit(127);
113
+ }
114
+ if (result.signal) {
115
+ // Forward child signal by re-raising equivalently
116
+ process.kill(process.pid, result.signal);
117
+ return;
118
+ }
76
119
  process.exit(result.status ?? 1);
77
120
  }
@@ -0,0 +1,60 @@
1
+ import * as fs from 'node:fs/promises';
2
+ // fmt.Sprintf directly in a DB call (single-line)
3
+ const SPRINTF_IN_QUERY = /(?:Query|Exec|QueryRow)\w*\s*\([^)]*fmt\.Sprintf/;
4
+ // fmt.Sprintf result assigned to variable then used in DB call (multi-line)
5
+ const SPRINTF_ASSIGN = /\bfmt\.Sprintf\s*\(/;
6
+ const DB_CALL = /(?:Query|Exec|QueryRow)\w*\s*\(\s*(\w+)/;
7
+ export const goSqlInjectionRule = {
8
+ name: 'go-sql-injection',
9
+ severity: 'critical',
10
+ async check(touchedFiles) {
11
+ const findings = [];
12
+ const goFiles = touchedFiles.filter(f => f.endsWith('.go') && !f.endsWith('_test.go'));
13
+ for (const file of goFiles) {
14
+ try {
15
+ const content = await fs.readFile(file, 'utf8');
16
+ const lines = content.split('\n');
17
+ // Track variables assigned from fmt.Sprintf (multi-line detection)
18
+ const sprintfVars = new Set();
19
+ for (const line of lines) {
20
+ const m = line.match(/^\s*(\w+)\s*(?::?=)\s*fmt\.Sprintf\s*\(/);
21
+ if (m)
22
+ sprintfVars.add(m[1]);
23
+ }
24
+ for (let i = 0; i < lines.length; i++) {
25
+ const line = lines[i];
26
+ let hit = false;
27
+ // Direct inline: db.Query(fmt.Sprintf(...))
28
+ if (SPRINTF_IN_QUERY.test(line))
29
+ hit = true;
30
+ // Indirect: variable from fmt.Sprintf passed to DB call
31
+ if (!hit && sprintfVars.size > 0) {
32
+ const dbMatch = line.match(DB_CALL);
33
+ if (dbMatch && sprintfVars.has(dbMatch[1]))
34
+ hit = true;
35
+ }
36
+ if (hit) {
37
+ findings.push({
38
+ id: `go-sql-injection:${file}:${i + 1}`,
39
+ source: 'static-rules',
40
+ severity: 'critical',
41
+ category: 'go-sql-injection',
42
+ file,
43
+ line: i + 1,
44
+ message: 'SQL injection risk: fmt.Sprintf used to build query string',
45
+ suggestion: 'Use parameterized queries: db.Query("WHERE id = $1", id)',
46
+ protectedPath: false,
47
+ createdAt: new Date().toISOString(),
48
+ });
49
+ }
50
+ }
51
+ }
52
+ catch {
53
+ // unreadable — skip
54
+ }
55
+ }
56
+ return findings;
57
+ },
58
+ };
59
+ export default goSqlInjectionRule;
60
+ //# sourceMappingURL=go-sql-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"go-sql-injection.js","sourceRoot":"","sources":["../../../../presets/go/rules/go-sql-injection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,kDAAkD;AAClD,MAAM,gBAAgB,GAAG,kDAAkD,CAAC;AAC5E,4EAA4E;AAC5E,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAC7C,MAAM,OAAO,GAAG,yCAAyC,CAAC;AAE1D,MAAM,CAAC,MAAM,kBAAkB,GAAe;IAC5C,IAAI,EAAE,kBAAkB;IACxB,QAAQ,EAAE,UAAU;IACpB,KAAK,CAAC,KAAK,CAAC,YAAsB;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QACvF,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAElC,mEAAmE;gBACnE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;gBACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;oBAChE,IAAI,CAAC;wBAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;gBAChC,CAAC;gBAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;oBACvB,IAAI,GAAG,GAAG,KAAK,CAAC;oBAEhB,4CAA4C;oBAC5C,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,GAAG,GAAG,IAAI,CAAC;oBAE5C,wDAAwD;oBACxD,IAAI,CAAC,GAAG,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;wBACjC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;wBACpC,IAAI,OAAO,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;4BAAE,GAAG,GAAG,IAAI,CAAC;oBAC1D,CAAC;oBAED,IAAI,GAAG,EAAE,CAAC;wBACR,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,oBAAoB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE;4BACvC,MAAM,EAAE,cAAc;4BACtB,QAAQ,EAAE,UAAU;4BACpB,QAAQ,EAAE,kBAAkB;4BAC5B,IAAI;4BACJ,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,4DAA4D;4BACrE,UAAU,EAAE,0DAA0D;4BACtE,aAAa,EAAE,KAAK;4BACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACpC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,37 @@
1
+ import * as fs from 'node:fs/promises';
2
+ export const supabaseRlsBypassRule = {
3
+ name: 'supabase-rls-bypass',
4
+ severity: 'critical',
5
+ async check(touchedFiles) {
6
+ const findings = [];
7
+ const clientSideFiles = touchedFiles.filter(f => (f.endsWith('.tsx') || f.includes('/components/')) &&
8
+ !f.includes('/api/') && !f.includes('.test.') && !f.includes('__tests__'));
9
+ for (const file of clientSideFiles) {
10
+ let content;
11
+ try {
12
+ content = await fs.readFile(file, 'utf8');
13
+ }
14
+ catch {
15
+ continue;
16
+ }
17
+ if (!content.includes('createServiceRoleClient'))
18
+ continue;
19
+ const lineIndex = content.split('\n').findIndex(l => l.includes('createServiceRoleClient'));
20
+ findings.push({
21
+ id: `supabase-rls-bypass-${file}-${lineIndex}`,
22
+ source: 'static-rules',
23
+ severity: 'critical',
24
+ category: 'supabase-rls-bypass',
25
+ file,
26
+ line: lineIndex >= 0 ? lineIndex + 1 : undefined,
27
+ message: 'createServiceRoleClient() in client-side code — service role key is a RLS bypass',
28
+ suggestion: 'Use createServerSupabase in a server component or route handler',
29
+ protectedPath: true,
30
+ createdAt: new Date().toISOString(),
31
+ });
32
+ }
33
+ return findings;
34
+ },
35
+ };
36
+ export default supabaseRlsBypassRule;
37
+ //# sourceMappingURL=supabase-rls-bypass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase-rls-bypass.js","sourceRoot":"","sources":["../../../../presets/nextjs-supabase/rules/supabase-rls-bypass.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAIvC,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,IAAI,EAAE,qBAAqB;IAC3B,QAAQ,EAAE,UAAU;IAEpB,KAAK,CAAC,KAAK,CAAC,YAAsB;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC9C,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAC1E,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACnC,IAAI,OAAe,CAAC;YACpB,IAAI,CAAC;gBAAC,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,SAAS;YAAC,CAAC;YACtE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC;gBAAE,SAAS;YAE3D,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAAC;YAC5F,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,uBAAuB,IAAI,IAAI,SAAS,EAAE;gBAC9C,MAAM,EAAE,cAAc;gBACtB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,qBAAqB;gBAC/B,IAAI;gBACJ,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;gBAChD,OAAO,EAAE,kFAAkF;gBAC3F,UAAU,EAAE,iEAAiE;gBAC7E,aAAa,EAAE,IAAI;gBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import * as fs from 'node:fs/promises';
2
+ // Routes that are decorated with state-mutating HTTP verbs but lack a Depends() auth call
3
+ const MUTATION_DECORATOR = /@(app|router)\.(post|put|patch|delete)\s*\(/i;
4
+ const HAS_AUTH_DEP = /Depends\s*\(\s*(?:get_current_user|require_auth|authenticate|verify_token)/i;
5
+ export const fastapiMissingAuthRule = {
6
+ name: 'fastapi-missing-auth',
7
+ severity: 'critical',
8
+ async check(touchedFiles) {
9
+ const findings = [];
10
+ const pyFiles = touchedFiles.filter(f => f.endsWith('.py'));
11
+ for (const file of pyFiles) {
12
+ try {
13
+ const content = await fs.readFile(file, 'utf8');
14
+ const lines = content.split('\n');
15
+ // Check whether any router-level dependency covers the whole file
16
+ const fileHasRouterAuth = HAS_AUTH_DEP.test(content.slice(0, 2000));
17
+ if (fileHasRouterAuth)
18
+ continue;
19
+ for (let i = 0; i < lines.length; i++) {
20
+ const line = lines[i];
21
+ if (!MUTATION_DECORATOR.test(line))
22
+ continue;
23
+ // Scan up to 40 lines after the decorator for per-endpoint auth
24
+ const block = lines.slice(i, i + 40).join('\n');
25
+ if (!HAS_AUTH_DEP.test(block)) {
26
+ findings.push({
27
+ id: `fastapi-missing-auth:${file}:${i + 1}`,
28
+ source: 'static-rules',
29
+ severity: 'critical',
30
+ category: 'fastapi-missing-auth',
31
+ file,
32
+ line: i + 1,
33
+ message: 'Mutation endpoint may be missing auth dependency',
34
+ suggestion: 'Add current_user: User = Depends(get_current_user) to the route parameters',
35
+ protectedPath: false,
36
+ createdAt: new Date().toISOString(),
37
+ });
38
+ }
39
+ }
40
+ }
41
+ catch {
42
+ // unreadable — skip
43
+ }
44
+ }
45
+ return findings;
46
+ },
47
+ };
48
+ export default fastapiMissingAuthRule;
49
+ //# sourceMappingURL=fastapi-missing-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastapi-missing-auth.js","sourceRoot":"","sources":["../../../../presets/python-fastapi/rules/fastapi-missing-auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,0FAA0F;AAC1F,MAAM,kBAAkB,GAAG,8CAA8C,CAAC;AAC1E,MAAM,YAAY,GAAG,6EAA6E,CAAC;AAEnG,MAAM,CAAC,MAAM,sBAAsB,GAAe;IAChD,IAAI,EAAE,sBAAsB;IAC5B,QAAQ,EAAE,UAAU;IACpB,KAAK,CAAC,KAAK,CAAC,YAAsB;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5D,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAClC,kEAAkE;gBAClE,MAAM,iBAAiB,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBACpE,IAAI,iBAAiB;oBAAE,SAAS;gBAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;oBACvB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;wBAAE,SAAS;oBAC7C,gEAAgE;oBAChE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAChD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC9B,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,wBAAwB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE;4BAC3C,MAAM,EAAE,cAAc;4BACtB,QAAQ,EAAE,UAAU;4BACpB,QAAQ,EAAE,sBAAsB;4BAChC,IAAI;4BACJ,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,kDAAkD;4BAC3D,UAAU,EAAE,4EAA4E;4BACxF,aAAa,EAAE,KAAK;4BACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACpC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import * as fs from 'node:fs/promises';
2
+ const INTERPOLATED_WHERE = /\.where\s*\(\s*["'`][^"'`]*#\{/;
3
+ const INTERPOLATED_ORDER = /\.order\s*\(\s*["'`][^"'`]*#\{/;
4
+ export const railsSqlInjectionRule = {
5
+ name: 'rails-sql-injection',
6
+ severity: 'critical',
7
+ async check(touchedFiles) {
8
+ const findings = [];
9
+ const rubyFiles = touchedFiles.filter(f => f.endsWith('.rb'));
10
+ for (const file of rubyFiles) {
11
+ try {
12
+ const lines = (await fs.readFile(file, 'utf8')).split('\n');
13
+ for (let i = 0; i < lines.length; i++) {
14
+ const line = lines[i];
15
+ if (INTERPOLATED_WHERE.test(line) || INTERPOLATED_ORDER.test(line)) {
16
+ findings.push({
17
+ id: `rails-sql-injection:${file}:${i + 1}`,
18
+ source: 'static-rules',
19
+ severity: 'critical',
20
+ category: 'rails-sql-injection',
21
+ file,
22
+ line: i + 1,
23
+ message: 'SQL injection risk: string interpolation in Active Record query',
24
+ suggestion: 'Use parameterized queries: .where("name = ?", params[:name])',
25
+ protectedPath: false,
26
+ createdAt: new Date().toISOString(),
27
+ });
28
+ }
29
+ }
30
+ }
31
+ catch {
32
+ // unreadable — skip
33
+ }
34
+ }
35
+ return findings;
36
+ },
37
+ };
38
+ export default railsSqlInjectionRule;
39
+ //# sourceMappingURL=rails-sql-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails-sql-injection.js","sourceRoot":"","sources":["../../../../presets/rails-postgres/rules/rails-sql-injection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,kBAAkB,GAAG,gCAAgC,CAAC;AAC5D,MAAM,kBAAkB,GAAG,gCAAgC,CAAC;AAE5D,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,IAAI,EAAE,qBAAqB;IAC3B,QAAQ,EAAE,UAAU;IACpB,KAAK,CAAC,KAAK,CAAC,YAAsB;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;oBACvB,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACnE,QAAQ,CAAC,IAAI,CAAC;4BACZ,EAAE,EAAE,uBAAuB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE;4BAC1C,MAAM,EAAE,cAAc;4BACtB,QAAQ,EAAE,UAAU;4BACpB,QAAQ,EAAE,qBAAqB;4BAC/B,IAAI;4BACJ,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,iEAAiE;4BAC1E,UAAU,EAAE,8DAA8D;4BAC1E,aAAa,EAAE,KAAK;4BACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBACpC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oBAAoB;YACtB,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import * as fs from 'node:fs/promises';
2
+ export const t3ServerOnlyRule = {
3
+ name: 't3-server-only',
4
+ severity: 'critical',
5
+ async check(touchedFiles) {
6
+ const findings = [];
7
+ for (const file of touchedFiles) {
8
+ if (!file.includes('src/server/') && !file.endsWith('.server.ts'))
9
+ continue;
10
+ try {
11
+ const content = await fs.readFile(file, 'utf8');
12
+ if (!content.includes("'server-only'") && !content.includes('"server-only"')) {
13
+ findings.push({
14
+ id: `t3-server-only:${file}`,
15
+ source: 'static-rules',
16
+ severity: 'critical',
17
+ category: 't3-server-only',
18
+ file,
19
+ message: 'Server utility missing `server-only` import guard',
20
+ suggestion: "Add `import 'server-only'` at the top of this file",
21
+ protectedPath: false,
22
+ createdAt: new Date().toISOString(),
23
+ });
24
+ }
25
+ }
26
+ catch {
27
+ // file unreadable — skip
28
+ }
29
+ }
30
+ return findings;
31
+ },
32
+ };
33
+ export default t3ServerOnlyRule;
34
+ //# sourceMappingURL=t3-server-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"t3-server-only.js","sourceRoot":"","sources":["../../../../presets/t3/rules/t3-server-only.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAe;IAC1C,IAAI,EAAE,gBAAgB;IACtB,QAAQ,EAAE,UAAU;IACpB,KAAK,CAAC,KAAK,CAAC,YAAsB;QAChC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAAE,SAAS;YAC5E,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAChD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBAC7E,QAAQ,CAAC,IAAI,CAAC;wBACZ,EAAE,EAAE,kBAAkB,IAAI,EAAE;wBAC5B,MAAM,EAAE,cAAc;wBACtB,QAAQ,EAAE,UAAU;wBACpB,QAAQ,EAAE,gBAAgB;wBAC1B,IAAI;wBACJ,OAAO,EAAE,mDAAmD;wBAC5D,UAAU,EAAE,oDAAoD;wBAChE,aAAa,EAAE,KAAK;wBACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;qBACpC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ // src/adapters/base.ts
2
+ export const CORE_ADAPTER_API_VERSION_MAJOR = 1;
3
+ export function checkApiVersionCompatibility(adapterApiVersion) {
4
+ const parts = adapterApiVersion.split('.');
5
+ const major = parseInt(parts[0] ?? '0', 10);
6
+ return major === CORE_ADAPTER_API_VERSION_MAJOR;
7
+ }
8
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,uBAAuB;AAYvB,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAEhD,MAAM,UAAU,4BAA4B,CAAC,iBAAyB;IACpE,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,KAAK,KAAK,8BAA8B,CAAC;AAClD,CAAC"}
@@ -0,0 +1,40 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { GuardrailError } from "../../core/errors.js";
3
+ import { classifyError } from "../review-engine/prompt-builder.js";
4
+ const SYSTEM_PROMPT = `You are a technical advisor reviewing a software design decision. Evaluate the provided context and question critically. Be direct and specific. Surface tradeoffs, risks, and your recommendation.`;
5
+ const MAX_OUTPUT_TOKENS = 2048;
6
+ export function makeClaudeCouncilAdapter(model, label) {
7
+ return {
8
+ label,
9
+ async consult(prompt, context) {
10
+ const apiKey = process.env.ANTHROPIC_API_KEY;
11
+ if (!apiKey) {
12
+ throw new GuardrailError('ANTHROPIC_API_KEY not set', { code: 'auth', provider: 'claude' });
13
+ }
14
+ const client = new Anthropic({ apiKey });
15
+ let response;
16
+ try {
17
+ response = await client.messages.create({
18
+ model,
19
+ max_tokens: MAX_OUTPUT_TOKENS,
20
+ system: SYSTEM_PROMPT,
21
+ messages: [{ role: 'user', content: `## Context\n\n${context}\n\n## Question\n\n${prompt}` }],
22
+ });
23
+ }
24
+ catch (err) {
25
+ const message = err instanceof Error ? err.message : String(err);
26
+ const code = classifyError(message);
27
+ throw new GuardrailError(`Claude council call failed: ${message}`, {
28
+ code,
29
+ provider: 'claude',
30
+ retryable: code === 'rate_limit',
31
+ });
32
+ }
33
+ return response.content
34
+ .filter(b => b.type === 'text')
35
+ .map(b => b.text)
36
+ .join('');
37
+ },
38
+ };
39
+ }
40
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../../src/adapters/council/claude.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,MAAM,aAAa,GAAG,qMAAqM,CAAC;AAC5N,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,KAAa;IACnE,OAAO;QACL,KAAK;QACL,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,OAAe;YAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,cAAc,CAAC,2BAA2B,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9F,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACzC,IAAI,QAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACtC,KAAK;oBACL,UAAU,EAAE,iBAAiB;oBAC7B,MAAM,EAAE,aAAa;oBACrB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,OAAO,sBAAsB,MAAM,EAAE,EAAE,CAAC;iBAC9F,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,IAAI,cAAc,CAAC,+BAA+B,OAAO,EAAE,EAAE;oBACjE,IAAI;oBACJ,QAAQ,EAAE,QAAQ;oBAClB,SAAS,EAAE,IAAI,KAAK,YAAY;iBACjC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,QAAQ,CAAC,OAAO;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAE,CAAyB,CAAC,IAAI,CAAC;iBACzC,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,39 @@
1
+ import OpenAI from 'openai';
2
+ import { GuardrailError } from "../../core/errors.js";
3
+ import { classifyError } from "../review-engine/prompt-builder.js";
4
+ const SYSTEM_PROMPT = `You are a technical advisor reviewing a software design decision. Evaluate the provided context and question critically. Be direct and specific. Surface tradeoffs, risks, and your recommendation.`;
5
+ const MAX_OUTPUT_TOKENS = 2048;
6
+ export function makeOpenAICouncilAdapter(model, label) {
7
+ return {
8
+ label,
9
+ async consult(prompt, context) {
10
+ const apiKey = process.env.OPENAI_API_KEY;
11
+ if (!apiKey) {
12
+ throw new GuardrailError('OPENAI_API_KEY not set', { code: 'auth', provider: 'openai' });
13
+ }
14
+ const client = new OpenAI({ apiKey });
15
+ let response;
16
+ try {
17
+ response = await client.chat.completions.create({
18
+ model,
19
+ max_tokens: MAX_OUTPUT_TOKENS,
20
+ messages: [
21
+ { role: 'system', content: SYSTEM_PROMPT },
22
+ { role: 'user', content: `## Context\n\n${context}\n\n## Question\n\n${prompt}` },
23
+ ],
24
+ });
25
+ }
26
+ catch (err) {
27
+ const message = err instanceof Error ? err.message : String(err);
28
+ const code = classifyError(message);
29
+ throw new GuardrailError(`OpenAI council call failed: ${message}`, {
30
+ code,
31
+ provider: 'openai',
32
+ retryable: code === 'rate_limit',
33
+ });
34
+ }
35
+ return response.choices[0]?.message?.content ?? '';
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../../src/adapters/council/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAGnE,MAAM,aAAa,GAAG,qMAAqM,CAAC;AAC5N,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,KAAa;IACnE,OAAO;QACL,KAAK;QACL,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,OAAe;YAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,cAAc,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACtC,IAAI,QAA+B,CAAC;YACpC,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;oBAC9C,KAAK;oBACL,UAAU,EAAE,iBAAiB;oBAC7B,QAAQ,EAAE;wBACR,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;wBAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,OAAO,sBAAsB,MAAM,EAAE,EAAE;qBAClF;iBACF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,IAAI,cAAc,CAAC,+BAA+B,OAAO,EAAE,EAAE;oBACjE,IAAI;oBACJ,QAAQ,EAAE,QAAQ;oBAClB,SAAS,EAAE,IAAI,KAAK,YAAY;iBACjC,CAAC,CAAC;YACL,CAAC;YACD,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QACrD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/adapters/council/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import * as path from 'node:path';
10
+ import { GuardrailError } from "../core/errors.js";
11
+ import { checkApiVersionCompatibility } from "./base.js";
12
+ const BUILTIN_PATHS = {
13
+ 'review-engine': {
14
+ codex: './review-engine/codex.ts',
15
+ claude: './review-engine/claude.ts',
16
+ gemini: './review-engine/gemini.ts',
17
+ 'openai-compatible': './review-engine/openai-compatible.ts',
18
+ auto: './review-engine/auto.ts',
19
+ },
20
+ 'vcs-host': { github: './vcs-host/github.ts' },
21
+ 'migration-runner': { supabase: './migration-runner/supabase.ts' },
22
+ 'review-bot-parser': { cursor: './review-bot-parser/cursor.ts' },
23
+ };
24
+ const REQUIRED_BY_POINT = {
25
+ 'review-engine': ['review', 'estimateTokens'],
26
+ 'vcs-host': ['getPrDiff', 'getPrMetadata', 'postComment', 'getReviewComments', 'replyToComment', 'createPr', 'push'],
27
+ 'migration-runner': ['discover', 'dryRun', 'apply', 'ledger', 'alreadyApplied'],
28
+ 'review-bot-parser': ['detect', 'fetchFindings', 'detectDismissal'],
29
+ };
30
+ function isPathRef(ref) {
31
+ return ref.startsWith('./') || ref.startsWith('/') || ref.startsWith('../') || ref.endsWith('.ts') || ref.endsWith('.js');
32
+ }
33
+ export async function loadAdapter(options) {
34
+ const { point, ref } = options;
35
+ let modulePath;
36
+ if (isPathRef(ref)) {
37
+ if (!options.unsafeAllowLocalAdapters) {
38
+ throw new GuardrailError(`Path-based adapter refs require unsafeAllowLocalAdapters:true — set this only for trusted local adapters`, { code: 'invalid_config', details: { point, ref } });
39
+ }
40
+ modulePath = path.resolve(ref);
41
+ }
42
+ else {
43
+ const builtin = BUILTIN_PATHS[point]?.[ref];
44
+ if (!builtin) {
45
+ throw new GuardrailError(`Unknown built-in ${point} adapter: "${ref}"`, {
46
+ code: 'invalid_config',
47
+ details: { point, ref, available: Object.keys(BUILTIN_PATHS[point] ?? {}) },
48
+ });
49
+ }
50
+ modulePath = new URL(builtin, import.meta.url).pathname;
51
+ }
52
+ let mod;
53
+ try {
54
+ mod = (await import(__rewriteRelativeImportExtension(modulePath)));
55
+ }
56
+ catch (err) {
57
+ throw new GuardrailError(`Failed to import adapter from ${modulePath}`, {
58
+ code: 'invalid_config',
59
+ details: { point, ref, modulePath, cause: err instanceof Error ? err.message : String(err) },
60
+ });
61
+ }
62
+ const adapter = ('default' in mod ? mod.default : mod);
63
+ if (!adapter || typeof adapter !== 'object') {
64
+ throw new GuardrailError(`Adapter module did not export a valid adapter object`, {
65
+ code: 'invalid_config',
66
+ details: { point, ref, modulePath },
67
+ });
68
+ }
69
+ validateShape(adapter, point, modulePath);
70
+ if (!checkApiVersionCompatibility(adapter.apiVersion)) {
71
+ throw new GuardrailError(`Adapter apiVersion ${adapter.apiVersion} incompatible with core`, {
72
+ code: 'invalid_config',
73
+ details: { point, ref, adapterApiVersion: adapter.apiVersion },
74
+ });
75
+ }
76
+ return adapter;
77
+ }
78
+ function validateShape(adapter, point, modulePath) {
79
+ const missing = [];
80
+ const required = ['getCapabilities', ...REQUIRED_BY_POINT[point]];
81
+ for (const method of required) {
82
+ if (typeof adapter[method] !== 'function')
83
+ missing.push(method);
84
+ }
85
+ if (typeof adapter.name !== 'string' || typeof adapter.apiVersion !== 'string') {
86
+ missing.push('name/apiVersion');
87
+ }
88
+ if (missing.length > 0) {
89
+ throw new GuardrailError(`Adapter at ${modulePath} missing required methods: ${missing.join(', ')}`, { code: 'invalid_config', details: { point, modulePath, missing } });
90
+ }
91
+ }
92
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/adapters/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { runSafe } from "../../core/shell.js";
4
+ export const supabaseAdapter = {
5
+ name: 'supabase',
6
+ apiVersion: '1.0.0',
7
+ getCapabilities() {
8
+ return { structuredOutput: false, streaming: false, maxContextTokens: 0, inlineComments: false };
9
+ },
10
+ discover(touchedFiles) {
11
+ const sqlFiles = touchedFiles.filter(f => f.match(/data\/deltas\/[^/]+\.sql$/));
12
+ return sqlFiles.map(p => ({
13
+ name: path.basename(p, '.sql'),
14
+ path: p,
15
+ }));
16
+ },
17
+ async dryRun(migration) {
18
+ try {
19
+ const content = migration.content ?? fs.readFileSync(migration.path, 'utf8');
20
+ if (!content.trim())
21
+ return { ok: false, errors: ['Migration file is empty'] };
22
+ return { ok: true };
23
+ }
24
+ catch (err) {
25
+ return { ok: false, errors: [err instanceof Error ? err.message : String(err)] };
26
+ }
27
+ },
28
+ async apply(migration, env) {
29
+ const start = Date.now();
30
+ const envFlag = env === 'prod' ? '--prod' : env === 'qa' ? '--qa' : '';
31
+ const args = ['tsx', 'scripts/supabase/migrate.ts', migration.path];
32
+ if (envFlag)
33
+ args.push(envFlag);
34
+ const result = runSafe('npx', args);
35
+ if (result === null) {
36
+ return { ok: false, errors: [`Migration apply failed for ${migration.name} on ${env}`] };
37
+ }
38
+ return { ok: true, durationMs: Date.now() - start };
39
+ },
40
+ async ledger(_env) {
41
+ // alpha.1: full ledger query lands in alpha.2
42
+ return [];
43
+ },
44
+ async alreadyApplied(migration, _env) {
45
+ const result = runSafe('npx', ['tsx', 'scripts/supabase/migrate.ts', migration.path, '--inspect']);
46
+ return result !== null && result.includes('already applied');
47
+ },
48
+ };
49
+ export default supabaseAdapter;
50
+ //# sourceMappingURL=supabase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../../../src/adapters/migration-runner/supabase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/adapters/migration-runner/types.ts"],"names":[],"mappings":""}