@nilsr0711/drydock 0.1.2 → 0.1.4

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 (160) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +5 -3
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +12 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  17. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  19. package/.next/standalone/.next/server/app/adrs/page.js +2 -2
  20. package/.next/standalone/.next/server/app/adrs/page.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/adrs/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/analytics/page.js +2 -0
  23. package/.next/standalone/.next/server/app/analytics/page.js.nft.json +1 -0
  24. package/.next/standalone/.next/server/app/analytics/page_client-reference-manifest.js +1 -0
  25. package/.next/standalone/.next/server/app/api/cost/export/route.js +2 -1
  26. package/.next/standalone/.next/server/app/api/cost/export/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/sse/dashboard/route.js +15 -2
  28. package/.next/standalone/.next/server/app/api/sse/dashboard/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/sse/jobs/[id]/route.js +2 -2
  30. package/.next/standalone/.next/server/app/api/sse/jobs/[id]/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/webhooks/[repoId]/route.js +14 -1
  32. package/.next/standalone/.next/server/app/api/webhooks/[repoId]/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/costs/page.js +2 -2
  34. package/.next/standalone/.next/server/app/costs/page.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/costs/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/jobs/[id]/page.js +3 -5
  37. package/.next/standalone/.next/server/app/jobs/[id]/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/jobs/[id]/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/jobs/page.js +2 -0
  40. package/.next/standalone/.next/server/app/jobs/page.js.nft.json +1 -0
  41. package/.next/standalone/.next/server/app/jobs/page_client-reference-manifest.js +1 -0
  42. package/.next/standalone/.next/server/app/needs-human/page.js +2 -2
  43. package/.next/standalone/.next/server/app/needs-human/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/needs-human/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/page.js +2 -2
  46. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/prompts/page.js +2 -2
  49. package/.next/standalone/.next/server/app/prompts/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/prompts/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/repos/[id]/page.js +2 -2
  52. package/.next/standalone/.next/server/app/repos/[id]/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/repos/[id]/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/settings/page.js +2 -2
  55. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app-paths-manifest.json +5 -3
  58. package/.next/standalone/.next/server/chunks/318.js +14 -0
  59. package/.next/standalone/.next/server/chunks/468.js +24 -0
  60. package/.next/standalone/.next/server/chunks/49.js +3 -0
  61. package/.next/standalone/.next/server/chunks/541.js +1 -1
  62. package/.next/standalone/.next/server/chunks/665.js +9 -0
  63. package/.next/standalone/.next/server/chunks/675.js +1 -0
  64. package/.next/standalone/.next/server/chunks/785.js +93 -0
  65. package/.next/standalone/.next/server/chunks/859.js +1 -0
  66. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  67. package/.next/standalone/.next/server/pages/500.html +1 -1
  68. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  70. package/.next/standalone/.next/static/chunks/131-754f0b3c6a7625f0.js +1 -0
  71. package/.next/standalone/.next/static/chunks/{750-1062dd98095cb147.js → 334-ac65cc1c43f3e786.js} +3 -3
  72. package/.next/standalone/.next/static/chunks/488-94313c3750ed9fec.js +1 -0
  73. package/.next/standalone/.next/static/chunks/626-25255b0a66c520cb.js +1 -0
  74. package/.next/standalone/.next/static/chunks/751-17d24a843c68c75a.js +1 -0
  75. package/.next/standalone/.next/static/chunks/860-5c68ffeb97288824.js +1 -0
  76. package/.next/standalone/.next/static/chunks/app/adrs/page-d427443f113c3575.js +1 -0
  77. package/.next/standalone/.next/static/chunks/app/analytics/page-4154e54399ac6fb4.js +1 -0
  78. package/.next/standalone/.next/static/chunks/app/costs/page-85ceb7f167a8095a.js +1 -0
  79. package/.next/standalone/.next/static/chunks/app/jobs/[id]/page-eb2e6d420c330df8.js +1 -0
  80. package/.next/standalone/.next/static/chunks/app/jobs/page-73240c8c9b0571cf.js +1 -0
  81. package/.next/standalone/.next/static/chunks/app/layout-717833ce6aaa45ee.js +1 -0
  82. package/.next/standalone/.next/static/chunks/app/needs-human/page-fd702f6eeab08820.js +1 -0
  83. package/.next/standalone/.next/static/chunks/app/page-43ce9934744597e6.js +1 -0
  84. package/.next/standalone/.next/static/chunks/app/prompts/page-ecd6816b8dd8b583.js +1 -0
  85. package/.next/standalone/.next/static/chunks/app/repos/[id]/page-df838c0805fce188.js +1 -0
  86. package/.next/standalone/.next/static/chunks/app/settings/page-3274e07b560fc8bc.js +1 -0
  87. package/.next/standalone/.next/static/css/1f98a1f790475168.css +3 -0
  88. package/.next/standalone/.next/static/eWyghWWF4zppTRQ7rmwde/_buildManifest.js +1 -0
  89. package/.next/standalone/drizzle/0010_one_shot_costs.sql +12 -0
  90. package/.next/standalone/drizzle/0021_robust_wind_dancer.sql +48 -0
  91. package/.next/standalone/drizzle/0022_issue_model_override.sql +2 -0
  92. package/.next/standalone/drizzle/meta/0021_snapshot.json +1780 -0
  93. package/.next/standalone/drizzle/meta/_journal.json +7 -0
  94. package/.next/standalone/package.json +2 -1
  95. package/.next/static/chunks/131-754f0b3c6a7625f0.js +1 -0
  96. package/.next/static/chunks/{750-1062dd98095cb147.js → 334-ac65cc1c43f3e786.js} +3 -3
  97. package/.next/static/chunks/488-94313c3750ed9fec.js +1 -0
  98. package/.next/static/chunks/626-25255b0a66c520cb.js +1 -0
  99. package/.next/static/chunks/751-17d24a843c68c75a.js +1 -0
  100. package/.next/static/chunks/860-5c68ffeb97288824.js +1 -0
  101. package/.next/static/chunks/app/adrs/page-d427443f113c3575.js +1 -0
  102. package/.next/static/chunks/app/analytics/page-4154e54399ac6fb4.js +1 -0
  103. package/.next/static/chunks/app/costs/page-85ceb7f167a8095a.js +1 -0
  104. package/.next/static/chunks/app/jobs/[id]/page-eb2e6d420c330df8.js +1 -0
  105. package/.next/static/chunks/app/jobs/page-73240c8c9b0571cf.js +1 -0
  106. package/.next/static/chunks/app/layout-717833ce6aaa45ee.js +1 -0
  107. package/.next/static/chunks/app/needs-human/page-fd702f6eeab08820.js +1 -0
  108. package/.next/static/chunks/app/page-43ce9934744597e6.js +1 -0
  109. package/.next/static/chunks/app/prompts/page-ecd6816b8dd8b583.js +1 -0
  110. package/.next/static/chunks/app/repos/[id]/page-df838c0805fce188.js +1 -0
  111. package/.next/static/chunks/app/settings/page-3274e07b560fc8bc.js +1 -0
  112. package/.next/static/css/1f98a1f790475168.css +3 -0
  113. package/.next/static/eWyghWWF4zppTRQ7rmwde/_buildManifest.js +1 -0
  114. package/README.md +12 -4
  115. package/bin/drydock.mjs +145 -7
  116. package/drizzle/0010_one_shot_costs.sql +12 -0
  117. package/drizzle/0021_robust_wind_dancer.sql +48 -0
  118. package/drizzle/0022_issue_model_override.sql +2 -0
  119. package/drizzle/meta/0021_snapshot.json +1780 -0
  120. package/drizzle/meta/_journal.json +7 -0
  121. package/package.json +2 -1
  122. package/.next/standalone/.next/server/chunks/185.js +0 -32
  123. package/.next/standalone/.next/server/chunks/235.js +0 -1
  124. package/.next/standalone/.next/server/chunks/309.js +0 -1
  125. package/.next/standalone/.next/server/chunks/350.js +0 -9
  126. package/.next/standalone/.next/server/chunks/39.js +0 -3
  127. package/.next/standalone/.next/server/chunks/447.js +0 -1
  128. package/.next/standalone/.next/server/chunks/507.js +0 -9
  129. package/.next/standalone/.next/server/chunks/579.js +0 -62
  130. package/.next/standalone/.next/server/chunks/710.js +0 -1
  131. package/.next/standalone/.next/server/chunks/777.js +0 -1
  132. package/.next/standalone/.next/server/chunks/9.js +0 -3
  133. package/.next/standalone/.next/static/ZVOWTwaHoyx4ZcNdVzldW/_buildManifest.js +0 -1
  134. package/.next/standalone/.next/static/chunks/66-a23941cbbf88d6cd.js +0 -1
  135. package/.next/standalone/.next/static/chunks/700-c294ac6d353097ec.js +0 -1
  136. package/.next/standalone/.next/static/chunks/app/adrs/page-e75b859d58967540.js +0 -1
  137. package/.next/standalone/.next/static/chunks/app/costs/page-737c89e70adff98b.js +0 -1
  138. package/.next/standalone/.next/static/chunks/app/jobs/[id]/page-265e757a89803698.js +0 -1
  139. package/.next/standalone/.next/static/chunks/app/layout-f6048a8c9f541e0d.js +0 -1
  140. package/.next/standalone/.next/static/chunks/app/needs-human/page-88cb4f2c3aaf76c4.js +0 -1
  141. package/.next/standalone/.next/static/chunks/app/page-ab315dafdd344c06.js +0 -1
  142. package/.next/standalone/.next/static/chunks/app/prompts/page-562338cf5f420f96.js +0 -1
  143. package/.next/standalone/.next/static/chunks/app/repos/[id]/page-3099a9a513358664.js +0 -1
  144. package/.next/standalone/.next/static/chunks/app/settings/page-b6af5304dba71aa3.js +0 -1
  145. package/.next/standalone/.next/static/css/64af283f7f467bc0.css +0 -3
  146. package/.next/static/ZVOWTwaHoyx4ZcNdVzldW/_buildManifest.js +0 -1
  147. package/.next/static/chunks/66-a23941cbbf88d6cd.js +0 -1
  148. package/.next/static/chunks/700-c294ac6d353097ec.js +0 -1
  149. package/.next/static/chunks/app/adrs/page-e75b859d58967540.js +0 -1
  150. package/.next/static/chunks/app/costs/page-737c89e70adff98b.js +0 -1
  151. package/.next/static/chunks/app/jobs/[id]/page-265e757a89803698.js +0 -1
  152. package/.next/static/chunks/app/layout-f6048a8c9f541e0d.js +0 -1
  153. package/.next/static/chunks/app/needs-human/page-88cb4f2c3aaf76c4.js +0 -1
  154. package/.next/static/chunks/app/page-ab315dafdd344c06.js +0 -1
  155. package/.next/static/chunks/app/prompts/page-562338cf5f420f96.js +0 -1
  156. package/.next/static/chunks/app/repos/[id]/page-3099a9a513358664.js +0 -1
  157. package/.next/static/chunks/app/settings/page-b6af5304dba71aa3.js +0 -1
  158. package/.next/static/css/64af283f7f467bc0.css +0 -3
  159. /package/.next/standalone/.next/static/{ZVOWTwaHoyx4ZcNdVzldW → eWyghWWF4zppTRQ7rmwde}/_ssgManifest.js +0 -0
  160. /package/.next/static/{ZVOWTwaHoyx4ZcNdVzldW → eWyghWWF4zppTRQ7rmwde}/_ssgManifest.js +0 -0
package/bin/drydock.mjs CHANGED
@@ -6,13 +6,43 @@
6
6
  // step or TypeScript runtime so it works straight from the published tarball.
7
7
 
8
8
  import { spawn } from "node:child_process";
9
- import { existsSync, mkdirSync, readFileSync } from "node:fs";
9
+ import { existsSync, mkdirSync, readFileSync, realpathSync } from "node:fs";
10
10
  import { homedir } from "node:os";
11
11
  import { dirname, join, resolve } from "node:path";
12
12
  import { fileURLToPath } from "node:url";
13
13
 
14
14
  const DEFAULT_HOST = "127.0.0.1";
15
15
  const DEFAULT_PORT = 3737;
16
+
17
+ /**
18
+ * Returns true when the given host address binds only to the local machine.
19
+ * Loopback addresses (127.0.0.1, ::1, localhost) are safe because they are
20
+ * unreachable from the network; all other values expand the attack surface.
21
+ *
22
+ * @param {string} host
23
+ */
24
+ export function isLoopbackHost(host) {
25
+ return host === "127.0.0.1" || host === "::1" || host === "localhost";
26
+ }
27
+
28
+ /**
29
+ * Throws an informative Error when `host` is a non-loopback address and the
30
+ * operator has not set DRYDOCK_ALLOW_REMOTE=1. This is the only gate between
31
+ * the unauthenticated dashboard and the network.
32
+ *
33
+ * @param {string} host
34
+ * @param {Record<string, string | undefined>} [env]
35
+ */
36
+ export function assertSafeHost(host, env = process.env) {
37
+ if (isLoopbackHost(host)) return;
38
+ if (env.DRYDOCK_ALLOW_REMOTE) return;
39
+ throw new Error(
40
+ `Refusing to bind to "${host}": the Drydock dashboard has no authentication and ` +
41
+ `would be reachable by anyone on the network.\n` +
42
+ `To opt in and accept this risk, set DRYDOCK_ALLOW_REMOTE=1:\n` +
43
+ ` DRYDOCK_ALLOW_REMOTE=1 drydock --host ${host}`,
44
+ );
45
+ }
16
46
  const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
17
47
 
18
48
  /**
@@ -129,20 +159,107 @@ export function detectInstallKind(packageRoot) {
129
159
  return "local";
130
160
  }
131
161
 
162
+ /** The npm package name this CLI is published under. */
163
+ const PACKAGE_NAME = "@nilsr0711/drydock";
164
+
132
165
  /** The command that updates a global install to the latest published version. */
133
166
  export function updateCommand() {
134
- return { command: "npm", args: ["install", "--global", "@nilsr0711/drydock@latest"] };
167
+ return { command: "npm", args: ["install", "--global", `${PACKAGE_NAME}@latest`] };
168
+ }
169
+
170
+ /**
171
+ * Compare two `x.y.z` versions (a leading `v` is tolerated). Returns 1 if `a` is
172
+ * newer, -1 if older, 0 if equal. Throws if either version is unparseable so
173
+ * callers can fall back rather than silently mis-ordering.
174
+ */
175
+ export function compareVersions(a, b) {
176
+ const parse = (v) => {
177
+ const m = /^v?(\d+)\.(\d+)\.(\d+)/.exec(String(v).trim());
178
+ if (!m) throw new Error(`unparseable version: ${v}`);
179
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
180
+ };
181
+ const pa = parse(a);
182
+ const pb = parse(b);
183
+ for (let i = 0; i < 3; i++) {
184
+ if (pa[i] > pb[i]) return 1;
185
+ if (pa[i] < pb[i]) return -1;
186
+ }
187
+ return 0;
188
+ }
189
+
190
+ /**
191
+ * Decide what `drydock update` should do given the installed version and the
192
+ * latest published version (which may be null/unparseable when the check fails).
193
+ * Degrades gracefully: when the latest version can't be determined, still
194
+ * attempts the install rather than blocking the user.
195
+ *
196
+ * @returns {{ action: "skip" | "install", reason: string, latestVersion?: string }}
197
+ */
198
+ export function planUpdate(currentVersion, latestVersion) {
199
+ if (!latestVersion) return { action: "install", reason: "unknown-latest" };
200
+ let cmp;
201
+ try {
202
+ cmp = compareVersions(latestVersion, currentVersion);
203
+ } catch {
204
+ return { action: "install", reason: "unknown-latest" };
205
+ }
206
+ if (cmp <= 0) return { action: "skip", reason: "up-to-date" };
207
+ return { action: "install", reason: "update-available", latestVersion };
208
+ }
209
+
210
+ /**
211
+ * Resolve the latest published version from the npm registry's `latest`
212
+ * dist-tag. Never throws: returns null on any network/HTTP/parse failure so the
213
+ * caller can fall back to a blind install.
214
+ *
215
+ * @param {string} pkg The (possibly scoped) package name.
216
+ * @param {{ fetchImpl?: typeof fetch }} [opts]
217
+ * @returns {Promise<string | null>}
218
+ */
219
+ export async function resolveLatestVersion(pkg, { fetchImpl = fetch } = {}) {
220
+ try {
221
+ const url = `https://registry.npmjs.org/${encodeURIComponent(pkg)}/latest`;
222
+ const res = await fetchImpl(url, {
223
+ headers: { Accept: "application/json", "User-Agent": "drydock-update" },
224
+ });
225
+ if (!res.ok) return null;
226
+ const body = await res.json();
227
+ return typeof body?.version === "string" ? body.version : null;
228
+ } catch {
229
+ return null;
230
+ }
135
231
  }
136
232
 
137
233
  /** Run the self-update, inheriting stdio so npm's progress is visible. */
138
- function runUpdate() {
234
+ async function runUpdate() {
235
+ const current = readVersion();
236
+ console.error(`Current version: drydock v${current}`);
237
+
238
+ const latest = await resolveLatestVersion(PACKAGE_NAME);
239
+ const plan = planUpdate(current, latest);
240
+
241
+ if (plan.action === "skip") {
242
+ console.error(`drydock is already up to date (v${current}).`);
243
+ process.exit(0);
244
+ }
245
+
246
+ if (plan.reason === "unknown-latest") {
247
+ console.error("Could not determine the latest version; attempting update anyway…");
248
+ } else {
249
+ console.error(`Updating drydock ${current} → ${plan.latestVersion} …`);
250
+ }
251
+
139
252
  const { command, args } = updateCommand();
140
- console.error(`Updating drydock: ${command} ${args.join(" ")}`);
141
253
  const child = spawn(command, args, {
142
254
  shell: process.platform === "win32",
143
255
  stdio: "inherit",
144
256
  });
145
- child.on("exit", (code) => process.exit(code ?? 0));
257
+ child.on("exit", (code) => {
258
+ if (code === 0 && plan.reason === "update-available") {
259
+ console.error(`Updated to drydock v${plan.latestVersion}.`);
260
+ }
261
+ process.exit(code ?? 0);
262
+ });
146
263
  child.on("error", (err) => {
147
264
  console.error(`Update failed: ${err.message}`);
148
265
  process.exit(1);
@@ -183,6 +300,8 @@ async function waitForServer(url, { attempts = 100, intervalMs = 100 } = {}) {
183
300
  }
184
301
 
185
302
  async function serve({ host, port, open }) {
303
+ assertSafeHost(host);
304
+
186
305
  const serverEntry = join(PACKAGE_ROOT, ".next", "standalone", "server.js");
187
306
  if (!existsSync(serverEntry)) {
188
307
  throw new Error(
@@ -244,15 +363,34 @@ async function main(argv) {
244
363
  console.log(readVersion());
245
364
  return;
246
365
  case "update":
247
- runUpdate();
366
+ await runUpdate();
248
367
  return;
249
368
  default:
250
369
  await serve(directive);
251
370
  }
252
371
  }
253
372
 
373
+ /**
374
+ * Decide whether this module is the program entry point. A plain string compare
375
+ * against `process.argv[1]` breaks for global/npx installs, where the bin is a
376
+ * symlink in a bin directory and argv[1] is that link rather than the real file.
377
+ * Resolving the entry path through symlinks (realpath) makes the two comparable,
378
+ * so `drydock`, `drydock --version`, etc. actually run when installed.
379
+ *
380
+ * @param {string} modulePath Absolute path to this module (resolved import.meta.url).
381
+ * @param {string | undefined} entryPath The invoked entry path (process.argv[1]).
382
+ */
383
+ export function isMainModule(modulePath, entryPath) {
384
+ if (!entryPath) return false;
385
+ try {
386
+ return modulePath === realpathSync(entryPath);
387
+ } catch {
388
+ return false;
389
+ }
390
+ }
391
+
254
392
  // Only run when executed directly, not when imported by tests.
255
- if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
393
+ if (isMainModule(fileURLToPath(import.meta.url), process.argv[1])) {
256
394
  main(process.argv.slice(2)).catch((err) => {
257
395
  console.error(err instanceof Error ? err.message : String(err));
258
396
  process.exit(1);
@@ -0,0 +1,12 @@
1
+ CREATE TABLE `one_shot_costs` (
2
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
3
+ `repo_id` integer NOT NULL,
4
+ `type` text NOT NULL,
5
+ `cost_usd` real DEFAULT 0 NOT NULL,
6
+ `input_tokens` integer DEFAULT 0 NOT NULL,
7
+ `output_tokens` integer DEFAULT 0 NOT NULL,
8
+ `created_at` integer DEFAULT (unixepoch()) NOT NULL,
9
+ FOREIGN KEY (`repo_id`) REFERENCES `repos`(`id`) ON UPDATE no action ON DELETE cascade
10
+ );
11
+ --> statement-breakpoint
12
+ CREATE INDEX `one_shot_costs_repo_idx` ON `one_shot_costs` (`repo_id`);
@@ -0,0 +1,48 @@
1
+ PRAGMA foreign_keys=OFF;--> statement-breakpoint
2
+ CREATE TABLE `__new_repos` (
3
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
4
+ `path` text NOT NULL,
5
+ `name` text NOT NULL,
6
+ `default_branch` text DEFAULT 'main' NOT NULL,
7
+ `queue_label` text DEFAULT 'drydock:queue' NOT NULL,
8
+ `working_label` text DEFAULT 'drydock:working' NOT NULL,
9
+ `needs_human_label` text DEFAULT 'drydock:needs-human' NOT NULL,
10
+ `default_model` text DEFAULT 'claude-opus-4-8' NOT NULL,
11
+ `agent` text DEFAULT 'claude' NOT NULL,
12
+ `platform` text DEFAULT 'github' NOT NULL,
13
+ `api_base_url` text,
14
+ `api_token` text,
15
+ `daily_cost_limit_usd` real DEFAULT 10 NOT NULL,
16
+ `adr_gating` integer DEFAULT false NOT NULL,
17
+ `sequential` integer DEFAULT true NOT NULL,
18
+ `auto_triage_enabled` integer DEFAULT false NOT NULL,
19
+ `auto_process_enabled` integer DEFAULT false NOT NULL,
20
+ `auto_heal_ci` integer DEFAULT false NOT NULL,
21
+ `auto_review_feedback` integer DEFAULT false NOT NULL,
22
+ `auto_resolve_merge_conflicts` integer DEFAULT false NOT NULL,
23
+ `include_progress_replies` integer DEFAULT false NOT NULL,
24
+ `auto_decompose` integer DEFAULT false NOT NULL,
25
+ `verify_pr` integer DEFAULT false NOT NULL,
26
+ `auto_heal_deployments` integer DEFAULT false NOT NULL,
27
+ `deployment_platform` text,
28
+ `trusted_reviewers` text DEFAULT '[]' NOT NULL,
29
+ `ignored_bots` text DEFAULT '["dependabot[bot]","github-actions[bot]","codecov[bot]"]' NOT NULL,
30
+ `ready_labels` text DEFAULT '["ready","ready-for-agent","ready-to-work"]' NOT NULL,
31
+ `blocking_labels` text DEFAULT '["blocked","question","needs-human","needs-discussion","wontfix","duplicate","invalid"]' NOT NULL,
32
+ `auto_label_whitelist` text DEFAULT '["bug","enhancement","documentation","ready"]' NOT NULL,
33
+ `priority_authors` text DEFAULT '[]' NOT NULL,
34
+ `min_author_association` text DEFAULT 'approved' NOT NULL,
35
+ `max_attempts` integer DEFAULT 3 NOT NULL,
36
+ `max_job_minutes` integer,
37
+ `max_ci_wait_minutes` integer,
38
+ `max_job_cost_usd` real,
39
+ `agent_instructions` text,
40
+ `release_enabled` integer DEFAULT false NOT NULL,
41
+ `webhook_secret` text,
42
+ `created_at` integer DEFAULT (unixepoch()) NOT NULL
43
+ );
44
+ --> statement-breakpoint
45
+ INSERT INTO `__new_repos`("id", "path", "name", "default_branch", "queue_label", "working_label", "needs_human_label", "default_model", "agent", "platform", "api_base_url", "api_token", "daily_cost_limit_usd", "adr_gating", "sequential", "auto_triage_enabled", "auto_process_enabled", "auto_heal_ci", "auto_review_feedback", "auto_resolve_merge_conflicts", "include_progress_replies", "auto_decompose", "verify_pr", "auto_heal_deployments", "deployment_platform", "trusted_reviewers", "ignored_bots", "ready_labels", "blocking_labels", "auto_label_whitelist", "priority_authors", "min_author_association", "max_attempts", "max_job_minutes", "max_ci_wait_minutes", "max_job_cost_usd", "agent_instructions", "release_enabled", "webhook_secret", "created_at") SELECT "id", "path", "name", "default_branch", "queue_label", "working_label", "needs_human_label", "default_model", "agent", "platform", "api_base_url", "api_token", "daily_cost_limit_usd", "adr_gating", "sequential", "auto_triage_enabled", "auto_process_enabled", "auto_heal_ci", "auto_review_feedback", "auto_resolve_merge_conflicts", "include_progress_replies", "auto_decompose", "verify_pr", "auto_heal_deployments", "deployment_platform", "trusted_reviewers", "ignored_bots", "ready_labels", "blocking_labels", "auto_label_whitelist", "priority_authors", "min_author_association", "max_attempts", "max_job_minutes", "max_ci_wait_minutes", "max_job_cost_usd", "agent_instructions", "release_enabled", "webhook_secret", "created_at" FROM `repos`;--> statement-breakpoint
46
+ DROP TABLE `repos`;--> statement-breakpoint
47
+ ALTER TABLE `__new_repos` RENAME TO `repos`;--> statement-breakpoint
48
+ PRAGMA foreign_keys=ON;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `issues` ADD COLUMN `model_override` text;--> statement-breakpoint
2
+ ALTER TABLE `issues` ADD COLUMN `agent_override` text;