@staff0rd/assist 0.461.3 → 0.463.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.461.3",
9
+ version: "0.463.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3365,7 +3365,7 @@ function collectHashComments(content, options2) {
3365
3365
  function collectComments(sourceFile) {
3366
3366
  const seen = /* @__PURE__ */ new Set();
3367
3367
  const comments3 = [];
3368
- const collect6 = (node) => {
3368
+ const collect5 = (node) => {
3369
3369
  for (const range of [
3370
3370
  ...node.getLeadingCommentRanges(),
3371
3371
  ...node.getTrailingCommentRanges()
@@ -3376,8 +3376,8 @@ function collectComments(sourceFile) {
3376
3376
  comments3.push({ pos, text: range.getText() });
3377
3377
  }
3378
3378
  };
3379
- collect6(sourceFile);
3380
- sourceFile.forEachDescendant(collect6);
3379
+ collect5(sourceFile);
3380
+ sourceFile.forEachDescendant(collect5);
3381
3381
  return comments3;
3382
3382
  }
3383
3383
 
@@ -3596,16 +3596,19 @@ var WRAPPER_TYPES = /* @__PURE__ */ new Set([
3596
3596
  "readonly",
3597
3597
  "catch"
3598
3598
  ]);
3599
+ var OPTIONAL_TYPES = /* @__PURE__ */ new Set(["optional", "nullish"]);
3599
3600
  function unwrapSchemaNode(node) {
3600
3601
  let current = node;
3601
3602
  let defaultValue;
3603
+ let optional = false;
3602
3604
  while (current.def && WRAPPER_TYPES.has(current.def.type ?? "") && current.def.innerType) {
3603
3605
  if (current.def.type === "default" && defaultValue === void 0) {
3604
3606
  defaultValue = current.def.defaultValue;
3605
3607
  }
3608
+ if (OPTIONAL_TYPES.has(current.def.type ?? "")) optional = true;
3606
3609
  current = current.def.innerType;
3607
3610
  }
3608
- return { inner: current, defaultValue };
3611
+ return { inner: current, defaultValue, optional };
3609
3612
  }
3610
3613
 
3611
3614
  // src/shared/scalarUnionMembers.ts
@@ -3649,7 +3652,67 @@ function scalarArrayItemType(node) {
3649
3652
  return isScalarLeafType(type) ? type : void 0;
3650
3653
  }
3651
3654
 
3652
- // src/shared/describeConfigLeaves.ts
3655
+ // src/shared/listConfigNode.ts
3656
+ function scalarListNode(inner, base, item) {
3657
+ const itemType = scalarArrayItemType(inner);
3658
+ if (!itemType || item.kind !== "scalar") return void 0;
3659
+ return { ...base, kind: "scalarList", itemType, item };
3660
+ }
3661
+ function objectListNode(base, item) {
3662
+ if (item.kind !== "object" && item.kind !== "unionOfObjects")
3663
+ return void 0;
3664
+ return { ...base, kind: "objectList", item };
3665
+ }
3666
+ function listConfigNode(inner, base, build2) {
3667
+ const element = inner.def?.element;
3668
+ if (inner.def?.type !== "array" || !element) return void 0;
3669
+ const item = build2(element, [...base.path, { kind: "item" }]);
3670
+ return scalarListNode(inner, base, item) ?? objectListNode(base, item);
3671
+ }
3672
+
3673
+ // src/shared/objectConfigNode.ts
3674
+ function objectConfigNode(inner, base, build2) {
3675
+ const shape = inner.def?.shape;
3676
+ if (inner.def?.type !== "object" || !shape) return void 0;
3677
+ const fields = Object.entries(shape).map(
3678
+ ([name, child]) => build2(child, [...base.path, { kind: "key", name }])
3679
+ );
3680
+ return { ...base, kind: "object", fields };
3681
+ }
3682
+ function unionOfObjectsConfigNode(inner, base, build2) {
3683
+ const options2 = inner.def?.options;
3684
+ if (inner.def?.type !== "union" || !options2?.length) return void 0;
3685
+ const variants = [];
3686
+ for (const option of options2) {
3687
+ const variant = build2(option, base.path);
3688
+ if (variant.kind !== "object") return void 0;
3689
+ variants.push(variant);
3690
+ }
3691
+ return { ...base, kind: "unionOfObjects", variants };
3692
+ }
3693
+
3694
+ // src/shared/recordConfigNode.ts
3695
+ function recordConfigNode(inner, base, build2) {
3696
+ const valueType = inner.def?.valueType;
3697
+ if (inner.def?.type !== "record" || !valueType) return void 0;
3698
+ const value = build2(valueType, [...base.path, { kind: "entry" }]);
3699
+ return { ...base, kind: "record", value };
3700
+ }
3701
+
3702
+ // src/shared/scalarConfigNode.ts
3703
+ function scalarConfigNode(inner, base) {
3704
+ const unionTypes = scalarUnionMembers(inner);
3705
+ if (unionTypes) return { ...base, kind: "scalar", type: "union", unionTypes };
3706
+ const type = leafTypeOf(inner);
3707
+ if (!isScalarLeafType(type)) return void 0;
3708
+ const values = type === "enum" ? enumValues(inner) : void 0;
3709
+ return {
3710
+ ...base,
3711
+ kind: "scalar",
3712
+ type,
3713
+ ...values ? { enumValues: values } : {}
3714
+ };
3715
+ }
3653
3716
  function enumValues(node) {
3654
3717
  const entries = node.def?.entries;
3655
3718
  if (!entries) return void 0;
@@ -3657,31 +3720,81 @@ function enumValues(node) {
3657
3720
  (value) => typeof value === "string"
3658
3721
  );
3659
3722
  }
3660
- function toLeaf(key, node, defaultValue) {
3661
- const unionTypes = scalarUnionMembers(node);
3662
- const type = unionTypes ? "union" : leafTypeOf(node);
3663
- const leaf = { key, type };
3664
- if (type === "enum") leaf.enumValues = enumValues(node);
3665
- if (unionTypes) leaf.unionTypes = unionTypes;
3666
- const itemType = scalarArrayItemType(node);
3667
- if (itemType) leaf.itemType = itemType;
3668
- if (defaultValue !== void 0) leaf.defaultValue = defaultValue;
3723
+
3724
+ // src/shared/describeConfigNode.ts
3725
+ function opaqueConfigNode(inner, base) {
3726
+ return { ...base, kind: "other", type: leafTypeOf(inner) };
3727
+ }
3728
+ function build(node, path71) {
3729
+ const { inner, defaultValue, optional } = unwrapSchemaNode(node);
3730
+ const base = {
3731
+ path: path71,
3732
+ ...optional ? { optional: true } : {},
3733
+ ...defaultValue === void 0 ? {} : { defaultValue }
3734
+ };
3735
+ return scalarConfigNode(inner, base) ?? objectConfigNode(inner, base, build) ?? listConfigNode(inner, base, build) ?? recordConfigNode(inner, base, build) ?? unionOfObjectsConfigNode(inner, base, build) ?? opaqueConfigNode(inner, base);
3736
+ }
3737
+ function describeConfigNode(schema2) {
3738
+ return build(schema2, []);
3739
+ }
3740
+
3741
+ // src/shared/formatConfigPath.ts
3742
+ var RECORD_ENTRY_TOKEN = "*";
3743
+ function segmentText(segment) {
3744
+ if (segment.kind === "key") return segment.name;
3745
+ if (segment.kind === "entry") return RECORD_ENTRY_TOKEN;
3746
+ if (segment.kind === "index") return `[${segment.index}]`;
3747
+ return "[]";
3748
+ }
3749
+ function formatConfigPath(path71) {
3750
+ let text17 = "";
3751
+ for (const segment of path71) {
3752
+ const dotted = segment.kind === "key" || segment.kind === "entry";
3753
+ const rendered = segmentText(segment);
3754
+ text17 += dotted && text17 ? `.${rendered}` : rendered;
3755
+ }
3756
+ return text17;
3757
+ }
3758
+
3759
+ // src/shared/describeConfigLeaves.ts
3760
+ function leafType(node) {
3761
+ switch (node.kind) {
3762
+ case "scalar":
3763
+ return node.type;
3764
+ case "scalarList":
3765
+ case "objectList":
3766
+ return "array";
3767
+ case "record":
3768
+ return "record";
3769
+ case "other":
3770
+ return node.type;
3771
+ default:
3772
+ return "other";
3773
+ }
3774
+ }
3775
+ function toLeaf(node) {
3776
+ const leaf = {
3777
+ key: formatConfigPath(node.path),
3778
+ type: leafType(node)
3779
+ };
3780
+ if (node.kind === "scalar") {
3781
+ if (node.enumValues) leaf.enumValues = node.enumValues;
3782
+ if (node.unionTypes) leaf.unionTypes = node.unionTypes;
3783
+ }
3784
+ if (node.kind === "scalarList") leaf.itemType = node.itemType;
3785
+ if (node.defaultValue !== void 0) leaf.defaultValue = node.defaultValue;
3669
3786
  return leaf;
3670
3787
  }
3671
- function collect(node, prefix2, out) {
3672
- const { inner, defaultValue } = unwrapSchemaNode(node);
3673
- const shape = inner.def?.shape;
3674
- if (inner.def?.type === "object" && shape) {
3675
- for (const [key, child] of Object.entries(shape)) {
3676
- collect(child, prefix2 ? `${prefix2}.${key}` : key, out);
3677
- }
3788
+ function flatten(node, out) {
3789
+ if (node.kind === "object") {
3790
+ for (const field of node.fields) flatten(field, out);
3678
3791
  return;
3679
3792
  }
3680
- out.push(toLeaf(prefix2, inner, defaultValue));
3793
+ out.push(toLeaf(node));
3681
3794
  }
3682
3795
  function describeConfigLeaves(schema2) {
3683
3796
  const out = [];
3684
- collect(schema2, "", out);
3797
+ flatten(describeConfigNode(schema2), out);
3685
3798
  return out.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
3686
3799
  }
3687
3800
 
@@ -3773,9 +3886,9 @@ function forbiddenStrings() {
3773
3886
  console.log("No forbidden-strings rules configured.");
3774
3887
  process.exit(0);
3775
3888
  }
3776
- const cache4 = /* @__PURE__ */ new Map();
3889
+ const cache5 = /* @__PURE__ */ new Map();
3777
3890
  const readJson = (file) => {
3778
- if (cache4.has(file)) return cache4.get(file);
3891
+ if (cache5.has(file)) return cache5.get(file);
3779
3892
  if (!existsSync12(file)) {
3780
3893
  console.log(`Forbidden-strings file not found: ${file}`);
3781
3894
  process.exit(1);
@@ -3787,7 +3900,7 @@ function forbiddenStrings() {
3787
3900
  console.log(`Could not parse ${file}: ${error.message}`);
3788
3901
  process.exit(1);
3789
3902
  }
3790
- cache4.set(file, parsed);
3903
+ cache5.set(file, parsed);
3791
3904
  return parsed;
3792
3905
  };
3793
3906
  const violations = findForbiddenStrings(rules, readJson);
@@ -8456,19 +8569,19 @@ import { dirname as dirname19, join as join23 } from "path";
8456
8569
  import { fileURLToPath as fileURLToPath4 } from "url";
8457
8570
  function createBundleHandler(importMetaUrl, bundlePath, contentType = "application/javascript") {
8458
8571
  const file = join23(dirname19(fileURLToPath4(importMetaUrl)), bundlePath);
8459
- let cache4;
8572
+ let cache5;
8460
8573
  return (req, res) => {
8461
8574
  const mtimeMs = statSync2(file).mtimeMs;
8462
- if (cache4?.mtimeMs !== mtimeMs) {
8575
+ if (cache5?.mtimeMs !== mtimeMs) {
8463
8576
  const body = readFileSync19(file, "utf8");
8464
8577
  const etag = `"${createHash("sha256").update(body).digest("hex").slice(0, 16)}"`;
8465
- cache4 = { body, etag, mtimeMs };
8578
+ cache5 = { body, etag, mtimeMs };
8466
8579
  }
8467
8580
  const headers = {
8468
- ETag: cache4.etag,
8581
+ ETag: cache5.etag,
8469
8582
  "Cache-Control": "no-cache"
8470
8583
  };
8471
- if (req.headers["if-none-match"] === cache4.etag) {
8584
+ if (req.headers["if-none-match"] === cache5.etag) {
8472
8585
  res.writeHead(304, headers);
8473
8586
  res.end();
8474
8587
  return;
@@ -8477,7 +8590,7 @@ function createBundleHandler(importMetaUrl, bundlePath, contentType = "applicati
8477
8590
  "Content-Type": contentType,
8478
8591
  ...headers
8479
8592
  });
8480
- res.end(cache4.body);
8593
+ res.end(cache5.body);
8481
8594
  };
8482
8595
  }
8483
8596
 
@@ -8971,67 +9084,119 @@ function getSessionParam(req) {
8971
9084
  return url.searchParams.get("session") ?? void 0;
8972
9085
  }
8973
9086
 
8974
- // src/shared/db/findCommitAnchor.ts
8975
- import { and as and7, asc as asc6, eq as eq16, inArray as inArray3 } from "drizzle-orm";
8976
- async function findCommitAnchor(db, itemId2) {
8977
- const rows = await db.select({ kind: itemGitRefs.kind, ref: itemGitRefs.ref }).from(itemGitRefs).where(
8978
- and7(
8979
- eq16(itemGitRefs.itemId, itemId2),
8980
- inArray3(itemGitRefs.kind, ["commit", "commit-parent"])
8981
- )
8982
- ).orderBy(asc6(itemGitRefs.createdAt));
8983
- const anchor = {};
8984
- for (const row of rows) {
8985
- if (row.kind === "commit") anchor.commit ??= row.ref;
8986
- else anchor.parent ??= row.ref;
8987
- }
8988
- return anchor;
8989
- }
8990
-
8991
9087
  // src/shared/db/findItemBySessionId.ts
8992
- import { asc as asc7, eq as eq17 } from "drizzle-orm";
9088
+ import { asc as asc6, eq as eq16 } from "drizzle-orm";
8993
9089
  async function findItemBySessionId(db, claudeSessionId) {
8994
- const rows = await db.select({ itemId: phaseUsage.itemId }).from(phaseUsage).where(eq17(phaseUsage.claudeSessionId, claudeSessionId)).orderBy(asc7(phaseUsage.itemId), asc7(phaseUsage.phaseIdx)).limit(1);
9090
+ const rows = await db.select({ itemId: phaseUsage.itemId }).from(phaseUsage).where(eq16(phaseUsage.claudeSessionId, claudeSessionId)).orderBy(asc6(phaseUsage.itemId), asc6(phaseUsage.phaseIdx)).limit(1);
8995
9091
  return rows[0]?.itemId;
8996
9092
  }
8997
9093
 
8998
- // src/commands/sessions/web/sessionCommitAnchor.ts
8999
- var EMPTY_TTL_MS = 3e4;
9000
- var cache3 = /* @__PURE__ */ new Map();
9001
- var inFlight = /* @__PURE__ */ new Map();
9002
- async function sessionCommitAnchor(sessionId) {
9003
- const cached = cache3.get(sessionId);
9004
- if (cached && cached.expiresAt > Date.now()) return cached.anchor;
9005
- const pending = inFlight.get(sessionId);
9006
- if (pending) return pending;
9007
- const lookup = loadAnchor(sessionId).finally(
9008
- () => inFlight.delete(sessionId)
9009
- );
9010
- inFlight.set(sessionId, lookup);
9011
- return lookup;
9012
- }
9013
- async function loadAnchor(sessionId) {
9014
- const anchor = await queryAnchor(sessionId);
9015
- const found = Boolean(anchor.commit || anchor.parent);
9016
- cache3.set(sessionId, {
9017
- anchor,
9018
- expiresAt: found ? Number.POSITIVE_INFINITY : Date.now() + EMPTY_TTL_MS
9019
- });
9020
- return anchor;
9094
+ // src/shared/db/listCommitRefs.ts
9095
+ import { and as and7, asc as asc7, eq as eq17 } from "drizzle-orm";
9096
+ async function listCommitRefs(db, itemId2) {
9097
+ const rows = await db.select({
9098
+ ref: itemGitRefs.ref,
9099
+ title: itemGitRefs.title,
9100
+ url: itemGitRefs.url
9101
+ }).from(itemGitRefs).where(and7(eq17(itemGitRefs.itemId, itemId2), eq17(itemGitRefs.kind, "commit"))).orderBy(asc7(itemGitRefs.createdAt), asc7(itemGitRefs.ref));
9102
+ return rows.map((row) => ({
9103
+ sha: row.ref,
9104
+ ...row.title ? { title: row.title } : {},
9105
+ ...row.url ? { url: row.url } : {}
9106
+ }));
9021
9107
  }
9022
- async function queryAnchor(sessionId) {
9108
+
9109
+ // src/commands/sessions/web/itemCommits.ts
9110
+ async function itemCommits(sessionId) {
9023
9111
  try {
9024
9112
  if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url)
9025
- return {};
9113
+ return [];
9026
9114
  const db = await getDb();
9027
9115
  const itemId2 = await findItemBySessionId(db, sessionId);
9028
- if (itemId2 === void 0) return {};
9029
- return await findCommitAnchor(db, itemId2);
9116
+ if (itemId2 === void 0) return [];
9117
+ return await listCommitRefs(db, itemId2);
9030
9118
  } catch {
9031
- return {};
9119
+ return [];
9032
9120
  }
9033
9121
  }
9034
9122
 
9123
+ // src/commands/sessions/web/resolveCommit.ts
9124
+ var GIT_EMPTY_TREE_HASH = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
9125
+ async function resolveCommit(cwd, sha) {
9126
+ if (!await commitExists(cwd, sha)) return void 0;
9127
+ const parent = await parentOf(cwd, sha);
9128
+ return {
9129
+ base: parent ?? GIT_EMPTY_TREE_HASH,
9130
+ paths: await commitPaths(cwd, sha)
9131
+ };
9132
+ }
9133
+ async function commitExists(cwd, sha) {
9134
+ try {
9135
+ await execGit(cwd, ["cat-file", "-e", `${sha}^{commit}`]);
9136
+ return true;
9137
+ } catch {
9138
+ return false;
9139
+ }
9140
+ }
9141
+ async function parentOf(cwd, sha) {
9142
+ try {
9143
+ const parent = await execGit(cwd, [
9144
+ "rev-parse",
9145
+ "--verify",
9146
+ "--quiet",
9147
+ `${sha}^`
9148
+ ]);
9149
+ return parent.trim() || void 0;
9150
+ } catch {
9151
+ return void 0;
9152
+ }
9153
+ }
9154
+ async function commitPaths(cwd, sha) {
9155
+ try {
9156
+ const output = await execGit(cwd, [
9157
+ "diff-tree",
9158
+ "--no-commit-id",
9159
+ "--name-only",
9160
+ "-r",
9161
+ "--root",
9162
+ sha
9163
+ ]);
9164
+ return output.split("\n").filter(Boolean);
9165
+ } catch {
9166
+ return [];
9167
+ }
9168
+ }
9169
+
9170
+ // src/commands/sessions/web/committedPaths.ts
9171
+ var cache3 = /* @__PURE__ */ new Map();
9172
+ var inFlight = /* @__PURE__ */ new Map();
9173
+ var CACHE_TTL_MS = 1e4;
9174
+ async function committedPaths(cwd, sessionId) {
9175
+ const key = `${cwd} ${sessionId}`;
9176
+ const cached = cache3.get(key);
9177
+ if (cached && cached.expiresAt > Date.now()) return cached.value;
9178
+ const pending = inFlight.get(key);
9179
+ if (pending) return pending;
9180
+ const lookup = loadCommittedPaths(cwd, sessionId).then((value) => {
9181
+ cache3.set(key, { value, expiresAt: Date.now() + CACHE_TTL_MS });
9182
+ return value;
9183
+ }).finally(() => inFlight.delete(key));
9184
+ inFlight.set(key, lookup);
9185
+ return lookup;
9186
+ }
9187
+ async function loadCommittedPaths(cwd, sessionId) {
9188
+ const commits2 = await itemCommits(sessionId);
9189
+ const bases = /* @__PURE__ */ new Map();
9190
+ for (const commit2 of commits2) {
9191
+ const resolved = await resolveCommit(cwd, commit2.sha);
9192
+ if (!resolved) continue;
9193
+ for (const path71 of resolved.paths) {
9194
+ if (!bases.has(path71)) bases.set(path71, resolved.base);
9195
+ }
9196
+ }
9197
+ return { commits: commits2, bases };
9198
+ }
9199
+
9035
9200
  // src/commands/sessions/web/windowsCwdToWslPath.ts
9036
9201
  function windowsCwdToWslPath(cwd) {
9037
9202
  const match = /^([A-Za-z]):[\\/](.*)$/.exec(cwd);
@@ -9046,55 +9211,37 @@ function toGitCwd(cwd) {
9046
9211
  return detectPlatform() === "wsl" ? windowsCwdToWslPath(cwd) : cwd;
9047
9212
  }
9048
9213
 
9049
- // src/commands/sessions/web/resolveDiffBase.ts
9050
- function baseCandidates(defaultBranch) {
9051
- return [
9052
- defaultBranch && `origin/${defaultBranch}`,
9053
- defaultBranch,
9054
- "origin/main",
9055
- "origin/master",
9056
- "main",
9057
- "master"
9058
- ].filter((candidate) => Boolean(candidate));
9214
+ // src/commands/sessions/web/itemChangeSet.ts
9215
+ async function itemChangeSet(cwd, sessionId) {
9216
+ if (!sessionId || !includesCommittedChanges(cwd)) return void 0;
9217
+ const { commits: commits2, bases } = await committedPaths(cwd, sessionId);
9218
+ if (bases.size === 0) return void 0;
9219
+ const groups = groupByBase(bases);
9220
+ const dirty = await dirtyPaths(cwd, bases);
9221
+ if (dirty.length > 0) groups.push({ base: "HEAD", paths: dirty });
9222
+ return { commits: commits2, groups };
9059
9223
  }
9060
- async function refExists2(cwd, ref) {
9224
+ function includesCommittedChanges(cwd) {
9061
9225
  try {
9062
- await execGit(cwd, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
9063
- return true;
9226
+ return Boolean(
9227
+ loadConfigFrom(toGitCwd(cwd)).sessions?.includeCommittedChanges
9228
+ );
9064
9229
  } catch {
9065
9230
  return false;
9066
9231
  }
9067
9232
  }
9068
- async function anchoredBase(cwd, sessionId) {
9069
- const { commit: commit2, parent } = await sessionCommitAnchor(sessionId);
9070
- if (parent && await refExists2(cwd, parent)) return parent;
9071
- if (commit2 && await refExists2(cwd, `${commit2}^`)) return `${commit2}^`;
9072
- return void 0;
9073
- }
9074
- async function resolveDiffBase(cwd, sessionId) {
9075
- let defaultBranch;
9076
- try {
9077
- const config = loadConfigFrom(toGitCwd(cwd));
9078
- if (!config.sessions?.includeCommittedChanges) return "HEAD";
9079
- defaultBranch = config.branch?.defaultBranch;
9080
- } catch {
9081
- return "HEAD";
9082
- }
9083
- if (sessionId) {
9084
- const anchored = await anchoredBase(cwd, sessionId);
9085
- if (anchored) return anchored;
9086
- }
9087
- for (const candidate of baseCandidates(defaultBranch)) {
9088
- if (!await refExists2(cwd, candidate)) continue;
9089
- try {
9090
- const base = await execGit(cwd, ["merge-base", "HEAD", candidate]);
9091
- const sha = base.trim();
9092
- if (sha) return sha;
9093
- } catch {
9094
- }
9095
- return "HEAD";
9233
+ function groupByBase(bases) {
9234
+ const groups = /* @__PURE__ */ new Map();
9235
+ for (const [path71, base] of bases) {
9236
+ const paths = groups.get(base);
9237
+ if (paths) paths.push(path71);
9238
+ else groups.set(base, [path71]);
9096
9239
  }
9097
- return "HEAD";
9240
+ return [...groups].map(([base, paths]) => ({ base, paths: paths.sort() }));
9241
+ }
9242
+ async function dirtyPaths(cwd, bases) {
9243
+ const output = await execGit(cwd, ["diff", "--name-only", "HEAD"]);
9244
+ return output.split("\n").filter((path71) => path71 && !bases.has(path71)).sort();
9098
9245
  }
9099
9246
 
9100
9247
  // src/commands/sessions/web/diff.ts
@@ -9117,14 +9264,26 @@ async function untrackedDiff(cwd) {
9117
9264
  );
9118
9265
  return diffs.join("");
9119
9266
  }
9267
+ async function groupedDiff(cwd, groups) {
9268
+ const diffs = await Promise.all(
9269
+ groups.map(
9270
+ (group) => execGit(cwd, ["diff", group.base, "--", ...group.paths], {
9271
+ maxBuffer: MAX_DIFF_BYTES
9272
+ })
9273
+ )
9274
+ );
9275
+ return diffs.join("");
9276
+ }
9277
+ async function trackedDiff(cwd, session) {
9278
+ const changeSet = await itemChangeSet(cwd, session);
9279
+ if (changeSet) return groupedDiff(cwd, changeSet.groups);
9280
+ return execGit(cwd, ["diff", "HEAD"], { maxBuffer: MAX_DIFF_BYTES });
9281
+ }
9120
9282
  async function diff2(req, res) {
9121
9283
  const cwd = getCwdParam(req, res);
9122
9284
  if (!cwd) return;
9123
9285
  try {
9124
- const base = await resolveDiffBase(cwd, getSessionParam(req));
9125
- const tracked = await execGit(cwd, ["diff", base], {
9126
- maxBuffer: MAX_DIFF_BYTES
9127
- });
9286
+ const tracked = await trackedDiff(cwd, getSessionParam(req));
9128
9287
  const untracked = await untrackedDiff(cwd);
9129
9288
  res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" });
9130
9289
  res.end(tracked + untracked);
@@ -9224,16 +9383,104 @@ function resolveConfigSource(key, layers) {
9224
9383
  return "default";
9225
9384
  }
9226
9385
 
9386
+ // src/shared/configNodeFieldName.ts
9387
+ function configNodeFieldName(node) {
9388
+ const last = node.path.at(-1);
9389
+ return last?.kind === "key" ? last.name : void 0;
9390
+ }
9391
+
9392
+ // src/shared/findConfigNode.ts
9393
+ function objectField(node, segment) {
9394
+ if (segment.kind !== "key") return void 0;
9395
+ return node.fields.find(
9396
+ (field) => configNodeFieldName(field) === segment.name
9397
+ );
9398
+ }
9399
+ function variantField(node, segment) {
9400
+ for (const variant of node.variants) {
9401
+ const found = objectField(variant, segment);
9402
+ if (found) return found;
9403
+ }
9404
+ return void 0;
9405
+ }
9406
+ function step(node, segment) {
9407
+ const intoItem = segment.kind === "item" || segment.kind === "index";
9408
+ const intoEntry = segment.kind === "entry" || segment.kind === "key";
9409
+ switch (node.kind) {
9410
+ case "object":
9411
+ return objectField(node, segment);
9412
+ case "unionOfObjects":
9413
+ return variantField(node, segment);
9414
+ case "objectList":
9415
+ case "scalarList":
9416
+ return intoItem ? node.item : void 0;
9417
+ case "record":
9418
+ return intoEntry ? node.value : void 0;
9419
+ default:
9420
+ return void 0;
9421
+ }
9422
+ }
9423
+ function findConfigNode(root, path71) {
9424
+ let current = root;
9425
+ for (const segment of path71) {
9426
+ if (!current) return void 0;
9427
+ current = step(current, segment);
9428
+ }
9429
+ return current;
9430
+ }
9431
+
9432
+ // src/shared/parseConfigPath.ts
9433
+ var INDEX = /^\d+$/;
9434
+ function bracketSegment(inner) {
9435
+ if (inner === "") return { kind: "item" };
9436
+ return INDEX.test(inner) ? { kind: "index", index: Number(inner) } : void 0;
9437
+ }
9438
+ function nameSegment(name) {
9439
+ return name === RECORD_ENTRY_TOKEN ? { kind: "entry" } : { kind: "key", name };
9440
+ }
9441
+ function parseConfigPath(text17) {
9442
+ const path71 = [];
9443
+ let at2 = 0;
9444
+ while (at2 < text17.length) {
9445
+ if (text17[at2] === "[") {
9446
+ const close = text17.indexOf("]", at2);
9447
+ const segment = close === -1 ? void 0 : bracketSegment(text17.slice(at2 + 1, close));
9448
+ if (!segment) return void 0;
9449
+ path71.push(segment);
9450
+ at2 = close + 1;
9451
+ continue;
9452
+ }
9453
+ if (text17[at2] === ".") {
9454
+ if (path71.length === 0) return void 0;
9455
+ at2 += 1;
9456
+ }
9457
+ const start3 = at2;
9458
+ while (at2 < text17.length && text17[at2] !== "." && text17[at2] !== "[") at2 += 1;
9459
+ const name = text17.slice(start3, at2);
9460
+ if (!name) return void 0;
9461
+ path71.push(nameSegment(name));
9462
+ }
9463
+ return path71;
9464
+ }
9465
+
9466
+ // src/commands/config/configEntryNode.ts
9467
+ function configEntryNode(root, key) {
9468
+ const path71 = parseConfigPath(key);
9469
+ return path71 ? findConfigNode(root, path71) : void 0;
9470
+ }
9471
+
9227
9472
  // src/commands/config/readConfigEntries.ts
9228
9473
  var KEYS_STRIPPED_FROM_MERGED_CONFIG = /* @__PURE__ */ new Set(["repos"]);
9229
9474
  function readConfigEntries(cwd) {
9230
9475
  const config = loadConfigFrom(cwd);
9231
9476
  const layers = readRawConfigLayers(cwd);
9477
+ const schema2 = describeConfigNode(assistConfigSchema);
9232
9478
  return describeConfigLeaves(assistConfigSchema).filter((leaf) => !KEYS_STRIPPED_FROM_MERGED_CONFIG.has(leaf.key)).map((leaf) => ({
9233
9479
  ...leaf,
9234
9480
  value: getNestedValue(config, leaf.key),
9235
9481
  source: resolveConfigSource(leaf.key, layers),
9236
- globalOnly: isGlobalOnlyConfigKey(leaf.key)
9482
+ globalOnly: isGlobalOnlyConfigKey(leaf.key),
9483
+ node: configEntryNode(schema2, leaf.key)
9237
9484
  }));
9238
9485
  }
9239
9486
 
@@ -9421,6 +9668,111 @@ function parseGitStatus(output) {
9421
9668
  return result;
9422
9669
  }
9423
9670
 
9671
+ // src/shared/db/findCommitAnchor.ts
9672
+ import { and as and8, asc as asc8, eq as eq18, inArray as inArray3 } from "drizzle-orm";
9673
+ async function findCommitAnchor(db, itemId2) {
9674
+ const rows = await db.select({ kind: itemGitRefs.kind, ref: itemGitRefs.ref }).from(itemGitRefs).where(
9675
+ and8(
9676
+ eq18(itemGitRefs.itemId, itemId2),
9677
+ inArray3(itemGitRefs.kind, ["commit", "commit-parent"])
9678
+ )
9679
+ ).orderBy(asc8(itemGitRefs.createdAt));
9680
+ const anchor = {};
9681
+ for (const row of rows) {
9682
+ if (row.kind === "commit") anchor.commit ??= row.ref;
9683
+ else anchor.parent ??= row.ref;
9684
+ }
9685
+ return anchor;
9686
+ }
9687
+
9688
+ // src/commands/sessions/web/sessionCommitAnchor.ts
9689
+ var EMPTY_TTL_MS = 3e4;
9690
+ var cache4 = /* @__PURE__ */ new Map();
9691
+ var inFlight2 = /* @__PURE__ */ new Map();
9692
+ async function sessionCommitAnchor(sessionId) {
9693
+ const cached = cache4.get(sessionId);
9694
+ if (cached && cached.expiresAt > Date.now()) return cached.anchor;
9695
+ const pending = inFlight2.get(sessionId);
9696
+ if (pending) return pending;
9697
+ const lookup = loadAnchor(sessionId).finally(
9698
+ () => inFlight2.delete(sessionId)
9699
+ );
9700
+ inFlight2.set(sessionId, lookup);
9701
+ return lookup;
9702
+ }
9703
+ async function loadAnchor(sessionId) {
9704
+ const anchor = await queryAnchor(sessionId);
9705
+ const found = Boolean(anchor.commit || anchor.parent);
9706
+ cache4.set(sessionId, {
9707
+ anchor,
9708
+ expiresAt: found ? Number.POSITIVE_INFINITY : Date.now() + EMPTY_TTL_MS
9709
+ });
9710
+ return anchor;
9711
+ }
9712
+ async function queryAnchor(sessionId) {
9713
+ try {
9714
+ if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url)
9715
+ return {};
9716
+ const db = await getDb();
9717
+ const itemId2 = await findItemBySessionId(db, sessionId);
9718
+ if (itemId2 === void 0) return {};
9719
+ return await findCommitAnchor(db, itemId2);
9720
+ } catch {
9721
+ return {};
9722
+ }
9723
+ }
9724
+
9725
+ // src/commands/sessions/web/resolveDiffBase.ts
9726
+ function baseCandidates(defaultBranch) {
9727
+ return [
9728
+ defaultBranch && `origin/${defaultBranch}`,
9729
+ defaultBranch,
9730
+ "origin/main",
9731
+ "origin/master",
9732
+ "main",
9733
+ "master"
9734
+ ].filter((candidate) => Boolean(candidate));
9735
+ }
9736
+ async function refExists2(cwd, ref) {
9737
+ try {
9738
+ await execGit(cwd, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
9739
+ return true;
9740
+ } catch {
9741
+ return false;
9742
+ }
9743
+ }
9744
+ async function anchoredBase(cwd, sessionId) {
9745
+ const { commit: commit2, parent } = await sessionCommitAnchor(sessionId);
9746
+ if (parent && await refExists2(cwd, parent)) return parent;
9747
+ if (commit2 && await refExists2(cwd, `${commit2}^`)) return `${commit2}^`;
9748
+ return void 0;
9749
+ }
9750
+ async function resolveDiffBase(cwd, sessionId) {
9751
+ let defaultBranch;
9752
+ try {
9753
+ const config = loadConfigFrom(toGitCwd(cwd));
9754
+ if (!config.sessions?.includeCommittedChanges) return "HEAD";
9755
+ defaultBranch = config.branch?.defaultBranch;
9756
+ } catch {
9757
+ return "HEAD";
9758
+ }
9759
+ if (sessionId) {
9760
+ const anchored = await anchoredBase(cwd, sessionId);
9761
+ if (anchored) return anchored;
9762
+ }
9763
+ for (const candidate of baseCandidates(defaultBranch)) {
9764
+ if (!await refExists2(cwd, candidate)) continue;
9765
+ try {
9766
+ const base = await execGit(cwd, ["merge-base", "HEAD", candidate]);
9767
+ const sha = base.trim();
9768
+ if (sha) return sha;
9769
+ } catch {
9770
+ }
9771
+ return "HEAD";
9772
+ }
9773
+ return "HEAD";
9774
+ }
9775
+
9424
9776
  // src/commands/sessions/web/gitStatus.ts
9425
9777
  async function untrackedPaths(cwd) {
9426
9778
  const list5 = await execGit(cwd, [
@@ -9586,7 +9938,7 @@ function rankFilePaths(paths, query, limit) {
9586
9938
 
9587
9939
  // src/commands/sessions/web/listFiles.ts
9588
9940
  var MAX_RESULTS = 20;
9589
- var CACHE_TTL_MS = 5e3;
9941
+ var CACHE_TTL_MS2 = 5e3;
9590
9942
  var LS_FILES_MAX_BUFFER = 32 * 1024 * 1024;
9591
9943
  var fileListCache = /* @__PURE__ */ new Map();
9592
9944
  async function repoFiles(cwd) {
@@ -9598,7 +9950,7 @@ async function repoFiles(cwd) {
9598
9950
  { maxBuffer: LS_FILES_MAX_BUFFER }
9599
9951
  );
9600
9952
  const files = [...new Set(output.split(/\r?\n/).filter(Boolean))];
9601
- fileListCache.set(cwd, { files, expires: Date.now() + CACHE_TTL_MS });
9953
+ fileListCache.set(cwd, { files, expires: Date.now() + CACHE_TTL_MS2 });
9602
9954
  return files;
9603
9955
  }
9604
9956
  async function listFiles(req, res) {
@@ -9737,14 +10089,14 @@ async function listNewsItems(_req, res) {
9737
10089
  }
9738
10090
 
9739
10091
  // src/shared/db/countUsagePeaks.ts
9740
- import { count, eq as eq18 } from "drizzle-orm";
10092
+ import { count, eq as eq19 } from "drizzle-orm";
9741
10093
  async function countUsagePeaks(db, window) {
9742
- const [row] = await db.select({ value: count() }).from(usagePeaks).where(window ? eq18(usagePeaks.window, window) : void 0);
10094
+ const [row] = await db.select({ value: count() }).from(usagePeaks).where(window ? eq19(usagePeaks.window, window) : void 0);
9743
10095
  return row?.value ?? 0;
9744
10096
  }
9745
10097
 
9746
10098
  // src/shared/db/listUsagePeaks.ts
9747
- import { and as and8, desc as desc2, eq as eq19, getTableColumns } from "drizzle-orm";
10099
+ import { and as and9, desc as desc2, eq as eq20, getTableColumns } from "drizzle-orm";
9748
10100
 
9749
10101
  // src/shared/db/avgContextPerCycle.ts
9750
10102
  import { count as count2, sql as sql16 } from "drizzle-orm";
@@ -9768,11 +10120,11 @@ async function listUsagePeaks(db, options2) {
9768
10120
  phaseCount: avgContext.phaseCount
9769
10121
  }).from(usagePeaks).leftJoin(
9770
10122
  avgContext,
9771
- and8(
9772
- eq19(usagePeaks.window, avgContext.window),
9773
- eq19(usagePeaks.resetsAt, avgContext.resetsAt)
10123
+ and9(
10124
+ eq20(usagePeaks.window, avgContext.window),
10125
+ eq20(usagePeaks.resetsAt, avgContext.resetsAt)
9774
10126
  )
9775
- ).where(options2?.window ? eq19(usagePeaks.window, options2.window) : void 0).orderBy(
10127
+ ).where(options2?.window ? eq20(usagePeaks.window, options2.window) : void 0).orderBy(
9776
10128
  desc2(usagePeaks.resetsAt),
9777
10129
  usagePeaks.window,
9778
10130
  desc2(usagePeaks.createdAt),
@@ -9824,14 +10176,14 @@ async function openInCode(req, res) {
9824
10176
  import { execFile as execFile5 } from "child_process";
9825
10177
  import { promisify as promisify5 } from "util";
9826
10178
  var execFileAsync4 = promisify5(execFile5);
9827
- var CACHE_TTL_MS2 = 3e4;
10179
+ var CACHE_TTL_MS3 = 3e4;
9828
10180
  function createCachedGhJson(args, parse3, fallback, options2 = {}) {
9829
10181
  const { cacheFallback = true } = options2;
9830
- const cache4 = /* @__PURE__ */ new Map();
10182
+ const cache5 = /* @__PURE__ */ new Map();
9831
10183
  return async (cwd, extraArgs = []) => {
9832
10184
  const key = extraArgs.length ? `${cwd}\0${extraArgs.join("\0")}` : cwd;
9833
10185
  const now = Date.now();
9834
- const cached = cache4.get(key);
10186
+ const cached = cache5.get(key);
9835
10187
  if (cached && cached.expires > now) return cached.value;
9836
10188
  let value = fallback;
9837
10189
  try {
@@ -9844,7 +10196,7 @@ function createCachedGhJson(args, parse3, fallback, options2 = {}) {
9844
10196
  value = fallback;
9845
10197
  }
9846
10198
  if (cacheFallback || value !== fallback)
9847
- cache4.set(key, { value, expires: now + CACHE_TTL_MS2 });
10199
+ cache5.set(key, { value, expires: now + CACHE_TTL_MS3 });
9848
10200
  return value;
9849
10201
  };
9850
10202
  }
@@ -10155,6 +10507,41 @@ function coerceString(key, raw) {
10155
10507
  return { ok: false, error: `${key}: expected a string` };
10156
10508
  }
10157
10509
 
10510
+ // src/shared/configLeafSchema.ts
10511
+ function configLeafSchema(schema2, key) {
10512
+ let current = schema2;
10513
+ for (const name of key.split(".")) {
10514
+ const { inner } = unwrapSchemaNode(current);
10515
+ const child = inner.def?.type === "object" ? inner.def.shape?.[name] : void 0;
10516
+ if (!child) return void 0;
10517
+ current = child;
10518
+ }
10519
+ return current;
10520
+ }
10521
+
10522
+ // src/commands/config/coerceStructuredConfigValue.ts
10523
+ function coerceStructuredConfigValue(key, raw) {
10524
+ const schema2 = configLeafSchema(assistConfigSchema, key);
10525
+ if (!schema2) return { ok: false, error: `Unknown config key "${key}"` };
10526
+ const parsed = schema2.safeParse(raw);
10527
+ if (parsed.success)
10528
+ return { ok: true, value: parsed.data };
10529
+ return {
10530
+ ok: false,
10531
+ error: parsed.error.issues.map((issue) => formatIssue2(key, issue)).join("\n")
10532
+ };
10533
+ }
10534
+ function formatIssue2(key, issue) {
10535
+ const path71 = formatConfigPath([
10536
+ { kind: "key", name: key },
10537
+ ...issue.path.map(toSegment)
10538
+ ]);
10539
+ return `${path71}: ${issue.message}`;
10540
+ }
10541
+ function toSegment(part) {
10542
+ return typeof part === "number" ? { kind: "index", index: part } : { kind: "key", name: String(part) };
10543
+ }
10544
+
10158
10545
  // src/commands/config/coerceConfigValue.ts
10159
10546
  var EDITABLE_TYPES = /* @__PURE__ */ new Set([
10160
10547
  "string",
@@ -10169,12 +10556,8 @@ function coerceConfigValue(key, raw) {
10169
10556
  );
10170
10557
  if (!leaf) return { ok: false, error: `Unknown config key "${key}"` };
10171
10558
  if (leaf.itemType) return coerceScalarList(key, raw, leaf.itemType);
10172
- if (!EDITABLE_TYPES.has(leaf.type)) {
10173
- return {
10174
- ok: false,
10175
- error: `"${key}" is a ${leaf.type} value and is read-only here`
10176
- };
10177
- }
10559
+ if (!EDITABLE_TYPES.has(leaf.type))
10560
+ return coerceStructuredConfigValue(key, raw);
10178
10561
  if (leaf.type === "union")
10179
10562
  return coerceUnion(key, raw, leaf.unionTypes ?? []);
10180
10563
  return coerceConfigScalar(key, raw, leaf.type);
@@ -10393,22 +10776,22 @@ import { readFileSync as readFileSync21 } from "fs";
10393
10776
  import { createRequire as createRequire2 } from "module";
10394
10777
  var require3 = createRequire2(import.meta.url);
10395
10778
  function createCssHandler(packageEntry) {
10396
- let cache4;
10779
+ let cache5;
10397
10780
  return (req, res) => {
10398
- if (!cache4) {
10781
+ if (!cache5) {
10399
10782
  const resolved = require3.resolve(packageEntry);
10400
10783
  const body = readFileSync21(resolved, "utf8");
10401
10784
  const etag = `"${createHash2("sha256").update(body).digest("hex").slice(0, 16)}"`;
10402
- cache4 = { body, etag };
10785
+ cache5 = { body, etag };
10403
10786
  }
10404
- const headers = { ETag: cache4.etag, "Cache-Control": "no-cache" };
10405
- if (req.headers["if-none-match"] === cache4.etag) {
10787
+ const headers = { ETag: cache5.etag, "Cache-Control": "no-cache" };
10788
+ if (req.headers["if-none-match"] === cache5.etag) {
10406
10789
  res.writeHead(304, headers);
10407
10790
  res.end();
10408
10791
  return;
10409
10792
  }
10410
10793
  res.writeHead(200, { "Content-Type": "text/css", ...headers });
10411
- res.end(cache4.body);
10794
+ res.end(cache5.body);
10412
10795
  };
10413
10796
  }
10414
10797
 
@@ -10907,11 +11290,11 @@ function registerActivityCommands(cmd) {
10907
11290
 
10908
11291
  // src/commands/backlog/associate-github/index.ts
10909
11292
  import chalk64 from "chalk";
10910
- import { eq as eq21 } from "drizzle-orm";
11293
+ import { eq as eq22 } from "drizzle-orm";
10911
11294
 
10912
11295
  // src/commands/backlog/beginAssociation.ts
10913
11296
  import chalk63 from "chalk";
10914
- import { eq as eq20 } from "drizzle-orm";
11297
+ import { eq as eq21 } from "drizzle-orm";
10915
11298
  async function beginAssociation(id, options2, clearPatch, label2) {
10916
11299
  const found = await findOneItem(id);
10917
11300
  if (!found) {
@@ -10921,7 +11304,7 @@ async function beginAssociation(id, options2, clearPatch, label2) {
10921
11304
  const { orm } = found;
10922
11305
  const itemId2 = found.item.id;
10923
11306
  if (options2.clear) {
10924
- await orm.update(items).set(clearPatch).where(eq20(items.id, itemId2));
11307
+ await orm.update(items).set(clearPatch).where(eq21(items.id, itemId2));
10925
11308
  console.log(
10926
11309
  chalk63.green(
10927
11310
  `Cleared ${label2} association on item ${formatItemId(itemId2)}.`
@@ -10989,7 +11372,7 @@ async function associateGithub(id, issue, options2) {
10989
11372
  return;
10990
11373
  }
10991
11374
  const title = fetchGithubIssueTitle(normalized);
10992
- await orm.update(items).set({ githubIssue: normalized, jiraKey: null }).where(eq21(items.id, itemId2));
11375
+ await orm.update(items).set({ githubIssue: normalized, jiraKey: null }).where(eq22(items.id, itemId2));
10993
11376
  console.log(
10994
11377
  chalk64.green(`Associated ${normalized} with item ${formatItemId(itemId2)}.`),
10995
11378
  title ? chalk64.dim(`(${title})`) : ""
@@ -11003,7 +11386,7 @@ function registerAssociateGithubCommand(cmd) {
11003
11386
 
11004
11387
  // src/commands/backlog/associate-jira/index.ts
11005
11388
  import chalk66 from "chalk";
11006
- import { eq as eq22 } from "drizzle-orm";
11389
+ import { eq as eq23 } from "drizzle-orm";
11007
11390
 
11008
11391
  // src/commands/jira/fetchIssue.ts
11009
11392
  import { execSync as execSync33 } from "child_process";
@@ -11068,7 +11451,7 @@ async function associateJira(id, key, options2) {
11068
11451
  const parsed = fetchIssue(normalized, "summary");
11069
11452
  const fields = parsed?.fields;
11070
11453
  const summary = fields?.summary;
11071
- await orm.update(items).set({ jiraKey: normalized, githubIssue: null }).where(eq22(items.id, itemId2));
11454
+ await orm.update(items).set({ jiraKey: normalized, githubIssue: null }).where(eq23(items.id, itemId2));
11072
11455
  console.log(
11073
11456
  chalk66.green(`Associated ${normalized} with item ${formatItemId(itemId2)}.`),
11074
11457
  summary ? chalk66.dim(`(${summary})`) : ""
@@ -11446,15 +11829,15 @@ function isClaudeCode() {
11446
11829
  }
11447
11830
 
11448
11831
  // src/commands/backlog/insertPhaseAt.ts
11449
- import { eq as eq24 } from "drizzle-orm";
11832
+ import { eq as eq25 } from "drizzle-orm";
11450
11833
 
11451
11834
  // src/commands/backlog/shiftPhasesUp.ts
11452
- import { and as and9, desc as desc3, eq as eq23, gte } from "drizzle-orm";
11835
+ import { and as and10, desc as desc3, eq as eq24, gte } from "drizzle-orm";
11453
11836
  async function shiftPhasesUp(db, itemId2, fromIdx) {
11454
- const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and9(eq23(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc3(planPhases.idx));
11837
+ const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and10(eq24(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc3(planPhases.idx));
11455
11838
  for (const p of toShift) {
11456
- await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and9(eq23(planTasks.itemId, itemId2), eq23(planTasks.phaseIdx, p.idx)));
11457
- await db.update(planPhases).set({ idx: p.idx + 1 }).where(and9(eq23(planPhases.itemId, itemId2), eq23(planPhases.idx, p.idx)));
11839
+ await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and10(eq24(planTasks.itemId, itemId2), eq24(planTasks.phaseIdx, p.idx)));
11840
+ await db.update(planPhases).set({ idx: p.idx + 1 }).where(and10(eq24(planPhases.itemId, itemId2), eq24(planPhases.idx, p.idx)));
11458
11841
  }
11459
11842
  }
11460
11843
 
@@ -11467,7 +11850,7 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
11467
11850
  await tx.insert(planTasks).values(tasks.map((task, i) => ({ itemId: itemId2, phaseIdx, idx: i, task })));
11468
11851
  }
11469
11852
  if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
11470
- await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(eq24(items.id, itemId2));
11853
+ await tx.update(items).set({ currentPhase: phaseIdx + 1 }).where(eq25(items.id, itemId2));
11471
11854
  }
11472
11855
  });
11473
11856
  }
@@ -11639,9 +12022,9 @@ import chalk76 from "chalk";
11639
12022
 
11640
12023
  // src/commands/backlog/resolveInsertPosition.ts
11641
12024
  import chalk75 from "chalk";
11642
- import { count as count3, eq as eq25 } from "drizzle-orm";
12025
+ import { count as count3, eq as eq26 } from "drizzle-orm";
11643
12026
  async function resolveInsertPosition(orm, itemId2, position) {
11644
- const [row] = await orm.select({ cnt: count3() }).from(planPhases).where(eq25(planPhases.itemId, itemId2));
12027
+ const [row] = await orm.select({ cnt: count3() }).from(planPhases).where(eq26(planPhases.itemId, itemId2));
11645
12028
  const phaseCount = row?.cnt ?? 0;
11646
12029
  if (position === void 0) return phaseCount;
11647
12030
  const pos = Number.parseInt(position, 10);
@@ -11997,9 +12380,9 @@ function hasCycle(adjacency, fromId, toId) {
11997
12380
  }
11998
12381
 
11999
12382
  // src/commands/backlog/loadDependencyGraph.ts
12000
- import { eq as eq26 } from "drizzle-orm";
12383
+ import { eq as eq27 } from "drizzle-orm";
12001
12384
  async function loadDependencyGraph(orm) {
12002
- const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq26(links.type, "depends-on"));
12385
+ const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq27(links.type, "depends-on"));
12003
12386
  const graph = /* @__PURE__ */ new Map();
12004
12387
  for (const { itemId: itemId2, targetId } of rows) {
12005
12388
  const bucket = graph.get(itemId2);
@@ -12066,7 +12449,7 @@ async function link(fromId, toId, opts) {
12066
12449
 
12067
12450
  // src/commands/backlog/unlink.ts
12068
12451
  import chalk82 from "chalk";
12069
- import { and as and10, eq as eq27 } from "drizzle-orm";
12452
+ import { and as and11, eq as eq28 } from "drizzle-orm";
12070
12453
  async function unlink(fromId, toId) {
12071
12454
  const fromNum = parseItemId(fromId);
12072
12455
  const toNum = parseItemId(toId);
@@ -12090,7 +12473,7 @@ async function unlink(fromId, toId) {
12090
12473
  );
12091
12474
  return;
12092
12475
  }
12093
- await orm.delete(links).where(and10(eq27(links.itemId, fromNum), eq27(links.targetId, toNum)));
12476
+ await orm.delete(links).where(and11(eq28(links.itemId, fromNum), eq28(links.targetId, toNum)));
12094
12477
  console.log(
12095
12478
  chalk82.green(
12096
12479
  `Removed link from ${formatItemId(fromNum)} to ${formatItemId(toNum)}.`
@@ -12110,7 +12493,7 @@ function registerLinkCommands(cmd) {
12110
12493
 
12111
12494
  // src/commands/backlog/move-repo/index.ts
12112
12495
  import chalk84 from "chalk";
12113
- import { eq as eq29 } from "drizzle-orm";
12496
+ import { eq as eq30 } from "drizzle-orm";
12114
12497
 
12115
12498
  // src/commands/backlog/move-repo/confirmMove.ts
12116
12499
  import chalk83 from "chalk";
@@ -12125,9 +12508,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
12125
12508
  }
12126
12509
 
12127
12510
  // src/commands/backlog/move-repo/countByOrigin.ts
12128
- import { count as count4, eq as eq28 } from "drizzle-orm";
12511
+ import { count as count4, eq as eq29 } from "drizzle-orm";
12129
12512
  async function countByOrigin(orm, origin) {
12130
- const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq28(items.origin, origin));
12513
+ const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq29(items.origin, origin));
12131
12514
  return cnt;
12132
12515
  }
12133
12516
 
@@ -12170,7 +12553,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
12170
12553
  console.log(chalk84.yellow("Move cancelled; no changes made."));
12171
12554
  return;
12172
12555
  }
12173
- await orm.update(items).set({ origin: newOrigin }).where(eq29(items.origin, oldOrigin));
12556
+ await orm.update(items).set({ origin: newOrigin }).where(eq30(items.origin, oldOrigin));
12174
12557
  console.log(
12175
12558
  chalk84.green(
12176
12559
  `Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
@@ -12587,10 +12970,10 @@ async function start(id) {
12587
12970
 
12588
12971
  // src/commands/backlog/stop/index.ts
12589
12972
  import chalk96 from "chalk";
12590
- import { and as and11, eq as eq30 } from "drizzle-orm";
12973
+ import { and as and12, eq as eq31 } from "drizzle-orm";
12591
12974
  async function stop() {
12592
12975
  const { orm } = await getReady();
12593
- const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and11(eq30(items.status, "in-progress"), eq30(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
12976
+ const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and12(eq31(items.status, "in-progress"), eq31(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
12594
12977
  if (stopped.length === 0) {
12595
12978
  console.log(chalk96.yellow("No in-progress items to stop."));
12596
12979
  return;
@@ -12707,13 +13090,13 @@ async function findSubtask(id, index3) {
12707
13090
  }
12708
13091
 
12709
13092
  // src/commands/backlog/updateSubtask.ts
12710
- import { and as and12, eq as eq31 } from "drizzle-orm";
13093
+ import { and as and13, eq as eq32 } from "drizzle-orm";
12711
13094
  async function updateSubtask(orm, itemId2, idx, fields) {
12712
13095
  const set = {};
12713
13096
  if (fields.title !== void 0) set.title = fields.title;
12714
13097
  if (fields.description !== void 0) set.description = fields.description;
12715
13098
  if (fields.status !== void 0) set.status = fields.status;
12716
- const [row] = await orm.update(itemSubtasks).set(set).where(and12(eq31(itemSubtasks.itemId, itemId2), eq31(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
13099
+ const [row] = await orm.update(itemSubtasks).set(set).where(and13(eq32(itemSubtasks.itemId, itemId2), eq32(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
12717
13100
  return row?.title;
12718
13101
  }
12719
13102
 
@@ -12768,16 +13151,16 @@ async function editSubtask(id, index3, options2) {
12768
13151
  import chalk102 from "chalk";
12769
13152
 
12770
13153
  // src/commands/backlog/deleteSubtask.ts
12771
- import { and as and13, asc as asc8, eq as eq32 } from "drizzle-orm";
13154
+ import { and as and14, asc as asc9, eq as eq33 } from "drizzle-orm";
12772
13155
  async function deleteSubtask(orm, itemId2, idx) {
12773
- const [row] = await orm.delete(itemSubtasks).where(and13(eq32(itemSubtasks.itemId, itemId2), eq32(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
13156
+ const [row] = await orm.delete(itemSubtasks).where(and14(eq33(itemSubtasks.itemId, itemId2), eq33(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
12774
13157
  if (!row) return void 0;
12775
- const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(eq32(itemSubtasks.itemId, itemId2)).orderBy(asc8(itemSubtasks.idx));
13158
+ const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(eq33(itemSubtasks.itemId, itemId2)).orderBy(asc9(itemSubtasks.idx));
12776
13159
  for (let i = 0; i < remaining.length; i++) {
12777
13160
  const oldIdx = remaining[i].idx;
12778
13161
  if (oldIdx === i) continue;
12779
13162
  await orm.update(itemSubtasks).set({ idx: i }).where(
12780
- and13(eq32(itemSubtasks.itemId, itemId2), eq32(itemSubtasks.idx, oldIdx))
13163
+ and14(eq33(itemSubtasks.itemId, itemId2), eq33(itemSubtasks.idx, oldIdx))
12781
13164
  );
12782
13165
  }
12783
13166
  return row.title;
@@ -12846,20 +13229,20 @@ function registerSubtaskCommands(cmd) {
12846
13229
 
12847
13230
  // src/commands/backlog/movePhase.ts
12848
13231
  import chalk104 from "chalk";
12849
- import { count as count6, eq as eq35 } from "drizzle-orm";
13232
+ import { count as count6, eq as eq36 } from "drizzle-orm";
12850
13233
 
12851
13234
  // src/commands/backlog/reorderPhaseRows.ts
12852
- import { and as and15, asc as asc10, eq as eq34 } from "drizzle-orm";
13235
+ import { and as and16, asc as asc11, eq as eq35 } from "drizzle-orm";
12853
13236
 
12854
13237
  // src/commands/backlog/reindexPhases.ts
12855
- import { and as and14, asc as asc9, count as count5, eq as eq33 } from "drizzle-orm";
13238
+ import { and as and15, asc as asc10, count as count5, eq as eq34 } from "drizzle-orm";
12856
13239
  async function reindexPhases(db, itemId2) {
12857
- const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq33(planPhases.itemId, itemId2)).orderBy(asc9(planPhases.idx));
13240
+ const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq34(planPhases.itemId, itemId2)).orderBy(asc10(planPhases.idx));
12858
13241
  for (let i = 0; i < remaining.length; i++) {
12859
13242
  const oldIdx = remaining[i].idx;
12860
13243
  if (oldIdx === i) continue;
12861
- await db.update(planTasks).set({ phaseIdx: i }).where(and14(eq33(planTasks.itemId, itemId2), eq33(planTasks.phaseIdx, oldIdx)));
12862
- await db.update(planPhases).set({ idx: i }).where(and14(eq33(planPhases.itemId, itemId2), eq33(planPhases.idx, oldIdx)));
13244
+ await db.update(planTasks).set({ phaseIdx: i }).where(and15(eq34(planTasks.itemId, itemId2), eq34(planTasks.phaseIdx, oldIdx)));
13245
+ await db.update(planPhases).set({ idx: i }).where(and15(eq34(planPhases.itemId, itemId2), eq34(planPhases.idx, oldIdx)));
12863
13246
  }
12864
13247
  }
12865
13248
  async function adjustCurrentPhase(db, item, removedIdx) {
@@ -12867,24 +13250,24 @@ async function adjustCurrentPhase(db, item, removedIdx) {
12867
13250
  if (currentPhase === void 0) return;
12868
13251
  const currentIdx = currentPhase - 1;
12869
13252
  if (removedIdx < currentIdx) {
12870
- await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq33(items.id, item.id));
13253
+ await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq34(items.id, item.id));
12871
13254
  return;
12872
13255
  }
12873
13256
  if (removedIdx !== currentIdx) return;
12874
- const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq33(planPhases.itemId, item.id));
13257
+ const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq34(planPhases.itemId, item.id));
12875
13258
  const cnt = row?.cnt ?? 0;
12876
- await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq33(items.id, item.id));
13259
+ await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq34(items.id, item.id));
12877
13260
  }
12878
13261
 
12879
13262
  // src/commands/backlog/reorderPhaseRows.ts
12880
13263
  async function reorderPhaseRows(orm, itemId2, fromIdx, toIdx) {
12881
13264
  await orm.transaction(async (tx) => {
12882
- const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and15(eq34(planPhases.itemId, itemId2), eq34(planPhases.idx, fromIdx)));
12883
- const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and15(eq34(planTasks.itemId, itemId2), eq34(planTasks.phaseIdx, fromIdx))).orderBy(asc10(planTasks.idx));
13265
+ const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and16(eq35(planPhases.itemId, itemId2), eq35(planPhases.idx, fromIdx)));
13266
+ const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and16(eq35(planTasks.itemId, itemId2), eq35(planTasks.phaseIdx, fromIdx))).orderBy(asc11(planTasks.idx));
12884
13267
  await tx.delete(planTasks).where(
12885
- and15(eq34(planTasks.itemId, itemId2), eq34(planTasks.phaseIdx, fromIdx))
13268
+ and16(eq35(planTasks.itemId, itemId2), eq35(planTasks.phaseIdx, fromIdx))
12886
13269
  );
12887
- await tx.delete(planPhases).where(and15(eq34(planPhases.itemId, itemId2), eq34(planPhases.idx, fromIdx)));
13270
+ await tx.delete(planPhases).where(and16(eq35(planPhases.itemId, itemId2), eq35(planPhases.idx, fromIdx)));
12888
13271
  await reindexPhases(tx, itemId2);
12889
13272
  await shiftPhasesUp(tx, itemId2, toIdx);
12890
13273
  await tx.insert(planPhases).values({
@@ -12925,7 +13308,7 @@ async function movePhase(id, from, to) {
12925
13308
  if (!found) return;
12926
13309
  const { orm, item } = found;
12927
13310
  const itemId2 = item.id;
12928
- const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(eq35(planPhases.itemId, itemId2));
13311
+ const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(eq36(planPhases.itemId, itemId2));
12929
13312
  const phaseCount = row?.cnt ?? 0;
12930
13313
  const fromIdx = toIndex(from, phaseCount);
12931
13314
  if (fromIdx === void 0) return;
@@ -12941,22 +13324,22 @@ async function movePhase(id, from, to) {
12941
13324
  import chalk106 from "chalk";
12942
13325
 
12943
13326
  // src/commands/backlog/applyPhaseUpdate.ts
12944
- import { and as and16, eq as eq36 } from "drizzle-orm";
13327
+ import { and as and17, eq as eq37 } from "drizzle-orm";
12945
13328
  async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
12946
13329
  await orm.transaction(async (tx) => {
12947
13330
  if (fields.name) {
12948
13331
  await tx.update(planPhases).set({ name: fields.name }).where(
12949
- and16(eq36(planPhases.itemId, itemId2), eq36(planPhases.idx, phaseIdx))
13332
+ and17(eq37(planPhases.itemId, itemId2), eq37(planPhases.idx, phaseIdx))
12950
13333
  );
12951
13334
  }
12952
13335
  if (fields.manualCheck) {
12953
13336
  await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
12954
- and16(eq36(planPhases.itemId, itemId2), eq36(planPhases.idx, phaseIdx))
13337
+ and17(eq37(planPhases.itemId, itemId2), eq37(planPhases.idx, phaseIdx))
12955
13338
  );
12956
13339
  }
12957
13340
  if (fields.task) {
12958
13341
  await tx.delete(planTasks).where(
12959
- and16(eq36(planTasks.itemId, itemId2), eq36(planTasks.phaseIdx, phaseIdx))
13342
+ and17(eq37(planTasks.itemId, itemId2), eq37(planTasks.phaseIdx, phaseIdx))
12960
13343
  );
12961
13344
  if (fields.task.length) {
12962
13345
  await tx.insert(planTasks).values(
@@ -12974,14 +13357,14 @@ async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
12974
13357
 
12975
13358
  // src/commands/backlog/findPhase.ts
12976
13359
  import chalk105 from "chalk";
12977
- import { and as and17, count as count7, eq as eq37 } from "drizzle-orm";
13360
+ import { and as and18, count as count7, eq as eq38 } from "drizzle-orm";
12978
13361
  async function findPhase(id, phase) {
12979
13362
  const found = await findOneItem(id);
12980
13363
  if (!found) return void 0;
12981
13364
  const { orm, item } = found;
12982
13365
  const itemId2 = item.id;
12983
13366
  const phaseIdx = Number.parseInt(phase, 10) - 1;
12984
- const [row] = await orm.select({ cnt: count7() }).from(planPhases).where(and17(eq37(planPhases.itemId, itemId2), eq37(planPhases.idx, phaseIdx)));
13367
+ const [row] = await orm.select({ cnt: count7() }).from(planPhases).where(and18(eq38(planPhases.itemId, itemId2), eq38(planPhases.idx, phaseIdx)));
12985
13368
  if (!row || row.cnt === 0) {
12986
13369
  console.log(
12987
13370
  chalk105.red(
@@ -13137,14 +13520,14 @@ async function updatePhase(id, phase, options2) {
13137
13520
  }
13138
13521
 
13139
13522
  // src/commands/backlog/registerUpdatePhaseCommand.ts
13140
- function collect2(value, previous) {
13523
+ function collect(value, previous) {
13141
13524
  return [...previous, value];
13142
13525
  }
13143
13526
  function registerUpdatePhaseCommand(cmd) {
13144
- cmd.command("update-phase <id> <phase>").alias("edit-phase").description("Modify a plan phase on a backlog item").option("--name <name>", "New phase name").option("--task <task...>", "Replace tasks (repeatable)").option("--manual-check <check...>", "Replace manual checks (repeatable)").option("--add-task <text>", "Append one task (repeatable)", collect2, []).option("--edit-task <n> <text...>", "Replace task n (1-based) in place").option("--remove-task <n>", "Remove task n (1-based)").option(
13527
+ cmd.command("update-phase <id> <phase>").alias("edit-phase").description("Modify a plan phase on a backlog item").option("--name <name>", "New phase name").option("--task <task...>", "Replace tasks (repeatable)").option("--manual-check <check...>", "Replace manual checks (repeatable)").option("--add-task <text>", "Append one task (repeatable)", collect, []).option("--edit-task <n> <text...>", "Replace task n (1-based) in place").option("--remove-task <n>", "Remove task n (1-based)").option(
13145
13528
  "--add-check <text>",
13146
13529
  "Append one manual check (repeatable)",
13147
- collect2,
13530
+ collect,
13148
13531
  []
13149
13532
  ).option(
13150
13533
  "--edit-check <n> <text...>",
@@ -13154,16 +13537,16 @@ function registerUpdatePhaseCommand(cmd) {
13154
13537
 
13155
13538
  // src/commands/backlog/removePhase.ts
13156
13539
  import chalk107 from "chalk";
13157
- import { and as and18, eq as eq38 } from "drizzle-orm";
13540
+ import { and as and19, eq as eq39 } from "drizzle-orm";
13158
13541
  async function removePhase(id, phase) {
13159
13542
  const found = await findPhase(id, phase);
13160
13543
  if (!found) return;
13161
13544
  const { item, orm, itemId: itemId2, phaseIdx } = found;
13162
13545
  await orm.transaction(async (tx) => {
13163
13546
  await tx.delete(planTasks).where(
13164
- and18(eq38(planTasks.itemId, itemId2), eq38(planTasks.phaseIdx, phaseIdx))
13547
+ and19(eq39(planTasks.itemId, itemId2), eq39(planTasks.phaseIdx, phaseIdx))
13165
13548
  );
13166
- await tx.delete(planPhases).where(and18(eq38(planPhases.itemId, itemId2), eq38(planPhases.idx, phaseIdx)));
13549
+ await tx.delete(planPhases).where(and19(eq39(planPhases.itemId, itemId2), eq39(planPhases.idx, phaseIdx)));
13167
13550
  await reindexPhases(tx, itemId2);
13168
13551
  await adjustCurrentPhase(tx, item, phaseIdx);
13169
13552
  });
@@ -13176,7 +13559,7 @@ async function removePhase(id, phase) {
13176
13559
 
13177
13560
  // src/commands/backlog/update/update.ts
13178
13561
  import chalk111 from "chalk";
13179
- import { eq as eq39 } from "drizzle-orm";
13562
+ import { eq as eq40 } from "drizzle-orm";
13180
13563
 
13181
13564
  // src/commands/backlog/update/buildUpdateValues.ts
13182
13565
  import chalk108 from "chalk";
@@ -13287,14 +13670,14 @@ async function update(id, options2) {
13287
13670
  if (!built) return;
13288
13671
  const { orm } = found;
13289
13672
  const itemId2 = found.item.id;
13290
- await orm.update(items).set(built.set).where(eq39(items.id, itemId2));
13673
+ await orm.update(items).set(built.set).where(eq40(items.id, itemId2));
13291
13674
  console.log(
13292
13675
  chalk111.green(`Updated ${built.fields} on item ${formatItemId(itemId2)}.`)
13293
13676
  );
13294
13677
  }
13295
13678
 
13296
13679
  // src/commands/backlog/registerUpdateCommands.ts
13297
- function collect3(value, previous) {
13680
+ function collect2(value, previous) {
13298
13681
  return [...previous, value];
13299
13682
  }
13300
13683
  function registerUpdateCommands(cmd) {
@@ -13304,7 +13687,7 @@ function registerUpdateCommands(cmd) {
13304
13687
  ).option("--type <type>", "New type (story or bug)").option("--ac <criterion...>", "Replace acceptance criteria (repeatable)").option(
13305
13688
  "--add-ac <text>",
13306
13689
  "Append one acceptance criterion (repeatable)",
13307
- collect3,
13690
+ collect2,
13308
13691
  []
13309
13692
  ).option(
13310
13693
  "--edit-ac <n> <text...>",
@@ -13489,9 +13872,9 @@ var UNPARSEABLE = { ok: false, error: "unable to parse" };
13489
13872
  function groupByOperator(tokens) {
13490
13873
  const groups = [[]];
13491
13874
  for (let i = 0; i < tokens.length; i++) {
13492
- const step = handleToken(tokens, i, groups);
13493
- if (!step.ok) return step;
13494
- i = step.nextIndex;
13875
+ const step2 = handleToken(tokens, i, groups);
13876
+ if (!step2.ok) return step2;
13877
+ i = step2.nextIndex;
13495
13878
  }
13496
13879
  return { ok: true, groups };
13497
13880
  }
@@ -17365,9 +17748,9 @@ function registerGithub(program2) {
17365
17748
  }
17366
17749
 
17367
17750
  // src/commands/handover/countPendingHandovers.ts
17368
- import { and as and19, eq as eq40, isNull, sql as sql18 } from "drizzle-orm";
17751
+ import { and as and20, eq as eq41, isNull, sql as sql18 } from "drizzle-orm";
17369
17752
  async function countPendingHandovers(orm, origin) {
17370
- const [row] = await orm.select({ count: sql18`count(*)::int` }).from(handovers).where(and19(eq40(handovers.origin, origin), isNull(handovers.recalledAt)));
17753
+ const [row] = await orm.select({ count: sql18`count(*)::int` }).from(handovers).where(and20(eq41(handovers.origin, origin), isNull(handovers.recalledAt)));
17371
17754
  return row?.count ?? 0;
17372
17755
  }
17373
17756
 
@@ -17507,13 +17890,13 @@ async function load2(options2 = {}) {
17507
17890
  }
17508
17891
 
17509
17892
  // src/commands/handover/listPendingHandovers.ts
17510
- import { and as and20, desc as desc4, eq as eq41, isNull as isNull2 } from "drizzle-orm";
17893
+ import { and as and21, desc as desc4, eq as eq42, isNull as isNull2 } from "drizzle-orm";
17511
17894
  async function listPendingHandovers(orm, origin) {
17512
17895
  return orm.select({
17513
17896
  id: handovers.id,
17514
17897
  summary: handovers.summary,
17515
17898
  createdAt: handovers.createdAt
17516
- }).from(handovers).where(and20(eq41(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc4(handovers.createdAt), desc4(handovers.id));
17899
+ }).from(handovers).where(and21(eq42(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc4(handovers.createdAt), desc4(handovers.id));
17517
17900
  }
17518
17901
 
17519
17902
  // src/commands/handover/printPendingHandovers.ts
@@ -17526,17 +17909,17 @@ async function printPendingHandovers() {
17526
17909
  }
17527
17910
 
17528
17911
  // src/commands/handover/recallHandover.ts
17529
- import { and as and21, desc as desc5, eq as eq42, isNull as isNull3 } from "drizzle-orm";
17912
+ import { and as and22, desc as desc5, eq as eq43, isNull as isNull3 } from "drizzle-orm";
17530
17913
  async function recallHandover(orm, origin, id) {
17531
17914
  const [row] = await orm.select().from(handovers).where(
17532
- and21(
17533
- eq42(handovers.origin, origin),
17915
+ and22(
17916
+ eq43(handovers.origin, origin),
17534
17917
  isNull3(handovers.recalledAt),
17535
- ...id === void 0 ? [] : [eq42(handovers.id, id)]
17918
+ ...id === void 0 ? [] : [eq43(handovers.id, id)]
17536
17919
  )
17537
17920
  ).orderBy(desc5(handovers.createdAt), desc5(handovers.id)).limit(1);
17538
17921
  if (!row) return void 0;
17539
- await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq42(handovers.id, row.id));
17922
+ await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq43(handovers.id, row.id));
17540
17923
  return row.content;
17541
17924
  }
17542
17925
 
@@ -17924,16 +18307,16 @@ function* durabilityProbes() {
17924
18307
  async function checkDurability(cwd) {
17925
18308
  if (!existsSync44(cwd)) return { durable: true };
17926
18309
  const probes = durabilityProbes();
17927
- let step = probes.next();
17928
- while (!step.done) step = probes.next(await gitResult(cwd, step.value));
17929
- return step.value;
18310
+ let step2 = probes.next();
18311
+ while (!step2.done) step2 = probes.next(await gitResult(cwd, step2.value));
18312
+ return step2.value;
17930
18313
  }
17931
18314
  function checkDurabilitySync(cwd) {
17932
18315
  if (!existsSync44(cwd)) return { durable: true };
17933
18316
  const probes = durabilityProbes();
17934
- let step = probes.next();
17935
- while (!step.done) step = probes.next(gitSyncResult(cwd, step.value));
17936
- return step.value;
18317
+ let step2 = probes.next();
18318
+ while (!step2.done) step2 = probes.next(gitSyncResult(cwd, step2.value));
18319
+ return step2.value;
17937
18320
  }
17938
18321
 
17939
18322
  // src/commands/sessions/daemon/worktree/worktreeConfigFor.ts
@@ -19552,20 +19935,20 @@ function resolveThread(threadId) {
19552
19935
  }
19553
19936
  }
19554
19937
  function requireCache(prNumber) {
19555
- const cache4 = loadCommentsCache(prNumber);
19556
- if (!cache4) {
19938
+ const cache5 = loadCommentsCache(prNumber);
19939
+ if (!cache5) {
19557
19940
  console.error(
19558
19941
  `Error: No cached comments found for PR #${prNumber}. Run "assist prs list-comments" first.`
19559
19942
  );
19560
19943
  process.exit(1);
19561
19944
  }
19562
- return cache4;
19945
+ return cache5;
19563
19946
  }
19564
19947
  function findLineComment(comments3, commentId) {
19565
19948
  return comments3.find((c) => c.type === "line" && c.id === commentId);
19566
19949
  }
19567
- function requireLineComment(cache4, commentId) {
19568
- const comment3 = findLineComment(cache4.comments, commentId);
19950
+ function requireLineComment(cache5, commentId) {
19951
+ const comment3 = findLineComment(cache5.comments, commentId);
19569
19952
  if (!comment3 || comment3.type !== "line" || !comment3.threadId) {
19570
19953
  console.error(
19571
19954
  `Error: Comment #${commentId} not found or has no thread ID.`
@@ -19574,8 +19957,8 @@ function requireLineComment(cache4, commentId) {
19574
19957
  }
19575
19958
  return comment3;
19576
19959
  }
19577
- function cleanupCacheIfDone(cache4, prNumber, commentId) {
19578
- const hasRemaining = cache4.comments.some(
19960
+ function cleanupCacheIfDone(cache5, prNumber, commentId) {
19961
+ const hasRemaining = cache5.comments.some(
19579
19962
  (c) => c.type === "line" && c.id !== commentId
19580
19963
  );
19581
19964
  if (!hasRemaining) deleteCommentsCache(prNumber);
@@ -19583,13 +19966,13 @@ function cleanupCacheIfDone(cache4, prNumber, commentId) {
19583
19966
  function resolveCommentWithReply(commentId, message2) {
19584
19967
  const prNumber = getCurrentPrNumber();
19585
19968
  const { org, repo } = getRepoInfo();
19586
- const cache4 = requireCache(prNumber);
19587
- const comment3 = requireLineComment(cache4, commentId);
19969
+ const cache5 = requireCache(prNumber);
19970
+ const comment3 = requireLineComment(cache5, commentId);
19588
19971
  replyToComment(org, repo, prNumber, commentId, message2);
19589
19972
  console.log("Reply posted successfully.");
19590
19973
  resolveThread(comment3.threadId);
19591
19974
  console.log("Thread resolved successfully.");
19592
- cleanupCacheIfDone(cache4, prNumber, commentId);
19975
+ cleanupCacheIfDone(cache5, prNumber, commentId);
19593
19976
  }
19594
19977
 
19595
19978
  // src/commands/prs/fixed.ts
@@ -20178,7 +20561,7 @@ var prsConfigHelp = [
20178
20561
  ];
20179
20562
 
20180
20563
  // src/commands/registerPrsEdit.ts
20181
- function collect4(value, previous) {
20564
+ function collect3(value, previous) {
20182
20565
  return previous.concat([value]);
20183
20566
  }
20184
20567
  function registerPrsEdit(prsCommand) {
@@ -20187,7 +20570,7 @@ function registerPrsEdit(prsCommand) {
20187
20570
  ).option("-t, --title <title>", "New title for the pull request").option("--what <what>", "Replace the ## What section").option("--why <why>", "Replace the ## Why section").option("--how <how>", "Replace the ## How section").option(
20188
20571
  "--resolves <key>",
20189
20572
  "Jira issue key resolved by this PR, appended to ## Why (repeatable)",
20190
- collect4,
20573
+ collect3,
20191
20574
  []
20192
20575
  ).action(edit);
20193
20576
  }
@@ -20288,7 +20671,7 @@ ${confirm}
20288
20671
  }
20289
20672
 
20290
20673
  // src/commands/registerPrsRaise.ts
20291
- function collect5(value, previous) {
20674
+ function collect4(value, previous) {
20292
20675
  return previous.concat([value]);
20293
20676
  }
20294
20677
  function registerPrsRaise(prsCommand) {
@@ -20297,20 +20680,20 @@ function registerPrsRaise(prsCommand) {
20297
20680
  ).option("-t, --title <title>", "Title for the pull request").option("--what <what>", "What the change does (## What section)").option("--why <why>", "Why the change is needed (## Why section)").option("--how <how>", "How the change works (optional ## How section)").option(
20298
20681
  "--resolves <key>",
20299
20682
  "Jira issue key resolved by this PR, appended to ## Why (repeatable)",
20300
- collect5,
20683
+ collect4,
20301
20684
  []
20302
20685
  ).option(
20303
20686
  "--force",
20304
20687
  "Overwrite the title and body of an existing pull request"
20305
- ).option("-B, --base <branch>", "Branch into which the pull request merges").option("-H, --head <branch>", "Branch that contains the commits").option("-d, --draft", "Mark the pull request as a draft").option("-w, --web", "Open the browser to create the pull request").option("-l, --label <label>", "Add a label (repeatable)", collect5, []).option(
20688
+ ).option("-B, --base <branch>", "Branch into which the pull request merges").option("-H, --head <branch>", "Branch that contains the commits").option("-d, --draft", "Mark the pull request as a draft").option("-w, --web", "Open the browser to create the pull request").option("-l, --label <label>", "Add a label (repeatable)", collect4, []).option(
20306
20689
  "-a, --assignee <login>",
20307
20690
  "Assign a person by login (repeatable)",
20308
- collect5,
20691
+ collect4,
20309
20692
  []
20310
20693
  ).option(
20311
20694
  "-r, --reviewer <handle>",
20312
20695
  "Request a review (repeatable)",
20313
- collect5,
20696
+ collect4,
20314
20697
  []
20315
20698
  ).option("-m, --milestone <name>", "Add the pull request to a milestone").addHelpText("after", () => raiseHelpText()).action(raise);
20316
20699
  }
@@ -27822,10 +28205,10 @@ function applyReviewPause(session, activity2) {
27822
28205
  }
27823
28206
 
27824
28207
  // src/shared/db/getPhaseActiveMs.ts
27825
- import { and as and22, eq as eq43 } from "drizzle-orm";
28208
+ import { and as and23, eq as eq44 } from "drizzle-orm";
27826
28209
  async function getPhaseActiveMs(db, itemId2, phaseIdx) {
27827
28210
  const [row] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
27828
- and22(eq43(phaseUsage.itemId, itemId2), eq43(phaseUsage.phaseIdx, phaseIdx))
28211
+ and23(eq44(phaseUsage.itemId, itemId2), eq44(phaseUsage.phaseIdx, phaseIdx))
27829
28212
  );
27830
28213
  return row?.activeMs ?? 0;
27831
28214
  }
@@ -28336,17 +28719,17 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
28336
28719
  }
28337
28720
 
28338
28721
  // src/shared/db/recordWindowTokens.ts
28339
- import { and as and23, eq as eq44, sql as sql24 } from "drizzle-orm";
28722
+ import { and as and24, eq as eq45, sql as sql24 } from "drizzle-orm";
28340
28723
  async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
28341
28724
  if (tokensUp <= 0 && tokensDown <= 0) return;
28342
28725
  await db.update(usagePeaks).set({
28343
28726
  tokensUp: sql24`${usagePeaks.tokensUp} + ${tokensUp}`,
28344
28727
  tokensDown: sql24`${usagePeaks.tokensDown} + ${tokensDown}`
28345
28728
  }).where(
28346
- and23(
28347
- eq44(usagePeaks.window, window),
28348
- eq44(usagePeaks.resetsAt, resetsAt),
28349
- eq44(usagePeaks.segment, 0)
28729
+ and24(
28730
+ eq45(usagePeaks.window, window),
28731
+ eq45(usagePeaks.resetsAt, resetsAt),
28732
+ eq45(usagePeaks.segment, 0)
28350
28733
  )
28351
28734
  );
28352
28735
  }