@staff0rd/assist 0.399.0 → 0.401.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.399.0",
9
+ version: "0.401.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -429,7 +429,7 @@ function getTranscriptConfig() {
429
429
  }
430
430
 
431
431
  // src/shared/db/schema.ts
432
- import { integer as integer14, pgTable as pgTable14, text as text14 } from "drizzle-orm/pg-core";
432
+ import { integer as integer15, pgTable as pgTable15, text as text15 } from "drizzle-orm/pg-core";
433
433
 
434
434
  // src/shared/db/backups.ts
435
435
  import { bigint, integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
@@ -562,74 +562,99 @@ var phaseCycleContext = pgTable8(
562
562
  ]
563
563
  );
564
564
 
565
- // src/shared/db/phaseUsage.ts
565
+ // src/shared/db/phaseSessions.ts
566
566
  import {
567
- bigint as bigint3,
568
- doublePrecision as doublePrecision2,
569
567
  integer as integer9,
570
568
  pgTable as pgTable9,
571
569
  primaryKey as primaryKey5,
572
- text as text9
570
+ text as text9,
571
+ timestamp as timestamp4
573
572
  } from "drizzle-orm/pg-core";
574
- var phaseUsage = pgTable9(
575
- "phase_usage",
573
+ var phaseSessions = pgTable9(
574
+ "phase_sessions",
576
575
  {
577
- itemId: integer9("item_id").notNull(),
576
+ itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
578
577
  phaseIdx: integer9("phase_idx").notNull(),
578
+ claudeSessionId: text9("claude_session_id").notNull(),
579
+ hostname: text9().notNull(),
580
+ osUser: text9("os_user").notNull(),
581
+ createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
582
+ },
583
+ (t) => [
584
+ primaryKey5({
585
+ columns: [t.itemId, t.phaseIdx, t.claudeSessionId]
586
+ })
587
+ ]
588
+ );
589
+
590
+ // src/shared/db/phaseUsage.ts
591
+ import {
592
+ bigint as bigint3,
593
+ doublePrecision as doublePrecision2,
594
+ integer as integer10,
595
+ pgTable as pgTable10,
596
+ primaryKey as primaryKey6,
597
+ text as text10
598
+ } from "drizzle-orm/pg-core";
599
+ var phaseUsage = pgTable10(
600
+ "phase_usage",
601
+ {
602
+ itemId: integer10("item_id").notNull(),
603
+ phaseIdx: integer10("phase_idx").notNull(),
579
604
  tokensUp: bigint3("tokens_up", { mode: "number" }).notNull().default(0),
580
605
  tokensDown: bigint3("tokens_down", { mode: "number" }).notNull().default(0),
581
606
  activeMs: bigint3("active_ms", { mode: "number" }).notNull().default(0),
582
607
  peakContextPct: doublePrecision2("peak_context_pct").notNull().default(0),
583
608
  lastTotalIn: bigint3("last_total_in", { mode: "number" }),
584
609
  lastTotalOut: bigint3("last_total_out", { mode: "number" }),
585
- claudeSessionId: text9("claude_session_id")
610
+ claudeSessionId: text10("claude_session_id")
586
611
  },
587
- (t) => [primaryKey5({ columns: [t.itemId, t.phaseIdx] })]
612
+ (t) => [primaryKey6({ columns: [t.itemId, t.phaseIdx] })]
588
613
  );
589
614
 
590
615
  // src/shared/db/phaseUsageMessages.ts
591
- import { integer as integer10, pgTable as pgTable10, primaryKey as primaryKey6, text as text10 } from "drizzle-orm/pg-core";
592
- var phaseUsageMessages = pgTable10(
616
+ import { integer as integer11, pgTable as pgTable11, primaryKey as primaryKey7, text as text11 } from "drizzle-orm/pg-core";
617
+ var phaseUsageMessages = pgTable11(
593
618
  "phase_usage_messages",
594
619
  {
595
- itemId: integer10("item_id").notNull(),
596
- phaseIdx: integer10("phase_idx").notNull(),
597
- messageId: text10("message_id").notNull()
620
+ itemId: integer11("item_id").notNull(),
621
+ phaseIdx: integer11("phase_idx").notNull(),
622
+ messageId: text11("message_id").notNull()
598
623
  },
599
- (t) => [primaryKey6({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
624
+ (t) => [primaryKey7({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
600
625
  );
601
626
 
602
627
  // src/shared/db/planPhases.ts
603
- import { integer as integer11, pgTable as pgTable11, primaryKey as primaryKey7, text as text11 } from "drizzle-orm/pg-core";
604
- var planPhases = pgTable11(
628
+ import { integer as integer12, pgTable as pgTable12, primaryKey as primaryKey8, text as text12 } from "drizzle-orm/pg-core";
629
+ var planPhases = pgTable12(
605
630
  "plan_phases",
606
631
  {
607
- itemId: integer11("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
608
- idx: integer11().notNull(),
609
- name: text11().notNull(),
610
- manualChecks: text11("manual_checks")
632
+ itemId: integer12("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
633
+ idx: integer12().notNull(),
634
+ name: text12().notNull(),
635
+ manualChecks: text12("manual_checks")
611
636
  },
612
- (t) => [primaryKey7({ columns: [t.itemId, t.idx] })]
637
+ (t) => [primaryKey8({ columns: [t.itemId, t.idx] })]
613
638
  );
614
639
 
615
640
  // src/shared/db/planTasks.ts
616
641
  import {
617
642
  foreignKey,
618
- integer as integer12,
619
- pgTable as pgTable12,
620
- primaryKey as primaryKey8,
621
- text as text12
643
+ integer as integer13,
644
+ pgTable as pgTable13,
645
+ primaryKey as primaryKey9,
646
+ text as text13
622
647
  } from "drizzle-orm/pg-core";
623
- var planTasks = pgTable12(
648
+ var planTasks = pgTable13(
624
649
  "plan_tasks",
625
650
  {
626
- itemId: integer12("item_id").notNull(),
627
- phaseIdx: integer12("phase_idx").notNull(),
628
- idx: integer12().notNull(),
629
- task: text12().notNull()
651
+ itemId: integer13("item_id").notNull(),
652
+ phaseIdx: integer13("phase_idx").notNull(),
653
+ idx: integer13().notNull(),
654
+ task: text13().notNull()
630
655
  },
631
656
  (t) => [
632
- primaryKey8({ columns: [t.itemId, t.phaseIdx, t.idx] }),
657
+ primaryKey9({ columns: [t.itemId, t.phaseIdx, t.idx] }),
633
658
  foreignKey({
634
659
  columns: [t.itemId, t.phaseIdx],
635
660
  foreignColumns: [planPhases.itemId, planPhases.idx]
@@ -642,35 +667,35 @@ import {
642
667
  bigint as bigint4,
643
668
  boolean as boolean2,
644
669
  doublePrecision as doublePrecision3,
645
- integer as integer13,
646
- pgTable as pgTable13,
647
- primaryKey as primaryKey9,
648
- text as text13,
649
- timestamp as timestamp4
670
+ integer as integer14,
671
+ pgTable as pgTable14,
672
+ primaryKey as primaryKey10,
673
+ text as text14,
674
+ timestamp as timestamp5
650
675
  } from "drizzle-orm/pg-core";
651
- var usagePeaks = pgTable13(
676
+ var usagePeaks = pgTable14(
652
677
  "usage_peaks",
653
678
  {
654
- window: text13().$type().notNull(),
679
+ window: text14().$type().notNull(),
655
680
  resetsAt: bigint4("resets_at", { mode: "number" }).notNull(),
656
- segment: integer13().notNull().default(0),
681
+ segment: integer14().notNull().default(0),
657
682
  usedPercentage: doublePrecision3("used_percentage").notNull(),
658
683
  resetDetected: boolean2("reset_detected").notNull().default(false),
659
684
  tokensUp: bigint4("tokens_up", { mode: "number" }).notNull().default(0),
660
685
  tokensDown: bigint4("tokens_down", { mode: "number" }).notNull().default(0),
661
- createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
686
+ createdAt: timestamp5("created_at", { withTimezone: true }).notNull().defaultNow()
662
687
  },
663
- (t) => [primaryKey9({ columns: [t.window, t.resetsAt, t.segment] })]
688
+ (t) => [primaryKey10({ columns: [t.window, t.resetsAt, t.segment] })]
664
689
  );
665
690
 
666
691
  // src/shared/db/schema.ts
667
- var metadata = pgTable14("metadata", {
668
- key: text14().primaryKey(),
669
- value: text14().notNull()
692
+ var metadata = pgTable15("metadata", {
693
+ key: text15().primaryKey(),
694
+ value: text15().notNull()
670
695
  });
671
- var feeds = pgTable14("feeds", {
672
- id: integer14().generatedByDefaultAsIdentity().primaryKey(),
673
- url: text14().notNull().unique()
696
+ var feeds = pgTable15("feeds", {
697
+ id: integer15().generatedByDefaultAsIdentity().primaryKey(),
698
+ url: text15().notNull().unique()
674
699
  });
675
700
  var schema = {
676
701
  items,
@@ -687,7 +712,8 @@ var schema = {
687
712
  backups,
688
713
  phaseUsage,
689
714
  phaseUsageMessages,
690
- phaseCycleContext
715
+ phaseCycleContext,
716
+ phaseSessions
691
717
  };
692
718
 
693
719
  // src/commands/backlog/addFeed.ts
@@ -1055,12 +1081,47 @@ var migration0004DropUsagePeaksContext = {
1055
1081
  sql: sql5
1056
1082
  };
1057
1083
 
1084
+ // src/shared/db/migrations/migration0005PhaseSessions.ts
1085
+ var sql6 = `
1086
+ CREATE TABLE IF NOT EXISTS phase_sessions (
1087
+ item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
1088
+ phase_idx INTEGER NOT NULL,
1089
+ claude_session_id TEXT NOT NULL,
1090
+ hostname TEXT NOT NULL,
1091
+ os_user TEXT NOT NULL,
1092
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
1093
+ PRIMARY KEY (item_id, phase_idx, claude_session_id)
1094
+ );
1095
+ `;
1096
+ var migration0005PhaseSessions = {
1097
+ id: 5,
1098
+ name: "phase-sessions",
1099
+ sql: sql6
1100
+ };
1101
+
1102
+ // src/shared/db/migrations/migration0006BackfillPhaseSessions.ts
1103
+ var sql7 = `
1104
+ INSERT INTO phase_sessions (item_id, phase_idx, claude_session_id, hostname, os_user)
1105
+ SELECT pu.item_id, pu.phase_idx, pu.claude_session_id, 'unknown', 'unknown'
1106
+ FROM phase_usage pu
1107
+ WHERE pu.claude_session_id IS NOT NULL
1108
+ AND EXISTS (SELECT 1 FROM items i WHERE i.id = pu.item_id)
1109
+ ON CONFLICT (item_id, phase_idx, claude_session_id) DO NOTHING;
1110
+ `;
1111
+ var migration0006BackfillPhaseSessions = {
1112
+ id: 6,
1113
+ name: "backfill-phase-sessions",
1114
+ sql: sql7
1115
+ };
1116
+
1058
1117
  // src/shared/db/migrations/index.ts
1059
1118
  var migrations = [
1060
1119
  migration0001Baseline,
1061
1120
  migration0002UsagePeaksContext,
1062
1121
  migration0003PhaseCycleContext,
1063
- migration0004DropUsagePeaksContext
1122
+ migration0004DropUsagePeaksContext,
1123
+ migration0005PhaseSessions,
1124
+ migration0006BackfillPhaseSessions
1064
1125
  ];
1065
1126
  var latestMigrationId = migrations.reduce(
1066
1127
  (max, m) => Math.max(max, m.id),
@@ -1143,8 +1204,8 @@ async function assertMigrationsInSync(exec3) {
1143
1204
  // src/shared/db/migrations/MigrationExecutor.ts
1144
1205
  function pgExecutor(queryable) {
1145
1206
  return {
1146
- exec: (sql20) => queryable.query(sql20),
1147
- query: async (sql20, params) => (await queryable.query(sql20, params)).rows
1207
+ exec: (sql23) => queryable.query(sql23),
1208
+ query: async (sql23, params) => (await queryable.query(sql23, params)).rows
1148
1209
  };
1149
1210
  }
1150
1211
 
@@ -2879,8 +2940,8 @@ function isBicepFile(filePath) {
2879
2940
  }
2880
2941
 
2881
2942
  // src/commands/verify/blockComments/collectBicepComments.ts
2882
- function blankNonNewline(text16) {
2883
- return text16.replace(/[^\n]/g, " ");
2943
+ function blankNonNewline(text17) {
2944
+ return text17.replace(/[^\n]/g, " ");
2884
2945
  }
2885
2946
  var STRING_LITERAL = /'''[\s\S]*?'''|'(?:[^'\\]|\\.)*'/g;
2886
2947
  var BLOCK_COMMENT = /\/\*[\s\S]*?\*[/]/g;
@@ -2902,8 +2963,8 @@ function collectBicepComments(content) {
2902
2963
  }
2903
2964
 
2904
2965
  // src/commands/verify/blockComments/collectHashComments.ts
2905
- function blankNonNewline2(text16) {
2906
- return text16.replace(/[^\n]/g, " ");
2966
+ function blankNonNewline2(text17) {
2967
+ return text17.replace(/[^\n]/g, " ");
2907
2968
  }
2908
2969
  function isHeaderLine(line) {
2909
2970
  const trimmed = line.trim();
@@ -2980,23 +3041,23 @@ var MACHINE_DIRECTIVES = [
2980
3041
  "@vitest-environment",
2981
3042
  MAINTAINABILITY_OVERRIDE_MARKER
2982
3043
  ];
2983
- function isCommentExempt(text16) {
2984
- const lower = text16.toLowerCase();
3044
+ function isCommentExempt(text17) {
3045
+ const lower = text17.toLowerCase();
2985
3046
  return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
2986
3047
  }
2987
3048
 
2988
3049
  // src/commands/verify/blockComments/collectSourceFindings.ts
2989
- function toSingleLine(text16) {
2990
- return text16.replace(/\s+/g, " ").trim();
3050
+ function toSingleLine(text17) {
3051
+ return text17.replace(/\s+/g, " ").trim();
2991
3052
  }
2992
3053
  function collectSourceFindings(file, lines, project) {
2993
3054
  const findings = [];
2994
3055
  const sourceFile = project.addSourceFileAtPath(file);
2995
- for (const { pos, text: text16 } of collectComments(sourceFile)) {
3056
+ for (const { pos, text: text17 } of collectComments(sourceFile)) {
2996
3057
  const { line } = sourceFile.getLineAndColumnAtPos(pos);
2997
3058
  if (!lines.has(line)) continue;
2998
- if (isCommentExempt(text16)) continue;
2999
- findings.push({ file, line, text: toSingleLine(text16) });
3059
+ if (isCommentExempt(text17)) continue;
3060
+ findings.push({ file, line, text: toSingleLine(text17) });
3000
3061
  }
3001
3062
  return findings;
3002
3063
  }
@@ -3016,10 +3077,10 @@ function collectYamlComments(content) {
3016
3077
  // src/commands/verify/blockComments/collectFileComments.ts
3017
3078
  function toFindings(file, lines, raw, exempt) {
3018
3079
  const findings = [];
3019
- for (const { line, text: text16 } of raw) {
3080
+ for (const { line, text: text17 } of raw) {
3020
3081
  if (!lines.has(line)) continue;
3021
- if (exempt && isCommentExempt(text16)) continue;
3022
- findings.push({ file, line, text: text16.replace(/\s+/g, " ").trim() });
3082
+ if (exempt && isCommentExempt(text17)) continue;
3083
+ findings.push({ file, line, text: text17.replace(/\s+/g, " ").trim() });
3023
3084
  }
3024
3085
  return findings;
3025
3086
  }
@@ -3121,8 +3182,8 @@ function blockComments() {
3121
3182
  process.exit(0);
3122
3183
  }
3123
3184
  console.log("Comments on changed lines:\n");
3124
- for (const { file, line, text: text16 } of findings) {
3125
- console.log(`${file}:${line} \u2192 ${text16}`);
3185
+ for (const { file, line, text: text17 } of findings) {
3186
+ console.log(`${file}:${line} \u2192 ${text17}`);
3126
3187
  }
3127
3188
  console.log(`
3128
3189
  Total: ${findings.length} comment(s)`);
@@ -4580,8 +4641,8 @@ async function buildDump(tables, copyOut) {
4580
4641
  // src/commands/backlog/dump/copyTableOut.ts
4581
4642
  import { to as copyTo } from "pg-copy-streams";
4582
4643
  async function copyTableOut(client, table) {
4583
- const sql20 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
4584
- const stream = client.query(copyTo(sql20));
4644
+ const sql23 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
4645
+ const stream = client.query(copyTo(sql23));
4585
4646
  const chunks = [];
4586
4647
  for await (const chunk of stream) {
4587
4648
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
@@ -4693,8 +4754,8 @@ async function backup({ out }) {
4693
4754
  const dir = expandTilde2(out ?? loadConfig().backup.dir);
4694
4755
  await mkdir2(dir, { recursive: true });
4695
4756
  const start3 = Date.now();
4696
- const timestamp5 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4697
- const filePath = resolve6(join11(dir, `backup-${timestamp5}.dump`));
4757
+ const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
4758
+ const filePath = resolve6(join11(dir, `backup-${timestamp6}.dump`));
4698
4759
  await exportBacklog(filePath);
4699
4760
  const { size } = await stat(filePath);
4700
4761
  const durationMs = Date.now() - start3;
@@ -5127,11 +5188,11 @@ import { promisify } from "util";
5127
5188
  // src/shared/withSpinner.ts
5128
5189
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5129
5190
  var TICK_MS = 80;
5130
- async function withSpinner(text16, task) {
5191
+ async function withSpinner(text17, task) {
5131
5192
  if (!process.stderr.isTTY) return task();
5132
5193
  let frame = 0;
5133
5194
  const render = () => {
5134
- process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text16}`);
5195
+ process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text17}`);
5135
5196
  };
5136
5197
  render();
5137
5198
  const timer = setInterval(() => {
@@ -5398,6 +5459,11 @@ var relationQueries = {
5398
5459
  ),
5399
5460
  subtasks: (orm, ids) => orm.select().from(itemSubtasks).where(inArray(itemSubtasks.itemId, ids)).orderBy(asc2(itemSubtasks.itemId), asc2(itemSubtasks.idx)),
5400
5461
  usage: (orm, ids) => orm.select().from(phaseUsage).where(inArray(phaseUsage.itemId, ids)).orderBy(asc2(phaseUsage.itemId), asc2(phaseUsage.phaseIdx)),
5462
+ sessions: (orm, ids) => orm.select().from(phaseSessions).where(inArray(phaseSessions.itemId, ids)).orderBy(
5463
+ asc2(phaseSessions.itemId),
5464
+ asc2(phaseSessions.phaseIdx),
5465
+ asc2(phaseSessions.createdAt)
5466
+ ),
5401
5467
  gitRefs: (orm, ids) => orm.select().from(itemGitRefs).where(inArray(itemGitRefs.itemId, ids)).orderBy(asc2(itemGitRefs.itemId), asc2(itemGitRefs.createdAt))
5402
5468
  };
5403
5469
 
@@ -5416,6 +5482,7 @@ async function loadRelations(orm, ids, {
5416
5482
  taskRows,
5417
5483
  subtaskRows,
5418
5484
  usageRows,
5485
+ sessionRows,
5419
5486
  gitRefRows
5420
5487
  ] = await Promise.all([
5421
5488
  includeComments ? relationQueries.comments(orm, ids) : [],
@@ -5424,6 +5491,7 @@ async function loadRelations(orm, ids, {
5424
5491
  includeTasks ? relationQueries.tasks(orm, ids) : [],
5425
5492
  includeSubtasks ? relationQueries.subtasks(orm, ids) : [],
5426
5493
  includeUsage ? relationQueries.usage(orm, ids) : [],
5494
+ includeUsage ? relationQueries.sessions(orm, ids) : [],
5427
5495
  includeGitRefs ? relationQueries.gitRefs(orm, ids) : []
5428
5496
  ]);
5429
5497
  return {
@@ -5433,6 +5501,7 @@ async function loadRelations(orm, ids, {
5433
5501
  tasks: groupByItem(taskRows),
5434
5502
  subtasks: groupByItem(subtaskRows),
5435
5503
  usage: groupByItem(usageRows),
5504
+ sessions: groupByItem(sessionRows),
5436
5505
  gitRefs: groupByItem(gitRefRows)
5437
5506
  };
5438
5507
  }
@@ -5454,6 +5523,20 @@ function attachGitRefs(item, rel, id) {
5454
5523
  if (gitRefs.length > 0) item.gitRefs = gitRefs;
5455
5524
  }
5456
5525
 
5526
+ // src/commands/backlog/attachSessions.ts
5527
+ function rowToSession(s) {
5528
+ return {
5529
+ phaseIdx: s.phaseIdx,
5530
+ claudeSessionId: s.claudeSessionId,
5531
+ hostname: s.hostname,
5532
+ osUser: s.osUser
5533
+ };
5534
+ }
5535
+ function attachSessions(item, rel, id) {
5536
+ const sessions = (rel.sessions.get(id) ?? []).map(rowToSession);
5537
+ if (sessions.length > 0) item.phaseSessions = sessions;
5538
+ }
5539
+
5457
5540
  // src/commands/backlog/attachSubtasks.ts
5458
5541
  function rowToSubtask(s) {
5459
5542
  const subtask = {
@@ -5573,6 +5656,7 @@ function rowToItem(row, rel) {
5573
5656
  attachLinks(item, rel, row.id);
5574
5657
  attachPlan(item, rel, row.id);
5575
5658
  attachUsage(item, rel, row.id);
5659
+ attachSessions(item, rel, row.id);
5576
5660
  attachGitRefs(item, rel, row.id);
5577
5661
  return item;
5578
5662
  }
@@ -5611,6 +5695,12 @@ var phaseUsageSchema = z3.strictObject({
5611
5695
  activeMs: z3.number(),
5612
5696
  peakContextPct: z3.number()
5613
5697
  });
5698
+ var phaseSessionSchema = z3.strictObject({
5699
+ phaseIdx: z3.number(),
5700
+ claudeSessionId: z3.string(),
5701
+ hostname: z3.string(),
5702
+ osUser: z3.string()
5703
+ });
5614
5704
  var phaseUsageTotalSchema = z3.strictObject({
5615
5705
  tokensUp: z3.number(),
5616
5706
  tokensDown: z3.number(),
@@ -5659,6 +5749,7 @@ var backlogItemSchema = z3.strictObject({
5659
5749
  subtasks: z3.array(subtaskSchema).optional(),
5660
5750
  links: z3.array(backlogLinkSchema).optional(),
5661
5751
  phaseUsage: z3.array(phaseUsageSchema).optional(),
5752
+ phaseSessions: z3.array(phaseSessionSchema).optional(),
5662
5753
  usageTotal: phaseUsageTotalSchema.optional(),
5663
5754
  gitRefs: z3.array(gitRefSchema).optional(),
5664
5755
  origin: z3.string().optional(),
@@ -5816,13 +5907,13 @@ async function loadItem(orm, id) {
5816
5907
  }
5817
5908
 
5818
5909
  // src/commands/backlog/saveAllItems.ts
5819
- import { eq as eq7, sql as sql6 } from "drizzle-orm";
5910
+ import { eq as eq7, sql as sql8 } from "drizzle-orm";
5820
5911
 
5821
5912
  // src/commands/backlog/deleteItemRelations.ts
5822
5913
  import { eq as eq6 } from "drizzle-orm";
5823
5914
 
5824
5915
  // src/commands/backlog/searchItemIds.ts
5825
- import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql7 } from "drizzle-orm";
5916
+ import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql9 } from "drizzle-orm";
5826
5917
  async function searchItemIds(orm, query, origin) {
5827
5918
  const pattern2 = `%${query}%`;
5828
5919
  const numberPattern = `%${query.replace(/^#/, "")}%`;
@@ -5836,7 +5927,7 @@ async function searchItemIds(orm, query, origin) {
5836
5927
  ilike(items.jiraKey, pattern2),
5837
5928
  ilike(comments.text, pattern2),
5838
5929
  ilike(planPhases.name, pattern2),
5839
- ilike(sql7`${items.id}::text`, numberPattern)
5930
+ ilike(sql9`${items.id}::text`, numberPattern)
5840
5931
  )
5841
5932
  )
5842
5933
  ).orderBy(asc4(items.id));
@@ -5960,12 +6051,12 @@ async function findPhaseBySessionId(db, itemId2, claudeSessionId) {
5960
6051
  }
5961
6052
 
5962
6053
  // src/commands/backlog/appendComment.ts
5963
- import { sql as sql8 } from "drizzle-orm";
5964
- async function appendComment(orm, itemId2, text16, opts = {}) {
6054
+ import { sql as sql10 } from "drizzle-orm";
6055
+ async function appendComment(orm, itemId2, text17, opts = {}) {
5965
6056
  await orm.insert(comments).values({
5966
6057
  itemId: itemId2,
5967
- idx: sql8`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
5968
- text: text16,
6058
+ idx: sql10`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
6059
+ text: text17,
5969
6060
  phase: opts.phase ?? null,
5970
6061
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5971
6062
  type: opts.type ?? "comment"
@@ -6413,6 +6504,43 @@ function launchPhaseSession(item, phaseNumber, phase, phaseLabel2, claudeSession
6413
6504
  );
6414
6505
  }
6415
6506
 
6507
+ // src/commands/backlog/persistPhaseSession.ts
6508
+ import os from "os";
6509
+
6510
+ // src/shared/db/recordPhaseSession.ts
6511
+ import { sql as sql11 } from "drizzle-orm";
6512
+ async function recordPhaseSession(db, itemId2, phaseIdx, claudeSessionId, hostname, osUser) {
6513
+ await db.insert(phaseSessions).values({ itemId: itemId2, phaseIdx, claudeSessionId, hostname, osUser }).onConflictDoUpdate({
6514
+ target: [
6515
+ phaseSessions.itemId,
6516
+ phaseSessions.phaseIdx,
6517
+ phaseSessions.claudeSessionId
6518
+ ],
6519
+ set: { hostname, osUser },
6520
+ setWhere: sql11`${phaseSessions.hostname} = 'unknown'`
6521
+ });
6522
+ }
6523
+
6524
+ // src/commands/backlog/persistPhaseSession.ts
6525
+ async function persistPhaseSession(itemId2, phaseIdx, claudeSessionId) {
6526
+ try {
6527
+ const { orm } = await getReady();
6528
+ await recordPhaseSession(
6529
+ orm,
6530
+ itemId2,
6531
+ phaseIdx,
6532
+ claudeSessionId,
6533
+ os.hostname(),
6534
+ os.userInfo().username
6535
+ );
6536
+ } catch (error) {
6537
+ console.error(
6538
+ `Failed to record phase session for item ${itemId2} phase ${phaseIdx}:`,
6539
+ error
6540
+ );
6541
+ }
6542
+ }
6543
+
6416
6544
  // src/shared/db/recordPhaseSessionId.ts
6417
6545
  async function recordPhaseSessionId(db, itemId2, phaseIdx, claudeSessionId) {
6418
6546
  await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, claudeSessionId }).onConflictDoUpdate({
@@ -6557,7 +6685,7 @@ import * as path24 from "path";
6557
6685
 
6558
6686
  // src/commands/sessions/shared/discoverSessions.ts
6559
6687
  import * as fs17 from "fs";
6560
- import * as os from "os";
6688
+ import * as os2 from "os";
6561
6689
  import * as path23 from "path";
6562
6690
 
6563
6691
  // src/commands/sessions/shared/parseSessionFile.ts
@@ -6592,8 +6720,8 @@ function deriveSessionType(commandName, name) {
6592
6720
  }
6593
6721
 
6594
6722
  // src/commands/sessions/shared/backlogRunMarkers.ts
6595
- function backlogRunMarkers(text16) {
6596
- const match = text16.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
6723
+ function backlogRunMarkers(text17) {
6724
+ const match = text17.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
6597
6725
  if (!match) return { commandName: "", commandArgs: "" };
6598
6726
  const title = match[2].trim();
6599
6727
  return {
@@ -6606,7 +6734,7 @@ function backlogRunMarkers(text16) {
6606
6734
  function extractSessionMeta(lines) {
6607
6735
  let sessionId = "";
6608
6736
  let cwd = "";
6609
- let timestamp5 = "";
6737
+ let timestamp6 = "";
6610
6738
  let name = "";
6611
6739
  let commandName = "";
6612
6740
  let commandArgs = "";
@@ -6614,14 +6742,14 @@ function extractSessionMeta(lines) {
6614
6742
  const entry = safeParse(line);
6615
6743
  if (!entry) continue;
6616
6744
  sessionId ||= strField(entry, "sessionId");
6617
- timestamp5 ||= strField(entry, "timestamp");
6745
+ timestamp6 ||= strField(entry, "timestamp");
6618
6746
  cwd ||= strField(entry, "cwd");
6619
6747
  if (entry.type === "user" && !entry.isMeta) {
6620
6748
  ({ name, commandName, commandArgs } = parseFirstUserEntry(entry));
6621
6749
  break;
6622
6750
  }
6623
6751
  }
6624
- return { sessionId, cwd, timestamp: timestamp5, name, commandName, commandArgs };
6752
+ return { sessionId, cwd, timestamp: timestamp6, name, commandName, commandArgs };
6625
6753
  }
6626
6754
  function parseFirstUserEntry(entry) {
6627
6755
  const raw = messageText(entry);
@@ -6647,11 +6775,11 @@ function messageText(entry) {
6647
6775
  const content = msg?.content;
6648
6776
  return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
6649
6777
  }
6650
- function stripMarkers(text16) {
6651
- return text16.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
6778
+ function stripMarkers(text17) {
6779
+ return text17.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
6652
6780
  }
6653
- function matchMarker(text16, tag) {
6654
- const match = text16.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
6781
+ function matchMarker(text17, tag) {
6782
+ const match = text17.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
6655
6783
  return match ? match[1].trim() : "";
6656
6784
  }
6657
6785
 
@@ -6662,13 +6790,13 @@ async function parseSessionFile(filePath, origin = "wsl") {
6662
6790
  handle = await fs16.promises.open(filePath, "r");
6663
6791
  const meta = extractSessionMeta(await readHeadLines(handle));
6664
6792
  if (!meta.sessionId) return null;
6665
- const timestamp5 = meta.timestamp || (await fs16.promises.stat(filePath)).mtime.toISOString();
6793
+ const timestamp6 = meta.timestamp || (await fs16.promises.stat(filePath)).mtime.toISOString();
6666
6794
  return {
6667
6795
  sessionId: meta.sessionId,
6668
6796
  name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
6669
6797
  project: deriveProject(meta.cwd, filePath, origin),
6670
6798
  cwd: meta.cwd,
6671
- timestamp: timestamp5,
6799
+ timestamp: timestamp6,
6672
6800
  origin,
6673
6801
  ...deriveHistoryFields(meta.commandName, meta.commandArgs, meta.name)
6674
6802
  };
@@ -6696,7 +6824,7 @@ function dirNameToProject(filePath) {
6696
6824
  // src/commands/sessions/shared/discoverSessions.ts
6697
6825
  function sessionRoots() {
6698
6826
  const roots = [
6699
- { dir: path23.join(os.homedir(), ".claude", "projects"), origin: "wsl" }
6827
+ { dir: path23.join(os2.homedir(), ".claude", "projects"), origin: "wsl" }
6700
6828
  ];
6701
6829
  const windowsRoot = loadConfig().sessions?.windowsProjectsRoot;
6702
6830
  if (windowsRoot) roots.push({ dir: windowsRoot, origin: "windows" });
@@ -6811,6 +6939,7 @@ async function executePhase(item, phaseIndex, phases, spawnOptions, totalPhases
6811
6939
  if (!resumeSessionId) {
6812
6940
  await persistPhaseSessionId(item.id, phaseIndex, claudeSessionId);
6813
6941
  }
6942
+ await persistPhaseSession(item.id, phaseIndex, claudeSessionId);
6814
6943
  const exitCode = await launchPhaseSession(
6815
6944
  item,
6816
6945
  phaseNumber,
@@ -7113,7 +7242,7 @@ function formatComment(entry) {
7113
7242
  // src/shared/renderMarkdownTerminal.ts
7114
7243
  import { Marked } from "marked";
7115
7244
  import { markedTerminal } from "marked-terminal";
7116
- function renderMarkdownTerminal(text16) {
7245
+ function renderMarkdownTerminal(text17) {
7117
7246
  const width = process.stdout.columns || 80;
7118
7247
  const marked = new Marked(markedTerminal({ width, reflowText: true }));
7119
7248
  marked.use({
@@ -7126,7 +7255,7 @@ function renderMarkdownTerminal(text16) {
7126
7255
  }
7127
7256
  }
7128
7257
  });
7129
- return marked.parse(text16).trimEnd();
7258
+ return marked.parse(text17).trimEnd();
7130
7259
  }
7131
7260
 
7132
7261
  // src/commands/backlog/show/printActivity.ts
@@ -7146,9 +7275,9 @@ function groupActivityRefs(refs, commitLimit = ACTIVITY_COMMIT_LIMIT) {
7146
7275
  }
7147
7276
 
7148
7277
  // src/commands/backlog/show/printActivity.ts
7149
- function printRef(label2, text16, ref) {
7278
+ function printRef(label2, text17, ref) {
7150
7279
  const url = ref.url ? ` ${chalk50.dim(ref.url)}` : "";
7151
- console.log(` ${chalk50.cyan(label2)} ${text16}${url}`);
7280
+ console.log(` ${chalk50.cyan(label2)} ${text17}${url}`);
7152
7281
  }
7153
7282
  function printActivity(item) {
7154
7283
  const { branches, commits: commits2, prs: prs2, hiddenCommits } = groupActivityRefs(
@@ -7238,17 +7367,38 @@ function phaseHeader(index3, name, isCurrent) {
7238
7367
  const label2 = isCurrent ? chalk53.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk53.bold(`Phase ${phaseNumber}:`)} ${name}`;
7239
7368
  return `${marker}${label2}`;
7240
7369
  }
7241
- function printPhase(phase, index3, isCurrent) {
7370
+ function printPhaseSessions(sessions) {
7371
+ if (sessions.length === 0) return;
7372
+ console.log(` ${chalk53.dim("Sessions:")}`);
7373
+ for (const s of sessions) {
7374
+ console.log(
7375
+ ` ${chalk53.dim(`- ${s.hostname} / ${s.osUser} / ${s.claudeSessionId}`)}`
7376
+ );
7377
+ }
7378
+ }
7379
+ function printPhase(phase, index3, isCurrent, sessions) {
7242
7380
  console.log(phaseHeader(index3, phase.name, isCurrent));
7243
7381
  printPhaseTasks(phase);
7382
+ printPhaseSessions(sessions);
7383
+ }
7384
+ function printReviewSessions(item, planLength) {
7385
+ const sessions = (item.phaseSessions ?? []).filter(
7386
+ (s) => s.phaseIdx >= planLength
7387
+ );
7388
+ if (sessions.length === 0) return;
7389
+ const isCurrent = item.currentPhase === planLength + 1;
7390
+ console.log(phaseHeader(planLength, REVIEW_PHASE_NAME, isCurrent));
7391
+ printPhaseSessions(sessions);
7244
7392
  }
7245
7393
  function printPlan(item) {
7246
7394
  if (!item.plan || item.plan.length === 0) return;
7247
7395
  console.log(chalk53.bold("Plan"));
7248
7396
  for (const [i, phase] of item.plan.entries()) {
7249
7397
  const isCurrent = item.currentPhase === i + 1;
7250
- printPhase(phase, i, isCurrent);
7398
+ const sessions = (item.phaseSessions ?? []).filter((s) => s.phaseIdx === i);
7399
+ printPhase(phase, i, isCurrent, sessions);
7251
7400
  }
7401
+ printReviewSessions(item, item.plan.length);
7252
7402
  console.log();
7253
7403
  }
7254
7404
 
@@ -7600,29 +7750,29 @@ import { eq as eq13 } from "drizzle-orm";
7600
7750
  import { asc as asc5, eq as eq12 } from "drizzle-orm";
7601
7751
 
7602
7752
  // src/commands/backlog/incompleteSubtaskCounts.ts
7603
- import { ne, sql as sql9 } from "drizzle-orm";
7753
+ import { ne, sql as sql12 } from "drizzle-orm";
7604
7754
  function incompleteSubtaskCounts(orm) {
7605
7755
  return orm.select({
7606
7756
  itemId: itemSubtasks.itemId,
7607
- count: sql9`count(*)::int`.as("incomplete_subtasks")
7757
+ count: sql12`count(*)::int`.as("incomplete_subtasks")
7608
7758
  }).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
7609
7759
  }
7610
7760
 
7611
7761
  // src/commands/backlog/phaseUsageTotals.ts
7612
- import { sql as sql10 } from "drizzle-orm";
7762
+ import { sql as sql13 } from "drizzle-orm";
7613
7763
  function phaseUsageTotals(orm) {
7614
7764
  return orm.select({
7615
7765
  itemId: phaseUsage.itemId,
7616
- tokensUp: sql10`sum(${phaseUsage.tokensUp})::bigint`.as(
7766
+ tokensUp: sql13`sum(${phaseUsage.tokensUp})::bigint`.as(
7617
7767
  "total_tokens_up"
7618
7768
  ),
7619
- tokensDown: sql10`sum(${phaseUsage.tokensDown})::bigint`.as(
7769
+ tokensDown: sql13`sum(${phaseUsage.tokensDown})::bigint`.as(
7620
7770
  "total_tokens_down"
7621
7771
  ),
7622
- activeMs: sql10`sum(${phaseUsage.activeMs})::bigint`.as(
7772
+ activeMs: sql13`sum(${phaseUsage.activeMs})::bigint`.as(
7623
7773
  "total_active_ms"
7624
7774
  ),
7625
- peakContextPct: sql10`max(${phaseUsage.peakContextPct})`.as(
7775
+ peakContextPct: sql13`max(${phaseUsage.peakContextPct})`.as(
7626
7776
  "max_peak_context_pct"
7627
7777
  )
7628
7778
  }).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
@@ -8233,7 +8383,7 @@ function runGitStatus(cwd) {
8233
8383
  }
8234
8384
 
8235
8385
  // src/shared/harnesses.ts
8236
- import * as os2 from "os";
8386
+ import * as os3 from "os";
8237
8387
  import * as path25 from "path";
8238
8388
 
8239
8389
  // src/shared/checkCliAvailable.ts
@@ -8262,7 +8412,7 @@ var harnesses = {
8262
8412
  claude: {
8263
8413
  kind: "claude",
8264
8414
  command: "claude",
8265
- homeDir: path25.join(os2.homedir(), ".claude"),
8415
+ homeDir: path25.join(os3.homedir(), ".claude"),
8266
8416
  sync: {
8267
8417
  agentsFile: "CLAUDE.md",
8268
8418
  commandDest: (name) => path25.join("commands", `${name}.md`)
@@ -8271,7 +8421,7 @@ var harnesses = {
8271
8421
  codex: {
8272
8422
  kind: "codex",
8273
8423
  command: "codex",
8274
- homeDir: path25.join(os2.homedir(), ".codex"),
8424
+ homeDir: path25.join(os3.homedir(), ".codex"),
8275
8425
  sync: {
8276
8426
  agentsFile: "AGENTS.md",
8277
8427
  commandDest: (name) => path25.join("skills", name, "SKILL.md")
@@ -8280,7 +8430,7 @@ var harnesses = {
8280
8430
  pi: {
8281
8431
  kind: "pi",
8282
8432
  command: "pi",
8283
- homeDir: path25.join(os2.homedir(), ".pi", "agent"),
8433
+ homeDir: path25.join(os3.homedir(), ".pi", "agent"),
8284
8434
  sync: {
8285
8435
  agentsFile: "AGENTS.md",
8286
8436
  commandDest: (name) => path25.join("prompts", `${name}.md`)
@@ -8380,9 +8530,9 @@ function excerpt(xml, ...tags) {
8380
8530
  for (const tag of tags) {
8381
8531
  const raw = extractText(xml, tag);
8382
8532
  if (!raw) continue;
8383
- const text16 = stripHtml(raw);
8384
- if (text16.length <= MAX_EXCERPT) return text16;
8385
- return `${text16.slice(0, MAX_EXCERPT)}\u2026`;
8533
+ const text17 = stripHtml(raw);
8534
+ if (text17.length <= MAX_EXCERPT) return text17;
8535
+ return `${text17.slice(0, MAX_EXCERPT)}\u2026`;
8386
8536
  }
8387
8537
  return "";
8388
8538
  }
@@ -8460,12 +8610,12 @@ async function listNewsItems(_req, res) {
8460
8610
  }
8461
8611
 
8462
8612
  // src/shared/db/listUsagePeaks.ts
8463
- import { and as and7, count, desc as desc2, eq as eq17, getTableColumns, sql as sql11 } from "drizzle-orm";
8613
+ import { and as and7, count, desc as desc2, eq as eq17, getTableColumns, sql as sql14 } from "drizzle-orm";
8464
8614
  async function listUsagePeaks(db, paging) {
8465
8615
  const avgContext = db.select({
8466
8616
  window: phaseCycleContext.window,
8467
8617
  resetsAt: phaseCycleContext.resetsAt,
8468
- avgContextPct: sql11`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
8618
+ avgContextPct: sql14`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
8469
8619
  "avg_context_pct"
8470
8620
  ),
8471
8621
  phaseCount: count().as("phase_count")
@@ -9314,10 +9464,10 @@ function registerAssociateJiraCommand(cmd) {
9314
9464
 
9315
9465
  // src/commands/backlog/comment/index.ts
9316
9466
  import chalk65 from "chalk";
9317
- async function comment(id, text16) {
9467
+ async function comment(id, text17) {
9318
9468
  const found = await findOneItem(id);
9319
9469
  if (!found) process.exit(1);
9320
- await appendComment(found.orm, found.item.id, text16);
9470
+ await appendComment(found.orm, found.item.id, text17);
9321
9471
  console.log(
9322
9472
  chalk65.green(`Comment added to item ${formatItemId(found.item.id)}.`)
9323
9473
  );
@@ -9422,9 +9572,9 @@ function readLine(dump, start3) {
9422
9572
  return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
9423
9573
  }
9424
9574
  function parseHeader(dump) {
9425
- const { text: text16, next: next3 } = readLine(dump, 0);
9575
+ const { text: text17, next: next3 } = readLine(dump, 0);
9426
9576
  try {
9427
- return { header: JSON.parse(text16), bodyStart: next3 };
9577
+ return { header: JSON.parse(text17), bodyStart: next3 };
9428
9578
  } catch {
9429
9579
  return invalid("header is not valid JSON.");
9430
9580
  }
@@ -9433,9 +9583,9 @@ function parseSections(dump, bodyStart) {
9433
9583
  const sections = /* @__PURE__ */ new Map();
9434
9584
  let cursor = bodyStart;
9435
9585
  while (cursor < dump.length) {
9436
- const { text: text16, next: next3 } = readLine(dump, cursor);
9437
- const match = text16.match(/^@table (\S+) (\d+)$/);
9438
- if (!match) invalid(`malformed table marker "${text16}".`);
9586
+ const { text: text17, next: next3 } = readLine(dump, cursor);
9587
+ const match = text17.match(/^@table (\S+) (\d+)$/);
9588
+ if (!match) invalid(`malformed table marker "${text17}".`);
9439
9589
  const [, name, bytes] = match;
9440
9590
  const end = next3 + Number(bytes);
9441
9591
  if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
@@ -9511,8 +9661,8 @@ async function readStdinBuffer() {
9511
9661
  import { finished } from "stream/promises";
9512
9662
  import { from as copyFrom } from "pg-copy-streams";
9513
9663
  async function copyTableIn(client, table, data) {
9514
- const sql20 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
9515
- const stream = client.query(copyFrom(sql20));
9664
+ const sql23 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
9665
+ const stream = client.query(copyFrom(sql23));
9516
9666
  stream.end(data);
9517
9667
  await finished(stream);
9518
9668
  }
@@ -9557,8 +9707,8 @@ async function replaceData(client, parsed) {
9557
9707
  await copyTableIn(client, table, data);
9558
9708
  }
9559
9709
  for (const col of await introspectIdentityColumns(client)) {
9560
- const { text: text16, values } = resyncIdentitySql(col);
9561
- await client.query(text16, values);
9710
+ const { text: text17, values } = resyncIdentitySql(col);
9711
+ await client.query(text17, values);
9562
9712
  }
9563
9713
  }
9564
9714
  async function restore(client, parsed) {
@@ -9636,11 +9786,11 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
9636
9786
  }
9637
9787
 
9638
9788
  // src/commands/backlog/insertSubtask.ts
9639
- import { sql as sql12 } from "drizzle-orm";
9789
+ import { sql as sql15 } from "drizzle-orm";
9640
9790
  async function insertSubtask(orm, itemId2, title, description) {
9641
9791
  await orm.insert(itemSubtasks).values({
9642
9792
  itemId: itemId2,
9643
- idx: sql12`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
9793
+ idx: sql15`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
9644
9794
  title,
9645
9795
  description: description ?? null,
9646
9796
  status: "todo"
@@ -11459,8 +11609,8 @@ var RAW_BUILTIN_DENIES = [
11459
11609
  regex
11460
11610
  }))
11461
11611
  ];
11462
- function matchBuiltinDeny(text16) {
11463
- return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text16));
11612
+ function matchBuiltinDeny(text17) {
11613
+ return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text17));
11464
11614
  }
11465
11615
  function toDecision(rule) {
11466
11616
  if (!rule) return void 0;
@@ -12181,8 +12331,8 @@ function formatHuman(cli, commands) {
12181
12331
  `];
12182
12332
  for (const cmd of sorted) {
12183
12333
  const full = `${cli} ${cmd.path.join(" ")}`;
12184
- const text16 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
12185
- lines.push(`${prefix(classifyVerb(cmd.path))}${text16}`);
12334
+ const text17 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
12335
+ lines.push(`${prefix(classifyVerb(cmd.path))}${text17}`);
12186
12336
  }
12187
12337
  return lines.join("\n");
12188
12338
  }
@@ -12461,38 +12611,38 @@ import chalk110 from "chalk";
12461
12611
  // src/commands/codeComment/validateCommentText.ts
12462
12612
  var MAX_COMMENT_LENGTH = 50;
12463
12613
  function validateCommentText(raw, isHash = false) {
12464
- const text16 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
12465
- if (/[\r\n]/.test(text16)) {
12614
+ const text17 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
12615
+ if (/[\r\n]/.test(text17)) {
12466
12616
  return {
12467
12617
  ok: false,
12468
12618
  reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
12469
12619
  };
12470
12620
  }
12471
- if (!isHash && (text16.includes("/*") || text16.includes("*/"))) {
12621
+ if (!isHash && (text17.includes("/*") || text17.includes("*/"))) {
12472
12622
  return {
12473
12623
  ok: false,
12474
12624
  reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
12475
12625
  };
12476
12626
  }
12477
- if (text16.length > MAX_COMMENT_LENGTH) {
12627
+ if (text17.length > MAX_COMMENT_LENGTH) {
12478
12628
  return {
12479
12629
  ok: false,
12480
- reason: `Comment text is ${text16.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
12630
+ reason: `Comment text is ${text17.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
12481
12631
  };
12482
12632
  }
12483
- return { ok: true, text: text16 };
12633
+ return { ok: true, text: text17 };
12484
12634
  }
12485
12635
 
12486
12636
  // src/commands/codeComment/issuePin.ts
12487
12637
  import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync25 } from "fs";
12488
12638
  import { randomInt } from "crypto";
12489
- function issuePin(file, lineNumber, text16) {
12639
+ function issuePin(file, lineNumber, text17) {
12490
12640
  const pin = generatePin();
12491
12641
  mkdirSync14(getRestrictedDir(), { recursive: true });
12492
12642
  sweepRestrictedDir();
12493
12643
  writeFileSync25(
12494
12644
  getPinStatePath(pin),
12495
- JSON.stringify({ pin, file, line: lineNumber, text: text16 })
12645
+ JSON.stringify({ pin, file, line: lineNumber, text: text17 })
12496
12646
  );
12497
12647
  return showNotification({
12498
12648
  title: "assist code-comment pin",
@@ -12504,7 +12654,7 @@ function generatePin() {
12504
12654
  }
12505
12655
 
12506
12656
  // src/commands/codeComment/codeCommentSet.ts
12507
- function codeCommentSet(file, line, text16) {
12657
+ function codeCommentSet(file, line, text17) {
12508
12658
  const lineNumber = Number.parseInt(line, 10);
12509
12659
  if (!Number.isInteger(lineNumber) || lineNumber < 1) {
12510
12660
  console.error(chalk110.red(`Invalid line number: ${line}`));
@@ -12513,7 +12663,7 @@ function codeCommentSet(file, line, text16) {
12513
12663
  }
12514
12664
  const hash = isHashCommentFile(file);
12515
12665
  const marker = hash ? "#" : "//";
12516
- const validation = validateCommentText(text16, hash);
12666
+ const validation = validateCommentText(text17, hash);
12517
12667
  if (!validation.ok) {
12518
12668
  console.error(chalk110.red(`Refused: ${validation.reason}`));
12519
12669
  console.error(chalk110.red("No pin issued."));
@@ -14648,12 +14798,12 @@ function isSourceFile(filePath) {
14648
14798
  if (!filePath) return false;
14649
14799
  return SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
14650
14800
  }
14651
- function blankNonNewline3(text16) {
14652
- return text16.replace(/[^\n]/g, " ");
14801
+ function blankNonNewline3(text17) {
14802
+ return text17.replace(/[^\n]/g, " ");
14653
14803
  }
14654
- function extractComments(text16) {
14804
+ function extractComments(text17) {
14655
14805
  const comments3 = [];
14656
- let work = text16.replace(
14806
+ let work = text17.replace(
14657
14807
  /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
14658
14808
  blankNonNewline3
14659
14809
  );
@@ -14668,11 +14818,11 @@ function extractComments(text16) {
14668
14818
  }
14669
14819
 
14670
14820
  // src/commands/editHook/extractYamlComments.ts
14671
- function blankNonNewline4(text16) {
14672
- return text16.replace(/[^\n]/g, " ");
14821
+ function blankNonNewline4(text17) {
14822
+ return text17.replace(/[^\n]/g, " ");
14673
14823
  }
14674
- function extractYamlComments(text16) {
14675
- const work = text16.replace(
14824
+ function extractYamlComments(text17) {
14825
+ const work = text17.replace(
14676
14826
  /"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
14677
14827
  blankNonNewline4
14678
14828
  );
@@ -14688,8 +14838,8 @@ function isHeaderLine2(line) {
14688
14838
  const trimmed = line.trim();
14689
14839
  return trimmed === "" || trimmed.startsWith("#");
14690
14840
  }
14691
- function extractShellComments(text16) {
14692
- const lines = text16.split("\n");
14841
+ function extractShellComments(text17) {
14842
+ const lines = text17.split("\n");
14693
14843
  let firstCodeLine = 0;
14694
14844
  while (firstCodeLine < lines.length && isHeaderLine2(lines[firstCodeLine])) {
14695
14845
  firstCodeLine++;
@@ -15059,9 +15209,9 @@ function registerGithub(program2) {
15059
15209
  }
15060
15210
 
15061
15211
  // src/commands/handover/countPendingHandovers.ts
15062
- import { and as and18, eq as eq36, isNull, sql as sql13 } from "drizzle-orm";
15212
+ import { and as and18, eq as eq36, isNull, sql as sql16 } from "drizzle-orm";
15063
15213
  async function countPendingHandovers(orm, origin) {
15064
- const [row] = await orm.select({ count: sql13`count(*)::int` }).from(handovers).where(and18(eq36(handovers.origin, origin), isNull(handovers.recalledAt)));
15214
+ const [row] = await orm.select({ count: sql16`count(*)::int` }).from(handovers).where(and18(eq36(handovers.origin, origin), isNull(handovers.recalledAt)));
15065
15215
  return row?.count ?? 0;
15066
15216
  }
15067
15217
 
@@ -15284,9 +15434,9 @@ import chalk143 from "chalk";
15284
15434
 
15285
15435
  // src/commands/jira/adfToText.ts
15286
15436
  function renderInline(node) {
15287
- const text16 = node.text ?? "";
15288
- if (node.marks?.some((m) => m.type === "code")) return `\`${text16}\``;
15289
- return text16;
15437
+ const text17 = node.text ?? "";
15438
+ if (node.marks?.some((m) => m.type === "code")) return `\`${text17}\``;
15439
+ return text17;
15290
15440
  }
15291
15441
  function renderChildren(node, indent2) {
15292
15442
  return renderNodes(node.content ?? [], indent2);
@@ -15328,8 +15478,8 @@ function isListNode(node) {
15328
15478
  function renderListChild(child, indent2, pad, marker, isFirst) {
15329
15479
  if (isListNode(child)) return renderNodes([child], indent2 + 1);
15330
15480
  if (child.type !== "paragraph") return renderNode(child, indent2);
15331
- const text16 = renderChildren(child, indent2);
15332
- return isFirst ? `${pad}${marker} ${text16}` : `${pad} ${text16}`;
15481
+ const text17 = renderChildren(child, indent2);
15482
+ return isFirst ? `${pad}${marker} ${text17}` : `${pad} ${text17}`;
15333
15483
  }
15334
15484
  function renderListItem(node, indent2, marker) {
15335
15485
  const pad = " ".repeat(indent2);
@@ -15521,9 +15671,9 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
15521
15671
  "[description]",
15522
15672
  `Text to forward to the /${slashCommand} slash command`
15523
15673
  ).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
15524
- (text16, opts) => launchMode(slashCommand, {
15674
+ (text17, opts) => launchMode(slashCommand, {
15525
15675
  once: opts.once,
15526
- description: text16,
15676
+ description: text17,
15527
15677
  resumeSessionId: opts.resumeSession
15528
15678
  })
15529
15679
  );
@@ -16020,8 +16170,8 @@ function dedupeLinks(links2) {
16020
16170
  }
16021
16171
 
16022
16172
  // src/commands/netcap/linkifyMentions.ts
16023
- function linkifyMentions(text16, mentions) {
16024
- let out = text16;
16173
+ function linkifyMentions(text17, mentions) {
16174
+ let out = text17;
16025
16175
  for (const m of mentions) {
16026
16176
  if (m.name && out.includes(m.name)) {
16027
16177
  out = out.replace(m.name, `[${m.name}](${m.url})`);
@@ -16048,13 +16198,13 @@ function resolveAuthor(mentionMap, author) {
16048
16198
  return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
16049
16199
  }
16050
16200
  function buildPost(raw, mentionMap, author) {
16051
- const text16 = joinText(raw.text);
16052
- if (!text16) return void 0;
16201
+ const text17 = joinText(raw.text);
16202
+ if (!text17) return void 0;
16053
16203
  const mentions = resolveMentions(raw, mentionMap, author);
16054
16204
  const relatedPosts = [...new Set(raw.related)];
16055
16205
  return {
16056
- text: text16,
16057
- markdown: linkifyMentions(text16, mentions),
16206
+ text: text17,
16207
+ markdown: linkifyMentions(text17, mentions),
16058
16208
  mentions,
16059
16209
  hashtags: [...new Set(raw.hashtags)],
16060
16210
  links: dedupeLinks(raw.links),
@@ -16195,8 +16345,8 @@ function activityUrnOf(update3) {
16195
16345
  return typeof urn === "string" ? urn : void 0;
16196
16346
  }
16197
16347
  function buildVoyagerPost(update3, profiles) {
16198
- const text16 = commentaryText(update3);
16199
- if (!text16) return void 0;
16348
+ const text17 = commentaryText(update3);
16349
+ if (!text17) return void 0;
16200
16350
  const author = resolveVoyagerAuthor(update3);
16201
16351
  const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
16202
16352
  update3,
@@ -16205,8 +16355,8 @@ function buildVoyagerPost(update3, profiles) {
16205
16355
  );
16206
16356
  const activityUrn = activityUrnOf(update3);
16207
16357
  return {
16208
- text: text16,
16209
- markdown: linkifyMentions(text16, mentions),
16358
+ text: text17,
16359
+ markdown: linkifyMentions(text17, mentions),
16210
16360
  mentions,
16211
16361
  hashtags,
16212
16362
  links: links2,
@@ -16747,8 +16897,8 @@ function isWallOfText(lines) {
16747
16897
  if (lines.some(isListLine)) {
16748
16898
  return false;
16749
16899
  }
16750
- const text16 = lines.join(" ").trim();
16751
- return text16.length > MAX_PARAGRAPH_CHARS || countSentences(text16) > MAX_PARAGRAPH_SENTENCES;
16900
+ const text17 = lines.join(" ").trim();
16901
+ return text17.length > MAX_PARAGRAPH_CHARS || countSentences(text17) > MAX_PARAGRAPH_SENTENCES;
16752
16902
  }
16753
16903
  function validatePrContent(title, body) {
16754
16904
  if (title.toLowerCase().includes("claude")) {
@@ -18520,9 +18670,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
18520
18670
  function extractTexts(target, allFunctions, statements) {
18521
18671
  const stmtTexts = statements.map((v) => v.getFullText().trim());
18522
18672
  const fnTexts = allFunctions.map((fn) => {
18523
- const text16 = fn.getFullText().trim();
18524
- if (fn === target && !text16.startsWith("export ")) return `export ${text16}`;
18525
- return text16;
18673
+ const text17 = fn.getFullText().trim();
18674
+ if (fn === target && !text17.startsWith("export ")) return `export ${text17}`;
18675
+ return text17;
18526
18676
  });
18527
18677
  return [...stmtTexts, ...fnTexts];
18528
18678
  }
@@ -20373,9 +20523,9 @@ var MultiSpinner = class {
20373
20523
  elapsedPrefix: prefix2
20374
20524
  });
20375
20525
  }
20376
- failRemaining(text16) {
20526
+ failRemaining(text17) {
20377
20527
  for (const entry of this.entries) {
20378
- if (entry.state === "running") this.resolve(entry, "failed", text16);
20528
+ if (entry.state === "running") this.resolve(entry, "failed", text17);
20379
20529
  }
20380
20530
  }
20381
20531
  add(entry) {
@@ -20388,14 +20538,14 @@ var MultiSpinner = class {
20388
20538
  set text(value) {
20389
20539
  entry.text = value;
20390
20540
  },
20391
- succeed: (text16) => this.resolve(entry, "succeeded", text16),
20392
- fail: (text16) => this.resolve(entry, "failed", text16)
20541
+ succeed: (text17) => this.resolve(entry, "succeeded", text17),
20542
+ fail: (text17) => this.resolve(entry, "failed", text17)
20393
20543
  };
20394
20544
  }
20395
- resolve(entry, state, text16) {
20545
+ resolve(entry, state, text17) {
20396
20546
  if (entry.state !== "running") return;
20397
20547
  entry.state = state;
20398
- if (text16 !== void 0) entry.text = text16;
20548
+ if (text17 !== void 0) entry.text = text17;
20399
20549
  entry.elapsedStart = void 0;
20400
20550
  this.render();
20401
20551
  this.maybeFinish();
@@ -20470,12 +20620,12 @@ function skippedCodexResult(outputPath) {
20470
20620
  // src/commands/review/formatReviewerFailure.ts
20471
20621
  var FAST_FAIL_MS = 1e3;
20472
20622
  var STDOUT_TAIL_LINES = 20;
20473
- function indent(text16) {
20474
- return text16.split(/\r?\n/).map((line) => ` ${line}`);
20623
+ function indent(text17) {
20624
+ return text17.split(/\r?\n/).map((line) => ` ${line}`);
20475
20625
  }
20476
- function tailLines(text16, maxLines) {
20477
- const lines = text16.split(/\r?\n/);
20478
- return lines.length <= maxLines ? text16 : lines.slice(-maxLines).join("\n");
20626
+ function tailLines(text17, maxLines) {
20627
+ const lines = text17.split(/\r?\n/);
20628
+ return lines.length <= maxLines ? text17 : lines.slice(-maxLines).join("\n");
20479
20629
  }
20480
20630
  function isFastFail(input) {
20481
20631
  return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
@@ -21410,8 +21560,8 @@ function filterToSql(filter) {
21410
21560
  // src/commands/seq/fetchSeqData.ts
21411
21561
  function buildDataParams(filter, count7, from, to) {
21412
21562
  const sqlFilter = filterToSql(filter);
21413
- const sql20 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count7}`;
21414
- const params = new URLSearchParams({ q: sql20 });
21563
+ const sql23 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count7}`;
21564
+ const params = new URLSearchParams({ q: sql23 });
21415
21565
  if (from) params.set("rangeStartUtc", from);
21416
21566
  if (to) params.set("rangeEndUtc", to);
21417
21567
  return params;
@@ -21672,26 +21822,26 @@ import chalk190 from "chalk";
21672
21822
  // src/commands/sql/loadConnections.ts
21673
21823
  function loadConnections3() {
21674
21824
  const raw = loadGlobalConfigRaw();
21675
- const sql20 = raw.sql;
21676
- return sql20?.connections ?? [];
21825
+ const sql23 = raw.sql;
21826
+ return sql23?.connections ?? [];
21677
21827
  }
21678
21828
  function saveConnections3(connections) {
21679
21829
  const raw = loadGlobalConfigRaw();
21680
- const sql20 = raw.sql ?? {};
21681
- sql20.connections = connections;
21682
- raw.sql = sql20;
21830
+ const sql23 = raw.sql ?? {};
21831
+ sql23.connections = connections;
21832
+ raw.sql = sql23;
21683
21833
  saveGlobalConfig(raw);
21684
21834
  }
21685
21835
  function getDefaultConnection2() {
21686
21836
  const raw = loadGlobalConfigRaw();
21687
- const sql20 = raw.sql;
21688
- return sql20?.defaultConnection;
21837
+ const sql23 = raw.sql;
21838
+ return sql23?.defaultConnection;
21689
21839
  }
21690
21840
  function setDefaultConnection2(name) {
21691
21841
  const raw = loadGlobalConfigRaw();
21692
- const sql20 = raw.sql ?? {};
21693
- sql20.defaultConnection = name;
21694
- raw.sql = sql20;
21842
+ const sql23 = raw.sql ?? {};
21843
+ sql23.defaultConnection = name;
21844
+ raw.sql = sql23;
21695
21845
  saveGlobalConfig(raw);
21696
21846
  }
21697
21847
 
@@ -21762,9 +21912,9 @@ function resolveConnection3(name) {
21762
21912
  }
21763
21913
 
21764
21914
  // src/commands/sql/sqlConnect.ts
21765
- import sql14 from "mssql";
21915
+ import sql17 from "mssql";
21766
21916
  async function sqlConnect(conn) {
21767
- return await sql14.connect({
21917
+ return await sql17.connect({
21768
21918
  server: conn.server,
21769
21919
  port: conn.port,
21770
21920
  user: conn.user,
@@ -21841,11 +21991,11 @@ var MUTATION_PATTERN = new RegExp(
21841
21991
  `\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
21842
21992
  "i"
21843
21993
  );
21844
- function stripComments(sql20) {
21845
- return sql20.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
21994
+ function stripComments(sql23) {
21995
+ return sql23.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
21846
21996
  }
21847
- function isMutation(sql20) {
21848
- const stripped = stripComments(sql20);
21997
+ function isMutation(sql23) {
21998
+ const stripped = stripComments(sql23);
21849
21999
  if (MUTATION_PATTERN.test(stripped)) return true;
21850
22000
  return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
21851
22001
  }
@@ -22044,8 +22194,8 @@ import {
22044
22194
  import { basename as basename13, join as join54 } from "path";
22045
22195
 
22046
22196
  // src/commands/transcript/cleanText.ts
22047
- function cleanText(text16) {
22048
- const words = text16.split(/\s+/);
22197
+ function cleanText(text17) {
22198
+ const words = text17.split(/\s+/);
22049
22199
  const cleaned = [];
22050
22200
  for (let i = 0; i < words.length; i++) {
22051
22201
  let isRepeat = false;
@@ -22065,8 +22215,8 @@ function cleanText(text16) {
22065
22215
  }
22066
22216
 
22067
22217
  // src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
22068
- function normalizeText(text16) {
22069
- return text16.toLowerCase().trim();
22218
+ function normalizeText(text17) {
22219
+ return text17.toLowerCase().trim();
22070
22220
  }
22071
22221
  function checkSubstringRelation(textI, textJ) {
22072
22222
  if (textI.includes(textJ) && textI.length > textJ.length)
@@ -22195,13 +22345,13 @@ function parseTimestampLine(line) {
22195
22345
  return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
22196
22346
  }
22197
22347
  function buildCue(startMs, endMs, fullText) {
22198
- const { speaker, text: text16 } = extractSpeaker(fullText);
22199
- return text16 ? { startMs, endMs, speaker, text: text16 } : null;
22348
+ const { speaker, text: text17 } = extractSpeaker(fullText);
22349
+ return text17 ? { startMs, endMs, speaker, text: text17 } : null;
22200
22350
  }
22201
22351
  function parseCueLine(lines, i) {
22202
22352
  const { startMs, endMs } = parseTimestampLine(lines[i]);
22203
- const { text: text16, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
22204
- return { cue: buildCue(startMs, endMs, text16), nextIndex: nextIndex2 };
22353
+ const { text: text17, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
22354
+ return { cue: buildCue(startMs, endMs, text17), nextIndex: nextIndex2 };
22205
22355
  }
22206
22356
  function isCueSeparator(line) {
22207
22357
  return line.trim().includes("-->");
@@ -22789,8 +22939,8 @@ async function exchangeToken(params) {
22789
22939
  body: body.toString()
22790
22940
  });
22791
22941
  if (!response.ok) {
22792
- const text16 = await response.text();
22793
- throw new Error(`Token exchange failed (${response.status}): ${text16}`);
22942
+ const text17 = await response.text();
22943
+ throw new Error(`Token exchange failed (${response.status}): ${text17}`);
22794
22944
  }
22795
22945
  return response.json();
22796
22946
  }
@@ -23533,8 +23683,8 @@ function buildOutputPath(outputDir, processName) {
23533
23683
  if (!existsSync52(outputDir)) {
23534
23684
  mkdirSync23(outputDir, { recursive: true });
23535
23685
  }
23536
- const timestamp5 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
23537
- return resolve15(outputDir, `${processName}-${timestamp5}.png`);
23686
+ const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
23687
+ return resolve15(outputDir, `${processName}-${timestamp6}.png`);
23538
23688
  }
23539
23689
  function runPowerShellScript(processName, outputPath) {
23540
23690
  const scriptPath = join64(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
@@ -24196,13 +24346,13 @@ function drainSessions(sessions, onDrained) {
24196
24346
  }
24197
24347
 
24198
24348
  // src/shared/db/recordPhaseActiveMs.ts
24199
- import { sql as sql15 } from "drizzle-orm";
24349
+ import { sql as sql18 } from "drizzle-orm";
24200
24350
  async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
24201
24351
  if (activeMs <= 0) return;
24202
24352
  await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
24203
24353
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
24204
24354
  set: {
24205
- activeMs: sql15`${phaseUsage.activeMs} + excluded.active_ms`
24355
+ activeMs: sql18`${phaseUsage.activeMs} + excluded.active_ms`
24206
24356
  }
24207
24357
  });
24208
24358
  }
@@ -24394,7 +24544,7 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
24394
24544
  }
24395
24545
 
24396
24546
  // src/shared/db/recordPhaseCycleContext.ts
24397
- import { sql as sql16 } from "drizzle-orm";
24547
+ import { sql as sql19 } from "drizzle-orm";
24398
24548
  async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt, pct) {
24399
24549
  if (pct <= 0) return;
24400
24550
  await db.insert(phaseCycleContext).values({ itemId: itemId2, phaseIdx, window, resetsAt, peakContextPct: pct }).onConflictDoUpdate({
@@ -24405,24 +24555,24 @@ async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt,
24405
24555
  phaseCycleContext.resetsAt
24406
24556
  ],
24407
24557
  set: {
24408
- peakContextPct: sql16`GREATEST(${phaseCycleContext.peakContextPct}, ${pct})`
24558
+ peakContextPct: sql19`GREATEST(${phaseCycleContext.peakContextPct}, ${pct})`
24409
24559
  }
24410
24560
  });
24411
24561
  }
24412
24562
 
24413
24563
  // src/shared/db/recordPhasePeakContext.ts
24414
- import { sql as sql17 } from "drizzle-orm";
24564
+ import { sql as sql20 } from "drizzle-orm";
24415
24565
  async function recordPhasePeakContext(db, itemId2, phaseIdx, pct) {
24416
24566
  await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, peakContextPct: pct }).onConflictDoUpdate({
24417
24567
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
24418
24568
  set: {
24419
- peakContextPct: sql17`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
24569
+ peakContextPct: sql20`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
24420
24570
  }
24421
24571
  });
24422
24572
  }
24423
24573
 
24424
24574
  // src/shared/db/recordPhaseTranscriptUsage.ts
24425
- import { sql as sql18 } from "drizzle-orm";
24575
+ import { sql as sql21 } from "drizzle-orm";
24426
24576
  async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
24427
24577
  const byId = /* @__PURE__ */ new Map();
24428
24578
  for (const r of responses) byId.set(r.messageId, r);
@@ -24442,8 +24592,8 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
24442
24592
  await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
24443
24593
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
24444
24594
  set: {
24445
- tokensUp: sql18`${phaseUsage.tokensUp} + ${tokensUp}`,
24446
- tokensDown: sql18`${phaseUsage.tokensDown} + ${tokensDown}`
24595
+ tokensUp: sql21`${phaseUsage.tokensUp} + ${tokensUp}`,
24596
+ tokensDown: sql21`${phaseUsage.tokensDown} + ${tokensDown}`
24447
24597
  }
24448
24598
  });
24449
24599
  return { tokensUp, tokensDown };
@@ -24451,12 +24601,12 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
24451
24601
  }
24452
24602
 
24453
24603
  // src/shared/db/recordWindowTokens.ts
24454
- import { and as and21, eq as eq39, sql as sql19 } from "drizzle-orm";
24604
+ import { and as and21, eq as eq39, sql as sql22 } from "drizzle-orm";
24455
24605
  async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
24456
24606
  if (tokensUp <= 0 && tokensDown <= 0) return;
24457
24607
  await db.update(usagePeaks).set({
24458
- tokensUp: sql19`${usagePeaks.tokensUp} + ${tokensUp}`,
24459
- tokensDown: sql19`${usagePeaks.tokensDown} + ${tokensDown}`
24608
+ tokensUp: sql22`${usagePeaks.tokensUp} + ${tokensUp}`,
24609
+ tokensDown: sql22`${usagePeaks.tokensDown} + ${tokensDown}`
24460
24610
  }).where(
24461
24611
  and21(
24462
24612
  eq39(usagePeaks.window, window),
@@ -25968,17 +26118,17 @@ function entryMessages(entry) {
25968
26118
  return [];
25969
26119
  }
25970
26120
  function userMessages(content) {
25971
- if (typeof content === "string") return text15("user", cleanUserText(content));
26121
+ if (typeof content === "string") return text16("user", cleanUserText(content));
25972
26122
  if (!Array.isArray(content)) return [];
25973
- return content.filter((c) => c.type === "text").flatMap((c) => text15("user", cleanUserText(c.text ?? "")));
26123
+ return content.filter((c) => c.type === "text").flatMap((c) => text16("user", cleanUserText(c.text ?? "")));
25974
26124
  }
25975
26125
  function assistantMessages(content) {
25976
- if (typeof content === "string") return text15("assistant", content.trim());
26126
+ if (typeof content === "string") return text16("assistant", content.trim());
25977
26127
  if (!Array.isArray(content)) return [];
25978
26128
  return content.flatMap((c) => assistantItem(c));
25979
26129
  }
25980
26130
  function assistantItem(c) {
25981
- if (c.type === "text") return text15("assistant", (c.text ?? "").trim());
26131
+ if (c.type === "text") return text16("assistant", (c.text ?? "").trim());
25982
26132
  if (c.type === "tool_use")
25983
26133
  return [
25984
26134
  {
@@ -25989,7 +26139,7 @@ function assistantItem(c) {
25989
26139
  ];
25990
26140
  return [];
25991
26141
  }
25992
- function text15(role, value) {
26142
+ function text16(role, value) {
25993
26143
  return value ? [{ role, text: value }] : [];
25994
26144
  }
25995
26145
  function cleanUserText(value) {
@@ -26363,16 +26513,16 @@ function parseUserLine(line) {
26363
26513
  if (entry.type !== "user") return void 0;
26364
26514
  const msg = entry.message;
26365
26515
  const c = msg?.content;
26366
- let text16;
26516
+ let text17;
26367
26517
  if (typeof c === "string") {
26368
- text16 = c;
26518
+ text17 = c;
26369
26519
  } else if (Array.isArray(c)) {
26370
26520
  const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
26371
- text16 = collected || void 0;
26521
+ text17 = collected || void 0;
26372
26522
  }
26373
- if (!text16) return void 0;
26523
+ if (!text17) return void 0;
26374
26524
  return {
26375
- text: text16,
26525
+ text: text17,
26376
26526
  entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
26377
26527
  };
26378
26528
  }
@@ -26401,13 +26551,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
26401
26551
 
26402
26552
  // src/commands/sessions/summarise/extractFirstUserMessage.ts
26403
26553
  function extractFirstUserMessage(filePath) {
26404
- for (const text16 of iterateUserMessages(filePath)) {
26405
- return truncate3(text16);
26554
+ for (const text17 of iterateUserMessages(filePath)) {
26555
+ return truncate3(text17);
26406
26556
  }
26407
26557
  return void 0;
26408
26558
  }
26409
- function truncate3(text16, maxChars = 500) {
26410
- const trimmed = text16.trim();
26559
+ function truncate3(text17, maxChars = 500) {
26560
+ const trimmed = text17.trim();
26411
26561
  if (trimmed.length <= maxChars) return trimmed;
26412
26562
  return `${trimmed.slice(0, maxChars)}\u2026`;
26413
26563
  }
@@ -26415,28 +26565,28 @@ function truncate3(text16, maxChars = 500) {
26415
26565
  // src/commands/sessions/summarise/scanSessionBacklogRefs.ts
26416
26566
  function scanSessionBacklogRefs(filePath) {
26417
26567
  const ids = /* @__PURE__ */ new Set();
26418
- for (const text16 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
26419
- for (const id of extractBacklogIds(text16)) {
26568
+ for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
26569
+ for (const id of extractBacklogIds(text17)) {
26420
26570
  ids.add(id);
26421
26571
  }
26422
26572
  }
26423
26573
  return [...ids].sort((a, b) => a - b);
26424
26574
  }
26425
- function extractBacklogIds(text16) {
26575
+ function extractBacklogIds(text17) {
26426
26576
  const ids = [];
26427
- for (const m of text16.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
26577
+ for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
26428
26578
  ids.push(Number.parseInt(m[1], 10));
26429
26579
  }
26430
- for (const m of text16.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
26580
+ for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
26431
26581
  ids.push(Number.parseInt(m[1], 10));
26432
26582
  }
26433
- for (const m of text16.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
26583
+ for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
26434
26584
  ids.push(Number.parseInt(m[1], 10));
26435
26585
  }
26436
- for (const m of text16.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
26586
+ for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
26437
26587
  ids.push(Number.parseInt(m[1], 10));
26438
26588
  }
26439
- for (const m of text16.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
26589
+ for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
26440
26590
  ids.push(Number.parseInt(m[1], 10));
26441
26591
  }
26442
26592
  return ids;
@@ -26737,7 +26887,7 @@ async function statusLine() {
26737
26887
 
26738
26888
  // src/commands/sync.ts
26739
26889
  import * as fs45 from "fs";
26740
- import * as os3 from "os";
26890
+ import * as os4 from "os";
26741
26891
  import * as path65 from "path";
26742
26892
  import { fileURLToPath as fileURLToPath9 } from "url";
26743
26893
 
@@ -26999,7 +27149,7 @@ async function sync(options2) {
26999
27149
  const config = loadConfig();
27000
27150
  const yes = options2?.yes ?? config.sync.autoConfirm;
27001
27151
  const claudeDir = path65.join(__dirname7, "..", "claude");
27002
- const targetBase = path65.join(os3.homedir(), ".claude");
27152
+ const targetBase = path65.join(os4.homedir(), ".claude");
27003
27153
  syncCommands(claudeDir, targetBase);
27004
27154
  syncDesign(claudeDir, targetBase);
27005
27155
  await syncSettings(claudeDir, targetBase, { yes });