@staff0rd/assist 0.953.0 → 0.954.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.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.953.0",
9
+ version: "0.954.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3755,29 +3755,19 @@ function getRepoLocation(req, res) {
3755
3755
  respondJson(res, 200, resolveRepoLocation(origin, void 0, baseDir));
3756
3756
  }
3757
3757
 
3758
+ // src/commands/backlog/updateStarred.ts
3759
+ import { eq as eq12 } from "drizzle-orm";
3760
+ async function updateStarred(orm, id, starred) {
3761
+ const [row3] = await orm.update(items).set({ starred }).where(eq12(items.id, id)).returning({ name: items.name });
3762
+ return row3?.name;
3763
+ }
3764
+
3758
3765
  // src/commands/backlog/web/applyCwdFromReq.ts
3759
3766
  function applyCwdFromReq(req) {
3760
3767
  const url = new URL(req.url ?? "/", "http://localhost");
3761
3768
  setBacklogDir(url.searchParams.get("cwd") ?? void 0);
3762
3769
  }
3763
3770
 
3764
- // src/commands/backlog/deleteComment.ts
3765
- import { and as and4, eq as eq12 } from "drizzle-orm";
3766
- async function deleteComment(orm, itemId2, commentId) {
3767
- const [row3] = await orm.select({ type: comments.type }).from(comments).where(and4(eq12(comments.id, commentId), eq12(comments.itemId, itemId2)));
3768
- if (!row3) return "not-found";
3769
- if (row3.type === "summary") return "is-summary";
3770
- await orm.delete(comments).where(and4(eq12(comments.id, commentId), eq12(comments.itemId, itemId2)));
3771
- return "deleted";
3772
- }
3773
-
3774
- // src/commands/backlog/updateStarred.ts
3775
- import { eq as eq13 } from "drizzle-orm";
3776
- async function updateStarred(orm, id, starred) {
3777
- const [row3] = await orm.update(items).set({ starred }).where(eq13(items.id, id)).returning({ name: items.name });
3778
- return row3?.name;
3779
- }
3780
-
3781
3771
  // src/commands/sessions/shared/lookupSessionsById.ts
3782
3772
  import * as path8 from "path";
3783
3773
 
@@ -4518,212 +4508,6 @@ async function patchItemStar(req, res, id) {
4518
4508
  respondJson(res, 200, updated2);
4519
4509
  }
4520
4510
 
4521
- // src/commands/backlog/web/deleteItemComment.ts
4522
- async function deleteItemComment(res, itemId2, commentId) {
4523
- const result = await findItemOr404(res, itemId2);
4524
- if (!result) return;
4525
- const outcome = await deleteComment(result.orm, itemId2, commentId);
4526
- if (outcome === "not-found") {
4527
- respondJson(res, 404, {
4528
- error: `Comment #${commentId} not found on item ${formatItemId(itemId2)}.`
4529
- });
4530
- return;
4531
- }
4532
- if (outcome === "is-summary") {
4533
- respondJson(res, 400, {
4534
- error: `Comment #${commentId} is a phase summary and cannot be deleted.`
4535
- });
4536
- return;
4537
- }
4538
- respondJson(res, 200, await loadItem(result.orm, itemId2));
4539
- }
4540
-
4541
- // src/commands/backlog/appendComment.ts
4542
- import { sql as sql15 } from "drizzle-orm";
4543
- async function appendComment(orm, itemId2, text18, opts = {}) {
4544
- await orm.insert(comments).values({
4545
- itemId: itemId2,
4546
- idx: sql15`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
4547
- text: text18,
4548
- phase: opts.phase ?? null,
4549
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4550
- type: opts.type ?? "comment"
4551
- });
4552
- }
4553
-
4554
- // src/commands/backlog/writeSignal.ts
4555
- import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
4556
- import { homedir as homedir9 } from "os";
4557
- import { dirname as dirname7, join as join17 } from "path";
4558
- import chalk8 from "chalk";
4559
-
4560
- // src/commands/backlog/recordSignalOwner.ts
4561
- import {
4562
- existsSync as existsSync13,
4563
- mkdirSync as mkdirSync3,
4564
- readFileSync as readFileSync6,
4565
- rmSync as rmSync3,
4566
- writeFileSync as writeFileSync3
4567
- } from "fs";
4568
- import { homedir as homedir8 } from "os";
4569
- import { dirname as dirname6, join as join16 } from "path";
4570
- function getOwnerPath(itemId2) {
4571
- return join16(homedir8(), ".assist", "signals", `owner-${itemId2}.json`);
4572
- }
4573
- function recordSignalOwner(itemId2) {
4574
- const sessionId = process.env.ASSIST_SESSION_ID;
4575
- if (!sessionId) return;
4576
- const path108 = getOwnerPath(itemId2);
4577
- mkdirSync3(dirname6(path108), { recursive: true });
4578
- writeFileSync3(path108, JSON.stringify({ sessionId }));
4579
- }
4580
- function readSignalOwner(itemId2) {
4581
- const path108 = getOwnerPath(itemId2);
4582
- if (!existsSync13(path108)) return void 0;
4583
- try {
4584
- const parsed = JSON.parse(readFileSync6(path108, "utf8"));
4585
- return parsed.sessionId;
4586
- } catch {
4587
- return void 0;
4588
- }
4589
- }
4590
- function clearSignalOwner(itemId2) {
4591
- const path108 = getOwnerPath(itemId2);
4592
- try {
4593
- rmSync3(path108);
4594
- } catch {
4595
- }
4596
- }
4597
-
4598
- // src/commands/backlog/writeSignal.ts
4599
- function getSignalPath(sessionId = process.env.ASSIST_SESSION_ID) {
4600
- if (!sessionId) return void 0;
4601
- return join17(homedir9(), ".assist", "signals", `signal-${sessionId}.json`);
4602
- }
4603
- function resolveSignalTarget(event, data) {
4604
- const caller = process.env.ASSIST_SESSION_ID;
4605
- const itemId2 = typeof data?.itemId === "number" ? data.itemId : void 0;
4606
- if (itemId2 === void 0) return caller;
4607
- const owner = readSignalOwner(itemId2);
4608
- if (owner) {
4609
- if (caller && owner !== caller) {
4610
- console.log(
4611
- chalk8.dim(
4612
- `Routing ${event} signal for item ${itemId2} to its run (${owner}), not this session (${caller}).`
4613
- )
4614
- );
4615
- }
4616
- return owner;
4617
- }
4618
- if (caller) {
4619
- console.log(
4620
- chalk8.yellow(
4621
- `Not signalling ${event} for item ${itemId2}: no live run owns it, and this session (${caller}) does not either.`
4622
- )
4623
- );
4624
- }
4625
- return void 0;
4626
- }
4627
- function writeSignal(event, data) {
4628
- const target = resolveSignalTarget(event, data);
4629
- if (!target) return;
4630
- const path108 = getSignalPath(target);
4631
- if (!path108) return;
4632
- const signal = { event, sessionId: target, ...data };
4633
- mkdirSync4(dirname7(path108), { recursive: true });
4634
- writeFileSync4(path108, JSON.stringify(signal));
4635
- }
4636
-
4637
- // src/commands/backlog/rewindItemToPhase.ts
4638
- async function rewindItemToPhase(orm, item, phaseNumber, reason4) {
4639
- const plan2 = resolveRewindPlan(item);
4640
- if (phaseNumber < 1 || phaseNumber > plan2.length) {
4641
- return {
4642
- ok: false,
4643
- error: `Phase ${phaseNumber} does not exist. Valid range: 1\u2013${plan2.length}.`
4644
- };
4645
- }
4646
- const currentPhase = item.currentPhase ?? 1;
4647
- if (phaseNumber >= currentPhase) {
4648
- return {
4649
- ok: false,
4650
- error: `Phase ${phaseNumber} is not earlier than the current phase (${currentPhase}).`
4651
- };
4652
- }
4653
- const phaseName = plan2[phaseNumber - 1].name;
4654
- await appendComment(
4655
- orm,
4656
- item.id,
4657
- `Rewound to phase ${phaseNumber} (${phaseName}): ${reason4}`,
4658
- { phase: phaseNumber }
4659
- );
4660
- await updateCurrentPhase(orm, item.id, phaseNumber);
4661
- await updateStatus(orm, item.id, "in-progress");
4662
- writeSignal("rewind", { itemId: item.id, targetPhase: phaseNumber - 1 });
4663
- return { ok: true, phaseName };
4664
- }
4665
-
4666
- // src/commands/backlog/web/rewindItemPhase.ts
4667
- async function rewindItemPhase(req, res, id) {
4668
- const { phase, reason: reason4 } = await parseRewindBody(req);
4669
- const result = await findItemOr404(res, id);
4670
- if (!result) return;
4671
- const { orm, item } = result;
4672
- const outcome = await rewindItemToPhase(orm, item, phase, reason4);
4673
- if (!outcome.ok) {
4674
- respondJson(res, 400, { error: outcome.error });
4675
- return;
4676
- }
4677
- respondJson(res, 200, await loadItem(orm, id));
4678
- }
4679
-
4680
- // src/commands/backlog/web/handleItemRoute.ts
4681
- var itemId = (match, group = 1) => parseItemId(match[group]);
4682
- var subId = (match, group) => Number.parseInt(match[group], 10);
4683
- var routes = [
4684
- {
4685
- pattern: /^\/api\/items\/(a?\d+)\/rewind$/,
4686
- method: "POST",
4687
- run: (req, res, m) => rewindItemPhase(req, res, itemId(m))
4688
- },
4689
- {
4690
- pattern: /^\/api\/items\/(a?\d+)\/star$/,
4691
- method: "POST",
4692
- run: (req, res, m) => patchItemStar(req, res, itemId(m))
4693
- },
4694
- {
4695
- pattern: /^\/api\/items\/(a?\d+)\/comments\/(\d+)$/,
4696
- method: "DELETE",
4697
- run: (_req, res, m) => deleteItemComment(res, itemId(m), subId(m, 2))
4698
- },
4699
- {
4700
- pattern: /^\/api\/items\/(a?\d+)$/,
4701
- method: "GET",
4702
- run: (_req, res, m) => getItemById(res, itemId(m))
4703
- },
4704
- {
4705
- pattern: /^\/api\/items\/(a?\d+)$/,
4706
- method: "PATCH",
4707
- run: (req, res, m) => patchItemStatus(req, res, itemId(m))
4708
- },
4709
- {
4710
- pattern: /^\/api\/items\/(a?\d+)$/,
4711
- method: "DELETE",
4712
- run: (_req, res, m) => deleteItem2(res, itemId(m))
4713
- }
4714
- ];
4715
- async function handleItemRoute(req, res, pathname) {
4716
- for (const route of routes) {
4717
- const match = pathname.match(route.pattern);
4718
- if (match && req.method === route.method) {
4719
- applyCwdFromReq(req);
4720
- await route.run(req, res, match);
4721
- return true;
4722
- }
4723
- }
4724
- return false;
4725
- }
4726
-
4727
4511
  // src/commands/sessions/web/readJsonBody.ts
4728
4512
  async function readJsonBody(req) {
4729
4513
  const chunks = [];
@@ -4920,20 +4704,20 @@ function includesCommittedChanges(cwd) {
4920
4704
  }
4921
4705
 
4922
4706
  // src/shared/db/findItemBySessionId.ts
4923
- import { asc as asc6, eq as eq14 } from "drizzle-orm";
4707
+ import { asc as asc6, eq as eq13 } from "drizzle-orm";
4924
4708
  async function findItemBySessionId(db, claudeSessionId) {
4925
- const rows = await db.select({ itemId: phaseUsage.itemId }).from(phaseUsage).where(eq14(phaseUsage.claudeSessionId, claudeSessionId)).orderBy(asc6(phaseUsage.itemId), asc6(phaseUsage.phaseIdx)).limit(1);
4709
+ const rows = await db.select({ itemId: phaseUsage.itemId }).from(phaseUsage).where(eq13(phaseUsage.claudeSessionId, claudeSessionId)).orderBy(asc6(phaseUsage.itemId), asc6(phaseUsage.phaseIdx)).limit(1);
4926
4710
  return rows[0]?.itemId;
4927
4711
  }
4928
4712
 
4929
4713
  // src/shared/db/listCommitRefs.ts
4930
- import { and as and5, asc as asc7, eq as eq15 } from "drizzle-orm";
4714
+ import { and as and4, asc as asc7, eq as eq14 } from "drizzle-orm";
4931
4715
  async function listCommitRefs(db, itemId2) {
4932
4716
  const rows = await db.select({
4933
4717
  ref: itemGitRefs.ref,
4934
4718
  title: itemGitRefs.title,
4935
4719
  url: itemGitRefs.url
4936
- }).from(itemGitRefs).where(and5(eq15(itemGitRefs.itemId, itemId2), eq15(itemGitRefs.kind, "commit"))).orderBy(asc7(itemGitRefs.createdAt), asc7(itemGitRefs.ref));
4720
+ }).from(itemGitRefs).where(and4(eq14(itemGitRefs.itemId, itemId2), eq14(itemGitRefs.kind, "commit"))).orderBy(asc7(itemGitRefs.createdAt), asc7(itemGitRefs.ref));
4937
4721
  return rows.map((row3) => ({
4938
4722
  sha: row3.ref,
4939
4723
  ...row3.title ? { title: row3.title } : {},
@@ -5182,12 +4966,12 @@ async function diffScopes(req, res) {
5182
4966
  }
5183
4967
 
5184
4968
  // src/commands/sessions/daemon/recordPromptJournal.ts
5185
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5 } from "fs";
5186
- import { dirname as dirname8 } from "path";
4969
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3 } from "fs";
4970
+ import { dirname as dirname6 } from "path";
5187
4971
  function recordPromptJournal(entry) {
5188
4972
  const line = JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...entry });
5189
4973
  try {
5190
- mkdirSync5(dirname8(daemonPaths.promptJournal), { recursive: true });
4974
+ mkdirSync3(dirname6(daemonPaths.promptJournal), { recursive: true });
5191
4975
  appendFileSync2(daemonPaths.promptJournal, `${line}
5192
4976
  `);
5193
4977
  } catch {
@@ -5360,11 +5144,11 @@ async function fileContent(req, res) {
5360
5144
  import { basename as basename6 } from "path";
5361
5145
 
5362
5146
  // src/commands/sessions/web/fromGithub/listClones.ts
5363
- import { existsSync as existsSync14, readdirSync as readdirSync2 } from "fs";
5364
- import { join as join18 } from "path";
5147
+ import { existsSync as existsSync13, readdirSync as readdirSync2 } from "fs";
5148
+ import { join as join16 } from "path";
5365
5149
  function listClones(baseDir) {
5366
- if (!existsSync14(baseDir)) return [];
5367
- return readdirSync2(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join18(baseDir, entry.name)).filter((dir) => existsSync14(join18(dir, ".git"))).sort();
5150
+ if (!existsSync13(baseDir)) return [];
5151
+ return readdirSync2(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join16(baseDir, entry.name)).filter((dir) => existsSync13(join16(dir, ".git"))).sort();
5368
5152
  }
5369
5153
 
5370
5154
  // src/commands/sessions/web/fromGithub/getClones.ts
@@ -5551,8 +5335,8 @@ function azureDevopsRepoUrl({ org, project, repo }) {
5551
5335
  }
5552
5336
 
5553
5337
  // src/commands/sessions/web/fromGithub/findAzureDevopsClone.ts
5554
- import { existsSync as existsSync15, readdirSync as readdirSync3 } from "fs";
5555
- import { join as join19 } from "path";
5338
+ import { existsSync as existsSync14, readdirSync as readdirSync3 } from "fs";
5339
+ import { join as join17 } from "path";
5556
5340
 
5557
5341
  // src/shared/azureDevops/parseAzureDevopsRemote.ts
5558
5342
  var HTTPS_DEV = /^https?:\/\/(?:[^@/]+@)?dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\/([^/]+)$/i;
@@ -5573,15 +5357,15 @@ function sameAzureDevopsRepo(a, b) {
5573
5357
 
5574
5358
  // src/commands/sessions/web/fromGithub/findAzureDevopsClone.ts
5575
5359
  function clonesRepo(dir, repo) {
5576
- if (!existsSync15(join19(dir, ".git"))) return false;
5360
+ if (!existsSync14(join17(dir, ".git"))) return false;
5577
5361
  const url = remoteUrl(dir).url;
5578
5362
  const remote = url ? parseAzureDevopsRemote(url) : null;
5579
5363
  return remote !== null && sameAzureDevopsRepo(remote, repo);
5580
5364
  }
5581
5365
  function findAzureDevopsClone(repo, baseDir) {
5582
- if (!existsSync15(baseDir)) return void 0;
5583
- const named = join19(baseDir, repo.repo);
5584
- const others = readdirSync3(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join19(baseDir, entry.name)).filter((dir) => dir !== named).sort();
5366
+ if (!existsSync14(baseDir)) return void 0;
5367
+ const named = join17(baseDir, repo.repo);
5368
+ const others = readdirSync3(baseDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join17(baseDir, entry.name)).filter((dir) => dir !== named).sort();
5585
5369
  return [named, ...others].find((dir) => clonesRepo(dir, repo));
5586
5370
  }
5587
5371
 
@@ -6674,11 +6458,11 @@ var reviewConfigHelp = [
6674
6458
  ];
6675
6459
 
6676
6460
  // src/commands/sync/printAutoConfirmHint.ts
6677
- import chalk9 from "chalk";
6461
+ import chalk8 from "chalk";
6678
6462
  var autoConfirmHintCommand = "assist config set sync.autoConfirm true --global";
6679
6463
  function printAutoConfirmHint() {
6680
6464
  console.log(
6681
- chalk9.dim(
6465
+ chalk8.dim(
6682
6466
  `Tip: run \`${autoConfirmHintCommand}\` to overwrite automatically next time`
6683
6467
  )
6684
6468
  );
@@ -7221,7 +7005,7 @@ function getHtml() {
7221
7005
  }
7222
7006
 
7223
7007
  // src/shared/resolveRunConfigs.ts
7224
- import { dirname as dirname9, relative as relative2, resolve as resolve7 } from "path";
7008
+ import { dirname as dirname7, relative as relative2, resolve as resolve7 } from "path";
7225
7009
 
7226
7010
  // src/shared/assertNoDuplicateRunNames.ts
7227
7011
  function findDuplicateNames(configs) {
@@ -7243,14 +7027,14 @@ function assertNoDuplicateRunNames(configs) {
7243
7027
  }
7244
7028
 
7245
7029
  // src/shared/findLinkedConfigPath.ts
7246
- import { existsSync as existsSync16 } from "fs";
7247
- import { join as join20, resolve as resolve5 } from "path";
7030
+ import { existsSync as existsSync15 } from "fs";
7031
+ import { join as join18, resolve as resolve5 } from "path";
7248
7032
  function findLinkedConfigPath(linkPath, fromDir) {
7249
7033
  const resolved = resolve5(fromDir, linkPath);
7250
- const claudePath = join20(resolved, ".claude", "assist.yml");
7251
- if (existsSync16(claudePath)) return claudePath;
7252
- const rootPath = join20(resolved, "assist.yml");
7253
- if (existsSync16(rootPath)) return rootPath;
7034
+ const claudePath = join18(resolved, ".claude", "assist.yml");
7035
+ if (existsSync15(claudePath)) return claudePath;
7036
+ const rootPath = join18(resolved, "assist.yml");
7037
+ if (existsSync15(rootPath)) return rootPath;
7254
7038
  throw new Error(`No assist.yml found in linked project: ${resolved}`);
7255
7039
  }
7256
7040
 
@@ -7292,7 +7076,7 @@ function loadAndResolveLink(linkPath, configDir, ctx) {
7292
7076
  const entries = loadLinkedEntries(configPath, ctx.visited);
7293
7077
  const defaultCwd = relativeToRoot(ctx, resolve7(configDir, linkPath));
7294
7078
  return setDefaultCwd(
7295
- resolveRecursive(entries, dirname9(configPath), ctx),
7079
+ resolveRecursive(entries, dirname7(configPath), ctx),
7296
7080
  defaultCwd
7297
7081
  );
7298
7082
  }
@@ -7343,20 +7127,20 @@ function handleServerRuns(req, res) {
7343
7127
 
7344
7128
  // src/commands/sessions/web/getReviewSynthesis.ts
7345
7129
  import { execFile as execFile4 } from "child_process";
7346
- import { readFileSync as readFileSync7 } from "fs";
7347
- import { homedir as homedir10 } from "os";
7348
- import { basename as basename9, join as join22 } from "path";
7130
+ import { readFileSync as readFileSync6 } from "fs";
7131
+ import { homedir as homedir8 } from "os";
7132
+ import { basename as basename9, join as join20 } from "path";
7349
7133
  import { promisify as promisify4 } from "util";
7350
7134
 
7351
7135
  // src/commands/sessions/web/findSynthesisForBranch.ts
7352
- import { existsSync as existsSync17, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
7353
- import { basename as basename8, dirname as dirname10, join as join21 } from "path";
7136
+ import { existsSync as existsSync16, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
7137
+ import { basename as basename8, dirname as dirname8, join as join19 } from "path";
7354
7138
  function findSynthesisForBranch(repoReviewsDir, branch2) {
7355
- const branchKeyPath = join21(repoReviewsDir, `${branch2}-`);
7356
- const parent = dirname10(branchKeyPath);
7139
+ const branchKeyPath = join19(repoReviewsDir, `${branch2}-`);
7140
+ const parent = dirname8(branchKeyPath);
7357
7141
  const branchPrefix = basename8(branchKeyPath);
7358
- if (!existsSync17(parent)) return null;
7359
- const synthesisFiles = readdirSync4(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join21(parent, name, "synthesis.md")).filter((path108) => existsSync17(path108)).map((path108) => ({ path: path108, mtime: statSync4(path108).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
7142
+ if (!existsSync16(parent)) return null;
7143
+ const synthesisFiles = readdirSync4(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join19(parent, name, "synthesis.md")).filter((path108) => existsSync16(path108)).map((path108) => ({ path: path108, mtime: statSync4(path108).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
7360
7144
  return synthesisFiles[0]?.path ?? null;
7361
7145
  }
7362
7146
 
@@ -7374,8 +7158,8 @@ async function resolveSynthesisPath(cwd) {
7374
7158
  runGit2(cwd, ["rev-parse", "--show-toplevel"]),
7375
7159
  runGit2(cwd, ["rev-parse", "--abbrev-ref", "HEAD"])
7376
7160
  ]);
7377
- const repoReviewsDir = join22(
7378
- homedir10(),
7161
+ const repoReviewsDir = join20(
7162
+ homedir8(),
7379
7163
  ".assist",
7380
7164
  "reviews",
7381
7165
  basename9(repoRoot2)
@@ -7391,7 +7175,7 @@ async function getReviewSynthesis(req, res) {
7391
7175
  respondJson(res, 404, { error: "No synthesis found" });
7392
7176
  return;
7393
7177
  }
7394
- respondJson(res, 200, { synthesis: readFileSync7(path108, "utf8") });
7178
+ respondJson(res, 200, { synthesis: readFileSync6(path108, "utf8") });
7395
7179
  } catch {
7396
7180
  respondJson(res, 404, { error: "No synthesis found" });
7397
7181
  }
@@ -7683,6 +7467,416 @@ async function gitStatus(req, res) {
7683
7467
  }
7684
7468
  }
7685
7469
 
7470
+ // src/commands/backlog/deleteComment.ts
7471
+ import { and as and5, eq as eq15 } from "drizzle-orm";
7472
+ async function deleteComment(orm, itemId2, commentId) {
7473
+ const [row3] = await orm.select({ type: comments.type }).from(comments).where(and5(eq15(comments.id, commentId), eq15(comments.itemId, itemId2)));
7474
+ if (!row3) return "not-found";
7475
+ if (row3.type === "summary") return "is-summary";
7476
+ await orm.delete(comments).where(and5(eq15(comments.id, commentId), eq15(comments.itemId, itemId2)));
7477
+ return "deleted";
7478
+ }
7479
+
7480
+ // src/commands/backlog/web/deleteItemComment.ts
7481
+ async function deleteItemComment(res, itemId2, commentId) {
7482
+ const result = await findItemOr404(res, itemId2);
7483
+ if (!result) return;
7484
+ const outcome = await deleteComment(result.orm, itemId2, commentId);
7485
+ if (outcome === "not-found") {
7486
+ respondJson(res, 404, {
7487
+ error: `Comment #${commentId} not found on item ${formatItemId(itemId2)}.`
7488
+ });
7489
+ return;
7490
+ }
7491
+ if (outcome === "is-summary") {
7492
+ respondJson(res, 400, {
7493
+ error: `Comment #${commentId} is a phase summary and cannot be deleted.`
7494
+ });
7495
+ return;
7496
+ }
7497
+ respondJson(res, 200, await loadItem(result.orm, itemId2));
7498
+ }
7499
+
7500
+ // src/commands/backlog/appendComment.ts
7501
+ import { sql as sql15 } from "drizzle-orm";
7502
+ async function appendComment(orm, itemId2, text18, opts = {}) {
7503
+ await orm.insert(comments).values({
7504
+ itemId: itemId2,
7505
+ idx: sql15`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
7506
+ text: text18,
7507
+ phase: opts.phase ?? null,
7508
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
7509
+ type: opts.type ?? "comment"
7510
+ });
7511
+ }
7512
+
7513
+ // src/commands/backlog/writeSignal.ts
7514
+ import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
7515
+ import { homedir as homedir10 } from "os";
7516
+ import { dirname as dirname10, join as join22 } from "path";
7517
+ import chalk9 from "chalk";
7518
+
7519
+ // src/commands/backlog/recordSignalOwner.ts
7520
+ import {
7521
+ existsSync as existsSync17,
7522
+ mkdirSync as mkdirSync4,
7523
+ readFileSync as readFileSync7,
7524
+ rmSync as rmSync3,
7525
+ writeFileSync as writeFileSync3
7526
+ } from "fs";
7527
+ import { homedir as homedir9 } from "os";
7528
+ import { dirname as dirname9, join as join21 } from "path";
7529
+ function getOwnerPath(itemId2) {
7530
+ return join21(homedir9(), ".assist", "signals", `owner-${itemId2}.json`);
7531
+ }
7532
+ function recordSignalOwner(itemId2) {
7533
+ const sessionId = process.env.ASSIST_SESSION_ID;
7534
+ if (!sessionId) return;
7535
+ const path108 = getOwnerPath(itemId2);
7536
+ mkdirSync4(dirname9(path108), { recursive: true });
7537
+ writeFileSync3(path108, JSON.stringify({ sessionId }));
7538
+ }
7539
+ function readSignalOwner(itemId2) {
7540
+ const path108 = getOwnerPath(itemId2);
7541
+ if (!existsSync17(path108)) return void 0;
7542
+ try {
7543
+ const parsed = JSON.parse(readFileSync7(path108, "utf8"));
7544
+ return parsed.sessionId;
7545
+ } catch {
7546
+ return void 0;
7547
+ }
7548
+ }
7549
+ function clearSignalOwner(itemId2) {
7550
+ const path108 = getOwnerPath(itemId2);
7551
+ try {
7552
+ rmSync3(path108);
7553
+ } catch {
7554
+ }
7555
+ }
7556
+
7557
+ // src/commands/backlog/writeSignal.ts
7558
+ function getSignalPath(sessionId = process.env.ASSIST_SESSION_ID) {
7559
+ if (!sessionId) return void 0;
7560
+ return join22(homedir10(), ".assist", "signals", `signal-${sessionId}.json`);
7561
+ }
7562
+ function resolveSignalTarget(event, data) {
7563
+ const caller = process.env.ASSIST_SESSION_ID;
7564
+ const itemId2 = typeof data?.itemId === "number" ? data.itemId : void 0;
7565
+ if (itemId2 === void 0) return caller;
7566
+ const owner = readSignalOwner(itemId2);
7567
+ if (owner) {
7568
+ if (caller && owner !== caller) {
7569
+ console.log(
7570
+ chalk9.dim(
7571
+ `Routing ${event} signal for item ${itemId2} to its run (${owner}), not this session (${caller}).`
7572
+ )
7573
+ );
7574
+ }
7575
+ return owner;
7576
+ }
7577
+ if (caller) {
7578
+ console.log(
7579
+ chalk9.yellow(
7580
+ `Not signalling ${event} for item ${itemId2}: no live run owns it, and this session (${caller}) does not either.`
7581
+ )
7582
+ );
7583
+ }
7584
+ return void 0;
7585
+ }
7586
+ function writeSignal(event, data) {
7587
+ const target = resolveSignalTarget(event, data);
7588
+ if (!target) return;
7589
+ const path108 = getSignalPath(target);
7590
+ if (!path108) return;
7591
+ const signal = { event, sessionId: target, ...data };
7592
+ mkdirSync5(dirname10(path108), { recursive: true });
7593
+ writeFileSync4(path108, JSON.stringify(signal));
7594
+ }
7595
+
7596
+ // src/commands/backlog/rewindItemToPhase.ts
7597
+ async function rewindItemToPhase(orm, item, phaseNumber, reason4) {
7598
+ const plan2 = resolveRewindPlan(item);
7599
+ if (phaseNumber < 1 || phaseNumber > plan2.length) {
7600
+ return {
7601
+ ok: false,
7602
+ error: `Phase ${phaseNumber} does not exist. Valid range: 1\u2013${plan2.length}.`
7603
+ };
7604
+ }
7605
+ const currentPhase = item.currentPhase ?? 1;
7606
+ if (phaseNumber >= currentPhase) {
7607
+ return {
7608
+ ok: false,
7609
+ error: `Phase ${phaseNumber} is not earlier than the current phase (${currentPhase}).`
7610
+ };
7611
+ }
7612
+ const phaseName = plan2[phaseNumber - 1].name;
7613
+ await appendComment(
7614
+ orm,
7615
+ item.id,
7616
+ `Rewound to phase ${phaseNumber} (${phaseName}): ${reason4}`,
7617
+ { phase: phaseNumber }
7618
+ );
7619
+ await updateCurrentPhase(orm, item.id, phaseNumber);
7620
+ await updateStatus(orm, item.id, "in-progress");
7621
+ writeSignal("rewind", { itemId: item.id, targetPhase: phaseNumber - 1 });
7622
+ return { ok: true, phaseName };
7623
+ }
7624
+
7625
+ // src/commands/backlog/web/rewindItemPhase.ts
7626
+ async function rewindItemPhase(req, res, id) {
7627
+ const { phase, reason: reason4 } = await parseRewindBody(req);
7628
+ const result = await findItemOr404(res, id);
7629
+ if (!result) return;
7630
+ const { orm, item } = result;
7631
+ const outcome = await rewindItemToPhase(orm, item, phase, reason4);
7632
+ if (!outcome.ok) {
7633
+ respondJson(res, 400, { error: outcome.error });
7634
+ return;
7635
+ }
7636
+ respondJson(res, 200, await loadItem(orm, id));
7637
+ }
7638
+
7639
+ // src/commands/backlog/web/handleItemRoute.ts
7640
+ var itemId = (match, group = 1) => parseItemId(match[group]);
7641
+ var subId = (match, group) => Number.parseInt(match[group], 10);
7642
+ var routes = [
7643
+ {
7644
+ pattern: /^\/api\/items\/(a?\d+)\/rewind$/,
7645
+ method: "POST",
7646
+ run: (req, res, m) => rewindItemPhase(req, res, itemId(m))
7647
+ },
7648
+ {
7649
+ pattern: /^\/api\/items\/(a?\d+)\/star$/,
7650
+ method: "POST",
7651
+ run: (req, res, m) => patchItemStar(req, res, itemId(m))
7652
+ },
7653
+ {
7654
+ pattern: /^\/api\/items\/(a?\d+)\/comments\/(\d+)$/,
7655
+ method: "DELETE",
7656
+ run: (_req, res, m) => deleteItemComment(res, itemId(m), subId(m, 2))
7657
+ },
7658
+ {
7659
+ pattern: /^\/api\/items\/(a?\d+)$/,
7660
+ method: "GET",
7661
+ run: (_req, res, m) => getItemById(res, itemId(m))
7662
+ },
7663
+ {
7664
+ pattern: /^\/api\/items\/(a?\d+)$/,
7665
+ method: "PATCH",
7666
+ run: (req, res, m) => patchItemStatus(req, res, itemId(m))
7667
+ },
7668
+ {
7669
+ pattern: /^\/api\/items\/(a?\d+)$/,
7670
+ method: "DELETE",
7671
+ run: (_req, res, m) => deleteItem2(res, itemId(m))
7672
+ }
7673
+ ];
7674
+ async function handleItemRoute(req, res, pathname) {
7675
+ for (const route of routes) {
7676
+ const match = pathname.match(route.pattern);
7677
+ if (match && req.method === route.method) {
7678
+ applyCwdFromReq(req);
7679
+ await route.run(req, res, match);
7680
+ return true;
7681
+ }
7682
+ }
7683
+ return false;
7684
+ }
7685
+
7686
+ // src/shared/db/dismissInboxMessage.ts
7687
+ import { and as and6, eq as eq16, isNull } from "drizzle-orm";
7688
+ async function dismissInboxMessage(orm, source, messageId) {
7689
+ const dismissed = await orm.update(inboxMessages).set({ dismissedAt: /* @__PURE__ */ new Date() }).where(
7690
+ and6(
7691
+ eq16(inboxMessages.source, source),
7692
+ eq16(inboxMessages.messageId, messageId),
7693
+ isNull(inboxMessages.dismissedAt)
7694
+ )
7695
+ ).returning({ messageId: inboxMessages.messageId });
7696
+ return dismissed.length > 0;
7697
+ }
7698
+
7699
+ // src/commands/sessions/web/inbox/inboxMessageKey.ts
7700
+ function inboxMessageKey(source, messageId) {
7701
+ return `${source}:${messageId}`;
7702
+ }
7703
+ function parseInboxMessageKey(key) {
7704
+ const separator = key.indexOf(":");
7705
+ if (separator <= 0 || separator === key.length - 1) return void 0;
7706
+ return {
7707
+ source: key.slice(0, separator),
7708
+ messageId: key.slice(separator + 1)
7709
+ };
7710
+ }
7711
+
7712
+ // src/commands/sessions/web/inbox/handleInboxRoute.ts
7713
+ var DISMISS = /^\/api\/inbox\/([^/]+)\/dismiss$/;
7714
+ async function handleInboxRoute(req, res, pathname) {
7715
+ const match = DISMISS.exec(pathname);
7716
+ if (!match || req.method !== "POST") return false;
7717
+ const key = parseInboxMessageKey(decodeURIComponent(match[1]));
7718
+ if (!key) {
7719
+ respondJson(res, 400, { error: "Invalid inbox message id" });
7720
+ return true;
7721
+ }
7722
+ const dismissed = await dismissInboxMessage(
7723
+ await getDb(),
7724
+ key.source,
7725
+ key.messageId
7726
+ );
7727
+ respondJson(
7728
+ res,
7729
+ dismissed ? 200 : 404,
7730
+ dismissed ? { ok: true } : { error: "Not found" }
7731
+ );
7732
+ return true;
7733
+ }
7734
+
7735
+ // src/commands/sessions/shared/loadLinkSpecs.ts
7736
+ function loadLinkSpecs() {
7737
+ return loadConfig().sessions?.links ?? [];
7738
+ }
7739
+ function findLinkSpec(name) {
7740
+ return loadLinkSpecs().find((spec) => spec.name === name);
7741
+ }
7742
+
7743
+ // src/commands/sessions/shared/newTraceId.ts
7744
+ import { randomUUID as randomUUID2 } from "crypto";
7745
+ var TRACE_HEADER = "x-assist-trace-id";
7746
+ function newTraceId() {
7747
+ return randomUUID2().slice(0, 8);
7748
+ }
7749
+
7750
+ // src/commands/sessions/web/forwardToPeer.ts
7751
+ import {
7752
+ request as httpRequest
7753
+ } from "http";
7754
+ import { request as httpsRequest } from "https";
7755
+
7756
+ // src/commands/sessions/web/boundUpstream.ts
7757
+ function boundUpstream(upstream, res, timeoutMs) {
7758
+ upstream.setTimeout(
7759
+ timeoutMs,
7760
+ () => upstream.destroy(new Error(`no response after ${timeoutMs}ms`))
7761
+ );
7762
+ res.on("close", () => {
7763
+ if (!res.writableFinished) upstream.destroy();
7764
+ });
7765
+ }
7766
+
7767
+ // src/commands/sessions/web/peerTimeoutMs.ts
7768
+ var peerTimeoutMs = 2e4;
7769
+
7770
+ // src/commands/sessions/web/peerTimeoutFor.ts
7771
+ var ASSIST_UPDATE_DURATION_MS = 6e5;
7772
+ function peerTimeoutFor(pathname) {
7773
+ return pathname === "/api/self-update" ? ASSIST_UPDATE_DURATION_MS : peerTimeoutMs;
7774
+ }
7775
+
7776
+ // src/commands/sessions/web/isQuietPoll.ts
7777
+ var POLLED_PATHS = /* @__PURE__ */ new Set(["/api/git-status", "/api/updates"]);
7778
+ function isQuietPoll(pathname, status2) {
7779
+ return POLLED_PATHS.has(pathname) && status2 >= 200 && status2 < 300;
7780
+ }
7781
+
7782
+ // src/commands/sessions/web/relayPeerResponse.ts
7783
+ function relayPeerResponse(peer, res, pathname, log2, done2) {
7784
+ const status2 = peer.statusCode ?? 502;
7785
+ if (!isQuietPoll(pathname, status2)) log2(String(status2));
7786
+ res.writeHead(status2, peer.headers);
7787
+ peer.pipe(res);
7788
+ peer.on("end", done2);
7789
+ peer.on("error", done2);
7790
+ }
7791
+
7792
+ // src/commands/sessions/web/forwardToPeer.ts
7793
+ var LINKED_FROM_HEADER = "x-assist-linked-from";
7794
+ function forwardToPeer(req, res, node, url) {
7795
+ const started = Date.now();
7796
+ const traceId = newTraceId();
7797
+ const label = `link ${node} http: ${req.method} ${url.pathname} trace=${traceId}`;
7798
+ const log2 = (outcome) => console.log(`${label} -> ${outcome} (${Date.now() - started}ms)`);
7799
+ const send = url.protocol === "https:" ? httpsRequest : httpRequest;
7800
+ return new Promise((resolve31) => {
7801
+ const upstream = send(
7802
+ url,
7803
+ {
7804
+ method: req.method,
7805
+ headers: {
7806
+ ...req.headers,
7807
+ host: url.host,
7808
+ [LINKED_FROM_HEADER]: resolveNodeName(),
7809
+ [TRACE_HEADER]: traceId
7810
+ }
7811
+ },
7812
+ (peer) => relayPeerResponse(peer, res, url.pathname, log2, resolve31)
7813
+ );
7814
+ boundUpstream(upstream, res, peerTimeoutFor(url.pathname));
7815
+ upstream.on("error", (error) => {
7816
+ log2(`failed: ${error.message}`);
7817
+ if (res.headersSent) res.destroy();
7818
+ else
7819
+ respondJson(res, 502, {
7820
+ error: `${node} unreachable: ${error.message}`
7821
+ });
7822
+ resolve31();
7823
+ });
7824
+ req.pipe(upstream);
7825
+ });
7826
+ }
7827
+
7828
+ // src/commands/sessions/web/proxyToNode.ts
7829
+ var LINKED_FROM_HEADER2 = "x-assist-linked-from";
7830
+ function arrivedOverLink(req) {
7831
+ return Boolean(req.headers[LINKED_FROM_HEADER2]);
7832
+ }
7833
+ function proxyTarget(req) {
7834
+ const url = new URL(req.url ?? "/", "http://localhost");
7835
+ const node = url.searchParams.get("node");
7836
+ if (!url.pathname.startsWith("/api/") || !node) return { kind: "local" };
7837
+ if (arrivedOverLink(req) || node === resolveNodeName())
7838
+ return { kind: "local" };
7839
+ const link3 = findLinkSpec(node);
7840
+ if (!link3) return { kind: "unknown", node };
7841
+ url.searchParams.delete("node");
7842
+ return {
7843
+ kind: "link",
7844
+ node,
7845
+ url: new URL(`${url.pathname}${url.search}`, link3.url)
7846
+ };
7847
+ }
7848
+ function logLinkedRequest(req, res) {
7849
+ const started = Date.now();
7850
+ const from = req.headers[LINKED_FROM_HEADER2];
7851
+ const trace = req.headers[TRACE_HEADER] ?? "none";
7852
+ const path108 = new URL(req.url ?? "/", "http://localhost").pathname;
7853
+ res.once("finish", () => {
7854
+ if (isQuietPoll(path108, res.statusCode)) return;
7855
+ console.log(
7856
+ `link-from ${from} http: ${req.method} ${path108} trace=${trace} -> ${res.statusCode} (${Date.now() - started}ms)`
7857
+ );
7858
+ });
7859
+ }
7860
+ async function proxyToNode(req, res) {
7861
+ if (arrivedOverLink(req)) logLinkedRequest(req, res);
7862
+ const target = proxyTarget(req);
7863
+ if (target.kind === "local") return false;
7864
+ if (target.kind === "unknown") {
7865
+ console.log(
7866
+ `link ${target.node} http: ${req.method} ${req.url} -> no such link`
7867
+ );
7868
+ respondJson(res, 404, { error: `No link to node ${target.node}` });
7869
+ return true;
7870
+ }
7871
+ await forwardToPeer(req, res, target.node, target.url);
7872
+ return true;
7873
+ }
7874
+
7875
+ // src/commands/sessions/web/handleDynamicRoute.ts
7876
+ async function handleDynamicRoute(req, res, pathname) {
7877
+ return await proxyToNode(req, res) || await handleInboxRoute(req, res, pathname) || handleItemRoute(req, res, pathname);
7878
+ }
7879
+
7686
7880
  // src/commands/sessions/web/harnessCapabilities.ts
7687
7881
  function harnessCapabilities(_req, res) {
7688
7882
  const config = loadConfig().harness;
@@ -7781,6 +7975,33 @@ async function historySearch(req, res) {
7781
7975
  respondJson(res, 200, { sessions: reply2.sessions ?? [] });
7782
7976
  }
7783
7977
 
7978
+ // src/shared/db/listInboxMessages.ts
7979
+ import { desc as desc2, isNull as isNull2, sql as sql16 } from "drizzle-orm";
7980
+ function listInboxMessages(orm) {
7981
+ return orm.select().from(inboxMessages).where(isNull2(inboxMessages.dismissedAt)).orderBy(
7982
+ desc2(
7983
+ sql16`coalesce(${inboxMessages.receivedAt}, ${inboxMessages.flaggedAt})`
7984
+ )
7985
+ );
7986
+ }
7987
+
7988
+ // src/commands/sessions/web/inbox/listInbox.ts
7989
+ async function listInbox(_req, res) {
7990
+ const rows = await listInboxMessages(await getDb());
7991
+ respondJson(
7992
+ res,
7993
+ 200,
7994
+ rows.map((row3) => ({
7995
+ id: inboxMessageKey(row3.source, row3.messageId),
7996
+ source: row3.source,
7997
+ sender: row3.sender,
7998
+ summary: row3.summary,
7999
+ link: row3.link,
8000
+ receivedAt: (row3.receivedAt ?? row3.flaggedAt).toISOString()
8001
+ }))
8002
+ );
8003
+ }
8004
+
7784
8005
  // src/shared/hotkeys/resolveHotkeys.ts
7785
8006
  function resolveHotkeys(overrides) {
7786
8007
  const bindings = { ...defaultHotkeys };
@@ -8895,22 +9116,22 @@ function listScopedRules(req, res) {
8895
9116
  }
8896
9117
 
8897
9118
  // src/shared/db/countUsagePeaks.ts
8898
- import { count, eq as eq16 } from "drizzle-orm";
9119
+ import { count, eq as eq17 } from "drizzle-orm";
8899
9120
  async function countUsagePeaks(db, window) {
8900
- const [row3] = await db.select({ value: count() }).from(usagePeaks).where(window ? eq16(usagePeaks.window, window) : void 0);
9121
+ const [row3] = await db.select({ value: count() }).from(usagePeaks).where(window ? eq17(usagePeaks.window, window) : void 0);
8901
9122
  return row3?.value ?? 0;
8902
9123
  }
8903
9124
 
8904
9125
  // src/shared/db/listUsagePeaks.ts
8905
- import { and as and6, desc as desc2, eq as eq17, getTableColumns } from "drizzle-orm";
9126
+ import { and as and7, desc as desc3, eq as eq18, getTableColumns } from "drizzle-orm";
8906
9127
 
8907
9128
  // src/shared/db/avgContextPerCycle.ts
8908
- import { count as count2, sql as sql16 } from "drizzle-orm";
9129
+ import { count as count2, sql as sql17 } from "drizzle-orm";
8909
9130
  function avgContextPerCycle(db) {
8910
9131
  return db.select({
8911
9132
  window: phaseCycleContext.window,
8912
9133
  resetsAt: phaseCycleContext.resetsAt,
8913
- avgContextPct: sql16`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
9134
+ avgContextPct: sql17`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
8914
9135
  "avg_context_pct"
8915
9136
  ),
8916
9137
  phaseCount: count2().as("phase_count")
@@ -8926,15 +9147,15 @@ async function listUsagePeaks(db, options2) {
8926
9147
  phaseCount: avgContext.phaseCount
8927
9148
  }).from(usagePeaks).leftJoin(
8928
9149
  avgContext,
8929
- and6(
8930
- eq17(usagePeaks.window, avgContext.window),
8931
- eq17(usagePeaks.resetsAt, avgContext.resetsAt)
9150
+ and7(
9151
+ eq18(usagePeaks.window, avgContext.window),
9152
+ eq18(usagePeaks.resetsAt, avgContext.resetsAt)
8932
9153
  )
8933
- ).where(options2?.window ? eq17(usagePeaks.window, options2.window) : void 0).orderBy(
8934
- desc2(usagePeaks.resetsAt),
9154
+ ).where(options2?.window ? eq18(usagePeaks.window, options2.window) : void 0).orderBy(
9155
+ desc3(usagePeaks.resetsAt),
8935
9156
  usagePeaks.window,
8936
- desc2(usagePeaks.createdAt),
8937
- desc2(usagePeaks.segment)
9157
+ desc3(usagePeaks.createdAt),
9158
+ desc3(usagePeaks.segment)
8938
9159
  );
8939
9160
  if (options2?.limit !== void 0) {
8940
9161
  return query.limit(options2.limit).offset(options2.offset ?? 0);
@@ -8999,26 +9220,26 @@ function listUsageHistory(req, res) {
8999
9220
  }
9000
9221
 
9001
9222
  // src/shared/db/countItemUsageByOrigin.ts
9002
- import { asc as asc8, desc as desc3, eq as eq18, sql as sql17 } from "drizzle-orm";
9223
+ import { asc as asc8, desc as desc4, eq as eq19, sql as sql18 } from "drizzle-orm";
9003
9224
  async function countItemUsageByOrigin(db) {
9004
- const count10 = sql17`count(distinct ${phaseUsage.itemId})::int`;
9005
- const rows = await db.select({ origin: items.origin, count: count10 }).from(items).innerJoin(phaseUsage, eq18(phaseUsage.itemId, items.id)).groupBy(items.origin).orderBy(desc3(count10), asc8(items.origin));
9225
+ const count10 = sql18`count(distinct ${phaseUsage.itemId})::int`;
9226
+ const rows = await db.select({ origin: items.origin, count: count10 }).from(items).innerJoin(phaseUsage, eq19(phaseUsage.itemId, items.id)).groupBy(items.origin).orderBy(desc4(count10), asc8(items.origin));
9006
9227
  return rows.map((row3) => ({ origin: row3.origin, count: Number(row3.count) }));
9007
9228
  }
9008
9229
 
9009
9230
  // src/shared/db/itemUsageWhere.ts
9010
- import { and as and7, eq as eq19, notInArray } from "drizzle-orm";
9231
+ import { and as and8, eq as eq20, notInArray } from "drizzle-orm";
9011
9232
  function parseItemUsageStatus(value) {
9012
9233
  return value === "done" || value === "running" ? value : void 0;
9013
9234
  }
9014
9235
  function statusClause(status2) {
9015
- if (status2 === "done") return eq19(items.status, "done");
9236
+ if (status2 === "done") return eq20(items.status, "done");
9016
9237
  if (status2 === "running") return notInArray(items.status, ["done", "wontdo"]);
9017
9238
  return void 0;
9018
9239
  }
9019
9240
  function itemUsageWhere(filter) {
9020
- return and7(
9021
- filter?.origin ? eq19(items.origin, filter.origin) : void 0,
9241
+ return and8(
9242
+ filter?.origin ? eq20(items.origin, filter.origin) : void 0,
9022
9243
  statusClause(filter?.status)
9023
9244
  );
9024
9245
  }
@@ -9043,23 +9264,23 @@ function parseItemUsageSort(field, direction) {
9043
9264
  }
9044
9265
 
9045
9266
  // src/shared/db/itemUsageStats.ts
9046
- import { eq as eq20, sql as sql18 } from "drizzle-orm";
9267
+ import { eq as eq21, sql as sql19 } from "drizzle-orm";
9047
9268
  function median(value) {
9048
- return sql18`coalesce(percentile_cont(0.5) within group (order by (${value})::double precision), 0)`;
9269
+ return sql19`coalesce(percentile_cont(0.5) within group (order by (${value})::double precision), 0)`;
9049
9270
  }
9050
9271
  async function itemUsageStats(db, options2) {
9051
9272
  const totals = phaseUsageTotals(db);
9052
9273
  const planned = planPhaseCounts(db);
9053
9274
  const [row3] = await db.select({
9054
- itemCount: sql18`count(*)::int`,
9055
- doneCount: sql18`count(*) filter (where ${items.status} = 'done')::int`,
9056
- repoCount: sql18`count(distinct ${items.origin})::int`,
9275
+ itemCount: sql19`count(*)::int`,
9276
+ doneCount: sql19`count(*) filter (where ${items.status} = 'done')::int`,
9277
+ repoCount: sql19`count(distinct ${items.origin})::int`,
9057
9278
  medianPhases: median(
9058
- sql18`coalesce(${planned.count}, ${totals.recordedPhases})`
9279
+ sql19`coalesce(${planned.count}, ${totals.recordedPhases})`
9059
9280
  ),
9060
9281
  medianActiveMs: median(totals.activeMs),
9061
- medianTokens: median(sql18`${totals.tokensUp} + ${totals.tokensDown}`)
9062
- }).from(items).innerJoin(totals, eq20(totals.itemId, items.id)).leftJoin(planned, eq20(planned.itemId, items.id)).where(itemUsageWhere(options2));
9282
+ medianTokens: median(sql19`${totals.tokensUp} + ${totals.tokensDown}`)
9283
+ }).from(items).innerJoin(totals, eq21(totals.itemId, items.id)).leftJoin(planned, eq21(planned.itemId, items.id)).where(itemUsageWhere(options2));
9063
9284
  return {
9064
9285
  itemCount: Number(row3?.itemCount ?? 0),
9065
9286
  doneCount: Number(row3?.doneCount ?? 0),
@@ -9071,30 +9292,30 @@ async function itemUsageStats(db, options2) {
9071
9292
  }
9072
9293
 
9073
9294
  // src/shared/db/listItemUsageSummaries.ts
9074
- import { eq as eq21 } from "drizzle-orm";
9295
+ import { eq as eq22 } from "drizzle-orm";
9075
9296
 
9076
9297
  // src/shared/db/itemUsageOrderBy.ts
9077
- import { desc as desc4, sql as sql19 } from "drizzle-orm";
9298
+ import { desc as desc5, sql as sql20 } from "drizzle-orm";
9078
9299
  function itemUsageOrderBy(joins, sort = defaultItemUsageSort) {
9079
9300
  const { totals, planned, lastPhase } = joins;
9080
9301
  const sortable = {
9081
- phases: sql19`coalesce(${planned.count}, ${totals.recordedPhases})`,
9082
- active: sql19`${totals.activeMs}`,
9083
- tokens: sql19`${totals.tokensUp} + ${totals.tokensDown}`,
9084
- peakContext: sql19`${totals.peakContextPct}`,
9085
- lastPhase: sql19`${lastPhase.at}`
9302
+ phases: sql20`coalesce(${planned.count}, ${totals.recordedPhases})`,
9303
+ active: sql20`${totals.activeMs}`,
9304
+ tokens: sql20`${totals.tokensUp} + ${totals.tokensDown}`,
9305
+ peakContext: sql20`${totals.peakContextPct}`,
9306
+ lastPhase: sql20`${lastPhase.at}`
9086
9307
  };
9087
- const order = sort.direction === "asc" ? sql19`asc` : sql19`desc`;
9088
- return [sql19`${sortable[sort.field]} ${order} nulls last`, desc4(items.id)];
9308
+ const order = sort.direction === "asc" ? sql20`asc` : sql20`desc`;
9309
+ return [sql20`${sortable[sort.field]} ${order} nulls last`, desc5(items.id)];
9089
9310
  }
9090
9311
 
9091
9312
  // src/shared/db/lastPhaseActivity.ts
9092
- import { sql as sql20 } from "drizzle-orm";
9313
+ import { sql as sql21 } from "drizzle-orm";
9093
9314
  function lastPhaseActivity(db) {
9094
9315
  return db.select({
9095
9316
  itemId: phaseSessions.itemId,
9096
- at: sql20`max(${phaseSessions.createdAt})`.as("last_phase_at"),
9097
- atIso: sql20`to_char(max(${phaseSessions.createdAt}) at time zone 'utc', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`.as(
9317
+ at: sql21`max(${phaseSessions.createdAt})`.as("last_phase_at"),
9318
+ atIso: sql21`to_char(max(${phaseSessions.createdAt}) at time zone 'utc', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')`.as(
9098
9319
  "last_phase_at_iso"
9099
9320
  )
9100
9321
  }).from(phaseSessions).groupBy(phaseSessions.itemId).as("last_phase_activity");
@@ -9132,7 +9353,7 @@ async function listItemUsageSummaries(db, options2) {
9132
9353
  activeMs: totals.activeMs,
9133
9354
  peakContextPct: totals.peakContextPct,
9134
9355
  lastPhaseAt: lastPhase.atIso
9135
- }).from(items).innerJoin(totals, eq21(totals.itemId, items.id)).leftJoin(planned, eq21(planned.itemId, items.id)).leftJoin(lastPhase, eq21(lastPhase.itemId, items.id)).where(itemUsageWhere(options2)).orderBy(
9356
+ }).from(items).innerJoin(totals, eq22(totals.itemId, items.id)).leftJoin(planned, eq22(planned.itemId, items.id)).leftJoin(lastPhase, eq22(lastPhase.itemId, items.id)).where(itemUsageWhere(options2)).orderBy(
9136
9357
  ...itemUsageOrderBy({ totals, planned, lastPhase }, options2?.sort)
9137
9358
  );
9138
9359
  const rows = options2?.limit === void 0 ? await query : await query.limit(options2.limit).offset(options2.offset ?? 0);
@@ -9236,146 +9457,6 @@ async function prList(req, res) {
9236
9457
  respondJson(res, 200, { prs: await getOpenPrs(cwd) });
9237
9458
  }
9238
9459
 
9239
- // src/commands/sessions/shared/loadLinkSpecs.ts
9240
- function loadLinkSpecs() {
9241
- return loadConfig().sessions?.links ?? [];
9242
- }
9243
- function findLinkSpec(name) {
9244
- return loadLinkSpecs().find((spec) => spec.name === name);
9245
- }
9246
-
9247
- // src/commands/sessions/shared/newTraceId.ts
9248
- import { randomUUID as randomUUID2 } from "crypto";
9249
- var TRACE_HEADER = "x-assist-trace-id";
9250
- function newTraceId() {
9251
- return randomUUID2().slice(0, 8);
9252
- }
9253
-
9254
- // src/commands/sessions/web/forwardToPeer.ts
9255
- import {
9256
- request as httpRequest
9257
- } from "http";
9258
- import { request as httpsRequest } from "https";
9259
-
9260
- // src/commands/sessions/web/boundUpstream.ts
9261
- function boundUpstream(upstream, res, timeoutMs) {
9262
- upstream.setTimeout(
9263
- timeoutMs,
9264
- () => upstream.destroy(new Error(`no response after ${timeoutMs}ms`))
9265
- );
9266
- res.on("close", () => {
9267
- if (!res.writableFinished) upstream.destroy();
9268
- });
9269
- }
9270
-
9271
- // src/commands/sessions/web/peerTimeoutMs.ts
9272
- var peerTimeoutMs = 2e4;
9273
-
9274
- // src/commands/sessions/web/peerTimeoutFor.ts
9275
- var ASSIST_UPDATE_DURATION_MS = 6e5;
9276
- function peerTimeoutFor(pathname) {
9277
- return pathname === "/api/self-update" ? ASSIST_UPDATE_DURATION_MS : peerTimeoutMs;
9278
- }
9279
-
9280
- // src/commands/sessions/web/isQuietPoll.ts
9281
- var POLLED_PATHS = /* @__PURE__ */ new Set(["/api/git-status", "/api/updates"]);
9282
- function isQuietPoll(pathname, status2) {
9283
- return POLLED_PATHS.has(pathname) && status2 >= 200 && status2 < 300;
9284
- }
9285
-
9286
- // src/commands/sessions/web/relayPeerResponse.ts
9287
- function relayPeerResponse(peer, res, pathname, log2, done2) {
9288
- const status2 = peer.statusCode ?? 502;
9289
- if (!isQuietPoll(pathname, status2)) log2(String(status2));
9290
- res.writeHead(status2, peer.headers);
9291
- peer.pipe(res);
9292
- peer.on("end", done2);
9293
- peer.on("error", done2);
9294
- }
9295
-
9296
- // src/commands/sessions/web/forwardToPeer.ts
9297
- var LINKED_FROM_HEADER = "x-assist-linked-from";
9298
- function forwardToPeer(req, res, node, url) {
9299
- const started = Date.now();
9300
- const traceId = newTraceId();
9301
- const label = `link ${node} http: ${req.method} ${url.pathname} trace=${traceId}`;
9302
- const log2 = (outcome) => console.log(`${label} -> ${outcome} (${Date.now() - started}ms)`);
9303
- const send = url.protocol === "https:" ? httpsRequest : httpRequest;
9304
- return new Promise((resolve31) => {
9305
- const upstream = send(
9306
- url,
9307
- {
9308
- method: req.method,
9309
- headers: {
9310
- ...req.headers,
9311
- host: url.host,
9312
- [LINKED_FROM_HEADER]: resolveNodeName(),
9313
- [TRACE_HEADER]: traceId
9314
- }
9315
- },
9316
- (peer) => relayPeerResponse(peer, res, url.pathname, log2, resolve31)
9317
- );
9318
- boundUpstream(upstream, res, peerTimeoutFor(url.pathname));
9319
- upstream.on("error", (error) => {
9320
- log2(`failed: ${error.message}`);
9321
- if (res.headersSent) res.destroy();
9322
- else
9323
- respondJson(res, 502, {
9324
- error: `${node} unreachable: ${error.message}`
9325
- });
9326
- resolve31();
9327
- });
9328
- req.pipe(upstream);
9329
- });
9330
- }
9331
-
9332
- // src/commands/sessions/web/proxyToNode.ts
9333
- var LINKED_FROM_HEADER2 = "x-assist-linked-from";
9334
- function arrivedOverLink(req) {
9335
- return Boolean(req.headers[LINKED_FROM_HEADER2]);
9336
- }
9337
- function proxyTarget(req) {
9338
- const url = new URL(req.url ?? "/", "http://localhost");
9339
- const node = url.searchParams.get("node");
9340
- if (!url.pathname.startsWith("/api/") || !node) return { kind: "local" };
9341
- if (arrivedOverLink(req) || node === resolveNodeName())
9342
- return { kind: "local" };
9343
- const link3 = findLinkSpec(node);
9344
- if (!link3) return { kind: "unknown", node };
9345
- url.searchParams.delete("node");
9346
- return {
9347
- kind: "link",
9348
- node,
9349
- url: new URL(`${url.pathname}${url.search}`, link3.url)
9350
- };
9351
- }
9352
- function logLinkedRequest(req, res) {
9353
- const started = Date.now();
9354
- const from = req.headers[LINKED_FROM_HEADER2];
9355
- const trace = req.headers[TRACE_HEADER] ?? "none";
9356
- const path108 = new URL(req.url ?? "/", "http://localhost").pathname;
9357
- res.once("finish", () => {
9358
- if (isQuietPoll(path108, res.statusCode)) return;
9359
- console.log(
9360
- `link-from ${from} http: ${req.method} ${path108} trace=${trace} -> ${res.statusCode} (${Date.now() - started}ms)`
9361
- );
9362
- });
9363
- }
9364
- async function proxyToNode(req, res) {
9365
- if (arrivedOverLink(req)) logLinkedRequest(req, res);
9366
- const target = proxyTarget(req);
9367
- if (target.kind === "local") return false;
9368
- if (target.kind === "unknown") {
9369
- console.log(
9370
- `link ${target.node} http: ${req.method} ${req.url} -> no such link`
9371
- );
9372
- respondJson(res, 404, { error: `No link to node ${target.node}` });
9373
- return true;
9374
- }
9375
- await forwardToPeer(req, res, target.node, target.url);
9376
- return true;
9377
- }
9378
-
9379
9460
  // src/commands/sessions/web/previewImage.ts
9380
9461
  import { createReadStream as createReadStream2 } from "fs";
9381
9462
  import { stat as stat2 } from "fs/promises";
@@ -11059,10 +11140,10 @@ function currentRepoLabel(shared, origin) {
11059
11140
  }
11060
11141
 
11061
11142
  // src/shared/db/saveRepoConfig.ts
11062
- import { eq as eq22 } from "drizzle-orm";
11143
+ import { eq as eq23 } from "drizzle-orm";
11063
11144
  async function saveRepoConfig(orm, repoKey, config) {
11064
11145
  if (Object.keys(config).length === 0) {
11065
- await orm.delete(repoConfigs).where(eq22(repoConfigs.repoKey, repoKey));
11146
+ await orm.delete(repoConfigs).where(eq23(repoConfigs.repoKey, repoKey));
11066
11147
  return;
11067
11148
  }
11068
11149
  await orm.insert(repoConfigs).values({ repoKey, config }).onConflictDoUpdate({
@@ -11935,6 +12016,7 @@ var routes2 = {
11935
12016
  "GET /api/pr-list": prList,
11936
12017
  "GET /api/next": nextItems,
11937
12018
  "POST /api/next/pickup": nextPickup,
12019
+ "GET /api/inbox": listInbox,
11938
12020
  "GET /api/news/items": listNewsItems,
11939
12021
  "GET /api/news/nav": newsNavConfig,
11940
12022
  "GET /api/releases/state": releasesState,
@@ -11954,7 +12036,7 @@ var routes2 = {
11954
12036
  var handleRequest = createFallbackHandler(
11955
12037
  routes2,
11956
12038
  htmlHandler,
11957
- async (req, res, pathname) => await proxyToNode(req, res) || handleItemRoute(req, res, pathname)
12039
+ handleDynamicRoute
11958
12040
  );
11959
12041
 
11960
12042
  // src/commands/sessions/web/restartMenu/installRestartMenu.ts
@@ -15292,11 +15374,11 @@ function registerActivityCommands(cmd) {
15292
15374
 
15293
15375
  // src/commands/backlog/associateGithub.ts
15294
15376
  import chalk43 from "chalk";
15295
- import { eq as eq24 } from "drizzle-orm";
15377
+ import { eq as eq25 } from "drizzle-orm";
15296
15378
 
15297
15379
  // src/commands/backlog/beginAssociation.ts
15298
15380
  import chalk42 from "chalk";
15299
- import { eq as eq23 } from "drizzle-orm";
15381
+ import { eq as eq24 } from "drizzle-orm";
15300
15382
  async function beginAssociation(id, options2, clearPatch, label) {
15301
15383
  const found = await findOneItem(id);
15302
15384
  if (!found) {
@@ -15306,7 +15388,7 @@ async function beginAssociation(id, options2, clearPatch, label) {
15306
15388
  const { orm } = found;
15307
15389
  const itemId2 = found.item.id;
15308
15390
  if (options2.clear) {
15309
- await orm.update(items).set(clearPatch).where(eq23(items.id, itemId2));
15391
+ await orm.update(items).set(clearPatch).where(eq24(items.id, itemId2));
15310
15392
  console.log(
15311
15393
  chalk42.green(
15312
15394
  `Cleared ${label} association on item ${formatItemId(itemId2)}.`
@@ -15374,7 +15456,7 @@ async function associateGithub(id, issue, options2) {
15374
15456
  return;
15375
15457
  }
15376
15458
  const title = fetchGithubIssueTitle(normalized);
15377
- await orm.update(items).set({ githubIssue: normalized, jiraKey: null }).where(eq24(items.id, itemId2));
15459
+ await orm.update(items).set({ githubIssue: normalized, jiraKey: null }).where(eq25(items.id, itemId2));
15378
15460
  console.log(
15379
15461
  chalk43.green(`Associated ${normalized} with item ${formatItemId(itemId2)}.`),
15380
15462
  title ? chalk43.dim(`(${title})`) : ""
@@ -15388,7 +15470,7 @@ function registerAssociateGithubCommand(cmd) {
15388
15470
 
15389
15471
  // src/commands/backlog/associateJira.ts
15390
15472
  import chalk45 from "chalk";
15391
- import { eq as eq25 } from "drizzle-orm";
15473
+ import { eq as eq26 } from "drizzle-orm";
15392
15474
 
15393
15475
  // src/commands/jira/fetchIssue.ts
15394
15476
  import { execSync as execSync17 } from "child_process";
@@ -15453,7 +15535,7 @@ async function associateJira(id, key, options2) {
15453
15535
  const parsed = fetchIssue(normalized, "summary");
15454
15536
  const fields = parsed?.fields;
15455
15537
  const summary = fields?.summary;
15456
- await orm.update(items).set({ jiraKey: normalized, githubIssue: null }).where(eq25(items.id, itemId2));
15538
+ await orm.update(items).set({ jiraKey: normalized, githubIssue: null }).where(eq26(items.id, itemId2));
15457
15539
  console.log(
15458
15540
  chalk45.green(`Associated ${normalized} with item ${formatItemId(itemId2)}.`),
15459
15541
  summary ? chalk45.dim(`(${summary})`) : ""
@@ -15838,15 +15920,15 @@ function isClaudeCode() {
15838
15920
  }
15839
15921
 
15840
15922
  // src/commands/backlog/insertPhaseAt.ts
15841
- import { eq as eq27 } from "drizzle-orm";
15923
+ import { eq as eq28 } from "drizzle-orm";
15842
15924
 
15843
15925
  // src/commands/backlog/shiftPhasesUp.ts
15844
- import { and as and8, desc as desc5, eq as eq26, gte } from "drizzle-orm";
15926
+ import { and as and9, desc as desc6, eq as eq27, gte } from "drizzle-orm";
15845
15927
  async function shiftPhasesUp(db, itemId2, fromIdx) {
15846
- const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and8(eq26(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc5(planPhases.idx));
15928
+ const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and9(eq27(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc6(planPhases.idx));
15847
15929
  for (const p of toShift) {
15848
- await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and8(eq26(planTasks.itemId, itemId2), eq26(planTasks.phaseIdx, p.idx)));
15849
- await db.update(planPhases).set({ idx: p.idx + 1 }).where(and8(eq26(planPhases.itemId, itemId2), eq26(planPhases.idx, p.idx)));
15930
+ await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and9(eq27(planTasks.itemId, itemId2), eq27(planTasks.phaseIdx, p.idx)));
15931
+ await db.update(planPhases).set({ idx: p.idx + 1 }).where(and9(eq27(planPhases.itemId, itemId2), eq27(planPhases.idx, p.idx)));
15850
15932
  }
15851
15933
  }
15852
15934
 
@@ -15859,7 +15941,7 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
15859
15941
  await tx.insert(planTasks).values(tasks.map((task, i) => ({ itemId: itemId2, phaseIdx, idx: i, task })));
15860
15942
  }
15861
15943
  if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
15862
- await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(eq27(items.id, itemId2));
15944
+ await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(eq28(items.id, itemId2));
15863
15945
  }
15864
15946
  });
15865
15947
  }
@@ -16016,9 +16098,9 @@ import chalk56 from "chalk";
16016
16098
 
16017
16099
  // src/commands/backlog/resolveInsertPosition.ts
16018
16100
  import chalk55 from "chalk";
16019
- import { count as count3, eq as eq28 } from "drizzle-orm";
16101
+ import { count as count3, eq as eq29 } from "drizzle-orm";
16020
16102
  async function resolveInsertPosition(orm, itemId2, position) {
16021
- const [row3] = await orm.select({ cnt: count3() }).from(planPhases).where(eq28(planPhases.itemId, itemId2));
16103
+ const [row3] = await orm.select({ cnt: count3() }).from(planPhases).where(eq29(planPhases.itemId, itemId2));
16022
16104
  const phaseCount = row3?.cnt ?? 0;
16023
16105
  if (position === void 0) return phaseCount;
16024
16106
  const pos = Number.parseInt(position, 10);
@@ -16438,9 +16520,9 @@ function hasCycle(adjacency, fromId, toId) {
16438
16520
  }
16439
16521
 
16440
16522
  // src/commands/backlog/loadDependencyGraph.ts
16441
- import { eq as eq29 } from "drizzle-orm";
16523
+ import { eq as eq30 } from "drizzle-orm";
16442
16524
  async function loadDependencyGraph(orm) {
16443
- const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq29(links.type, "depends-on"));
16525
+ const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq30(links.type, "depends-on"));
16444
16526
  const graph = /* @__PURE__ */ new Map();
16445
16527
  for (const { itemId: itemId2, targetId } of rows) {
16446
16528
  const bucket = graph.get(itemId2);
@@ -16507,7 +16589,7 @@ async function link(fromId, toId, opts) {
16507
16589
 
16508
16590
  // src/commands/backlog/unlink.ts
16509
16591
  import chalk64 from "chalk";
16510
- import { and as and9, eq as eq30 } from "drizzle-orm";
16592
+ import { and as and10, eq as eq31 } from "drizzle-orm";
16511
16593
  async function unlink(fromId, toId) {
16512
16594
  const fromNum = parseItemId(fromId);
16513
16595
  const toNum = parseItemId(toId);
@@ -16531,7 +16613,7 @@ async function unlink(fromId, toId) {
16531
16613
  );
16532
16614
  return;
16533
16615
  }
16534
- await orm.delete(links).where(and9(eq30(links.itemId, fromNum), eq30(links.targetId, toNum)));
16616
+ await orm.delete(links).where(and10(eq31(links.itemId, fromNum), eq31(links.targetId, toNum)));
16535
16617
  console.log(
16536
16618
  chalk64.green(
16537
16619
  `Removed link from ${formatItemId(fromNum)} to ${formatItemId(toNum)}.`
@@ -16551,7 +16633,7 @@ function registerLinkCommands(cmd) {
16551
16633
 
16552
16634
  // src/commands/backlog/moveRepo.ts
16553
16635
  import chalk66 from "chalk";
16554
- import { eq as eq32 } from "drizzle-orm";
16636
+ import { eq as eq33 } from "drizzle-orm";
16555
16637
 
16556
16638
  // src/commands/backlog/move-repo/confirmMove.ts
16557
16639
  import chalk65 from "chalk";
@@ -16566,9 +16648,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
16566
16648
  }
16567
16649
 
16568
16650
  // src/commands/backlog/move-repo/countByOrigin.ts
16569
- import { count as count4, eq as eq31 } from "drizzle-orm";
16651
+ import { count as count4, eq as eq32 } from "drizzle-orm";
16570
16652
  async function countByOrigin(orm, origin) {
16571
- const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq31(items.origin, origin));
16653
+ const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq32(items.origin, origin));
16572
16654
  return cnt;
16573
16655
  }
16574
16656
 
@@ -16611,7 +16693,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
16611
16693
  console.log(chalk66.yellow("Move cancelled; no changes made."));
16612
16694
  return;
16613
16695
  }
16614
- await orm.update(items).set({ origin: newOrigin }).where(eq32(items.origin, oldOrigin));
16696
+ await orm.update(items).set({ origin: newOrigin }).where(eq33(items.origin, oldOrigin));
16615
16697
  console.log(
16616
16698
  chalk66.green(
16617
16699
  `Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
@@ -17193,12 +17275,12 @@ async function ensureDone(id) {
17193
17275
  import chalk70 from "chalk";
17194
17276
 
17195
17277
  // src/shared/db/findPhaseBySessionId.ts
17196
- import { and as and10, eq as eq33 } from "drizzle-orm";
17278
+ import { and as and11, eq as eq34 } from "drizzle-orm";
17197
17279
  async function findPhaseBySessionId(db, itemId2, claudeSessionId) {
17198
17280
  const rows = await db.select({ phaseIdx: phaseUsage.phaseIdx }).from(phaseUsage).where(
17199
- and10(
17200
- eq33(phaseUsage.itemId, itemId2),
17201
- eq33(phaseUsage.claudeSessionId, claudeSessionId)
17281
+ and11(
17282
+ eq34(phaseUsage.itemId, itemId2),
17283
+ eq34(phaseUsage.claudeSessionId, claudeSessionId)
17202
17284
  )
17203
17285
  ).limit(1);
17204
17286
  return rows[0]?.phaseIdx;
@@ -17665,7 +17747,7 @@ import { randomUUID as randomUUID6 } from "crypto";
17665
17747
  import os4 from "os";
17666
17748
 
17667
17749
  // src/shared/db/recordPhaseSession.ts
17668
- import { sql as sql21 } from "drizzle-orm";
17750
+ import { sql as sql22 } from "drizzle-orm";
17669
17751
  async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostname2, osUser) {
17670
17752
  await db.insert(phaseSessions).values({ itemId: itemId2, phaseIdx, claudeSessionId, hostname: hostname2, osUser }).onConflictDoUpdate({
17671
17753
  target: [
@@ -17674,7 +17756,7 @@ async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostna
17674
17756
  phaseSessions.claudeSessionId
17675
17757
  ],
17676
17758
  set: { hostname: hostname2, osUser },
17677
- setWhere: sql21`${phaseSessions.hostname} = 'unknown'`
17759
+ setWhere: sql22`${phaseSessions.hostname} = 'unknown'`
17678
17760
  });
17679
17761
  }
17680
17762
 
@@ -18545,10 +18627,10 @@ async function start(id) {
18545
18627
 
18546
18628
  // src/commands/backlog/stop.ts
18547
18629
  import chalk92 from "chalk";
18548
- import { and as and11, eq as eq34 } from "drizzle-orm";
18630
+ import { and as and12, eq as eq35 } from "drizzle-orm";
18549
18631
  async function stop() {
18550
18632
  const { orm } = await getReady();
18551
- const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and11(eq34(items.status, "in-progress"), eq34(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
18633
+ const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and12(eq35(items.status, "in-progress"), eq35(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
18552
18634
  if (stopped.length === 0) {
18553
18635
  console.log(chalk92.yellow("No in-progress items to stop."));
18554
18636
  return;
@@ -18606,20 +18688,20 @@ function registerStatusCommands(cmd) {
18606
18688
 
18607
18689
  // src/commands/backlog/movePhase.ts
18608
18690
  import chalk95 from "chalk";
18609
- import { count as count6, eq as eq37 } from "drizzle-orm";
18691
+ import { count as count6, eq as eq38 } from "drizzle-orm";
18610
18692
 
18611
18693
  // src/commands/backlog/reorderPhaseRows.ts
18612
- import { and as and13, asc as asc10, eq as eq36 } from "drizzle-orm";
18694
+ import { and as and14, asc as asc10, eq as eq37 } from "drizzle-orm";
18613
18695
 
18614
18696
  // src/commands/backlog/reindexPhases.ts
18615
- import { and as and12, asc as asc9, count as count5, eq as eq35 } from "drizzle-orm";
18697
+ import { and as and13, asc as asc9, count as count5, eq as eq36 } from "drizzle-orm";
18616
18698
  async function reindexPhases(db, itemId2) {
18617
- const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq35(planPhases.itemId, itemId2)).orderBy(asc9(planPhases.idx));
18699
+ const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq36(planPhases.itemId, itemId2)).orderBy(asc9(planPhases.idx));
18618
18700
  for (let i = 0; i < remaining.length; i++) {
18619
18701
  const oldIdx = remaining[i].idx;
18620
18702
  if (oldIdx === i) continue;
18621
- await db.update(planTasks).set({ phaseIdx: i }).where(and12(eq35(planTasks.itemId, itemId2), eq35(planTasks.phaseIdx, oldIdx)));
18622
- await db.update(planPhases).set({ idx: i }).where(and12(eq35(planPhases.itemId, itemId2), eq35(planPhases.idx, oldIdx)));
18703
+ await db.update(planTasks).set({ phaseIdx: i }).where(and13(eq36(planTasks.itemId, itemId2), eq36(planTasks.phaseIdx, oldIdx)));
18704
+ await db.update(planPhases).set({ idx: i }).where(and13(eq36(planPhases.itemId, itemId2), eq36(planPhases.idx, oldIdx)));
18623
18705
  }
18624
18706
  }
18625
18707
  async function adjustCurrentPhase(db, item, removedIdx) {
@@ -18627,24 +18709,24 @@ async function adjustCurrentPhase(db, item, removedIdx) {
18627
18709
  if (currentPhase === void 0) return;
18628
18710
  const currentIdx = currentPhase - 1;
18629
18711
  if (removedIdx < currentIdx) {
18630
- await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq35(items.id, item.id));
18712
+ await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq36(items.id, item.id));
18631
18713
  return;
18632
18714
  }
18633
18715
  if (removedIdx !== currentIdx) return;
18634
- const [row3] = await db.select({ cnt: count5() }).from(planPhases).where(eq35(planPhases.itemId, item.id));
18716
+ const [row3] = await db.select({ cnt: count5() }).from(planPhases).where(eq36(planPhases.itemId, item.id));
18635
18717
  const cnt = row3?.cnt ?? 0;
18636
- await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq35(items.id, item.id));
18718
+ await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq36(items.id, item.id));
18637
18719
  }
18638
18720
 
18639
18721
  // src/commands/backlog/reorderPhaseRows.ts
18640
18722
  async function reorderPhaseRows(orm, itemId2, fromIdx, toIdx) {
18641
18723
  await orm.transaction(async (tx) => {
18642
- const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and13(eq36(planPhases.itemId, itemId2), eq36(planPhases.idx, fromIdx)));
18643
- const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and13(eq36(planTasks.itemId, itemId2), eq36(planTasks.phaseIdx, fromIdx))).orderBy(asc10(planTasks.idx));
18724
+ const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and14(eq37(planPhases.itemId, itemId2), eq37(planPhases.idx, fromIdx)));
18725
+ const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and14(eq37(planTasks.itemId, itemId2), eq37(planTasks.phaseIdx, fromIdx))).orderBy(asc10(planTasks.idx));
18644
18726
  await tx.delete(planTasks).where(
18645
- and13(eq36(planTasks.itemId, itemId2), eq36(planTasks.phaseIdx, fromIdx))
18727
+ and14(eq37(planTasks.itemId, itemId2), eq37(planTasks.phaseIdx, fromIdx))
18646
18728
  );
18647
- await tx.delete(planPhases).where(and13(eq36(planPhases.itemId, itemId2), eq36(planPhases.idx, fromIdx)));
18729
+ await tx.delete(planPhases).where(and14(eq37(planPhases.itemId, itemId2), eq37(planPhases.idx, fromIdx)));
18648
18730
  await reindexPhases(tx, itemId2);
18649
18731
  await shiftPhasesUp(tx, itemId2, toIdx);
18650
18732
  await tx.insert(planPhases).values({
@@ -18685,7 +18767,7 @@ async function movePhase(id, from, to) {
18685
18767
  if (!found) return;
18686
18768
  const { orm, item } = found;
18687
18769
  const itemId2 = item.id;
18688
- const [row3] = await orm.select({ cnt: count6() }).from(planPhases).where(eq37(planPhases.itemId, itemId2));
18770
+ const [row3] = await orm.select({ cnt: count6() }).from(planPhases).where(eq38(planPhases.itemId, itemId2));
18689
18771
  const phaseCount = row3?.cnt ?? 0;
18690
18772
  const fromIdx = toIndex2(from, phaseCount);
18691
18773
  if (fromIdx === void 0) return;
@@ -18701,22 +18783,22 @@ async function movePhase(id, from, to) {
18701
18783
  import chalk97 from "chalk";
18702
18784
 
18703
18785
  // src/commands/backlog/applyPhaseUpdate.ts
18704
- import { and as and14, eq as eq38 } from "drizzle-orm";
18786
+ import { and as and15, eq as eq39 } from "drizzle-orm";
18705
18787
  async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
18706
18788
  await orm.transaction(async (tx) => {
18707
18789
  if (fields.name) {
18708
18790
  await tx.update(planPhases).set({ name: fields.name }).where(
18709
- and14(eq38(planPhases.itemId, itemId2), eq38(planPhases.idx, phaseIdx))
18791
+ and15(eq39(planPhases.itemId, itemId2), eq39(planPhases.idx, phaseIdx))
18710
18792
  );
18711
18793
  }
18712
18794
  if (fields.manualCheck) {
18713
18795
  await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
18714
- and14(eq38(planPhases.itemId, itemId2), eq38(planPhases.idx, phaseIdx))
18796
+ and15(eq39(planPhases.itemId, itemId2), eq39(planPhases.idx, phaseIdx))
18715
18797
  );
18716
18798
  }
18717
18799
  if (fields.task) {
18718
18800
  await tx.delete(planTasks).where(
18719
- and14(eq38(planTasks.itemId, itemId2), eq38(planTasks.phaseIdx, phaseIdx))
18801
+ and15(eq39(planTasks.itemId, itemId2), eq39(planTasks.phaseIdx, phaseIdx))
18720
18802
  );
18721
18803
  if (fields.task.length) {
18722
18804
  await tx.insert(planTasks).values(
@@ -18734,14 +18816,14 @@ async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
18734
18816
 
18735
18817
  // src/commands/backlog/findPhase.ts
18736
18818
  import chalk96 from "chalk";
18737
- import { and as and15, count as count7, eq as eq39 } from "drizzle-orm";
18819
+ import { and as and16, count as count7, eq as eq40 } from "drizzle-orm";
18738
18820
  async function findPhase(id, phase) {
18739
18821
  const found = await findOneItem(id);
18740
18822
  if (!found) return void 0;
18741
18823
  const { orm, item } = found;
18742
18824
  const itemId2 = item.id;
18743
18825
  const phaseIdx = Number.parseInt(phase, 10) - 1;
18744
- const [row3] = await orm.select({ cnt: count7() }).from(planPhases).where(and15(eq39(planPhases.itemId, itemId2), eq39(planPhases.idx, phaseIdx)));
18826
+ const [row3] = await orm.select({ cnt: count7() }).from(planPhases).where(and16(eq40(planPhases.itemId, itemId2), eq40(planPhases.idx, phaseIdx)));
18745
18827
  if (!row3 || row3.cnt === 0) {
18746
18828
  console.log(
18747
18829
  chalk96.red(
@@ -18914,16 +18996,16 @@ function registerUpdatePhaseCommand(cmd) {
18914
18996
 
18915
18997
  // src/commands/backlog/removePhase.ts
18916
18998
  import chalk98 from "chalk";
18917
- import { and as and16, eq as eq40 } from "drizzle-orm";
18999
+ import { and as and17, eq as eq41 } from "drizzle-orm";
18918
19000
  async function removePhase(id, phase) {
18919
19001
  const found = await findPhase(id, phase);
18920
19002
  if (!found) return;
18921
19003
  const { item, orm, itemId: itemId2, phaseIdx } = found;
18922
19004
  await orm.transaction(async (tx) => {
18923
19005
  await tx.delete(planTasks).where(
18924
- and16(eq40(planTasks.itemId, itemId2), eq40(planTasks.phaseIdx, phaseIdx))
19006
+ and17(eq41(planTasks.itemId, itemId2), eq41(planTasks.phaseIdx, phaseIdx))
18925
19007
  );
18926
- await tx.delete(planPhases).where(and16(eq40(planPhases.itemId, itemId2), eq40(planPhases.idx, phaseIdx)));
19008
+ await tx.delete(planPhases).where(and17(eq41(planPhases.itemId, itemId2), eq41(planPhases.idx, phaseIdx)));
18927
19009
  await reindexPhases(tx, itemId2);
18928
19010
  await adjustCurrentPhase(tx, item, phaseIdx);
18929
19011
  });
@@ -18936,7 +19018,7 @@ async function removePhase(id, phase) {
18936
19018
 
18937
19019
  // src/commands/backlog/update/update.ts
18938
19020
  import chalk102 from "chalk";
18939
- import { eq as eq41 } from "drizzle-orm";
19021
+ import { eq as eq42 } from "drizzle-orm";
18940
19022
 
18941
19023
  // src/commands/backlog/update/buildUpdateValues.ts
18942
19024
  import chalk99 from "chalk";
@@ -19047,7 +19129,7 @@ async function update(id, options2) {
19047
19129
  if (!built) return;
19048
19130
  const { orm } = found;
19049
19131
  const itemId2 = found.item.id;
19050
- await orm.update(items).set(built.set).where(eq41(items.id, itemId2));
19132
+ await orm.update(items).set(built.set).where(eq42(items.id, itemId2));
19051
19133
  console.log(
19052
19134
  chalk102.green(`Updated ${built.fields} on item ${formatItemId(itemId2)}.`)
19053
19135
  );
@@ -19093,7 +19175,7 @@ function readPlanUpdate(source) {
19093
19175
  }
19094
19176
 
19095
19177
  // src/commands/backlog/updatePlan/replacePlan.ts
19096
- import { eq as eq42 } from "drizzle-orm";
19178
+ import { eq as eq43 } from "drizzle-orm";
19097
19179
 
19098
19180
  // src/commands/backlog/updatePlan/clampCurrentPhase.ts
19099
19181
  function clampCurrentPhase(currentPhase, phaseCount) {
@@ -19104,8 +19186,8 @@ function clampCurrentPhase(currentPhase, phaseCount) {
19104
19186
  // src/commands/backlog/updatePlan/replacePlan.ts
19105
19187
  async function replacePlan(orm, itemId2, phases, currentPhase) {
19106
19188
  await orm.transaction(async (tx) => {
19107
- await tx.delete(planTasks).where(eq42(planTasks.itemId, itemId2));
19108
- await tx.delete(planPhases).where(eq42(planPhases.itemId, itemId2));
19189
+ await tx.delete(planTasks).where(eq43(planTasks.itemId, itemId2));
19190
+ await tx.delete(planPhases).where(eq43(planPhases.itemId, itemId2));
19109
19191
  if (phases.length > 0) {
19110
19192
  await tx.insert(planPhases).values(
19111
19193
  phases.map((phase, idx) => ({
@@ -19123,7 +19205,7 @@ async function replacePlan(orm, itemId2, phases, currentPhase) {
19123
19205
  if (currentPhase === void 0) return;
19124
19206
  const clamped = clampCurrentPhase(currentPhase, phases.length);
19125
19207
  if (clamped === currentPhase) return;
19126
- await tx.update(items).set({ currentPhase: clamped }).where(eq42(items.id, itemId2));
19208
+ await tx.update(items).set({ currentPhase: clamped }).where(eq43(items.id, itemId2));
19127
19209
  });
19128
19210
  }
19129
19211
 
@@ -27567,18 +27649,6 @@ function registerGithub(program) {
27567
27649
 
27568
27650
  // src/commands/inbox/list.ts
27569
27651
  import chalk171 from "chalk";
27570
-
27571
- // src/shared/db/listInboxMessages.ts
27572
- import { desc as desc6, isNull, sql as sql22 } from "drizzle-orm";
27573
- function listInboxMessages(orm) {
27574
- return orm.select().from(inboxMessages).where(isNull(inboxMessages.dismissedAt)).orderBy(
27575
- desc6(
27576
- sql22`coalesce(${inboxMessages.receivedAt}, ${inboxMessages.flaggedAt})`
27577
- )
27578
- );
27579
- }
27580
-
27581
- // src/commands/inbox/list.ts
27582
27652
  async function list3() {
27583
27653
  const messages = await listInboxMessages(await getDb());
27584
27654
  if (messages.length === 0) {
@@ -27599,10 +27669,10 @@ async function list3() {
27599
27669
  import chalk172 from "chalk";
27600
27670
 
27601
27671
  // src/shared/db/readInboxLastScan.ts
27602
- import { eq as eq43 } from "drizzle-orm";
27672
+ import { eq as eq44 } from "drizzle-orm";
27603
27673
  var INBOX_LAST_SCAN_KEY = "inbox.lastScanAt";
27604
27674
  async function readInboxLastScan(orm) {
27605
- const [row3] = await orm.select().from(metadata).where(eq43(metadata.key, INBOX_LAST_SCAN_KEY));
27675
+ const [row3] = await orm.select().from(metadata).where(eq44(metadata.key, INBOX_LAST_SCAN_KEY));
27606
27676
  return row3 ? new Date(row3.value) : void 0;
27607
27677
  }
27608
27678
 
@@ -30337,9 +30407,9 @@ async function list4() {
30337
30407
  import chalk188 from "chalk";
30338
30408
 
30339
30409
  // src/commands/backlog/removeFeed.ts
30340
- import { eq as eq44 } from "drizzle-orm";
30410
+ import { eq as eq45 } from "drizzle-orm";
30341
30411
  async function removeFeed(db, url) {
30342
- const deleted = await db.delete(feeds).where(eq44(feeds.url, url)).returning({ id: feeds.id });
30412
+ const deleted = await db.delete(feeds).where(eq45(feeds.url, url)).returning({ id: feeds.id });
30343
30413
  return deleted.length > 0;
30344
30414
  }
30345
30415
 
@@ -38454,7 +38524,10 @@ function selectInDiffFindings(lineBound, prDiff) {
38454
38524
  return {
38455
38525
  inDiff,
38456
38526
  unanchored: outOfDiff.map(
38457
- (finding) => ({ ...finding, reason: "out-of-diff" })
38527
+ (finding) => ({
38528
+ ...finding,
38529
+ reason: "out-of-diff"
38530
+ })
38458
38531
  )
38459
38532
  };
38460
38533
  }
@@ -38491,7 +38564,10 @@ function selectPostableFindings(markdown, prInfo) {
38491
38564
  );
38492
38565
  }
38493
38566
  const carriedUnlocated = unlocated.map(
38494
- (finding) => ({ ...finding, reason: "unlocated" })
38567
+ (finding) => ({
38568
+ ...finding,
38569
+ reason: "unlocated"
38570
+ })
38495
38571
  );
38496
38572
  if (lineBound.length === 0) {
38497
38573
  console.log("No line-bound findings to comment on.");
@@ -44675,12 +44751,12 @@ function parseEnvPairs(pairs) {
44675
44751
  if (pairs.length === 0) return void 0;
44676
44752
  const env = {};
44677
44753
  for (const pair of pairs) {
44678
- const eq47 = pair.indexOf("=");
44679
- if (eq47 <= 0) {
44754
+ const eq48 = pair.indexOf("=");
44755
+ if (eq48 <= 0) {
44680
44756
  console.error(`--env must be KEY=VALUE, got "${pair}"`);
44681
44757
  process.exit(1);
44682
44758
  }
44683
- env[pair.slice(0, eq47)] = pair.slice(eq47 + 1);
44759
+ env[pair.slice(0, eq48)] = pair.slice(eq48 + 1);
44684
44760
  }
44685
44761
  return env;
44686
44762
  }
@@ -44693,11 +44769,11 @@ function fail9(spec) {
44693
44769
  process.exit(1);
44694
44770
  }
44695
44771
  function parseParamSpec(spec) {
44696
- const eq47 = spec.indexOf("=");
44697
- const name = eq47 === -1 ? spec : spec.slice(0, eq47);
44698
- if (eq47 !== -1) {
44699
- if (eq47 === 0 || name.endsWith("!")) fail9(spec);
44700
- return { name, default: spec.slice(eq47 + 1) };
44772
+ const eq48 = spec.indexOf("=");
44773
+ const name = eq48 === -1 ? spec : spec.slice(0, eq48);
44774
+ if (eq48 !== -1) {
44775
+ if (eq48 === 0 || name.endsWith("!")) fail9(spec);
44776
+ return { name, default: spec.slice(eq48 + 1) };
44701
44777
  }
44702
44778
  if (name.endsWith("!")) {
44703
44779
  if (name.length === 1) fail9(spec);
@@ -47961,10 +48037,10 @@ function applyReviewPause(session, activity2) {
47961
48037
  }
47962
48038
 
47963
48039
  // src/shared/db/getPhaseActiveMs.ts
47964
- import { and as and17, eq as eq45 } from "drizzle-orm";
48040
+ import { and as and18, eq as eq46 } from "drizzle-orm";
47965
48041
  async function getPhaseActiveMs(db, itemId2, phaseIdx) {
47966
48042
  const [row3] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
47967
- and17(eq45(phaseUsage.itemId, itemId2), eq45(phaseUsage.phaseIdx, phaseIdx))
48043
+ and18(eq46(phaseUsage.itemId, itemId2), eq46(phaseUsage.phaseIdx, phaseIdx))
47968
48044
  );
47969
48045
  return row3?.activeMs ?? 0;
47970
48046
  }
@@ -48806,17 +48882,17 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
48806
48882
  }
48807
48883
 
48808
48884
  // src/shared/db/recordWindowTokens.ts
48809
- import { and as and18, eq as eq46, sql as sql28 } from "drizzle-orm";
48885
+ import { and as and19, eq as eq47, sql as sql28 } from "drizzle-orm";
48810
48886
  async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
48811
48887
  if (tokensUp <= 0 && tokensDown <= 0) return;
48812
48888
  await db.update(usagePeaks).set({
48813
48889
  tokensUp: sql28`${usagePeaks.tokensUp} + ${tokensUp}`,
48814
48890
  tokensDown: sql28`${usagePeaks.tokensDown} + ${tokensDown}`
48815
48891
  }).where(
48816
- and18(
48817
- eq46(usagePeaks.window, window),
48818
- eq46(usagePeaks.resetsAt, resetsAt),
48819
- eq46(usagePeaks.segment, 0)
48892
+ and19(
48893
+ eq47(usagePeaks.window, window),
48894
+ eq47(usagePeaks.resetsAt, resetsAt),
48895
+ eq47(usagePeaks.segment, 0)
48820
48896
  )
48821
48897
  );
48822
48898
  }