@delegance/claude-autopilot 2.5.0 → 5.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +169 -106
  3. package/bin/_launcher.js +77 -0
  4. package/bin/claude-autopilot.js +3 -0
  5. package/bin/guardrail.js +3 -0
  6. package/package.json +23 -9
  7. package/presets/generic/guardrail.config.yaml +35 -0
  8. package/presets/generic/stack.md +40 -0
  9. package/presets/nextjs-supabase/{autopilot.config.yaml → guardrail.config.yaml} +7 -0
  10. package/scripts/autoregress.ts +27 -11
  11. package/skills/autopilot/SKILL.md +170 -0
  12. package/skills/claude-autopilot.md +80 -0
  13. package/skills/guardrail.md +39 -0
  14. package/skills/migrate/SKILL.md +83 -0
  15. package/src/adapters/council/claude.ts +41 -0
  16. package/src/adapters/council/openai.ts +40 -0
  17. package/src/adapters/council/types.ts +7 -0
  18. package/src/adapters/loader.ts +7 -7
  19. package/src/adapters/review-engine/auto.ts +2 -2
  20. package/src/adapters/review-engine/claude.ts +9 -11
  21. package/src/adapters/review-engine/codex.ts +9 -11
  22. package/src/adapters/review-engine/gemini.ts +9 -11
  23. package/src/adapters/review-engine/openai-compatible.ts +10 -12
  24. package/src/adapters/review-engine/parse-output.ts +32 -6
  25. package/src/adapters/review-engine/prompt-builder.ts +19 -0
  26. package/src/adapters/review-engine/types.ts +1 -1
  27. package/src/adapters/vcs-host/commit-status.ts +39 -0
  28. package/src/adapters/vcs-host/github.ts +2 -2
  29. package/src/cli/baseline.ts +125 -0
  30. package/src/cli/ci.ts +11 -8
  31. package/src/cli/costs.ts +2 -2
  32. package/src/cli/council.ts +96 -0
  33. package/src/cli/detector.ts +21 -5
  34. package/src/cli/explain.ts +197 -0
  35. package/src/cli/fix.ts +173 -111
  36. package/src/cli/hook.ts +72 -27
  37. package/src/cli/ignore-helper.ts +116 -0
  38. package/src/cli/index.ts +355 -31
  39. package/src/cli/init.ts +12 -12
  40. package/src/cli/lsp.ts +200 -0
  41. package/src/cli/mcp.ts +206 -0
  42. package/src/cli/pr-comment.ts +5 -5
  43. package/src/cli/pr-desc.ts +168 -0
  44. package/src/cli/pr-review-comments.ts +3 -3
  45. package/src/cli/pr.ts +76 -0
  46. package/src/cli/preflight.ts +109 -32
  47. package/src/cli/report.ts +186 -0
  48. package/src/cli/run.ts +140 -36
  49. package/src/cli/scan.ts +233 -0
  50. package/src/cli/setup.ts +121 -15
  51. package/src/cli/test-gen.ts +125 -0
  52. package/src/cli/triage.ts +137 -0
  53. package/src/cli/watch.ts +52 -31
  54. package/src/cli/worker.ts +109 -0
  55. package/src/core/cache/review-cache.ts +2 -2
  56. package/src/core/chunking/index.ts +2 -2
  57. package/src/core/config/loader.ts +10 -10
  58. package/src/core/config/preset-resolver.ts +6 -6
  59. package/src/core/config/schema.ts +103 -2
  60. package/src/core/config/types.ts +57 -2
  61. package/src/core/council/config.ts +71 -0
  62. package/src/core/council/context.ts +17 -0
  63. package/src/core/council/runner.ts +83 -0
  64. package/src/core/council/types.ts +45 -0
  65. package/src/core/detect/llm-key.ts +89 -0
  66. package/src/core/detect/workspaces.ts +103 -0
  67. package/src/core/errors.ts +4 -4
  68. package/src/core/fix/generator.ts +149 -0
  69. package/src/core/ignore/index.ts +4 -4
  70. package/src/core/mcp/concurrency.ts +16 -0
  71. package/src/core/mcp/handlers/fix-finding.ts +126 -0
  72. package/src/core/mcp/handlers/get-capabilities.ts +62 -0
  73. package/src/core/mcp/handlers/get-findings.ts +36 -0
  74. package/src/core/mcp/handlers/review-diff.ts +65 -0
  75. package/src/core/mcp/handlers/scan-files.ts +65 -0
  76. package/src/core/mcp/handlers/validate-fix.ts +41 -0
  77. package/src/core/mcp/run-store.ts +85 -0
  78. package/src/core/mcp/workspace.ts +35 -0
  79. package/src/core/persist/baseline.ts +112 -0
  80. package/src/core/persist/cost-log.ts +1 -1
  81. package/src/core/persist/findings-cache.ts +1 -1
  82. package/src/core/persist/triage.ts +112 -0
  83. package/src/core/phases/static-rules.ts +18 -5
  84. package/src/core/pipeline/review-phase.ts +65 -26
  85. package/src/core/pipeline/run.ts +42 -10
  86. package/src/core/runtime/lock.ts +2 -2
  87. package/src/core/runtime/state.ts +2 -2
  88. package/src/core/schema-alignment/detector.ts +59 -0
  89. package/src/core/schema-alignment/extractor/index.ts +24 -0
  90. package/src/core/schema-alignment/extractor/prisma.ts +21 -0
  91. package/src/core/schema-alignment/extractor/sql.ts +99 -0
  92. package/src/core/schema-alignment/llm-check.ts +91 -0
  93. package/src/core/schema-alignment/scanner.ts +107 -0
  94. package/src/core/schema-alignment/types.ts +43 -0
  95. package/src/core/shell.ts +3 -3
  96. package/src/core/static-rules/registry.ts +17 -8
  97. package/src/core/static-rules/rules/brand-tokens.ts +145 -0
  98. package/src/core/static-rules/rules/hardcoded-secrets.ts +27 -1
  99. package/src/core/static-rules/rules/insecure-redirect.ts +67 -0
  100. package/src/core/static-rules/rules/missing-auth.ts +70 -0
  101. package/src/core/static-rules/rules/schema-alignment.ts +132 -0
  102. package/src/core/static-rules/rules/sql-injection.ts +71 -0
  103. package/src/core/static-rules/rules/ssrf.ts +63 -0
  104. package/src/core/static-rules/tailwind-extractor.ts +38 -0
  105. package/src/core/test-gen/coverage-analyzer.ts +93 -0
  106. package/src/core/test-gen/framework-detector.ts +21 -0
  107. package/src/core/test-gen/test-writer.ts +33 -0
  108. package/src/core/ui/design-context-loader.ts +87 -0
  109. package/src/core/worker/client.ts +46 -0
  110. package/src/core/worker/lockfile.ts +38 -0
  111. package/src/core/worker/server.ts +81 -0
  112. package/src/formatters/junit.ts +52 -0
  113. package/src/formatters/sarif.ts +2 -2
  114. package/src/index.ts +1 -2
  115. package/tests/snapshots/baselines/src-formatters-sarif.json +4 -4
  116. package/tests/snapshots/index.json +3 -3
  117. package/tests/snapshots/src-formatters-sarif.snap.ts +1 -1
  118. package/tests/snapshots/src-snapshots-impact-selector.snap.ts +3 -3
  119. package/tests/snapshots/src-snapshots-import-scanner.snap.ts +3 -3
  120. package/tests/snapshots/src-snapshots-serializer.snap.ts +2 -2
  121. package/bin/autopilot.js +0 -20
  122. package/skills/autopilot.md +0 -157
  123. /package/presets/go/{autopilot.config.yaml → guardrail.config.yaml} +0 -0
  124. /package/presets/python-fastapi/{autopilot.config.yaml → guardrail.config.yaml} +0 -0
  125. /package/presets/rails-postgres/{autopilot.config.yaml → guardrail.config.yaml} +0 -0
  126. /package/presets/t3/{autopilot.config.yaml → guardrail.config.yaml} +0 -0
  127. /package/{src → scripts}/snapshots/impact-selector.ts +0 -0
  128. /package/{src → scripts}/snapshots/import-scanner.ts +0 -0
  129. /package/{src → scripts}/snapshots/serializer.ts +0 -0
@@ -0,0 +1,81 @@
1
+ import * as http from 'node:http';
2
+ import * as net from 'node:net';
3
+ import type { GuardrailConfig } from '../config/types.ts';
4
+ import type { Finding } from '../findings/types.ts';
5
+
6
+ export interface WorkerServerOptions {
7
+ cwd: string;
8
+ onReview: (files: string[], config: GuardrailConfig) => Promise<{ findings: Finding[]; usage?: { costUSD: number } }>;
9
+ }
10
+
11
+ export interface WorkerServer {
12
+ port: number;
13
+ close(): Promise<void>;
14
+ }
15
+
16
+ async function getRandomPort(): Promise<number> {
17
+ return new Promise((resolve, reject) => {
18
+ const srv = net.createServer();
19
+ srv.listen(0, '127.0.0.1', () => {
20
+ const addr = srv.address() as net.AddressInfo;
21
+ srv.close(() => resolve(addr.port));
22
+ });
23
+ srv.on('error', reject);
24
+ });
25
+ }
26
+
27
+ export async function startWorkerServer(opts: WorkerServerOptions): Promise<WorkerServer> {
28
+ const port = await getRandomPort();
29
+ let jobsProcessed = 0;
30
+ const startedAt = Date.now();
31
+
32
+ const server = http.createServer(async (req, res) => {
33
+ if (req.method === 'GET' && req.url === '/status') {
34
+ res.writeHead(200, { 'Content-Type': 'application/json' });
35
+ res.end(JSON.stringify({
36
+ pid: process.pid, port, jobsProcessed,
37
+ queueDepth: 0,
38
+ uptimeMs: Date.now() - startedAt,
39
+ }));
40
+ return;
41
+ }
42
+
43
+ if (req.method === 'POST' && req.url === '/stop') {
44
+ res.writeHead(200);
45
+ res.end('{"ok":true}');
46
+ setImmediate(() => server.close());
47
+ return;
48
+ }
49
+
50
+ if (req.method === 'POST' && req.url === '/review') {
51
+ let body = '';
52
+ req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
53
+ req.on('end', async () => {
54
+ try {
55
+ const { files, config } = JSON.parse(body) as { files: string[]; config: GuardrailConfig };
56
+ const result = await opts.onReview(files, config);
57
+ jobsProcessed++;
58
+ res.writeHead(200, { 'Content-Type': 'application/json' });
59
+ res.end(JSON.stringify(result));
60
+ } catch (err) {
61
+ res.writeHead(500, { 'Content-Type': 'application/json' });
62
+ res.end(JSON.stringify({ error: String(err) }));
63
+ }
64
+ });
65
+ return;
66
+ }
67
+
68
+ res.writeHead(404);
69
+ res.end('Not found');
70
+ });
71
+
72
+ await new Promise<void>((resolve, reject) => {
73
+ server.listen(port, '127.0.0.1', () => resolve());
74
+ server.on('error', reject);
75
+ });
76
+
77
+ return {
78
+ port,
79
+ close: () => new Promise<void>(resolve => server.close(() => resolve())),
80
+ };
81
+ }
@@ -0,0 +1,52 @@
1
+ import type { RunResult } from '../core/pipeline/run.ts';
2
+
3
+ function escapeXml(s: string): string {
4
+ return s
5
+ .replace(/&/g, '&amp;')
6
+ .replace(/</g, '&lt;')
7
+ .replace(/>/g, '&gt;')
8
+ .replace(/"/g, '&quot;')
9
+ .replace(/'/g, '&apos;');
10
+ }
11
+
12
+ export function toJUnit(result: RunResult, opts: { suiteName?: string } = {}): string {
13
+ const name = opts.suiteName ?? 'guardrail';
14
+ const findings = result.allFindings;
15
+ const failures = findings.filter(f => f.severity === 'critical').length;
16
+ const total = findings.length;
17
+ const time = (result.durationMs / 1000).toFixed(3);
18
+
19
+ const lines: string[] = [
20
+ '<?xml version="1.0" encoding="UTF-8"?>',
21
+ `<testsuites name="${escapeXml(name)}" tests="${total}" failures="${failures}" time="${time}">`,
22
+ ` <testsuite name="${escapeXml(name)}" tests="${total}" failures="${failures}" errors="0" time="${time}">`,
23
+ ];
24
+
25
+ if (findings.length === 0) {
26
+ lines.push(` <testcase name="no findings" classname="${escapeXml(name)}" />`);
27
+ }
28
+
29
+ for (const f of findings) {
30
+ const loc = f.line ? `${f.file}:${f.line}` : f.file;
31
+ const testName = escapeXml(`[${f.severity.toUpperCase()}] ${f.category} — ${loc}`);
32
+ const classname = escapeXml(f.file.replace(/\//g, '.').replace(/\.[tj]sx?$/, ''));
33
+ const body = escapeXml(f.message + (f.suggestion ? `\n${f.suggestion}` : ''));
34
+
35
+ if (f.severity === 'critical') {
36
+ lines.push(
37
+ ` <testcase name="${testName}" classname="${classname}">`,
38
+ ` <failure type="${escapeXml(f.category)}" message="${escapeXml(f.message)}">${body}</failure>`,
39
+ ` </testcase>`,
40
+ );
41
+ } else {
42
+ lines.push(
43
+ ` <testcase name="${testName}" classname="${classname}">`,
44
+ ` <system-out>${body}</system-out>`,
45
+ ` </testcase>`,
46
+ );
47
+ }
48
+ }
49
+
50
+ lines.push(' </testsuite>', '</testsuites>');
51
+ return lines.join('\n');
52
+ }
@@ -91,9 +91,9 @@ export function toSarif(
91
91
  runs: [{
92
92
  tool: {
93
93
  driver: {
94
- name: 'claude-autopilot',
94
+ name: 'guardrail',
95
95
  version: opts.toolVersion,
96
- informationUri: 'https://github.com/axledbetter/claude-autopilot',
96
+ informationUri: 'https://github.com/axledbetter/guardrail',
97
97
  rules: [...rulesMap.values()],
98
98
  },
99
99
  },
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export type { Finding, Severity, FindingSource } from './core/findings/types.js';
2
2
  export type { RunResult, RunInput, PhaseResult } from './core/pipeline/run.js';
3
- export type { AutopilotConfig, AdapterRef, AdapterReference } from './core/config/types.js';
4
- export { normalizeSnapshot } from './snapshots/serializer.js';
3
+ export type { GuardrailConfig, AdapterRef, AdapterReference } from './core/config/types.js';
@@ -13,9 +13,9 @@
13
13
  {
14
14
  "tool": {
15
15
  "driver": {
16
- "name": "claude-autopilot",
16
+ "name": "guardrail",
17
17
  "version": "9.9.9",
18
- "informationUri": "https://github.com/axledbetter/claude-autopilot",
18
+ "informationUri": "https://github.com/axledbetter/guardrail",
19
19
  "rules": [
20
20
  {
21
21
  "id": "no-secrets",
@@ -137,9 +137,9 @@
137
137
  {
138
138
  "tool": {
139
139
  "driver": {
140
- "name": "claude-autopilot",
140
+ "name": "guardrail",
141
141
  "version": "1.2.3",
142
- "informationUri": "https://github.com/axledbetter/claude-autopilot",
142
+ "informationUri": "https://github.com/axledbetter/guardrail",
143
143
  "rules": [
144
144
  {
145
145
  "id": "cat-a",
@@ -3,12 +3,12 @@
3
3
  "src/formatters/sarif.ts"
4
4
  ],
5
5
  "tests/snapshots/src-snapshots-impact-selector.snap.ts": [
6
- "src/snapshots/impact-selector.ts"
6
+ "scripts/snapshots/impact-selector.ts"
7
7
  ],
8
8
  "tests/snapshots/src-snapshots-import-scanner.snap.ts": [
9
- "src/snapshots/import-scanner.ts"
9
+ "scripts/snapshots/import-scanner.ts"
10
10
  ],
11
11
  "tests/snapshots/src-snapshots-serializer.snap.ts": [
12
- "src/snapshots/serializer.ts"
12
+ "scripts/snapshots/serializer.ts"
13
13
  ]
14
14
  }
@@ -10,7 +10,7 @@ import { fileURLToPath } from 'node:url';
10
10
  import * as path from 'node:path';
11
11
 
12
12
  import { normalizeSarifUri, toSarif } from '../../src/formatters/sarif.ts';
13
- import { normalizeSnapshot } from '../../src/snapshots/serializer.ts';
13
+ import { normalizeSnapshot } from '../../scripts/snapshots/serializer.ts';
14
14
 
15
15
  const SLUG = 'src-formatters-sarif';
16
16
  const baselineRaw =
@@ -1,4 +1,4 @@
1
- // @snapshot-for: src/snapshots/impact-selector.ts
1
+ // @snapshot-for: scripts/snapshots/impact-selector.ts
2
2
  // @generated-at: 2026-04-21T17:42:06.431Z
3
3
  // @source-commit: d207869
4
4
  // @generator-version: 1.0.0-alpha.6
@@ -9,8 +9,8 @@ import assert from 'node:assert/strict';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import * as path from 'node:path';
11
11
 
12
- import { selectSnapshots } from '../../src/snapshots/impact-selector.ts';
13
- import { normalizeSnapshot } from '../../src/snapshots/serializer.ts';
12
+ import { selectSnapshots } from '../../scripts/snapshots/impact-selector.ts';
13
+ import { normalizeSnapshot } from '../../scripts/snapshots/serializer.ts';
14
14
 
15
15
  const SLUG = 'src-snapshots-impact-selector';
16
16
  const baselineRaw = process.env.CAPTURE_BASELINE === '1' ? '{}' : fs.readFileSync(fileURLToPath(new URL('./baselines/src-snapshots-impact-selector.json', import.meta.url)), 'utf8');
@@ -1,4 +1,4 @@
1
- // @snapshot-for: src/snapshots/import-scanner.ts
1
+ // @snapshot-for: scripts/snapshots/import-scanner.ts
2
2
  // @generated-at: 2026-04-21T17:42:06.431Z
3
3
  // @source-commit: d207869
4
4
  // @generator-version: 1.0.0-alpha.6
@@ -9,8 +9,8 @@ import assert from 'node:assert/strict';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import * as path from 'node:path';
11
11
 
12
- import { buildImportMap } from '../../src/snapshots/import-scanner.ts';
13
- import { normalizeSnapshot } from '../../src/snapshots/serializer.ts';
12
+ import { buildImportMap } from '../../scripts/snapshots/import-scanner.ts';
13
+ import { normalizeSnapshot } from '../../scripts/snapshots/serializer.ts';
14
14
 
15
15
  const SLUG = 'src-snapshots-import-scanner';
16
16
  void SLUG;
@@ -1,4 +1,4 @@
1
- // @snapshot-for: src/snapshots/serializer.ts
1
+ // @snapshot-for: scripts/snapshots/serializer.ts
2
2
  // @generated-at: 2026-04-21T17:42:06.431Z
3
3
  // @source-commit: d207869
4
4
  // @generator-version: 1.0.0-alpha.6
@@ -8,7 +8,7 @@ import { describe, it } from 'node:test';
8
8
  import assert from 'node:assert/strict';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import * as path from 'node:path';
11
- import { normalizeSnapshot } from '../../src/snapshots/serializer.ts';
11
+ import { normalizeSnapshot } from '../../scripts/snapshots/serializer.ts';
12
12
 
13
13
  const SLUG = 'src-snapshots-serializer';
14
14
  const baselineRaw = process.env.CAPTURE_BASELINE === '1' ? '{}' : fs.readFileSync(fileURLToPath(new URL('./baselines/src-snapshots-serializer.json', import.meta.url)), 'utf8');
package/bin/autopilot.js DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env node
2
- import { fileURLToPath } from 'node:url';
3
- import { spawnSync } from 'node:child_process';
4
- import * as fs from 'node:fs';
5
- import * as path from 'node:path';
6
-
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- const entrypoint = path.resolve(__dirname, '..', 'src', 'cli', 'index.ts');
9
-
10
- // Locate tsx: own node_modules (dev) → consumer's node_modules/.bin → PATH
11
- function findTsx() {
12
- const own = path.resolve(__dirname, '..', 'node_modules', '.bin', 'tsx');
13
- if (fs.existsSync(own)) return own;
14
- const consumer = path.resolve(__dirname, '..', '..', '..', '.bin', 'tsx');
15
- if (fs.existsSync(consumer)) return consumer;
16
- return 'tsx';
17
- }
18
-
19
- const result = spawnSync(findTsx(), [entrypoint, ...process.argv.slice(2)], { stdio: 'inherit' });
20
- process.exit(result.status ?? 1);
@@ -1,157 +0,0 @@
1
- ---
2
- name: autopilot
3
- description: Run the @delegance/claude-autopilot code review pipeline — static rules, LLM review, snapshot regression. Use before any PR or after completing a feature.
4
- ---
5
-
6
- # autopilot — Code Review Pipeline
7
-
8
- Runs static rules, optional LLM review, and impact-aware snapshot regression on git-changed files. Auto-detects stack, protected paths, and test command from the project. Outputs findings inline and optionally as SARIF for GitHub Code Scanning.
9
-
10
- ## When to Use
11
-
12
- - Before creating a PR: `npx autopilot run --base main`
13
- - Inside CI: `npx autopilot ci` (one-command, posts PR comment + SARIF)
14
- - Dev loop: `npx autopilot watch`
15
- - First setup: `npx autopilot setup && npx autopilot doctor`
16
-
17
- ## Prerequisites
18
-
19
- ```bash
20
- npx autopilot doctor # checks Node 22+, tsx, gh CLI, API key, git config
21
- ```
22
-
23
- ## Commands
24
-
25
- ### `run` — pipeline on git-changed files
26
-
27
- ```bash
28
- npx autopilot run # diff HEAD~1 (default)
29
- npx autopilot run --base main # diff against branch
30
- npx autopilot run --files src/a.ts,src/b.ts # explicit files
31
- npx autopilot run --dry-run # show what would run
32
- npx autopilot run --post-comments # post/update summary on open PR
33
- npx autopilot run --format sarif --output autopilot.sarif
34
- ```
35
-
36
- ### `ci` — opinionated CI entrypoint
37
-
38
- ```bash
39
- npx autopilot ci # base=GITHUB_BASE_REF, post-comments=true, sarif written
40
- npx autopilot ci --base develop
41
- npx autopilot ci --no-post-comments
42
- npx autopilot ci --output results.sarif
43
- ```
44
-
45
- Equivalent to `run --base <ref> --post-comments --format sarif --output <path>`. Base ref resolves from `GITHUB_BASE_REF` → `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` → `HEAD~1`.
46
-
47
- ### `setup` — zero-prompt first run
48
-
49
- ```bash
50
- npx autopilot setup # auto-detect stack, write config, install hook
51
- npx autopilot setup --force # overwrite existing config
52
- ```
53
-
54
- Auto-detects: Go, Rails, FastAPI, T3, Next.js+Supabase. Runs doctor at end.
55
-
56
- ### `watch` — dev loop
57
-
58
- ```bash
59
- npx autopilot watch
60
- npx autopilot watch --debounce 500
61
- ```
62
-
63
- ### `autoregress` — snapshot regression
64
-
65
- ```bash
66
- npx autopilot autoregress generate # create baselines for changed files
67
- npx autopilot autoregress run # run impact-selected snapshots
68
- npx autopilot autoregress run --all # run all snapshots
69
- npx autopilot autoregress diff # show diffs vs baselines
70
- npx autopilot autoregress update # overwrite baselines after intentional change
71
- ```
72
-
73
- ### `hook` — pre-push git hook
74
-
75
- ```bash
76
- npx autopilot hook install
77
- npx autopilot hook uninstall
78
- npx autopilot hook status
79
- ```
80
-
81
- ## LLM Review Adapters
82
-
83
- Configure via `reviewEngine.adapter` in `autopilot.config.yaml`:
84
-
85
- | Adapter | Key env var | Notes |
86
- |---------|-------------|-------|
87
- | `auto` | any | Picks available provider; prefers the one already used in code |
88
- | `claude` | `ANTHROPIC_API_KEY` | Claude Opus 4.7 |
89
- | `gemini` | `GEMINI_API_KEY` or `GOOGLE_API_KEY` | Gemini 2.5 Pro, 1M context |
90
- | `codex` | `OPENAI_API_KEY` | gpt-5.3-codex via responses API |
91
- | `openai-compatible` | configurable | Any OpenAI-API endpoint (Groq, Ollama, Together) |
92
-
93
- `auto` priority order: Anthropic → Gemini → OpenAI → Groq. When multiple keys are present, `auto` scans the project source files and prefers the provider already referenced most.
94
-
95
- ## Auto-Detection
96
-
97
- When config fields are absent, `autopilot run` fills them in automatically:
98
-
99
- - **stack** — parsed from `package.json`, `go.mod`, `Cargo.toml`, `requirements.txt`, `Gemfile`; injected into review prompt
100
- - **protectedPaths** — migration dirs (`data/deltas/`, `migrations/`, `prisma/migrations/`, etc.), schema files, infra dirs (`terraform/`, `.github/workflows/`)
101
- - **testCommand** — re-detected at run time from project files; set `testCommand: null` to disable explicitly
102
- - **git context** — branch + last commit injected as `Change context: branch: X | last commit: Y`
103
-
104
- Detection lines are printed dim after the file count: `auto-detected: stack: Next.js + Supabase | protected: data/deltas/** ...`
105
-
106
- ## Interpreting Results
107
-
108
- **Exit code 0** — pass or warnings only. Safe to proceed.
109
- **Exit code 1** — blocking findings. Fix before merging.
110
-
111
- Finding severities: `critical` blocks merge, `warning` should fix, `note` informational.
112
-
113
- PR comment (via `--post-comments` or `ci`): status badge, phase table, critical/warning findings, cost footer. Edits existing comment on re-runs (tracked via `<!-- autopilot-review -->` marker).
114
-
115
- SARIF output: upload with `github/codeql-action/upload-sarif@v3` for inline PR diff annotations. Also auto-emits `::error`/`::warning` annotations when `GITHUB_ACTIONS=true`.
116
-
117
- ## Config (`autopilot.config.yaml`)
118
-
119
- ```yaml
120
- configVersion: 1
121
- reviewEngine:
122
- adapter: auto # auto, claude, gemini, codex, openai-compatible
123
- testCommand: npm test # null to disable
124
- protectedPaths: # auto-detected if omitted
125
- - data/deltas/**
126
- - .github/workflows/**
127
- staticRules:
128
- - hardcoded-secrets
129
- - npm-audit
130
- - package-lock-sync
131
- - console-log
132
- - todo-fixme
133
- - large-file
134
- - missing-tests
135
- ```
136
-
137
- Preset defaults at: `node_modules/@delegance/claude-autopilot/presets/<name>/autopilot.config.yaml`
138
-
139
- ## GitHub Actions
140
-
141
- ```yaml
142
- - uses: axledbetter/claude-autopilot/.github/actions/ci@main
143
- with:
144
- anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} # or openai/gemini/groq
145
- ```
146
-
147
- Runs `npx autopilot ci`, uploads SARIF, annotates PR diff. All API key inputs optional — whichever is set gets used by `auto`.
148
-
149
- ## Integration with Development Pipeline
150
-
151
- ```bash
152
- # After implementing feature
153
- npx autopilot run --base main
154
-
155
- # If findings → fix → re-run (max 3 iterations)
156
- # If clean → push → create PR
157
- ```
File without changes
File without changes
File without changes