@delegance/claude-autopilot 5.5.2 → 7.2.0

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 (150) hide show
  1. package/CHANGELOG.md +1776 -6
  2. package/README.md +65 -1
  3. package/bin/_launcher.js +38 -23
  4. package/dist/src/adapters/council/openai.js +12 -6
  5. package/dist/src/adapters/deploy/_http.d.ts +43 -0
  6. package/dist/src/adapters/deploy/_http.js +99 -0
  7. package/dist/src/adapters/deploy/fly.d.ts +206 -0
  8. package/dist/src/adapters/deploy/fly.js +696 -0
  9. package/dist/src/adapters/deploy/index.d.ts +2 -0
  10. package/dist/src/adapters/deploy/index.js +33 -0
  11. package/dist/src/adapters/deploy/render.d.ts +181 -0
  12. package/dist/src/adapters/deploy/render.js +550 -0
  13. package/dist/src/adapters/deploy/types.d.ts +67 -3
  14. package/dist/src/adapters/deploy/vercel.d.ts +17 -1
  15. package/dist/src/adapters/deploy/vercel.js +29 -49
  16. package/dist/src/adapters/pricing.d.ts +36 -0
  17. package/dist/src/adapters/pricing.js +40 -0
  18. package/dist/src/adapters/review-engine/codex.js +10 -7
  19. package/dist/src/cli/autopilot.d.ts +75 -0
  20. package/dist/src/cli/autopilot.js +750 -0
  21. package/dist/src/cli/brainstorm.d.ts +23 -0
  22. package/dist/src/cli/brainstorm.js +131 -0
  23. package/dist/src/cli/costs.d.ts +15 -1
  24. package/dist/src/cli/costs.js +99 -10
  25. package/dist/src/cli/dashboard/index.d.ts +5 -0
  26. package/dist/src/cli/dashboard/index.js +49 -0
  27. package/dist/src/cli/dashboard/login.d.ts +22 -0
  28. package/dist/src/cli/dashboard/login.js +260 -0
  29. package/dist/src/cli/dashboard/logout.d.ts +12 -0
  30. package/dist/src/cli/dashboard/logout.js +45 -0
  31. package/dist/src/cli/dashboard/status.d.ts +30 -0
  32. package/dist/src/cli/dashboard/status.js +65 -0
  33. package/dist/src/cli/dashboard/upload.d.ts +16 -0
  34. package/dist/src/cli/dashboard/upload.js +48 -0
  35. package/dist/src/cli/deploy.d.ts +3 -3
  36. package/dist/src/cli/deploy.js +34 -9
  37. package/dist/src/cli/engine-flag-deprecation.d.ts +14 -0
  38. package/dist/src/cli/engine-flag-deprecation.js +20 -0
  39. package/dist/src/cli/fix.d.ts +18 -0
  40. package/dist/src/cli/fix.js +105 -11
  41. package/dist/src/cli/help-text.d.ts +52 -0
  42. package/dist/src/cli/help-text.js +416 -0
  43. package/dist/src/cli/implement.d.ts +91 -0
  44. package/dist/src/cli/implement.js +196 -0
  45. package/dist/src/cli/index.d.ts +2 -1
  46. package/dist/src/cli/index.js +774 -245
  47. package/dist/src/cli/json-envelope.d.ts +187 -0
  48. package/dist/src/cli/json-envelope.js +270 -0
  49. package/dist/src/cli/json-mode.d.ts +33 -0
  50. package/dist/src/cli/json-mode.js +201 -0
  51. package/dist/src/cli/migrate.d.ts +111 -0
  52. package/dist/src/cli/migrate.js +305 -0
  53. package/dist/src/cli/plan.d.ts +81 -0
  54. package/dist/src/cli/plan.js +149 -0
  55. package/dist/src/cli/pr.d.ts +106 -0
  56. package/dist/src/cli/pr.js +191 -19
  57. package/dist/src/cli/preflight.js +26 -0
  58. package/dist/src/cli/review.d.ts +27 -0
  59. package/dist/src/cli/review.js +126 -0
  60. package/dist/src/cli/runs-watch-renderer.d.ts +45 -0
  61. package/dist/src/cli/runs-watch-renderer.js +275 -0
  62. package/dist/src/cli/runs-watch.d.ts +41 -0
  63. package/dist/src/cli/runs-watch.js +395 -0
  64. package/dist/src/cli/runs.d.ts +122 -0
  65. package/dist/src/cli/runs.js +902 -0
  66. package/dist/src/cli/scaffold.d.ts +39 -0
  67. package/dist/src/cli/scaffold.js +287 -0
  68. package/dist/src/cli/scan.d.ts +93 -0
  69. package/dist/src/cli/scan.js +166 -40
  70. package/dist/src/cli/setup.d.ts +30 -0
  71. package/dist/src/cli/setup.js +137 -0
  72. package/dist/src/cli/spec.d.ts +66 -0
  73. package/dist/src/cli/spec.js +132 -0
  74. package/dist/src/cli/validate.d.ts +29 -0
  75. package/dist/src/cli/validate.js +131 -0
  76. package/dist/src/core/config/schema.d.ts +9 -0
  77. package/dist/src/core/config/schema.js +7 -0
  78. package/dist/src/core/config/types.d.ts +11 -0
  79. package/dist/src/core/council/runner.d.ts +10 -1
  80. package/dist/src/core/council/runner.js +25 -3
  81. package/dist/src/core/council/types.d.ts +7 -0
  82. package/dist/src/core/errors.d.ts +1 -1
  83. package/dist/src/core/errors.js +11 -0
  84. package/dist/src/core/logging/redaction.d.ts +13 -0
  85. package/dist/src/core/logging/redaction.js +20 -0
  86. package/dist/src/core/migrate/schema-validator.js +15 -1
  87. package/dist/src/core/phases/static-rules.d.ts +5 -1
  88. package/dist/src/core/phases/static-rules.js +2 -5
  89. package/dist/src/core/run-state/budget.d.ts +88 -0
  90. package/dist/src/core/run-state/budget.js +141 -0
  91. package/dist/src/core/run-state/cli-internal.d.ts +21 -0
  92. package/dist/src/core/run-state/cli-internal.js +174 -0
  93. package/dist/src/core/run-state/events.d.ts +59 -0
  94. package/dist/src/core/run-state/events.js +512 -0
  95. package/dist/src/core/run-state/lock.d.ts +61 -0
  96. package/dist/src/core/run-state/lock.js +206 -0
  97. package/dist/src/core/run-state/phase-context.d.ts +60 -0
  98. package/dist/src/core/run-state/phase-context.js +108 -0
  99. package/dist/src/core/run-state/phase-registry.d.ts +137 -0
  100. package/dist/src/core/run-state/phase-registry.js +162 -0
  101. package/dist/src/core/run-state/phase-runner.d.ts +80 -0
  102. package/dist/src/core/run-state/phase-runner.js +447 -0
  103. package/dist/src/core/run-state/provider-readback.d.ts +130 -0
  104. package/dist/src/core/run-state/provider-readback.js +426 -0
  105. package/dist/src/core/run-state/replay-decision.d.ts +69 -0
  106. package/dist/src/core/run-state/replay-decision.js +144 -0
  107. package/dist/src/core/run-state/resolve-engine.d.ts +45 -0
  108. package/dist/src/core/run-state/resolve-engine.js +74 -0
  109. package/dist/src/core/run-state/resume-preflight.d.ts +66 -0
  110. package/dist/src/core/run-state/resume-preflight.js +116 -0
  111. package/dist/src/core/run-state/run-phase-with-lifecycle.d.ts +69 -0
  112. package/dist/src/core/run-state/run-phase-with-lifecycle.js +193 -0
  113. package/dist/src/core/run-state/runs.d.ts +57 -0
  114. package/dist/src/core/run-state/runs.js +288 -0
  115. package/dist/src/core/run-state/snapshot.d.ts +14 -0
  116. package/dist/src/core/run-state/snapshot.js +114 -0
  117. package/dist/src/core/run-state/state.d.ts +40 -0
  118. package/dist/src/core/run-state/state.js +164 -0
  119. package/dist/src/core/run-state/types.d.ts +284 -0
  120. package/dist/src/core/run-state/types.js +19 -0
  121. package/dist/src/core/run-state/ulid.d.ts +11 -0
  122. package/dist/src/core/run-state/ulid.js +95 -0
  123. package/dist/src/core/schema-alignment/extractor/index.d.ts +1 -1
  124. package/dist/src/core/schema-alignment/extractor/index.js +2 -2
  125. package/dist/src/core/schema-alignment/extractor/prisma.d.ts +13 -1
  126. package/dist/src/core/schema-alignment/extractor/prisma.js +65 -10
  127. package/dist/src/core/schema-alignment/git-history.d.ts +19 -0
  128. package/dist/src/core/schema-alignment/git-history.js +53 -0
  129. package/dist/src/core/static-rules/rules/brand-tokens.js +2 -2
  130. package/dist/src/core/static-rules/rules/schema-alignment.js +14 -4
  131. package/dist/src/dashboard/auto-upload.d.ts +26 -0
  132. package/dist/src/dashboard/auto-upload.js +107 -0
  133. package/dist/src/dashboard/config.d.ts +22 -0
  134. package/dist/src/dashboard/config.js +109 -0
  135. package/dist/src/dashboard/upload/canonical.d.ts +3 -0
  136. package/dist/src/dashboard/upload/canonical.js +16 -0
  137. package/dist/src/dashboard/upload/chain.d.ts +9 -0
  138. package/dist/src/dashboard/upload/chain.js +27 -0
  139. package/dist/src/dashboard/upload/snapshot.d.ts +23 -0
  140. package/dist/src/dashboard/upload/snapshot.js +66 -0
  141. package/dist/src/dashboard/upload/uploader.d.ts +54 -0
  142. package/dist/src/dashboard/upload/uploader.js +330 -0
  143. package/package.json +19 -3
  144. package/scripts/autoregress.ts +1 -1
  145. package/scripts/test-runner.mjs +4 -0
  146. package/skills/claude-autopilot.md +1 -1
  147. package/skills/make-interfaces-feel-better/SKILL.md +104 -0
  148. package/skills/simplify-ui/SKILL.md +103 -0
  149. package/skills/ui/SKILL.md +117 -0
  150. package/skills/ui-ux-pro-max/SKILL.md +90 -0
@@ -34,6 +34,16 @@ export interface VercelDeployAdapterOptions {
34
34
  sleepImpl?: (ms: number) => Promise<void>;
35
35
  /** Wall-clock source — tests pass a controllable counter. */
36
36
  nowImpl?: () => number;
37
+ /**
38
+ * Optional caller-supplied redaction patterns (in addition to the
39
+ * built-in default set in `core/logging/redaction.ts`). Typically wired
40
+ * from `config.persistence.redactionPatterns` by the CLI; tests omit it.
41
+ *
42
+ * Phase 5 of v5.6 brought Vercel into parity with Fly/Render — the v5.4
43
+ * adapter previously emitted `output` lines verbatim, which was a real
44
+ * leak hazard for any build that echoed an env var into stdout.
45
+ */
46
+ redactionPatterns?: readonly string[];
37
47
  }
38
48
  /**
39
49
  * Vercel deploy adapter.
@@ -52,6 +62,7 @@ export declare class VercelDeployAdapter implements DeployAdapter {
52
62
  private readonly fetchImpl;
53
63
  private readonly sleep;
54
64
  private readonly now;
65
+ private readonly redactionPatterns;
55
66
  constructor(opts: VercelDeployAdapterOptions);
56
67
  deploy(input: DeployInput): Promise<DeployResult>;
57
68
  status(input: DeployStatusInput): Promise<DeployStatusResult>;
@@ -95,6 +106,12 @@ export declare class VercelDeployAdapter implements DeployAdapter {
95
106
  * display (defaults to 5).
96
107
  */
97
108
  listDeployments(limit?: number, signal?: AbortSignal): Promise<VercelDeployListItem[]>;
109
+ /**
110
+ * Apply the adapter's redaction patterns to a streamed log line's `text`.
111
+ * Mirrors the Fly/Render redactLine helpers introduced in v5.6 so secrets
112
+ * never escape the adapter via streamed log entries.
113
+ */
114
+ private redactLine;
98
115
  /**
99
116
  * Returns the deployment immediately preceding the current production
100
117
  * deployment, or `null` if no rollback target exists.
@@ -111,7 +128,6 @@ export declare class VercelDeployAdapter implements DeployAdapter {
111
128
  private urlWithTeam;
112
129
  private buildLogsUrl;
113
130
  private assertOkOrThrow;
114
- private fetchWithRetry;
115
131
  /**
116
132
  * Like `fetchWithRetry` but tuned for the events endpoint:
117
133
  * - 404 right after a deploy POST is a known race (the deploy hasn't yet
@@ -10,6 +10,8 @@
10
10
  //
11
11
  // Spec: docs/specs/v5.4-vercel-adapter.md
12
12
  import { GuardrailError } from "../../core/errors.js";
13
+ import { redactLogLines } from "../../core/logging/redaction.js";
14
+ import { fetchWithRetry, safeReadBody } from "./_http.js";
13
15
  const VERCEL_API_BASE = 'https://api.vercel.com';
14
16
  /**
15
17
  * Vercel deploy adapter.
@@ -28,6 +30,7 @@ export class VercelDeployAdapter {
28
30
  fetchImpl;
29
31
  sleep;
30
32
  now;
33
+ redactionPatterns;
31
34
  constructor(opts) {
32
35
  const token = opts.token ?? process.env.VERCEL_TOKEN;
33
36
  if (!token) {
@@ -45,6 +48,7 @@ export class VercelDeployAdapter {
45
48
  this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
46
49
  this.sleep = opts.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
47
50
  this.now = opts.nowImpl ?? Date.now;
51
+ this.redactionPatterns = opts.redactionPatterns;
48
52
  }
49
53
  async deploy(input) {
50
54
  const start = this.now();
@@ -65,12 +69,12 @@ export class VercelDeployAdapter {
65
69
  else if (input.ref) {
66
70
  body.gitSource = { type: 'github', ref: input.ref };
67
71
  }
68
- const res = await this.fetchWithRetry(url, {
72
+ const res = await fetchWithRetry(this.fetchImpl, url, {
69
73
  method: 'POST',
70
74
  headers: this.headers(),
71
75
  body: JSON.stringify(body),
72
76
  signal: input.signal,
73
- });
77
+ }, { sleepImpl: this.sleep, provider: 'vercel' });
74
78
  await this.assertOkOrThrow(res, 'create deployment');
75
79
  const created = (await res.json());
76
80
  if (!created.id) {
@@ -90,11 +94,11 @@ export class VercelDeployAdapter {
90
94
  async status(input) {
91
95
  const start = this.now();
92
96
  const url = this.urlWithTeam(`${VERCEL_API_BASE}/v13/deployments/${encodeURIComponent(input.deployId)}`);
93
- const res = await this.fetchWithRetry(url, {
97
+ const res = await fetchWithRetry(this.fetchImpl, url, {
94
98
  method: 'GET',
95
99
  headers: this.headers(),
96
100
  signal: input.signal,
97
- });
101
+ }, { sleepImpl: this.sleep, provider: 'vercel' });
98
102
  await this.assertOkOrThrow(res, 'get deployment');
99
103
  const data = (await res.json());
100
104
  const state = data.readyState ?? data.state;
@@ -133,7 +137,7 @@ export class VercelDeployAdapter {
133
137
  if (buf.length > 0) {
134
138
  const line = parseEventLine(buf);
135
139
  if (line)
136
- yield line;
140
+ yield this.redactLine(line);
137
141
  }
138
142
  return;
139
143
  }
@@ -144,7 +148,7 @@ export class VercelDeployAdapter {
144
148
  buf = buf.slice(nl + 1);
145
149
  const line = parseEventLine(raw);
146
150
  if (line)
147
- yield line;
151
+ yield this.redactLine(line);
148
152
  nl = buf.indexOf('\n');
149
153
  }
150
154
  }
@@ -181,12 +185,12 @@ export class VercelDeployAdapter {
181
185
  targetId = prev.id;
182
186
  }
183
187
  const url = this.urlWithTeam(`${VERCEL_API_BASE}/v13/deployments/${encodeURIComponent(targetId)}/promote`);
184
- const res = await this.fetchWithRetry(url, {
188
+ const res = await fetchWithRetry(this.fetchImpl, url, {
185
189
  method: 'POST',
186
190
  headers: this.headers(),
187
191
  body: '{}',
188
192
  signal: input.signal,
189
- });
193
+ }, { sleepImpl: this.sleep, provider: 'vercel' });
190
194
  await this.assertOkOrThrow(res, 'promote deployment');
191
195
  // Promote responses are typically empty (204) or echo the deployment.
192
196
  // Be defensive — parse if there's a body, otherwise carry on with the
@@ -205,7 +209,7 @@ export class VercelDeployAdapter {
205
209
  deployUrl: data?.url ? `https://${data.url}` : undefined,
206
210
  buildLogsUrl: this.buildLogsUrl(targetId),
207
211
  durationMs: this.now() - start,
208
- output: `Vercel deployment ${targetId} promoted to production`,
212
+ output: redactLogLines(`Vercel deployment ${targetId} promoted to production`, this.redactionPatterns),
209
213
  };
210
214
  }
211
215
  /**
@@ -224,11 +228,11 @@ export class VercelDeployAdapter {
224
228
  `?projectId=${encodeURIComponent(this.project)}` +
225
229
  `&limit=${encodeURIComponent(String(limit))}` +
226
230
  `&target=production`);
227
- const res = await this.fetchWithRetry(url, {
231
+ const res = await fetchWithRetry(this.fetchImpl, url, {
228
232
  method: 'GET',
229
233
  headers: this.headers(),
230
234
  signal,
231
- });
235
+ }, { sleepImpl: this.sleep, provider: 'vercel' });
232
236
  await this.assertOkOrThrow(res, 'list deployments');
233
237
  const data = (await res.json());
234
238
  return Array.isArray(data.deployments) ? data.deployments : [];
@@ -236,6 +240,14 @@ export class VercelDeployAdapter {
236
240
  // ─────────────────────────────────────────────────────────────────────────────
237
241
  // private helpers
238
242
  // ─────────────────────────────────────────────────────────────────────────────
243
+ /**
244
+ * Apply the adapter's redaction patterns to a streamed log line's `text`.
245
+ * Mirrors the Fly/Render redactLine helpers introduced in v5.6 so secrets
246
+ * never escape the adapter via streamed log entries.
247
+ */
248
+ redactLine(line) {
249
+ return { ...line, text: redactLogLines(line.text, this.redactionPatterns) };
250
+ }
239
251
  /**
240
252
  * Returns the deployment immediately preceding the current production
241
253
  * deployment, or `null` if no rollback target exists.
@@ -265,14 +277,14 @@ export class VercelDeployAdapter {
265
277
  deployId,
266
278
  durationMs: this.now() - start,
267
279
  buildLogsUrl: this.buildLogsUrl(deployId),
268
- output: `Deployment still in progress after ${this.maxPollMs}ms — check ${this.buildLogsUrl(deployId)}`,
280
+ output: redactLogLines(`Deployment still in progress after ${this.maxPollMs}ms — check ${this.buildLogsUrl(deployId)}`, this.redactionPatterns),
269
281
  };
270
282
  }
271
- const res = await this.fetchWithRetry(url, {
283
+ const res = await fetchWithRetry(this.fetchImpl, url, {
272
284
  method: 'GET',
273
285
  headers: this.headers(),
274
286
  signal,
275
- });
287
+ }, { sleepImpl: this.sleep, provider: 'vercel' });
276
288
  await this.assertOkOrThrow(res, 'poll deployment');
277
289
  const data = (await res.json());
278
290
  const state = data.readyState ?? data.state;
@@ -290,7 +302,9 @@ export class VercelDeployAdapter {
290
302
  deployUrl: data.url ? `https://${data.url}` : undefined,
291
303
  buildLogsUrl: this.buildLogsUrl(deployId),
292
304
  durationMs,
293
- output: state ? `Vercel deployment ${deployId}: state=${state}` : undefined,
305
+ output: state
306
+ ? redactLogLines(`Vercel deployment ${deployId}: state=${state}`, this.redactionPatterns)
307
+ : undefined,
294
308
  };
295
309
  }
296
310
  headers() {
@@ -321,32 +335,6 @@ export class VercelDeployAdapter {
321
335
  }
322
336
  throw new GuardrailError(`Vercel API error (${res.status}) on ${step}: ${bodyText}`, { code: 'adapter_bug', provider: 'vercel', step, details: { status: res.status } });
323
337
  }
324
- async fetchWithRetry(url, init, attempts = 3, baseMs = 500) {
325
- let lastErr;
326
- for (let i = 0; i < attempts; i++) {
327
- try {
328
- const res = await this.fetchImpl(url, init);
329
- // 5xx is transient — retry. 4xx is the caller's problem — fail fast.
330
- if (res.status >= 500 && res.status < 600 && i < attempts - 1) {
331
- lastErr = new Error(`HTTP ${res.status}`);
332
- await this.sleep(baseMs * 2 ** i);
333
- continue;
334
- }
335
- return res;
336
- }
337
- catch (err) {
338
- lastErr = err;
339
- // AbortError is intentional cancellation — surface it directly without retry.
340
- if (err instanceof Error && err.name === 'AbortError')
341
- throw err;
342
- if (i < attempts - 1) {
343
- await this.sleep(baseMs * 2 ** i);
344
- continue;
345
- }
346
- }
347
- }
348
- throw new GuardrailError(`Vercel API unreachable after ${attempts} attempts: ${lastErr?.message ?? String(lastErr)}`, { code: 'transient_network', provider: 'vercel' });
349
- }
350
338
  /**
351
339
  * Like `fetchWithRetry` but tuned for the events endpoint:
352
340
  * - 404 right after a deploy POST is a known race (the deploy hasn't yet
@@ -392,14 +380,6 @@ export class VercelDeployAdapter {
392
380
  return lastRes;
393
381
  }
394
382
  }
395
- async function safeReadBody(res) {
396
- try {
397
- return (await res.text()).slice(0, 500);
398
- }
399
- catch {
400
- return '<no body>';
401
- }
402
- }
403
383
  /**
404
384
  * Parse a single line from Vercel's events endpoint into a `DeployLogLine`.
405
385
  *
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Canonical per-model pricing for cost-ledger / cost-estimate / cost-cap features.
3
+ *
4
+ * Computed client-side because the OpenAI Responses API and most provider APIs
5
+ * return token counts but no $-cost field. Without these constants every codex
6
+ * run logged costUSD=0 even though tokens were tracked correctly.
7
+ *
8
+ * Units: USD per 1,000,000 tokens.
9
+ *
10
+ * `cachedInputPer1M` is the price for cached-input tokens (OpenAI's prompt-cache
11
+ * read tier — typically ~1/8 of `inputPer1M`). Set to `null` when the provider
12
+ * doesn't surface a cached tier or we don't have a confirmed published number.
13
+ *
14
+ * Adding a model here does NOT auto-wire it into any adapter — the per-adapter
15
+ * COST_PER_M_INPUT/OUTPUT constants in src/adapters/{council,review-engine}/*.ts
16
+ * remain the actual source of truth for runtime cost computation, and stay
17
+ * env-overridable. This table is the documentation/single-source-of-truth for
18
+ * "what should the defaults be" + drives the cost-ledger config defaults.
19
+ *
20
+ * Keep entries sorted: oldest → newest within each provider, providers
21
+ * alphabetical.
22
+ */
23
+ export interface ModelPricing {
24
+ inputPer1M: number;
25
+ outputPer1M: number;
26
+ cachedInputPer1M: number | null;
27
+ }
28
+ export declare const MODEL_PRICING: Record<string, ModelPricing>;
29
+ /**
30
+ * Look up canonical pricing for a model. Returns `undefined` for unknown
31
+ * models — callers should fall back to env-var defaults rather than throwing,
32
+ * because this table is intentionally non-exhaustive (adapters work with any
33
+ * model the underlying SDK accepts).
34
+ */
35
+ export declare function getModelPricing(model: string): ModelPricing | undefined;
36
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1,40 @@
1
+ export const MODEL_PRICING = {
2
+ // OpenAI ----------------------------------------------------------------
3
+ // gpt-5.3-codex: legacy default (pre-2026-04-23). Kept for back-compat —
4
+ // users may have pinned via CODEX_MODEL env var.
5
+ 'gpt-5.3-codex': {
6
+ inputPer1M: 1.25,
7
+ outputPer1M: 10.0,
8
+ cachedInputPer1M: null,
9
+ },
10
+ // gpt-5.4: superseded by gpt-5.5 on 2026-04-23. Kept for back-compat.
11
+ 'gpt-5.4': {
12
+ inputPer1M: 2.5,
13
+ outputPer1M: 15.0,
14
+ cachedInputPer1M: null,
15
+ },
16
+ // gpt-5.5 (codename Spud, released 2026-04-23): current default for codex
17
+ // adapter + council openai adapter. Better at coding than 5.4 with fewer
18
+ // tokens, but ~2× more expensive per token. Available via standard
19
+ // Responses/Chat Completions API at `gpt-5.5` (no `-codex` suffix).
20
+ // Bugbot MEDIUM PR #93: `cachedInputPer1M` is `null` (NOT 0) until we have
21
+ // a confirmed published number. The interface contract treats `0` as
22
+ // "cached tokens are free" — using it would make consumers silently
23
+ // compute $0 for cached usage. Heuristic is ~1/8 of input (~$0.625/1M)
24
+ // per OpenAI's prompt-cache pattern, but no definitive source yet.
25
+ 'gpt-5.5': {
26
+ inputPer1M: 5.0,
27
+ outputPer1M: 30.0,
28
+ cachedInputPer1M: null,
29
+ },
30
+ };
31
+ /**
32
+ * Look up canonical pricing for a model. Returns `undefined` for unknown
33
+ * models — callers should fall back to env-var defaults rather than throwing,
34
+ * because this table is intentionally non-exhaustive (adapters work with any
35
+ * model the underlying SDK accepts).
36
+ */
37
+ export function getModelPricing(model) {
38
+ return MODEL_PRICING[model];
39
+ }
40
+ //# sourceMappingURL=pricing.js.map
@@ -2,14 +2,17 @@ import { parseReviewOutput } from "./parse-output.js";
2
2
  import { GuardrailError } from "../../core/errors.js";
3
3
  import { buildSystemPrompt, classifyError } from "./prompt-builder.js";
4
4
  import { loadOpenAI } from "../sdk-loader.js";
5
- const DEFAULT_MODEL = process.env.CODEX_MODEL ?? 'gpt-5.3-codex';
5
+ import { getModelPricing } from "../pricing.js";
6
+ const DEFAULT_MODEL = process.env.CODEX_MODEL ?? 'gpt-5.5';
6
7
  const MAX_OUTPUT_TOKENS = 4096;
7
- // Per-million-token rates for gpt-5.3-codex (override via env for other models).
8
- // Computed client-side because the OpenAI Responses API returns token counts
9
- // but no $-cost field. Without this, every codex run logged costUSD=0 even
10
- // though tokens were tracked correctly.
11
- const COST_PER_M_INPUT = Number(process.env.CODEX_COST_INPUT_PER_M ?? 1.25);
12
- const COST_PER_M_OUTPUT = Number(process.env.CODEX_COST_OUTPUT_PER_M ?? 10.0);
8
+ // Per-million-token rates. Bugbot LOW PR #93: wired to read from the
9
+ // canonical MODEL_PRICING table so the table is no longer dead code.
10
+ // Resolution order: env override MODEL_PRICING entry for DEFAULT_MODEL
11
+ // numeric fallback (gpt-5.5 published rates). Costs are computed client-side
12
+ // because the OpenAI Responses API returns token counts but no $-cost field.
13
+ const _pricing = getModelPricing(DEFAULT_MODEL);
14
+ const COST_PER_M_INPUT = Number(process.env.CODEX_COST_INPUT_PER_M ?? _pricing?.inputPer1M ?? 5.0);
15
+ const COST_PER_M_OUTPUT = Number(process.env.CODEX_COST_OUTPUT_PER_M ?? _pricing?.outputPer1M ?? 30.0);
13
16
  const SYSTEM_PROMPT_TEMPLATE = `You are a senior software architect providing feedback on designs, proposals, and ideas.
14
17
 
15
18
  The codebase context:
@@ -0,0 +1,75 @@
1
+ import { PHASE_REGISTRY, DEFAULT_FULL_PHASES, type PhaseName } from '../core/run-state/phase-registry.ts';
2
+ export type AutopilotMode = 'full';
3
+ export interface AutopilotOptions {
4
+ cwd?: string;
5
+ configPath?: string;
6
+ /** Pipeline mode. v6.2.0 supports `'full'` only (scan → spec → plan →
7
+ * implement). Defaults to `'full'` when neither `mode` nor `phases`
8
+ * is supplied. */
9
+ mode?: AutopilotMode;
10
+ /** Explicit phase list (overrides `mode`). Validated against
11
+ * PHASE_REGISTRY before any run dir is created — unknown names exit 1
12
+ * with `invalid_config`. */
13
+ phases?: readonly string[];
14
+ /** Run-scope budget (USD). When set, every phase passes through the
15
+ * shared `BudgetConfig` with `scope: 'run'` so `actualSoFar` accumulates
16
+ * across phases. */
17
+ budgetUSD?: number;
18
+ /** v6.0.x — engine knob. The orchestrator REJECTS engine-off explicitly
19
+ * (per spec "Engine-off"); these fields exist so the dispatcher can pass
20
+ * them through and the orchestrator can produce a clear error message. */
21
+ cliEngine?: boolean;
22
+ envEngine?: string;
23
+ /** Test seam — keep stdout banners suppressed. Production callers MUST
24
+ * NOT pass this; the dispatcher does not surface a flag for it. */
25
+ __silent?: boolean;
26
+ /** v7.0 Phase 2.3 — opt out of auto-upload at run.complete. Surfaced by
27
+ * the CLI as `--no-upload`. Equivalent to `CLAUDE_AUTOPILOT_UPLOAD=off`
28
+ * but scoped per-invocation. */
29
+ noUpload?: boolean;
30
+ }
31
+ export interface AutopilotPhaseSummary {
32
+ name: string;
33
+ status: 'success' | 'failed' | 'skipped' | 'not-run';
34
+ errorCode?: string;
35
+ errorMessage?: string;
36
+ costUSD: number;
37
+ durationMs: number;
38
+ }
39
+ export interface AutopilotResult {
40
+ runId: string | null;
41
+ runDir: string | null;
42
+ exitCode: number;
43
+ errorCode?: string;
44
+ errorMessage?: string;
45
+ phases: AutopilotPhaseSummary[];
46
+ totalCostUSD: number;
47
+ durationMs: number;
48
+ }
49
+ export declare function runAutopilot(options?: AutopilotOptions): Promise<AutopilotResult>;
50
+ export interface AutopilotJsonOptions extends AutopilotOptions {
51
+ /** Test seam — install process-level uncaughtException / unhandledRejection
52
+ * handlers that emit a fallback envelope if the orchestrator throws past
53
+ * our try/catch. Default: true (production behavior). Tests pass false to
54
+ * avoid leaking handlers across the suite. */
55
+ __testInstallProcessHandlers?: boolean;
56
+ /** Test seam — when set, the orchestrator throws AFTER the success
57
+ * envelope is written. Used to verify the single-write latch suppresses
58
+ * the uncaughtException handler's fallback envelope. Production code
59
+ * never sets this. */
60
+ __testThrowAfterEnvelope?: () => never;
61
+ }
62
+ /** v6.2.2 entrypoint for `claude-autopilot autopilot --json`.
63
+ *
64
+ * Wraps `runAutopilot` (which already handles pre-run failures inline by
65
+ * returning an `AutopilotResult` with `runId: null` + populated
66
+ * `errorCode` / `errorMessage`) and emits exactly one envelope on stdout.
67
+ * Process-level fatal handlers (codex WARNING #2) catch async failures
68
+ * that would otherwise bypass our try/catch.
69
+ *
70
+ * Returns the exit code the dispatcher should propagate via
71
+ * `process.exit`. */
72
+ export declare function runAutopilotWithJsonEnvelope(options?: AutopilotJsonOptions): Promise<number>;
73
+ export { PHASE_REGISTRY, DEFAULT_FULL_PHASES };
74
+ export type { PhaseName };
75
+ //# sourceMappingURL=autopilot.d.ts.map