@staff0rd/assist 0.386.0 → 0.387.1

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.386.0",
9
+ version: "0.387.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -422,13 +422,7 @@ function getTranscriptConfig() {
422
422
  }
423
423
 
424
424
  // src/shared/db/schema.ts
425
- import {
426
- foreignKey,
427
- integer as integer9,
428
- pgTable as pgTable9,
429
- primaryKey as primaryKey6,
430
- text as text9
431
- } from "drizzle-orm/pg-core";
425
+ import { integer as integer14, pgTable as pgTable14, text as text14 } from "drizzle-orm/pg-core";
432
426
 
433
427
  // src/shared/db/backups.ts
434
428
  import { bigint, integer, pgTable, text, timestamp } from "drizzle-orm/pg-core";
@@ -440,193 +434,236 @@ var backups = pgTable("backups", {
440
434
  durationMs: integer("duration_ms")
441
435
  });
442
436
 
443
- // src/shared/db/handovers.ts
444
- import { index, integer as integer2, pgTable as pgTable2, text as text2, timestamp as timestamp2 } from "drizzle-orm/pg-core";
445
- var handovers = pgTable2(
446
- "handovers",
437
+ // src/shared/db/comments.ts
438
+ import { integer as integer3, pgTable as pgTable3, text as text3 } from "drizzle-orm/pg-core";
439
+
440
+ // src/shared/db/items.ts
441
+ import { boolean, index, integer as integer2, pgTable as pgTable2, text as text2 } from "drizzle-orm/pg-core";
442
+ var items = pgTable2(
443
+ "items",
447
444
  {
448
445
  id: integer2().generatedByDefaultAsIdentity().primaryKey(),
449
446
  origin: text2().notNull(),
450
- summary: text2().notNull(),
451
- content: text2().notNull(),
447
+ type: text2().notNull().default("story"),
448
+ name: text2().notNull(),
449
+ description: text2(),
450
+ acceptanceCriteria: text2("acceptance_criteria").notNull().default("[]"),
451
+ status: text2().notNull().default("todo"),
452
+ currentPhase: integer2("current_phase"),
453
+ starred: boolean().notNull().default(false),
454
+ jiraKey: text2("jira_key")
455
+ },
456
+ (t) => [index("items_origin_idx").on(t.origin)]
457
+ );
458
+
459
+ // src/shared/db/comments.ts
460
+ var comments = pgTable3("comments", {
461
+ id: integer3().generatedByDefaultAsIdentity().primaryKey(),
462
+ itemId: integer3("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
463
+ idx: integer3().notNull(),
464
+ text: text3().notNull(),
465
+ phase: integer3(),
466
+ timestamp: text3().notNull(),
467
+ type: text3().notNull().default("comment")
468
+ });
469
+
470
+ // src/shared/db/handovers.ts
471
+ import { index as index2, integer as integer4, pgTable as pgTable4, text as text4, timestamp as timestamp2 } from "drizzle-orm/pg-core";
472
+ var handovers = pgTable4(
473
+ "handovers",
474
+ {
475
+ id: integer4().generatedByDefaultAsIdentity().primaryKey(),
476
+ origin: text4().notNull(),
477
+ summary: text4().notNull(),
478
+ content: text4().notNull(),
452
479
  createdAt: timestamp2("created_at", { withTimezone: true }).notNull().defaultNow(),
453
480
  recalledAt: timestamp2("recalled_at", { withTimezone: true })
454
481
  },
455
- (t) => [index("handovers_origin_idx").on(t.origin)]
482
+ (t) => [index2("handovers_origin_idx").on(t.origin)]
456
483
  );
457
484
 
458
485
  // src/shared/db/itemGitRefs.ts
459
486
  import {
460
- integer as integer4,
461
- pgTable as pgTable4,
487
+ integer as integer5,
488
+ pgTable as pgTable5,
462
489
  primaryKey,
463
- text as text4,
490
+ text as text5,
464
491
  timestamp as timestamp3
465
492
  } from "drizzle-orm/pg-core";
466
-
467
- // src/shared/db/items.ts
468
- import { boolean, index as index2, integer as integer3, pgTable as pgTable3, text as text3 } from "drizzle-orm/pg-core";
469
- var items = pgTable3(
470
- "items",
471
- {
472
- id: integer3().generatedByDefaultAsIdentity().primaryKey(),
473
- origin: text3().notNull(),
474
- type: text3().notNull().default("story"),
475
- name: text3().notNull(),
476
- description: text3(),
477
- acceptanceCriteria: text3("acceptance_criteria").notNull().default("[]"),
478
- status: text3().notNull().default("todo"),
479
- currentPhase: integer3("current_phase"),
480
- starred: boolean().notNull().default(false),
481
- jiraKey: text3("jira_key")
482
- },
483
- (t) => [index2("items_origin_idx").on(t.origin)]
484
- );
485
-
486
- // src/shared/db/itemGitRefs.ts
487
- var itemGitRefs = pgTable4(
493
+ var itemGitRefs = pgTable5(
488
494
  "item_git_refs",
489
495
  {
490
- itemId: integer4("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
491
- kind: text4().notNull(),
492
- ref: text4().notNull(),
493
- title: text4(),
494
- url: text4(),
495
- state: text4(),
496
+ itemId: integer5("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
497
+ kind: text5().notNull(),
498
+ ref: text5().notNull(),
499
+ title: text5(),
500
+ url: text5(),
501
+ state: text5(),
496
502
  createdAt: timestamp3("created_at", { withTimezone: true }).notNull().defaultNow()
497
503
  },
498
504
  (t) => [primaryKey({ columns: [t.itemId, t.kind, t.ref] })]
499
505
  );
500
506
 
501
507
  // src/shared/db/itemSubtasks.ts
502
- import { integer as integer5, pgTable as pgTable5, primaryKey as primaryKey2, text as text5 } from "drizzle-orm/pg-core";
503
- var itemSubtasks = pgTable5(
508
+ import { integer as integer6, pgTable as pgTable6, primaryKey as primaryKey2, text as text6 } from "drizzle-orm/pg-core";
509
+ var itemSubtasks = pgTable6(
504
510
  "item_subtasks",
505
511
  {
506
- itemId: integer5("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
507
- idx: integer5().notNull(),
508
- title: text5().notNull(),
509
- description: text5(),
510
- status: text5().notNull().default("todo")
512
+ itemId: integer6("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
513
+ idx: integer6().notNull(),
514
+ title: text6().notNull(),
515
+ description: text6(),
516
+ status: text6().notNull().default("todo")
511
517
  },
512
518
  (t) => [primaryKey2({ columns: [t.itemId, t.idx] })]
513
519
  );
514
520
 
515
- // src/shared/db/phaseUsage.ts
516
- import {
517
- bigint as bigint2,
518
- doublePrecision,
519
- integer as integer6,
520
- pgTable as pgTable6,
521
- primaryKey as primaryKey3,
522
- text as text6
523
- } from "drizzle-orm/pg-core";
524
- var phaseUsage = pgTable6(
525
- "phase_usage",
521
+ // src/shared/db/links.ts
522
+ import { integer as integer7, pgTable as pgTable7, primaryKey as primaryKey3, text as text7 } from "drizzle-orm/pg-core";
523
+ var links = pgTable7(
524
+ "links",
526
525
  {
527
- itemId: integer6("item_id").notNull(),
528
- phaseIdx: integer6("phase_idx").notNull(),
529
- tokensUp: bigint2("tokens_up", { mode: "number" }).notNull().default(0),
530
- tokensDown: bigint2("tokens_down", { mode: "number" }).notNull().default(0),
531
- activeMs: bigint2("active_ms", { mode: "number" }).notNull().default(0),
532
- peakContextPct: doublePrecision("peak_context_pct").notNull().default(0),
533
- lastTotalIn: bigint2("last_total_in", { mode: "number" }),
534
- lastTotalOut: bigint2("last_total_out", { mode: "number" }),
535
- claudeSessionId: text6("claude_session_id")
526
+ itemId: integer7("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
527
+ type: text7().notNull(),
528
+ targetId: integer7("target_id").notNull()
536
529
  },
537
- (t) => [primaryKey3({ columns: [t.itemId, t.phaseIdx] })]
530
+ (t) => [primaryKey3({ columns: [t.itemId, t.type, t.targetId] })]
538
531
  );
539
532
 
540
- // src/shared/db/phaseUsageMessages.ts
541
- import { integer as integer7, pgTable as pgTable7, primaryKey as primaryKey4, text as text7 } from "drizzle-orm/pg-core";
542
- var phaseUsageMessages = pgTable7(
543
- "phase_usage_messages",
533
+ // src/shared/db/phaseCycleContext.ts
534
+ import {
535
+ bigint as bigint2,
536
+ doublePrecision,
537
+ integer as integer8,
538
+ pgTable as pgTable8,
539
+ primaryKey as primaryKey4,
540
+ text as text8
541
+ } from "drizzle-orm/pg-core";
542
+ var phaseCycleContext = pgTable8(
543
+ "phase_cycle_context",
544
544
  {
545
- itemId: integer7("item_id").notNull(),
546
- phaseIdx: integer7("phase_idx").notNull(),
547
- messageId: text7("message_id").notNull()
545
+ itemId: integer8("item_id").notNull(),
546
+ phaseIdx: integer8("phase_idx").notNull(),
547
+ window: text8().$type().notNull(),
548
+ resetsAt: bigint2("resets_at", { mode: "number" }).notNull(),
549
+ peakContextPct: doublePrecision("peak_context_pct").notNull().default(0)
548
550
  },
549
- (t) => [primaryKey4({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
551
+ (t) => [
552
+ primaryKey4({
553
+ columns: [t.itemId, t.phaseIdx, t.window, t.resetsAt]
554
+ })
555
+ ]
550
556
  );
551
557
 
552
- // src/shared/db/usagePeaks.ts
558
+ // src/shared/db/phaseUsage.ts
553
559
  import {
554
560
  bigint as bigint3,
555
- boolean as boolean2,
556
561
  doublePrecision as doublePrecision2,
557
- integer as integer8,
558
- pgTable as pgTable8,
562
+ integer as integer9,
563
+ pgTable as pgTable9,
559
564
  primaryKey as primaryKey5,
560
- text as text8,
561
- timestamp as timestamp4
565
+ text as text9
562
566
  } from "drizzle-orm/pg-core";
563
- var usagePeaks = pgTable8(
564
- "usage_peaks",
567
+ var phaseUsage = pgTable9(
568
+ "phase_usage",
565
569
  {
566
- window: text8().$type().notNull(),
567
- resetsAt: bigint3("resets_at", { mode: "number" }).notNull(),
568
- segment: integer8().notNull().default(0),
569
- usedPercentage: doublePrecision2("used_percentage").notNull(),
570
- resetDetected: boolean2("reset_detected").notNull().default(false),
570
+ itemId: integer9("item_id").notNull(),
571
+ phaseIdx: integer9("phase_idx").notNull(),
571
572
  tokensUp: bigint3("tokens_up", { mode: "number" }).notNull().default(0),
572
573
  tokensDown: bigint3("tokens_down", { mode: "number" }).notNull().default(0),
573
- createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
574
+ activeMs: bigint3("active_ms", { mode: "number" }).notNull().default(0),
575
+ peakContextPct: doublePrecision2("peak_context_pct").notNull().default(0),
576
+ lastTotalIn: bigint3("last_total_in", { mode: "number" }),
577
+ lastTotalOut: bigint3("last_total_out", { mode: "number" }),
578
+ claudeSessionId: text9("claude_session_id")
574
579
  },
575
- (t) => [primaryKey5({ columns: [t.window, t.resetsAt, t.segment] })]
580
+ (t) => [primaryKey5({ columns: [t.itemId, t.phaseIdx] })]
576
581
  );
577
582
 
578
- // src/shared/db/schema.ts
579
- var comments = pgTable9("comments", {
580
- id: integer9().generatedByDefaultAsIdentity().primaryKey(),
581
- itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
582
- idx: integer9().notNull(),
583
- text: text9().notNull(),
584
- phase: integer9(),
585
- timestamp: text9().notNull(),
586
- type: text9().notNull().default("comment")
587
- });
588
- var links = pgTable9(
589
- "links",
583
+ // src/shared/db/phaseUsageMessages.ts
584
+ import { integer as integer10, pgTable as pgTable10, primaryKey as primaryKey6, text as text10 } from "drizzle-orm/pg-core";
585
+ var phaseUsageMessages = pgTable10(
586
+ "phase_usage_messages",
590
587
  {
591
- itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
592
- type: text9().notNull(),
593
- targetId: integer9("target_id").notNull()
588
+ itemId: integer10("item_id").notNull(),
589
+ phaseIdx: integer10("phase_idx").notNull(),
590
+ messageId: text10("message_id").notNull()
594
591
  },
595
- (t) => [primaryKey6({ columns: [t.itemId, t.type, t.targetId] })]
592
+ (t) => [primaryKey6({ columns: [t.itemId, t.phaseIdx, t.messageId] })]
596
593
  );
597
- var planPhases = pgTable9(
594
+
595
+ // src/shared/db/planPhases.ts
596
+ import { integer as integer11, pgTable as pgTable11, primaryKey as primaryKey7, text as text11 } from "drizzle-orm/pg-core";
597
+ var planPhases = pgTable11(
598
598
  "plan_phases",
599
599
  {
600
- itemId: integer9("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
601
- idx: integer9().notNull(),
602
- name: text9().notNull(),
603
- manualChecks: text9("manual_checks")
600
+ itemId: integer11("item_id").notNull().references(() => items.id, { onDelete: "cascade" }),
601
+ idx: integer11().notNull(),
602
+ name: text11().notNull(),
603
+ manualChecks: text11("manual_checks")
604
604
  },
605
- (t) => [primaryKey6({ columns: [t.itemId, t.idx] })]
605
+ (t) => [primaryKey7({ columns: [t.itemId, t.idx] })]
606
606
  );
607
- var planTasks = pgTable9(
607
+
608
+ // src/shared/db/planTasks.ts
609
+ import {
610
+ foreignKey,
611
+ integer as integer12,
612
+ pgTable as pgTable12,
613
+ primaryKey as primaryKey8,
614
+ text as text12
615
+ } from "drizzle-orm/pg-core";
616
+ var planTasks = pgTable12(
608
617
  "plan_tasks",
609
618
  {
610
- itemId: integer9("item_id").notNull(),
611
- phaseIdx: integer9("phase_idx").notNull(),
612
- idx: integer9().notNull(),
613
- task: text9().notNull()
619
+ itemId: integer12("item_id").notNull(),
620
+ phaseIdx: integer12("phase_idx").notNull(),
621
+ idx: integer12().notNull(),
622
+ task: text12().notNull()
614
623
  },
615
624
  (t) => [
616
- primaryKey6({ columns: [t.itemId, t.phaseIdx, t.idx] }),
625
+ primaryKey8({ columns: [t.itemId, t.phaseIdx, t.idx] }),
617
626
  foreignKey({
618
627
  columns: [t.itemId, t.phaseIdx],
619
628
  foreignColumns: [planPhases.itemId, planPhases.idx]
620
629
  }).onDelete("cascade")
621
630
  ]
622
631
  );
623
- var metadata = pgTable9("metadata", {
624
- key: text9().primaryKey(),
625
- value: text9().notNull()
632
+
633
+ // src/shared/db/usagePeaks.ts
634
+ import {
635
+ bigint as bigint4,
636
+ boolean as boolean2,
637
+ doublePrecision as doublePrecision3,
638
+ integer as integer13,
639
+ pgTable as pgTable13,
640
+ primaryKey as primaryKey9,
641
+ text as text13,
642
+ timestamp as timestamp4
643
+ } from "drizzle-orm/pg-core";
644
+ var usagePeaks = pgTable13(
645
+ "usage_peaks",
646
+ {
647
+ window: text13().$type().notNull(),
648
+ resetsAt: bigint4("resets_at", { mode: "number" }).notNull(),
649
+ segment: integer13().notNull().default(0),
650
+ usedPercentage: doublePrecision3("used_percentage").notNull(),
651
+ resetDetected: boolean2("reset_detected").notNull().default(false),
652
+ tokensUp: bigint4("tokens_up", { mode: "number" }).notNull().default(0),
653
+ tokensDown: bigint4("tokens_down", { mode: "number" }).notNull().default(0),
654
+ createdAt: timestamp4("created_at", { withTimezone: true }).notNull().defaultNow()
655
+ },
656
+ (t) => [primaryKey9({ columns: [t.window, t.resetsAt, t.segment] })]
657
+ );
658
+
659
+ // src/shared/db/schema.ts
660
+ var metadata = pgTable14("metadata", {
661
+ key: text14().primaryKey(),
662
+ value: text14().notNull()
626
663
  });
627
- var feeds = pgTable9("feeds", {
628
- id: integer9().generatedByDefaultAsIdentity().primaryKey(),
629
- url: text9().notNull().unique()
664
+ var feeds = pgTable14("feeds", {
665
+ id: integer14().generatedByDefaultAsIdentity().primaryKey(),
666
+ url: text14().notNull().unique()
630
667
  });
631
668
  var schema = {
632
669
  items,
@@ -642,7 +679,8 @@ var schema = {
642
679
  usagePeaks,
643
680
  backups,
644
681
  phaseUsage,
645
- phaseUsageMessages
682
+ phaseUsageMessages,
683
+ phaseCycleContext
646
684
  };
647
685
 
648
686
  // src/commands/backlog/addFeed.ts
@@ -968,8 +1006,55 @@ var migration0001Baseline = {
968
1006
  sql: sql2
969
1007
  };
970
1008
 
1009
+ // src/shared/db/migrations/migration0002UsagePeaksContext.ts
1010
+ var sql3 = `
1011
+ ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS context_pct_sum DOUBLE PRECISION NOT NULL DEFAULT 0;
1012
+ ALTER TABLE usage_peaks ADD COLUMN IF NOT EXISTS context_readings BIGINT NOT NULL DEFAULT 0;
1013
+ `;
1014
+ var migration0002UsagePeaksContext = {
1015
+ id: 2,
1016
+ name: "usage-peaks-context",
1017
+ sql: sql3
1018
+ };
1019
+
1020
+ // src/shared/db/migrations/migration0003PhaseCycleContext.ts
1021
+ var sql4 = `
1022
+ CREATE TABLE IF NOT EXISTS phase_cycle_context (
1023
+ item_id INTEGER NOT NULL REFERENCES items(id) ON DELETE CASCADE,
1024
+ phase_idx INTEGER NOT NULL,
1025
+ "window" TEXT NOT NULL,
1026
+ resets_at BIGINT NOT NULL,
1027
+ peak_context_pct DOUBLE PRECISION NOT NULL DEFAULT 0,
1028
+ PRIMARY KEY (item_id, phase_idx, "window", resets_at)
1029
+ );
1030
+ `;
1031
+ var migration0003PhaseCycleContext = {
1032
+ id: 3,
1033
+ name: "phase-cycle-context",
1034
+ sql: sql4
1035
+ };
1036
+
1037
+ // src/shared/db/migrations/migration0004DropUsagePeaksContext.ts
1038
+ var sql5 = `
1039
+ -- destructive-ok: the context_pct_sum/context_readings accumulator (added in
1040
+ -- migration 2) was superseded by phase_cycle_context (migration 3); no build
1041
+ -- reads these columns \u2014 they are unmapped in Drizzle and never selected.
1042
+ ALTER TABLE usage_peaks DROP COLUMN IF EXISTS context_pct_sum;
1043
+ ALTER TABLE usage_peaks DROP COLUMN IF EXISTS context_readings;
1044
+ `;
1045
+ var migration0004DropUsagePeaksContext = {
1046
+ id: 4,
1047
+ name: "drop-usage-peaks-context",
1048
+ sql: sql5
1049
+ };
1050
+
971
1051
  // src/shared/db/migrations/index.ts
972
- var migrations = [migration0001Baseline];
1052
+ var migrations = [
1053
+ migration0001Baseline,
1054
+ migration0002UsagePeaksContext,
1055
+ migration0003PhaseCycleContext,
1056
+ migration0004DropUsagePeaksContext
1057
+ ];
973
1058
  var latestMigrationId = migrations.reduce(
974
1059
  (max, m) => Math.max(max, m.id),
975
1060
  0
@@ -1051,8 +1136,8 @@ async function assertMigrationsInSync(exec3) {
1051
1136
  // src/shared/db/migrations/MigrationExecutor.ts
1052
1137
  function pgExecutor(queryable) {
1053
1138
  return {
1054
- exec: (sql15) => queryable.query(sql15),
1055
- query: async (sql15, params) => (await queryable.query(sql15, params)).rows
1139
+ exec: (sql20) => queryable.query(sql20),
1140
+ query: async (sql20, params) => (await queryable.query(sql20, params)).rows
1056
1141
  };
1057
1142
  }
1058
1143
 
@@ -2776,8 +2861,8 @@ function isHashCommentFile(filePath) {
2776
2861
  import fs13 from "fs";
2777
2862
 
2778
2863
  // src/commands/verify/blockComments/collectHashComments.ts
2779
- function blankNonNewline(text11) {
2780
- return text11.replace(/[^\n]/g, " ");
2864
+ function blankNonNewline(text16) {
2865
+ return text16.replace(/[^\n]/g, " ");
2781
2866
  }
2782
2867
  function isHeaderLine(line) {
2783
2868
  const trimmed = line.trim();
@@ -2854,23 +2939,23 @@ var MACHINE_DIRECTIVES = [
2854
2939
  "@vitest-environment",
2855
2940
  MAINTAINABILITY_OVERRIDE_MARKER
2856
2941
  ];
2857
- function isCommentExempt(text11) {
2858
- const lower = text11.toLowerCase();
2942
+ function isCommentExempt(text16) {
2943
+ const lower = text16.toLowerCase();
2859
2944
  return MACHINE_DIRECTIVES.some((d) => lower.includes(d));
2860
2945
  }
2861
2946
 
2862
2947
  // src/commands/verify/blockComments/collectSourceFindings.ts
2863
- function toSingleLine(text11) {
2864
- return text11.replace(/\s+/g, " ").trim();
2948
+ function toSingleLine(text16) {
2949
+ return text16.replace(/\s+/g, " ").trim();
2865
2950
  }
2866
2951
  function collectSourceFindings(file, lines, project) {
2867
2952
  const findings = [];
2868
2953
  const sourceFile = project.addSourceFileAtPath(file);
2869
- for (const { pos, text: text11 } of collectComments(sourceFile)) {
2954
+ for (const { pos, text: text16 } of collectComments(sourceFile)) {
2870
2955
  const { line } = sourceFile.getLineAndColumnAtPos(pos);
2871
2956
  if (!lines.has(line)) continue;
2872
- if (isCommentExempt(text11)) continue;
2873
- findings.push({ file, line, text: toSingleLine(text11) });
2957
+ if (isCommentExempt(text16)) continue;
2958
+ findings.push({ file, line, text: toSingleLine(text16) });
2874
2959
  }
2875
2960
  return findings;
2876
2961
  }
@@ -2890,10 +2975,10 @@ function collectYamlComments(content) {
2890
2975
  // src/commands/verify/blockComments/collectFileComments.ts
2891
2976
  function toFindings(file, lines, raw, exempt) {
2892
2977
  const findings = [];
2893
- for (const { line, text: text11 } of raw) {
2978
+ for (const { line, text: text16 } of raw) {
2894
2979
  if (!lines.has(line)) continue;
2895
- if (exempt && isCommentExempt(text11)) continue;
2896
- findings.push({ file, line, text: text11.replace(/\s+/g, " ").trim() });
2980
+ if (exempt && isCommentExempt(text16)) continue;
2981
+ findings.push({ file, line, text: text16.replace(/\s+/g, " ").trim() });
2897
2982
  }
2898
2983
  return findings;
2899
2984
  }
@@ -2991,8 +3076,8 @@ function blockComments() {
2991
3076
  process.exit(0);
2992
3077
  }
2993
3078
  console.log("Comments on changed lines:\n");
2994
- for (const { file, line, text: text11 } of findings) {
2995
- console.log(`${file}:${line} \u2192 ${text11}`);
3079
+ for (const { file, line, text: text16 } of findings) {
3080
+ console.log(`${file}:${line} \u2192 ${text16}`);
2996
3081
  }
2997
3082
  console.log(`
2998
3083
  Total: ${findings.length} comment(s)`);
@@ -4450,8 +4535,8 @@ async function buildDump(tables, copyOut) {
4450
4535
  // src/commands/backlog/dump/copyTableOut.ts
4451
4536
  import { to as copyTo } from "pg-copy-streams";
4452
4537
  async function copyTableOut(client, table) {
4453
- const sql15 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
4454
- const stream = client.query(copyTo(sql15));
4538
+ const sql20 = `COPY ${table.name} (${table.columns.join(", ")}) TO STDOUT`;
4539
+ const stream = client.query(copyTo(sql20));
4455
4540
  const chunks = [];
4456
4541
  for await (const chunk of stream) {
4457
4542
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
@@ -4993,11 +5078,11 @@ import { promisify } from "util";
4993
5078
  // src/shared/withSpinner.ts
4994
5079
  var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
4995
5080
  var TICK_MS = 80;
4996
- async function withSpinner(text11, task) {
5081
+ async function withSpinner(text16, task) {
4997
5082
  if (!process.stderr.isTTY) return task();
4998
5083
  let frame = 0;
4999
5084
  const render = () => {
5000
- process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text11}`);
5085
+ process.stderr.write(`\r${SPINNER_FRAMES[frame]} ${text16}`);
5001
5086
  };
5002
5087
  render();
5003
5088
  const timer = setInterval(() => {
@@ -5682,13 +5767,13 @@ async function loadItem(orm, id) {
5682
5767
  }
5683
5768
 
5684
5769
  // src/commands/backlog/saveAllItems.ts
5685
- import { eq as eq7, sql as sql3 } from "drizzle-orm";
5770
+ import { eq as eq7, sql as sql6 } from "drizzle-orm";
5686
5771
 
5687
5772
  // src/commands/backlog/deleteItemRelations.ts
5688
5773
  import { eq as eq6 } from "drizzle-orm";
5689
5774
 
5690
5775
  // src/commands/backlog/searchItemIds.ts
5691
- import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql4 } from "drizzle-orm";
5776
+ import { and as and3, asc as asc4, eq as eq8, ilike, or, sql as sql7 } from "drizzle-orm";
5692
5777
  async function searchItemIds(orm, query, origin) {
5693
5778
  const pattern2 = `%${query}%`;
5694
5779
  const numberPattern = `%${query.replace(/^#/, "")}%`;
@@ -5702,7 +5787,7 @@ async function searchItemIds(orm, query, origin) {
5702
5787
  ilike(items.jiraKey, pattern2),
5703
5788
  ilike(comments.text, pattern2),
5704
5789
  ilike(planPhases.name, pattern2),
5705
- ilike(sql4`${items.id}::text`, numberPattern)
5790
+ ilike(sql7`${items.id}::text`, numberPattern)
5706
5791
  )
5707
5792
  )
5708
5793
  ).orderBy(asc4(items.id));
@@ -5825,12 +5910,12 @@ async function findPhaseBySessionId(db, itemId2, claudeSessionId) {
5825
5910
  }
5826
5911
 
5827
5912
  // src/commands/backlog/appendComment.ts
5828
- import { sql as sql5 } from "drizzle-orm";
5829
- async function appendComment(orm, itemId2, text11, opts = {}) {
5913
+ import { sql as sql8 } from "drizzle-orm";
5914
+ async function appendComment(orm, itemId2, text16, opts = {}) {
5830
5915
  await orm.insert(comments).values({
5831
5916
  itemId: itemId2,
5832
- idx: sql5`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
5833
- text: text11,
5917
+ idx: sql8`(SELECT COALESCE(MAX(${comments.idx}) + 1, 0) FROM ${comments} WHERE ${comments.itemId} = ${itemId2})`,
5918
+ text: text16,
5834
5919
  phase: opts.phase ?? null,
5835
5920
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5836
5921
  type: opts.type ?? "comment"
@@ -6424,8 +6509,8 @@ function deriveSessionType(commandName, name) {
6424
6509
  }
6425
6510
 
6426
6511
  // src/commands/sessions/shared/backlogRunMarkers.ts
6427
- function backlogRunMarkers(text11) {
6428
- const match = text11.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
6512
+ function backlogRunMarkers(text16) {
6513
+ const match = text16.match(/backlog item a(\d+):[ \t]*([^\n]*)/);
6429
6514
  if (!match) return { commandName: "", commandArgs: "" };
6430
6515
  const title = match[2].trim();
6431
6516
  return {
@@ -6479,11 +6564,11 @@ function messageText(entry) {
6479
6564
  const content = msg?.content;
6480
6565
  return typeof content === "string" ? content : Array.isArray(content) ? content.find((c) => c.type === "text")?.text ?? "" : "";
6481
6566
  }
6482
- function stripMarkers(text11) {
6483
- return text11.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
6567
+ function stripMarkers(text16) {
6568
+ return text16.replace(/<command-[^>]*>[^<]*<\/command-[^>]*>/g, "").trim().slice(0, 80);
6484
6569
  }
6485
- function matchMarker(text11, tag) {
6486
- const match = text11.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
6570
+ function matchMarker(text16, tag) {
6571
+ const match = text16.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
6487
6572
  return match ? match[1].trim() : "";
6488
6573
  }
6489
6574
 
@@ -6938,7 +7023,7 @@ function formatComment(entry) {
6938
7023
  // src/shared/renderMarkdownTerminal.ts
6939
7024
  import { Marked } from "marked";
6940
7025
  import { markedTerminal } from "marked-terminal";
6941
- function renderMarkdownTerminal(text11) {
7026
+ function renderMarkdownTerminal(text16) {
6942
7027
  const width = process.stdout.columns || 80;
6943
7028
  const marked = new Marked(markedTerminal({ width, reflowText: true }));
6944
7029
  marked.use({
@@ -6951,7 +7036,7 @@ function renderMarkdownTerminal(text11) {
6951
7036
  }
6952
7037
  }
6953
7038
  });
6954
- return marked.parse(text11).trimEnd();
7039
+ return marked.parse(text16).trimEnd();
6955
7040
  }
6956
7041
 
6957
7042
  // src/commands/backlog/show/printActivity.ts
@@ -6971,9 +7056,9 @@ function groupActivityRefs(refs, commitLimit = ACTIVITY_COMMIT_LIMIT) {
6971
7056
  }
6972
7057
 
6973
7058
  // src/commands/backlog/show/printActivity.ts
6974
- function printRef(label2, text11, ref) {
7059
+ function printRef(label2, text16, ref) {
6975
7060
  const url = ref.url ? ` ${chalk50.dim(ref.url)}` : "";
6976
- console.log(` ${chalk50.cyan(label2)} ${text11}${url}`);
7061
+ console.log(` ${chalk50.cyan(label2)} ${text16}${url}`);
6977
7062
  }
6978
7063
  function printActivity(item) {
6979
7064
  const { branches, commits: commits2, prs: prs2, hiddenCommits } = groupActivityRefs(
@@ -7425,29 +7510,29 @@ import { eq as eq13 } from "drizzle-orm";
7425
7510
  import { asc as asc5, eq as eq12 } from "drizzle-orm";
7426
7511
 
7427
7512
  // src/commands/backlog/incompleteSubtaskCounts.ts
7428
- import { ne, sql as sql6 } from "drizzle-orm";
7513
+ import { ne, sql as sql9 } from "drizzle-orm";
7429
7514
  function incompleteSubtaskCounts(orm) {
7430
7515
  return orm.select({
7431
7516
  itemId: itemSubtasks.itemId,
7432
- count: sql6`count(*)::int`.as("incomplete_subtasks")
7517
+ count: sql9`count(*)::int`.as("incomplete_subtasks")
7433
7518
  }).from(itemSubtasks).where(ne(itemSubtasks.status, "done")).groupBy(itemSubtasks.itemId).as("incomplete_counts");
7434
7519
  }
7435
7520
 
7436
7521
  // src/commands/backlog/phaseUsageTotals.ts
7437
- import { sql as sql7 } from "drizzle-orm";
7522
+ import { sql as sql10 } from "drizzle-orm";
7438
7523
  function phaseUsageTotals(orm) {
7439
7524
  return orm.select({
7440
7525
  itemId: phaseUsage.itemId,
7441
- tokensUp: sql7`sum(${phaseUsage.tokensUp})::bigint`.as(
7526
+ tokensUp: sql10`sum(${phaseUsage.tokensUp})::bigint`.as(
7442
7527
  "total_tokens_up"
7443
7528
  ),
7444
- tokensDown: sql7`sum(${phaseUsage.tokensDown})::bigint`.as(
7529
+ tokensDown: sql10`sum(${phaseUsage.tokensDown})::bigint`.as(
7445
7530
  "total_tokens_down"
7446
7531
  ),
7447
- activeMs: sql7`sum(${phaseUsage.activeMs})::bigint`.as(
7532
+ activeMs: sql10`sum(${phaseUsage.activeMs})::bigint`.as(
7448
7533
  "total_active_ms"
7449
7534
  ),
7450
- peakContextPct: sql7`max(${phaseUsage.peakContextPct})`.as(
7535
+ peakContextPct: sql10`max(${phaseUsage.peakContextPct})`.as(
7451
7536
  "max_peak_context_pct"
7452
7537
  )
7453
7538
  }).from(phaseUsage).groupBy(phaseUsage.itemId).as("usage_totals");
@@ -8119,9 +8204,9 @@ function excerpt(xml, ...tags) {
8119
8204
  for (const tag of tags) {
8120
8205
  const raw = extractText(xml, tag);
8121
8206
  if (!raw) continue;
8122
- const text11 = stripHtml(raw);
8123
- if (text11.length <= MAX_EXCERPT) return text11;
8124
- return `${text11.slice(0, MAX_EXCERPT)}\u2026`;
8207
+ const text16 = stripHtml(raw);
8208
+ if (text16.length <= MAX_EXCERPT) return text16;
8209
+ return `${text16.slice(0, MAX_EXCERPT)}\u2026`;
8125
8210
  }
8126
8211
  return "";
8127
8212
  }
@@ -8199,9 +8284,25 @@ async function listNewsItems(_req, res) {
8199
8284
  }
8200
8285
 
8201
8286
  // src/shared/db/listUsagePeaks.ts
8202
- import { count, desc as desc2 } from "drizzle-orm";
8287
+ import { and as and7, count, desc as desc2, eq as eq17, getTableColumns, sql as sql11 } from "drizzle-orm";
8203
8288
  async function listUsagePeaks(db, paging) {
8204
- const query = db.select().from(usagePeaks).orderBy(
8289
+ const avgContext = db.select({
8290
+ window: phaseCycleContext.window,
8291
+ resetsAt: phaseCycleContext.resetsAt,
8292
+ avgContextPct: sql11`cast(avg(${phaseCycleContext.peakContextPct}) as double precision)`.as(
8293
+ "avg_context_pct"
8294
+ )
8295
+ }).from(phaseCycleContext).groupBy(phaseCycleContext.window, phaseCycleContext.resetsAt).as("avg_context");
8296
+ const query = db.select({
8297
+ ...getTableColumns(usagePeaks),
8298
+ avgContextPct: avgContext.avgContextPct
8299
+ }).from(usagePeaks).leftJoin(
8300
+ avgContext,
8301
+ and7(
8302
+ eq17(usagePeaks.window, avgContext.window),
8303
+ eq17(usagePeaks.resetsAt, avgContext.resetsAt)
8304
+ )
8305
+ ).orderBy(
8205
8306
  desc2(usagePeaks.resetsAt),
8206
8307
  usagePeaks.window,
8207
8308
  desc2(usagePeaks.createdAt),
@@ -8957,7 +9058,7 @@ function registerActivityCommands(cmd) {
8957
9058
 
8958
9059
  // src/commands/backlog/associate-jira/index.ts
8959
9060
  import chalk64 from "chalk";
8960
- import { eq as eq17 } from "drizzle-orm";
9061
+ import { eq as eq18 } from "drizzle-orm";
8961
9062
 
8962
9063
  // src/commands/jira/fetchIssue.ts
8963
9064
  import { execSync as execSync29 } from "child_process";
@@ -8999,7 +9100,7 @@ async function associateJira(id, key, options2) {
8999
9100
  const { orm } = found;
9000
9101
  const itemId2 = found.item.id;
9001
9102
  if (options2.clear) {
9002
- await orm.update(items).set({ jiraKey: null }).where(eq17(items.id, itemId2));
9103
+ await orm.update(items).set({ jiraKey: null }).where(eq18(items.id, itemId2));
9003
9104
  console.log(
9004
9105
  chalk64.green(`Cleared Jira association on item ${formatItemId(itemId2)}.`)
9005
9106
  );
@@ -9020,7 +9121,7 @@ async function associateJira(id, key, options2) {
9020
9121
  const parsed = fetchIssue(key, "summary");
9021
9122
  const fields = parsed?.fields;
9022
9123
  const summary = fields?.summary;
9023
- await orm.update(items).set({ jiraKey: key }).where(eq17(items.id, itemId2));
9124
+ await orm.update(items).set({ jiraKey: key }).where(eq18(items.id, itemId2));
9024
9125
  console.log(
9025
9126
  chalk64.green(`Associated ${key} with item ${formatItemId(itemId2)}.`),
9026
9127
  summary ? chalk64.dim(`(${summary})`) : ""
@@ -9034,10 +9135,10 @@ function registerAssociateJiraCommand(cmd) {
9034
9135
 
9035
9136
  // src/commands/backlog/comment/index.ts
9036
9137
  import chalk65 from "chalk";
9037
- async function comment(id, text11) {
9138
+ async function comment(id, text16) {
9038
9139
  const found = await findOneItem(id);
9039
9140
  if (!found) process.exit(1);
9040
- await appendComment(found.orm, found.item.id, text11);
9141
+ await appendComment(found.orm, found.item.id, text16);
9041
9142
  console.log(
9042
9143
  chalk65.green(`Comment added to item ${formatItemId(found.item.id)}.`)
9043
9144
  );
@@ -9142,9 +9243,9 @@ function readLine(dump, start3) {
9142
9243
  return { text: dump.subarray(start3, eol).toString("utf8"), next: eol + 1 };
9143
9244
  }
9144
9245
  function parseHeader(dump) {
9145
- const { text: text11, next: next3 } = readLine(dump, 0);
9246
+ const { text: text16, next: next3 } = readLine(dump, 0);
9146
9247
  try {
9147
- return { header: JSON.parse(text11), bodyStart: next3 };
9248
+ return { header: JSON.parse(text16), bodyStart: next3 };
9148
9249
  } catch {
9149
9250
  return invalid("header is not valid JSON.");
9150
9251
  }
@@ -9153,9 +9254,9 @@ function parseSections(dump, bodyStart) {
9153
9254
  const sections = /* @__PURE__ */ new Map();
9154
9255
  let cursor = bodyStart;
9155
9256
  while (cursor < dump.length) {
9156
- const { text: text11, next: next3 } = readLine(dump, cursor);
9157
- const match = text11.match(/^@table (\S+) (\d+)$/);
9158
- if (!match) invalid(`malformed table marker "${text11}".`);
9257
+ const { text: text16, next: next3 } = readLine(dump, cursor);
9258
+ const match = text16.match(/^@table (\S+) (\d+)$/);
9259
+ if (!match) invalid(`malformed table marker "${text16}".`);
9159
9260
  const [, name, bytes] = match;
9160
9261
  const end = next3 + Number(bytes);
9161
9262
  if (end > dump.length) invalid(`section "${name}" overruns the dump.`);
@@ -9231,8 +9332,8 @@ async function readStdinBuffer() {
9231
9332
  import { finished } from "stream/promises";
9232
9333
  import { from as copyFrom } from "pg-copy-streams";
9233
9334
  async function copyTableIn(client, table, data) {
9234
- const sql15 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
9235
- const stream = client.query(copyFrom(sql15));
9335
+ const sql20 = `COPY ${table.name} (${table.columns.join(", ")}) FROM STDIN`;
9336
+ const stream = client.query(copyFrom(sql20));
9236
9337
  stream.end(data);
9237
9338
  await finished(stream);
9238
9339
  }
@@ -9277,8 +9378,8 @@ async function replaceData(client, parsed) {
9277
9378
  await copyTableIn(client, table, data);
9278
9379
  }
9279
9380
  for (const col of await introspectIdentityColumns(client)) {
9280
- const { text: text11, values } = resyncIdentitySql(col);
9281
- await client.query(text11, values);
9381
+ const { text: text16, values } = resyncIdentitySql(col);
9382
+ await client.query(text16, values);
9282
9383
  }
9283
9384
  }
9284
9385
  async function restore(client, parsed) {
@@ -9329,22 +9430,22 @@ function registerImportCommand(cmd) {
9329
9430
  import chalk71 from "chalk";
9330
9431
 
9331
9432
  // src/commands/backlog/insertPhaseAt.ts
9332
- import { count as count2, eq as eq19 } from "drizzle-orm";
9433
+ import { count as count2, eq as eq20 } from "drizzle-orm";
9333
9434
 
9334
9435
  // src/commands/backlog/shiftPhasesUp.ts
9335
- import { and as and7, desc as desc3, eq as eq18, gte } from "drizzle-orm";
9436
+ import { and as and8, desc as desc3, eq as eq19, gte } from "drizzle-orm";
9336
9437
  async function shiftPhasesUp(db, itemId2, fromIdx) {
9337
- const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and7(eq18(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc3(planPhases.idx));
9438
+ const toShift = await db.select({ idx: planPhases.idx }).from(planPhases).where(and8(eq19(planPhases.itemId, itemId2), gte(planPhases.idx, fromIdx))).orderBy(desc3(planPhases.idx));
9338
9439
  for (const p of toShift) {
9339
- await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and7(eq18(planTasks.itemId, itemId2), eq18(planTasks.phaseIdx, p.idx)));
9340
- await db.update(planPhases).set({ idx: p.idx + 1 }).where(and7(eq18(planPhases.itemId, itemId2), eq18(planPhases.idx, p.idx)));
9440
+ await db.update(planTasks).set({ phaseIdx: p.idx + 1 }).where(and8(eq19(planTasks.itemId, itemId2), eq19(planTasks.phaseIdx, p.idx)));
9441
+ await db.update(planPhases).set({ idx: p.idx + 1 }).where(and8(eq19(planPhases.itemId, itemId2), eq19(planPhases.idx, p.idx)));
9341
9442
  }
9342
9443
  }
9343
9444
 
9344
9445
  // src/commands/backlog/insertPhaseAt.ts
9345
9446
  async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks, currentPhase) {
9346
9447
  await orm.transaction(async (tx) => {
9347
- const [row] = await tx.select({ cnt: count2() }).from(planPhases).where(eq19(planPhases.itemId, itemId2));
9448
+ const [row] = await tx.select({ cnt: count2() }).from(planPhases).where(eq20(planPhases.itemId, itemId2));
9348
9449
  const phaseCount = row?.cnt ?? 0;
9349
9450
  await shiftPhasesUp(tx, itemId2, phaseIdx);
9350
9451
  await tx.insert(planPhases).values({ itemId: itemId2, idx: phaseIdx, name, manualChecks });
@@ -9353,17 +9454,17 @@ async function insertPhaseAt(orm, itemId2, phaseIdx, name, tasks, manualChecks,
9353
9454
  }
9354
9455
  if (currentPhase !== void 0 && currentPhase - 1 >= phaseIdx) {
9355
9456
  const atReviewSlot = currentPhase - 1 >= phaseCount;
9356
- await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq19(items.id, itemId2));
9457
+ await tx.update(items).set({ currentPhase: atReviewSlot ? phaseIdx + 1 : currentPhase + 1 }).where(eq20(items.id, itemId2));
9357
9458
  }
9358
9459
  });
9359
9460
  }
9360
9461
 
9361
9462
  // src/commands/backlog/insertSubtask.ts
9362
- import { sql as sql8 } from "drizzle-orm";
9463
+ import { sql as sql12 } from "drizzle-orm";
9363
9464
  async function insertSubtask(orm, itemId2, title, description) {
9364
9465
  await orm.insert(itemSubtasks).values({
9365
9466
  itemId: itemId2,
9366
- idx: sql8`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
9467
+ idx: sql12`(SELECT COALESCE(MAX(${itemSubtasks.idx}) + 1, 0) FROM ${itemSubtasks} WHERE ${itemSubtasks.itemId} = ${itemId2})`,
9367
9468
  title,
9368
9469
  description: description ?? null,
9369
9470
  status: "todo"
@@ -9487,9 +9588,9 @@ import chalk73 from "chalk";
9487
9588
 
9488
9589
  // src/commands/backlog/resolveInsertPosition.ts
9489
9590
  import chalk72 from "chalk";
9490
- import { count as count3, eq as eq20 } from "drizzle-orm";
9591
+ import { count as count3, eq as eq21 } from "drizzle-orm";
9491
9592
  async function resolveInsertPosition(orm, itemId2, position) {
9492
- const [row] = await orm.select({ cnt: count3() }).from(planPhases).where(eq20(planPhases.itemId, itemId2));
9593
+ const [row] = await orm.select({ cnt: count3() }).from(planPhases).where(eq21(planPhases.itemId, itemId2));
9493
9594
  const phaseCount = row?.cnt ?? 0;
9494
9595
  if (position === void 0) return phaseCount;
9495
9596
  const pos = Number.parseInt(position, 10);
@@ -9617,9 +9718,9 @@ function hasCycle(adjacency, fromId, toId) {
9617
9718
  }
9618
9719
 
9619
9720
  // src/commands/backlog/loadDependencyGraph.ts
9620
- import { eq as eq21 } from "drizzle-orm";
9721
+ import { eq as eq22 } from "drizzle-orm";
9621
9722
  async function loadDependencyGraph(orm) {
9622
- const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq21(links.type, "depends-on"));
9723
+ const rows = await orm.select({ itemId: links.itemId, targetId: links.targetId }).from(links).where(eq22(links.type, "depends-on"));
9623
9724
  const graph = /* @__PURE__ */ new Map();
9624
9725
  for (const { itemId: itemId2, targetId } of rows) {
9625
9726
  const bucket = graph.get(itemId2);
@@ -9686,7 +9787,7 @@ async function link(fromId, toId, opts) {
9686
9787
 
9687
9788
  // src/commands/backlog/unlink.ts
9688
9789
  import chalk77 from "chalk";
9689
- import { and as and8, eq as eq22 } from "drizzle-orm";
9790
+ import { and as and9, eq as eq23 } from "drizzle-orm";
9690
9791
  async function unlink(fromId, toId) {
9691
9792
  const fromNum = parseItemId(fromId);
9692
9793
  const toNum = parseItemId(toId);
@@ -9710,7 +9811,7 @@ async function unlink(fromId, toId) {
9710
9811
  );
9711
9812
  return;
9712
9813
  }
9713
- await orm.delete(links).where(and8(eq22(links.itemId, fromNum), eq22(links.targetId, toNum)));
9814
+ await orm.delete(links).where(and9(eq23(links.itemId, fromNum), eq23(links.targetId, toNum)));
9714
9815
  console.log(
9715
9816
  chalk77.green(
9716
9817
  `Removed link from ${formatItemId(fromNum)} to ${formatItemId(toNum)}.`
@@ -9730,7 +9831,7 @@ function registerLinkCommands(cmd) {
9730
9831
 
9731
9832
  // src/commands/backlog/move-repo/index.ts
9732
9833
  import chalk79 from "chalk";
9733
- import { eq as eq24 } from "drizzle-orm";
9834
+ import { eq as eq25 } from "drizzle-orm";
9734
9835
 
9735
9836
  // src/commands/backlog/move-repo/confirmMove.ts
9736
9837
  import chalk78 from "chalk";
@@ -9745,9 +9846,9 @@ async function confirmMove(cnt, oldOrigin, newOrigin) {
9745
9846
  }
9746
9847
 
9747
9848
  // src/commands/backlog/move-repo/countByOrigin.ts
9748
- import { count as count4, eq as eq23 } from "drizzle-orm";
9849
+ import { count as count4, eq as eq24 } from "drizzle-orm";
9749
9850
  async function countByOrigin(orm, origin) {
9750
- const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq23(items.origin, origin));
9851
+ const [{ cnt }] = await orm.select({ cnt: count4() }).from(items).where(eq24(items.origin, origin));
9751
9852
  return cnt;
9752
9853
  }
9753
9854
 
@@ -9790,7 +9891,7 @@ async function moveRepo(oldOriginRaw, newOriginRaw, options2 = {}) {
9790
9891
  console.log(chalk79.yellow("Move cancelled; no changes made."));
9791
9892
  return;
9792
9893
  }
9793
- await orm.update(items).set({ origin: newOrigin }).where(eq24(items.origin, oldOrigin));
9894
+ await orm.update(items).set({ origin: newOrigin }).where(eq25(items.origin, oldOrigin));
9794
9895
  console.log(
9795
9896
  chalk79.green(
9796
9897
  `Moved ${pluralItems(cnt)} from "${oldOrigin}" to "${newOrigin}".`
@@ -10155,10 +10256,10 @@ async function start(id) {
10155
10256
 
10156
10257
  // src/commands/backlog/stop/index.ts
10157
10258
  import chalk91 from "chalk";
10158
- import { and as and9, eq as eq25 } from "drizzle-orm";
10259
+ import { and as and10, eq as eq26 } from "drizzle-orm";
10159
10260
  async function stop() {
10160
10261
  const { orm } = await getReady();
10161
- const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and9(eq25(items.status, "in-progress"), eq25(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
10262
+ const stopped = await orm.update(items).set({ status: "todo", currentPhase: 1 }).where(and10(eq26(items.status, "in-progress"), eq26(items.origin, getOrigin()))).returning({ id: items.id, name: items.name });
10162
10263
  if (stopped.length === 0) {
10163
10264
  console.log(chalk91.yellow("No in-progress items to stop."));
10164
10265
  return;
@@ -10275,13 +10376,13 @@ async function findSubtask(id, index3) {
10275
10376
  }
10276
10377
 
10277
10378
  // src/commands/backlog/updateSubtask.ts
10278
- import { and as and10, eq as eq26 } from "drizzle-orm";
10379
+ import { and as and11, eq as eq27 } from "drizzle-orm";
10279
10380
  async function updateSubtask(orm, itemId2, idx, fields) {
10280
10381
  const set = {};
10281
10382
  if (fields.title !== void 0) set.title = fields.title;
10282
10383
  if (fields.description !== void 0) set.description = fields.description;
10283
10384
  if (fields.status !== void 0) set.status = fields.status;
10284
- const [row] = await orm.update(itemSubtasks).set(set).where(and10(eq26(itemSubtasks.itemId, itemId2), eq26(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
10385
+ const [row] = await orm.update(itemSubtasks).set(set).where(and11(eq27(itemSubtasks.itemId, itemId2), eq27(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
10285
10386
  return row?.title;
10286
10387
  }
10287
10388
 
@@ -10336,16 +10437,16 @@ async function editSubtask(id, index3, options2) {
10336
10437
  import chalk97 from "chalk";
10337
10438
 
10338
10439
  // src/commands/backlog/deleteSubtask.ts
10339
- import { and as and11, asc as asc6, eq as eq27 } from "drizzle-orm";
10440
+ import { and as and12, asc as asc6, eq as eq28 } from "drizzle-orm";
10340
10441
  async function deleteSubtask(orm, itemId2, idx) {
10341
- const [row] = await orm.delete(itemSubtasks).where(and11(eq27(itemSubtasks.itemId, itemId2), eq27(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
10442
+ const [row] = await orm.delete(itemSubtasks).where(and12(eq28(itemSubtasks.itemId, itemId2), eq28(itemSubtasks.idx, idx))).returning({ title: itemSubtasks.title });
10342
10443
  if (!row) return void 0;
10343
- const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(eq27(itemSubtasks.itemId, itemId2)).orderBy(asc6(itemSubtasks.idx));
10444
+ const remaining = await orm.select({ idx: itemSubtasks.idx }).from(itemSubtasks).where(eq28(itemSubtasks.itemId, itemId2)).orderBy(asc6(itemSubtasks.idx));
10344
10445
  for (let i = 0; i < remaining.length; i++) {
10345
10446
  const oldIdx = remaining[i].idx;
10346
10447
  if (oldIdx === i) continue;
10347
10448
  await orm.update(itemSubtasks).set({ idx: i }).where(
10348
- and11(eq27(itemSubtasks.itemId, itemId2), eq27(itemSubtasks.idx, oldIdx))
10449
+ and12(eq28(itemSubtasks.itemId, itemId2), eq28(itemSubtasks.idx, oldIdx))
10349
10450
  );
10350
10451
  }
10351
10452
  return row.title;
@@ -10414,20 +10515,20 @@ function registerSubtaskCommands(cmd) {
10414
10515
 
10415
10516
  // src/commands/backlog/movePhase.ts
10416
10517
  import chalk99 from "chalk";
10417
- import { count as count6, eq as eq30 } from "drizzle-orm";
10518
+ import { count as count6, eq as eq31 } from "drizzle-orm";
10418
10519
 
10419
10520
  // src/commands/backlog/reorderPhaseRows.ts
10420
- import { and as and13, asc as asc8, eq as eq29 } from "drizzle-orm";
10521
+ import { and as and14, asc as asc8, eq as eq30 } from "drizzle-orm";
10421
10522
 
10422
10523
  // src/commands/backlog/reindexPhases.ts
10423
- import { and as and12, asc as asc7, count as count5, eq as eq28 } from "drizzle-orm";
10524
+ import { and as and13, asc as asc7, count as count5, eq as eq29 } from "drizzle-orm";
10424
10525
  async function reindexPhases(db, itemId2) {
10425
- const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq28(planPhases.itemId, itemId2)).orderBy(asc7(planPhases.idx));
10526
+ const remaining = await db.select({ idx: planPhases.idx }).from(planPhases).where(eq29(planPhases.itemId, itemId2)).orderBy(asc7(planPhases.idx));
10426
10527
  for (let i = 0; i < remaining.length; i++) {
10427
10528
  const oldIdx = remaining[i].idx;
10428
10529
  if (oldIdx === i) continue;
10429
- await db.update(planTasks).set({ phaseIdx: i }).where(and12(eq28(planTasks.itemId, itemId2), eq28(planTasks.phaseIdx, oldIdx)));
10430
- await db.update(planPhases).set({ idx: i }).where(and12(eq28(planPhases.itemId, itemId2), eq28(planPhases.idx, oldIdx)));
10530
+ await db.update(planTasks).set({ phaseIdx: i }).where(and13(eq29(planTasks.itemId, itemId2), eq29(planTasks.phaseIdx, oldIdx)));
10531
+ await db.update(planPhases).set({ idx: i }).where(and13(eq29(planPhases.itemId, itemId2), eq29(planPhases.idx, oldIdx)));
10431
10532
  }
10432
10533
  }
10433
10534
  async function adjustCurrentPhase(db, item, removedIdx) {
@@ -10435,24 +10536,24 @@ async function adjustCurrentPhase(db, item, removedIdx) {
10435
10536
  if (currentPhase === void 0) return;
10436
10537
  const currentIdx = currentPhase - 1;
10437
10538
  if (removedIdx < currentIdx) {
10438
- await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq28(items.id, item.id));
10539
+ await db.update(items).set({ currentPhase: currentPhase - 1 }).where(eq29(items.id, item.id));
10439
10540
  return;
10440
10541
  }
10441
10542
  if (removedIdx !== currentIdx) return;
10442
- const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq28(planPhases.itemId, item.id));
10543
+ const [row] = await db.select({ cnt: count5() }).from(planPhases).where(eq29(planPhases.itemId, item.id));
10443
10544
  const cnt = row?.cnt ?? 0;
10444
- await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq28(items.id, item.id));
10545
+ await db.update(items).set({ currentPhase: cnt === 0 ? null : Math.min(currentPhase, cnt) }).where(eq29(items.id, item.id));
10445
10546
  }
10446
10547
 
10447
10548
  // src/commands/backlog/reorderPhaseRows.ts
10448
10549
  async function reorderPhaseRows(orm, itemId2, fromIdx, toIdx) {
10449
10550
  await orm.transaction(async (tx) => {
10450
- const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and13(eq29(planPhases.itemId, itemId2), eq29(planPhases.idx, fromIdx)));
10451
- const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and13(eq29(planTasks.itemId, itemId2), eq29(planTasks.phaseIdx, fromIdx))).orderBy(asc8(planTasks.idx));
10551
+ const [phaseRow] = await tx.select({ name: planPhases.name, manualChecks: planPhases.manualChecks }).from(planPhases).where(and14(eq30(planPhases.itemId, itemId2), eq30(planPhases.idx, fromIdx)));
10552
+ const tasks = await tx.select({ idx: planTasks.idx, task: planTasks.task }).from(planTasks).where(and14(eq30(planTasks.itemId, itemId2), eq30(planTasks.phaseIdx, fromIdx))).orderBy(asc8(planTasks.idx));
10452
10553
  await tx.delete(planTasks).where(
10453
- and13(eq29(planTasks.itemId, itemId2), eq29(planTasks.phaseIdx, fromIdx))
10554
+ and14(eq30(planTasks.itemId, itemId2), eq30(planTasks.phaseIdx, fromIdx))
10454
10555
  );
10455
- await tx.delete(planPhases).where(and13(eq29(planPhases.itemId, itemId2), eq29(planPhases.idx, fromIdx)));
10556
+ await tx.delete(planPhases).where(and14(eq30(planPhases.itemId, itemId2), eq30(planPhases.idx, fromIdx)));
10456
10557
  await reindexPhases(tx, itemId2);
10457
10558
  await shiftPhasesUp(tx, itemId2, toIdx);
10458
10559
  await tx.insert(planPhases).values({
@@ -10493,7 +10594,7 @@ async function movePhase(id, from, to) {
10493
10594
  if (!found) return;
10494
10595
  const { orm, item } = found;
10495
10596
  const itemId2 = item.id;
10496
- const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(eq30(planPhases.itemId, itemId2));
10597
+ const [row] = await orm.select({ cnt: count6() }).from(planPhases).where(eq31(planPhases.itemId, itemId2));
10497
10598
  const phaseCount = row?.cnt ?? 0;
10498
10599
  const fromIdx = toIndex(from, phaseCount);
10499
10600
  if (fromIdx === void 0) return;
@@ -10509,22 +10610,22 @@ async function movePhase(id, from, to) {
10509
10610
  import chalk101 from "chalk";
10510
10611
 
10511
10612
  // src/commands/backlog/applyPhaseUpdate.ts
10512
- import { and as and14, eq as eq31 } from "drizzle-orm";
10613
+ import { and as and15, eq as eq32 } from "drizzle-orm";
10513
10614
  async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
10514
10615
  await orm.transaction(async (tx) => {
10515
10616
  if (fields.name) {
10516
10617
  await tx.update(planPhases).set({ name: fields.name }).where(
10517
- and14(eq31(planPhases.itemId, itemId2), eq31(planPhases.idx, phaseIdx))
10618
+ and15(eq32(planPhases.itemId, itemId2), eq32(planPhases.idx, phaseIdx))
10518
10619
  );
10519
10620
  }
10520
10621
  if (fields.manualCheck) {
10521
10622
  await tx.update(planPhases).set({ manualChecks: JSON.stringify(fields.manualCheck) }).where(
10522
- and14(eq31(planPhases.itemId, itemId2), eq31(planPhases.idx, phaseIdx))
10623
+ and15(eq32(planPhases.itemId, itemId2), eq32(planPhases.idx, phaseIdx))
10523
10624
  );
10524
10625
  }
10525
10626
  if (fields.task) {
10526
10627
  await tx.delete(planTasks).where(
10527
- and14(eq31(planTasks.itemId, itemId2), eq31(planTasks.phaseIdx, phaseIdx))
10628
+ and15(eq32(planTasks.itemId, itemId2), eq32(planTasks.phaseIdx, phaseIdx))
10528
10629
  );
10529
10630
  if (fields.task.length) {
10530
10631
  await tx.insert(planTasks).values(
@@ -10542,14 +10643,14 @@ async function applyPhaseUpdate(orm, itemId2, phaseIdx, fields) {
10542
10643
 
10543
10644
  // src/commands/backlog/findPhase.ts
10544
10645
  import chalk100 from "chalk";
10545
- import { and as and15, count as count7, eq as eq32 } from "drizzle-orm";
10646
+ import { and as and16, count as count7, eq as eq33 } from "drizzle-orm";
10546
10647
  async function findPhase(id, phase) {
10547
10648
  const found = await findOneItem(id);
10548
10649
  if (!found) return void 0;
10549
10650
  const { orm, item } = found;
10550
10651
  const itemId2 = item.id;
10551
10652
  const phaseIdx = Number.parseInt(phase, 10) - 1;
10552
- const [row] = await orm.select({ cnt: count7() }).from(planPhases).where(and15(eq32(planPhases.itemId, itemId2), eq32(planPhases.idx, phaseIdx)));
10653
+ const [row] = await orm.select({ cnt: count7() }).from(planPhases).where(and16(eq33(planPhases.itemId, itemId2), eq33(planPhases.idx, phaseIdx)));
10553
10654
  if (!row || row.cnt === 0) {
10554
10655
  console.log(
10555
10656
  chalk100.red(
@@ -10722,16 +10823,16 @@ function registerUpdatePhaseCommand(cmd) {
10722
10823
 
10723
10824
  // src/commands/backlog/removePhase.ts
10724
10825
  import chalk102 from "chalk";
10725
- import { and as and16, eq as eq33 } from "drizzle-orm";
10826
+ import { and as and17, eq as eq34 } from "drizzle-orm";
10726
10827
  async function removePhase(id, phase) {
10727
10828
  const found = await findPhase(id, phase);
10728
10829
  if (!found) return;
10729
10830
  const { item, orm, itemId: itemId2, phaseIdx } = found;
10730
10831
  await orm.transaction(async (tx) => {
10731
10832
  await tx.delete(planTasks).where(
10732
- and16(eq33(planTasks.itemId, itemId2), eq33(planTasks.phaseIdx, phaseIdx))
10833
+ and17(eq34(planTasks.itemId, itemId2), eq34(planTasks.phaseIdx, phaseIdx))
10733
10834
  );
10734
- await tx.delete(planPhases).where(and16(eq33(planPhases.itemId, itemId2), eq33(planPhases.idx, phaseIdx)));
10835
+ await tx.delete(planPhases).where(and17(eq34(planPhases.itemId, itemId2), eq34(planPhases.idx, phaseIdx)));
10735
10836
  await reindexPhases(tx, itemId2);
10736
10837
  await adjustCurrentPhase(tx, item, phaseIdx);
10737
10838
  });
@@ -10744,7 +10845,7 @@ async function removePhase(id, phase) {
10744
10845
 
10745
10846
  // src/commands/backlog/update/index.ts
10746
10847
  import chalk104 from "chalk";
10747
- import { eq as eq34 } from "drizzle-orm";
10848
+ import { eq as eq35 } from "drizzle-orm";
10748
10849
 
10749
10850
  // src/commands/backlog/update/applyAcMutations.ts
10750
10851
  function hasAcMutations(options2) {
@@ -10824,7 +10925,7 @@ async function update(id, options2) {
10824
10925
  if (!built) return;
10825
10926
  const { orm } = found;
10826
10927
  const itemId2 = found.item.id;
10827
- await orm.update(items).set(built.set).where(eq34(items.id, itemId2));
10928
+ await orm.update(items).set(built.set).where(eq35(items.id, itemId2));
10828
10929
  console.log(
10829
10930
  chalk104.green(`Updated ${built.fields} on item ${formatItemId(itemId2)}.`)
10830
10931
  );
@@ -11125,8 +11226,8 @@ var RAW_BUILTIN_DENIES = [
11125
11226
  regex
11126
11227
  }))
11127
11228
  ];
11128
- function matchBuiltinDeny(text11) {
11129
- return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text11));
11229
+ function matchBuiltinDeny(text16) {
11230
+ return RAW_BUILTIN_DENIES.find((rule) => rule.regex.test(text16));
11130
11231
  }
11131
11232
  function toDecision(rule) {
11132
11233
  if (!rule) return void 0;
@@ -11866,8 +11967,8 @@ function formatHuman(cli, commands) {
11866
11967
  `];
11867
11968
  for (const cmd of sorted) {
11868
11969
  const full = `${cli} ${cmd.path.join(" ")}`;
11869
- const text11 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
11870
- lines.push(`${prefix(classifyVerb(cmd.path))}${text11}`);
11970
+ const text16 = cmd.description ? `${full} \u2014 ${cmd.description}` : full;
11971
+ lines.push(`${prefix(classifyVerb(cmd.path))}${text16}`);
11871
11972
  }
11872
11973
  return lines.join("\n");
11873
11974
  }
@@ -12146,38 +12247,38 @@ import chalk110 from "chalk";
12146
12247
  // src/commands/codeComment/validateCommentText.ts
12147
12248
  var MAX_COMMENT_LENGTH = 50;
12148
12249
  function validateCommentText(raw, isHash = false) {
12149
- const text11 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
12150
- if (/[\r\n]/.test(text11)) {
12250
+ const text16 = isHash ? raw.replace(/^#\s?/, "") : raw.replace(/^\/\/\s?/, "");
12251
+ if (/[\r\n]/.test(text16)) {
12151
12252
  return {
12152
12253
  ok: false,
12153
12254
  reason: "Comment must be a single line \u2014 multi-line comments are not allowed."
12154
12255
  };
12155
12256
  }
12156
- if (!isHash && (text11.includes("/*") || text11.includes("*/"))) {
12257
+ if (!isHash && (text16.includes("/*") || text16.includes("*/"))) {
12157
12258
  return {
12158
12259
  ok: false,
12159
12260
  reason: "Block comments (/* */) are not allowed \u2014 only single-line // comments."
12160
12261
  };
12161
12262
  }
12162
- if (text11.length > MAX_COMMENT_LENGTH) {
12263
+ if (text16.length > MAX_COMMENT_LENGTH) {
12163
12264
  return {
12164
12265
  ok: false,
12165
- reason: `Comment text is ${text11.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
12266
+ reason: `Comment text is ${text16.length} chars; the cap is ${MAX_COMMENT_LENGTH}. Make it shorter or, better, make the code self-documenting.`
12166
12267
  };
12167
12268
  }
12168
- return { ok: true, text: text11 };
12269
+ return { ok: true, text: text16 };
12169
12270
  }
12170
12271
 
12171
12272
  // src/commands/codeComment/issuePin.ts
12172
12273
  import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync25 } from "fs";
12173
12274
  import { randomInt } from "crypto";
12174
- function issuePin(file, lineNumber, text11) {
12275
+ function issuePin(file, lineNumber, text16) {
12175
12276
  const pin = generatePin();
12176
12277
  mkdirSync14(getRestrictedDir(), { recursive: true });
12177
12278
  sweepRestrictedDir();
12178
12279
  writeFileSync25(
12179
12280
  getPinStatePath(pin),
12180
- JSON.stringify({ pin, file, line: lineNumber, text: text11 })
12281
+ JSON.stringify({ pin, file, line: lineNumber, text: text16 })
12181
12282
  );
12182
12283
  return showNotification({
12183
12284
  title: "assist code-comment pin",
@@ -12189,7 +12290,7 @@ function generatePin() {
12189
12290
  }
12190
12291
 
12191
12292
  // src/commands/codeComment/codeCommentSet.ts
12192
- function codeCommentSet(file, line, text11) {
12293
+ function codeCommentSet(file, line, text16) {
12193
12294
  const lineNumber = Number.parseInt(line, 10);
12194
12295
  if (!Number.isInteger(lineNumber) || lineNumber < 1) {
12195
12296
  console.error(chalk110.red(`Invalid line number: ${line}`));
@@ -12198,7 +12299,7 @@ function codeCommentSet(file, line, text11) {
12198
12299
  }
12199
12300
  const hash = isHashCommentFile(file);
12200
12301
  const marker = hash ? "#" : "//";
12201
- const validation = validateCommentText(text11, hash);
12302
+ const validation = validateCommentText(text16, hash);
12202
12303
  if (!validation.ok) {
12203
12304
  console.error(chalk110.red(`Refused: ${validation.reason}`));
12204
12305
  console.error(chalk110.red("No pin issued."));
@@ -14272,12 +14373,12 @@ function isSourceFile(filePath) {
14272
14373
  if (!filePath) return false;
14273
14374
  return SOURCE_EXTENSIONS.some((ext) => filePath.endsWith(ext));
14274
14375
  }
14275
- function blankNonNewline2(text11) {
14276
- return text11.replace(/[^\n]/g, " ");
14376
+ function blankNonNewline2(text16) {
14377
+ return text16.replace(/[^\n]/g, " ");
14277
14378
  }
14278
- function extractComments(text11) {
14379
+ function extractComments(text16) {
14279
14380
  const comments3 = [];
14280
- let work = text11.replace(
14381
+ let work = text16.replace(
14281
14382
  /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`/g,
14282
14383
  blankNonNewline2
14283
14384
  );
@@ -14292,11 +14393,11 @@ function extractComments(text11) {
14292
14393
  }
14293
14394
 
14294
14395
  // src/commands/editHook/extractYamlComments.ts
14295
- function blankNonNewline3(text11) {
14296
- return text11.replace(/[^\n]/g, " ");
14396
+ function blankNonNewline3(text16) {
14397
+ return text16.replace(/[^\n]/g, " ");
14297
14398
  }
14298
- function extractYamlComments(text11) {
14299
- const work = text11.replace(
14399
+ function extractYamlComments(text16) {
14400
+ const work = text16.replace(
14300
14401
  /"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'/g,
14301
14402
  blankNonNewline3
14302
14403
  );
@@ -14312,8 +14413,8 @@ function isHeaderLine2(line) {
14312
14413
  const trimmed = line.trim();
14313
14414
  return trimmed === "" || trimmed.startsWith("#");
14314
14415
  }
14315
- function extractShellComments(text11) {
14316
- const lines = text11.split("\n");
14416
+ function extractShellComments(text16) {
14417
+ const lines = text16.split("\n");
14317
14418
  let firstCodeLine = 0;
14318
14419
  while (firstCodeLine < lines.length && isHeaderLine2(lines[firstCodeLine])) {
14319
14420
  firstCodeLine++;
@@ -14683,9 +14784,9 @@ function registerGithub(program2) {
14683
14784
  }
14684
14785
 
14685
14786
  // src/commands/handover/countPendingHandovers.ts
14686
- import { and as and17, eq as eq35, isNull, sql as sql9 } from "drizzle-orm";
14787
+ import { and as and18, eq as eq36, isNull, sql as sql13 } from "drizzle-orm";
14687
14788
  async function countPendingHandovers(orm, origin) {
14688
- const [row] = await orm.select({ count: sql9`count(*)::int` }).from(handovers).where(and17(eq35(handovers.origin, origin), isNull(handovers.recalledAt)));
14789
+ const [row] = await orm.select({ count: sql13`count(*)::int` }).from(handovers).where(and18(eq36(handovers.origin, origin), isNull(handovers.recalledAt)));
14689
14790
  return row?.count ?? 0;
14690
14791
  }
14691
14792
 
@@ -14825,13 +14926,13 @@ async function load2(options2 = {}) {
14825
14926
  }
14826
14927
 
14827
14928
  // src/commands/handover/listPendingHandovers.ts
14828
- import { and as and18, desc as desc4, eq as eq36, isNull as isNull2 } from "drizzle-orm";
14929
+ import { and as and19, desc as desc4, eq as eq37, isNull as isNull2 } from "drizzle-orm";
14829
14930
  async function listPendingHandovers(orm, origin) {
14830
14931
  return orm.select({
14831
14932
  id: handovers.id,
14832
14933
  summary: handovers.summary,
14833
14934
  createdAt: handovers.createdAt
14834
- }).from(handovers).where(and18(eq36(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc4(handovers.createdAt), desc4(handovers.id));
14935
+ }).from(handovers).where(and19(eq37(handovers.origin, origin), isNull2(handovers.recalledAt))).orderBy(desc4(handovers.createdAt), desc4(handovers.id));
14835
14936
  }
14836
14937
 
14837
14938
  // src/commands/handover/printPendingHandovers.ts
@@ -14844,17 +14945,17 @@ async function printPendingHandovers() {
14844
14945
  }
14845
14946
 
14846
14947
  // src/commands/handover/recallHandover.ts
14847
- import { and as and19, desc as desc5, eq as eq37, isNull as isNull3 } from "drizzle-orm";
14948
+ import { and as and20, desc as desc5, eq as eq38, isNull as isNull3 } from "drizzle-orm";
14848
14949
  async function recallHandover(orm, origin, id) {
14849
14950
  const [row] = await orm.select().from(handovers).where(
14850
- and19(
14851
- eq37(handovers.origin, origin),
14951
+ and20(
14952
+ eq38(handovers.origin, origin),
14852
14953
  isNull3(handovers.recalledAt),
14853
- ...id === void 0 ? [] : [eq37(handovers.id, id)]
14954
+ ...id === void 0 ? [] : [eq38(handovers.id, id)]
14854
14955
  )
14855
14956
  ).orderBy(desc5(handovers.createdAt), desc5(handovers.id)).limit(1);
14856
14957
  if (!row) return void 0;
14857
- await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq37(handovers.id, row.id));
14958
+ await orm.update(handovers).set({ recalledAt: /* @__PURE__ */ new Date() }).where(eq38(handovers.id, row.id));
14858
14959
  return row.content;
14859
14960
  }
14860
14961
 
@@ -14908,9 +15009,9 @@ import chalk143 from "chalk";
14908
15009
 
14909
15010
  // src/commands/jira/adfToText.ts
14910
15011
  function renderInline(node) {
14911
- const text11 = node.text ?? "";
14912
- if (node.marks?.some((m) => m.type === "code")) return `\`${text11}\``;
14913
- return text11;
15012
+ const text16 = node.text ?? "";
15013
+ if (node.marks?.some((m) => m.type === "code")) return `\`${text16}\``;
15014
+ return text16;
14914
15015
  }
14915
15016
  function renderChildren(node, indent2) {
14916
15017
  return renderNodes(node.content ?? [], indent2);
@@ -14952,8 +15053,8 @@ function isListNode(node) {
14952
15053
  function renderListChild(child, indent2, pad, marker, isFirst) {
14953
15054
  if (isListNode(child)) return renderNodes([child], indent2 + 1);
14954
15055
  if (child.type !== "paragraph") return renderNode(child, indent2);
14955
- const text11 = renderChildren(child, indent2);
14956
- return isFirst ? `${pad}${marker} ${text11}` : `${pad} ${text11}`;
15056
+ const text16 = renderChildren(child, indent2);
15057
+ return isFirst ? `${pad}${marker} ${text16}` : `${pad} ${text16}`;
14957
15058
  }
14958
15059
  function renderListItem(node, indent2, marker) {
14959
15060
  const pad = " ".repeat(indent2);
@@ -15112,9 +15213,9 @@ function registerDescriptionLaunch(program2, name, slashCommand, description, al
15112
15213
  "[description]",
15113
15214
  `Text to forward to the /${slashCommand} slash command`
15114
15215
  ).description(description).option("--once", "Exit when the initial task completes").option("--resume-session <id>", RESUME_SESSION_FLAG).action(
15115
- (text11, opts) => launchMode(slashCommand, {
15216
+ (text16, opts) => launchMode(slashCommand, {
15116
15217
  once: opts.once,
15117
- description: text11,
15218
+ description: text16,
15118
15219
  resumeSessionId: opts.resumeSession
15119
15220
  })
15120
15221
  );
@@ -15616,8 +15717,8 @@ function dedupeLinks(links2) {
15616
15717
  }
15617
15718
 
15618
15719
  // src/commands/netcap/linkifyMentions.ts
15619
- function linkifyMentions(text11, mentions) {
15620
- let out = text11;
15720
+ function linkifyMentions(text16, mentions) {
15721
+ let out = text16;
15621
15722
  for (const m of mentions) {
15622
15723
  if (m.name && out.includes(m.name)) {
15623
15724
  out = out.replace(m.name, `[${m.name}](${m.url})`);
@@ -15644,13 +15745,13 @@ function resolveAuthor(mentionMap, author) {
15644
15745
  return mentionMap.get(author) ?? { slug: author, url: profileUrl(author) };
15645
15746
  }
15646
15747
  function buildPost(raw, mentionMap, author) {
15647
- const text11 = joinText(raw.text);
15648
- if (!text11) return void 0;
15748
+ const text16 = joinText(raw.text);
15749
+ if (!text16) return void 0;
15649
15750
  const mentions = resolveMentions(raw, mentionMap, author);
15650
15751
  const relatedPosts = [...new Set(raw.related)];
15651
15752
  return {
15652
- text: text11,
15653
- markdown: linkifyMentions(text11, mentions),
15753
+ text: text16,
15754
+ markdown: linkifyMentions(text16, mentions),
15654
15755
  mentions,
15655
15756
  hashtags: [...new Set(raw.hashtags)],
15656
15757
  links: dedupeLinks(raw.links),
@@ -15791,8 +15892,8 @@ function activityUrnOf(update3) {
15791
15892
  return typeof urn === "string" ? urn : void 0;
15792
15893
  }
15793
15894
  function buildVoyagerPost(update3, profiles) {
15794
- const text11 = commentaryText(update3);
15795
- if (!text11) return void 0;
15895
+ const text16 = commentaryText(update3);
15896
+ if (!text16) return void 0;
15796
15897
  const author = resolveVoyagerAuthor(update3);
15797
15898
  const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
15798
15899
  update3,
@@ -15801,8 +15902,8 @@ function buildVoyagerPost(update3, profiles) {
15801
15902
  );
15802
15903
  const activityUrn = activityUrnOf(update3);
15803
15904
  return {
15804
- text: text11,
15805
- markdown: linkifyMentions(text11, mentions),
15905
+ text: text16,
15906
+ markdown: linkifyMentions(text16, mentions),
15806
15907
  mentions,
15807
15908
  hashtags,
15808
15909
  links: links2,
@@ -16306,8 +16407,8 @@ function isWallOfText(lines) {
16306
16407
  if (lines.some(isListLine)) {
16307
16408
  return false;
16308
16409
  }
16309
- const text11 = lines.join(" ").trim();
16310
- return text11.length > MAX_PARAGRAPH_CHARS || countSentences(text11) > MAX_PARAGRAPH_SENTENCES;
16410
+ const text16 = lines.join(" ").trim();
16411
+ return text16.length > MAX_PARAGRAPH_CHARS || countSentences(text16) > MAX_PARAGRAPH_SENTENCES;
16311
16412
  }
16312
16413
  function validatePrContent(title, body) {
16313
16414
  if (title.toLowerCase().includes("claude")) {
@@ -18061,9 +18162,9 @@ function resolveImports(target, dependencies, sourceFile, statements = []) {
18061
18162
  function extractTexts(target, allFunctions, statements) {
18062
18163
  const stmtTexts = statements.map((v) => v.getFullText().trim());
18063
18164
  const fnTexts = allFunctions.map((fn) => {
18064
- const text11 = fn.getFullText().trim();
18065
- if (fn === target && !text11.startsWith("export ")) return `export ${text11}`;
18066
- return text11;
18165
+ const text16 = fn.getFullText().trim();
18166
+ if (fn === target && !text16.startsWith("export ")) return `export ${text16}`;
18167
+ return text16;
18067
18168
  });
18068
18169
  return [...stmtTexts, ...fnTexts];
18069
18170
  }
@@ -19913,9 +20014,9 @@ var MultiSpinner = class {
19913
20014
  elapsedPrefix: prefix2
19914
20015
  });
19915
20016
  }
19916
- failRemaining(text11) {
20017
+ failRemaining(text16) {
19917
20018
  for (const entry of this.entries) {
19918
- if (entry.state === "running") this.resolve(entry, "failed", text11);
20019
+ if (entry.state === "running") this.resolve(entry, "failed", text16);
19919
20020
  }
19920
20021
  }
19921
20022
  add(entry) {
@@ -19928,14 +20029,14 @@ var MultiSpinner = class {
19928
20029
  set text(value) {
19929
20030
  entry.text = value;
19930
20031
  },
19931
- succeed: (text11) => this.resolve(entry, "succeeded", text11),
19932
- fail: (text11) => this.resolve(entry, "failed", text11)
20032
+ succeed: (text16) => this.resolve(entry, "succeeded", text16),
20033
+ fail: (text16) => this.resolve(entry, "failed", text16)
19933
20034
  };
19934
20035
  }
19935
- resolve(entry, state, text11) {
20036
+ resolve(entry, state, text16) {
19936
20037
  if (entry.state !== "running") return;
19937
20038
  entry.state = state;
19938
- if (text11 !== void 0) entry.text = text11;
20039
+ if (text16 !== void 0) entry.text = text16;
19939
20040
  entry.elapsedStart = void 0;
19940
20041
  this.render();
19941
20042
  this.maybeFinish();
@@ -20010,12 +20111,12 @@ function skippedCodexResult(outputPath) {
20010
20111
  // src/commands/review/formatReviewerFailure.ts
20011
20112
  var FAST_FAIL_MS = 1e3;
20012
20113
  var STDOUT_TAIL_LINES = 20;
20013
- function indent(text11) {
20014
- return text11.split(/\r?\n/).map((line) => ` ${line}`);
20114
+ function indent(text16) {
20115
+ return text16.split(/\r?\n/).map((line) => ` ${line}`);
20015
20116
  }
20016
- function tailLines(text11, maxLines) {
20017
- const lines = text11.split(/\r?\n/);
20018
- return lines.length <= maxLines ? text11 : lines.slice(-maxLines).join("\n");
20117
+ function tailLines(text16, maxLines) {
20118
+ const lines = text16.split(/\r?\n/);
20119
+ return lines.length <= maxLines ? text16 : lines.slice(-maxLines).join("\n");
20019
20120
  }
20020
20121
  function isFastFail(input) {
20021
20122
  return input.exitCode !== 0 && input.elapsedMs !== void 0 && input.elapsedMs < FAST_FAIL_MS;
@@ -20950,8 +21051,8 @@ function filterToSql(filter) {
20950
21051
  // src/commands/seq/fetchSeqData.ts
20951
21052
  function buildDataParams(filter, count8, from, to) {
20952
21053
  const sqlFilter = filterToSql(filter);
20953
- const sql15 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count8}`;
20954
- const params = new URLSearchParams({ q: sql15 });
21054
+ const sql20 = `select @Timestamp, @Level, @Exception, @Message from stream where ${sqlFilter} order by @Timestamp desc limit ${count8}`;
21055
+ const params = new URLSearchParams({ q: sql20 });
20955
21056
  if (from) params.set("rangeStartUtc", from);
20956
21057
  if (to) params.set("rangeEndUtc", to);
20957
21058
  return params;
@@ -21212,26 +21313,26 @@ import chalk190 from "chalk";
21212
21313
  // src/commands/sql/loadConnections.ts
21213
21314
  function loadConnections3() {
21214
21315
  const raw = loadGlobalConfigRaw();
21215
- const sql15 = raw.sql;
21216
- return sql15?.connections ?? [];
21316
+ const sql20 = raw.sql;
21317
+ return sql20?.connections ?? [];
21217
21318
  }
21218
21319
  function saveConnections3(connections) {
21219
21320
  const raw = loadGlobalConfigRaw();
21220
- const sql15 = raw.sql ?? {};
21221
- sql15.connections = connections;
21222
- raw.sql = sql15;
21321
+ const sql20 = raw.sql ?? {};
21322
+ sql20.connections = connections;
21323
+ raw.sql = sql20;
21223
21324
  saveGlobalConfig(raw);
21224
21325
  }
21225
21326
  function getDefaultConnection2() {
21226
21327
  const raw = loadGlobalConfigRaw();
21227
- const sql15 = raw.sql;
21228
- return sql15?.defaultConnection;
21328
+ const sql20 = raw.sql;
21329
+ return sql20?.defaultConnection;
21229
21330
  }
21230
21331
  function setDefaultConnection2(name) {
21231
21332
  const raw = loadGlobalConfigRaw();
21232
- const sql15 = raw.sql ?? {};
21233
- sql15.defaultConnection = name;
21234
- raw.sql = sql15;
21333
+ const sql20 = raw.sql ?? {};
21334
+ sql20.defaultConnection = name;
21335
+ raw.sql = sql20;
21235
21336
  saveGlobalConfig(raw);
21236
21337
  }
21237
21338
 
@@ -21302,9 +21403,9 @@ function resolveConnection3(name) {
21302
21403
  }
21303
21404
 
21304
21405
  // src/commands/sql/sqlConnect.ts
21305
- import sql10 from "mssql";
21406
+ import sql14 from "mssql";
21306
21407
  async function sqlConnect(conn) {
21307
- return await sql10.connect({
21408
+ return await sql14.connect({
21308
21409
  server: conn.server,
21309
21410
  port: conn.port,
21310
21411
  user: conn.user,
@@ -21381,11 +21482,11 @@ var MUTATION_PATTERN = new RegExp(
21381
21482
  `\\b(${MUTATION_KEYWORDS.join("|")})\\b`,
21382
21483
  "i"
21383
21484
  );
21384
- function stripComments(sql15) {
21385
- return sql15.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
21485
+ function stripComments(sql20) {
21486
+ return sql20.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/--[^\n]*/g, " ");
21386
21487
  }
21387
- function isMutation(sql15) {
21388
- const stripped = stripComments(sql15);
21488
+ function isMutation(sql20) {
21489
+ const stripped = stripComments(sql20);
21389
21490
  if (MUTATION_PATTERN.test(stripped)) return true;
21390
21491
  return /\bSELECT\b[\s\S]+\bINTO\s+\w/i.test(stripped);
21391
21492
  }
@@ -21584,8 +21685,8 @@ import {
21584
21685
  import { basename as basename13, join as join53 } from "path";
21585
21686
 
21586
21687
  // src/commands/transcript/cleanText.ts
21587
- function cleanText(text11) {
21588
- const words = text11.split(/\s+/);
21688
+ function cleanText(text16) {
21689
+ const words = text16.split(/\s+/);
21589
21690
  const cleaned = [];
21590
21691
  for (let i = 0; i < words.length; i++) {
21591
21692
  let isRepeat = false;
@@ -21605,8 +21706,8 @@ function cleanText(text11) {
21605
21706
  }
21606
21707
 
21607
21708
  // src/commands/transcript/convert/parseVtt/deduplicateCues/removeSubstringDuplicates.ts
21608
- function normalizeText(text11) {
21609
- return text11.toLowerCase().trim();
21709
+ function normalizeText(text16) {
21710
+ return text16.toLowerCase().trim();
21610
21711
  }
21611
21712
  function checkSubstringRelation(textI, textJ) {
21612
21713
  if (textI.includes(textJ) && textI.length > textJ.length)
@@ -21735,13 +21836,13 @@ function parseTimestampLine(line) {
21735
21836
  return { startMs: parseTimestamp(startStr), endMs: parseTimestamp(endStr) };
21736
21837
  }
21737
21838
  function buildCue(startMs, endMs, fullText) {
21738
- const { speaker, text: text11 } = extractSpeaker(fullText);
21739
- return text11 ? { startMs, endMs, speaker, text: text11 } : null;
21839
+ const { speaker, text: text16 } = extractSpeaker(fullText);
21840
+ return text16 ? { startMs, endMs, speaker, text: text16 } : null;
21740
21841
  }
21741
21842
  function parseCueLine(lines, i) {
21742
21843
  const { startMs, endMs } = parseTimestampLine(lines[i]);
21743
- const { text: text11, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
21744
- return { cue: buildCue(startMs, endMs, text11), nextIndex: nextIndex2 };
21844
+ const { text: text16, nextIndex: nextIndex2 } = collectTextLines(lines, i + 1);
21845
+ return { cue: buildCue(startMs, endMs, text16), nextIndex: nextIndex2 };
21745
21846
  }
21746
21847
  function isCueSeparator(line) {
21747
21848
  return line.trim().includes("-->");
@@ -22329,8 +22430,8 @@ async function exchangeToken(params) {
22329
22430
  body: body.toString()
22330
22431
  });
22331
22432
  if (!response.ok) {
22332
- const text11 = await response.text();
22333
- throw new Error(`Token exchange failed (${response.status}): ${text11}`);
22433
+ const text16 = await response.text();
22434
+ throw new Error(`Token exchange failed (${response.status}): ${text16}`);
22334
22435
  }
22335
22436
  return response.json();
22336
22437
  }
@@ -23711,13 +23812,13 @@ function drainSessions(sessions, onDrained) {
23711
23812
  }
23712
23813
 
23713
23814
  // src/shared/db/recordPhaseActiveMs.ts
23714
- import { sql as sql11 } from "drizzle-orm";
23815
+ import { sql as sql15 } from "drizzle-orm";
23715
23816
  async function recordPhaseActiveMs(db, itemId2, phaseIdx, activeMs) {
23716
23817
  if (activeMs <= 0) return;
23717
23818
  await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, activeMs }).onConflictDoUpdate({
23718
23819
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
23719
23820
  set: {
23720
- activeMs: sql11`${phaseUsage.activeMs} + excluded.active_ms`
23821
+ activeMs: sql15`${phaseUsage.activeMs} + excluded.active_ms`
23721
23822
  }
23722
23823
  });
23723
23824
  }
@@ -23908,19 +24009,36 @@ function makeStatusChangeHandler(dismiss, notify2, reuseForRun) {
23908
24009
  return (s, status3, exitCode) => applyStatusChange(s, status3, exitCode, dismiss, notify2, reuseForRun);
23909
24010
  }
23910
24011
 
24012
+ // src/shared/db/recordPhaseCycleContext.ts
24013
+ import { sql as sql16 } from "drizzle-orm";
24014
+ async function recordPhaseCycleContext(db, itemId2, phaseIdx, window, resetsAt, pct) {
24015
+ if (pct <= 0) return;
24016
+ await db.insert(phaseCycleContext).values({ itemId: itemId2, phaseIdx, window, resetsAt, peakContextPct: pct }).onConflictDoUpdate({
24017
+ target: [
24018
+ phaseCycleContext.itemId,
24019
+ phaseCycleContext.phaseIdx,
24020
+ phaseCycleContext.window,
24021
+ phaseCycleContext.resetsAt
24022
+ ],
24023
+ set: {
24024
+ peakContextPct: sql16`GREATEST(${phaseCycleContext.peakContextPct}, ${pct})`
24025
+ }
24026
+ });
24027
+ }
24028
+
23911
24029
  // src/shared/db/recordPhasePeakContext.ts
23912
- import { sql as sql12 } from "drizzle-orm";
24030
+ import { sql as sql17 } from "drizzle-orm";
23913
24031
  async function recordPhasePeakContext(db, itemId2, phaseIdx, pct) {
23914
24032
  await db.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, peakContextPct: pct }).onConflictDoUpdate({
23915
24033
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
23916
24034
  set: {
23917
- peakContextPct: sql12`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
24035
+ peakContextPct: sql17`GREATEST(${phaseUsage.peakContextPct}, ${pct})`
23918
24036
  }
23919
24037
  });
23920
24038
  }
23921
24039
 
23922
24040
  // src/shared/db/recordPhaseTranscriptUsage.ts
23923
- import { sql as sql13 } from "drizzle-orm";
24041
+ import { sql as sql18 } from "drizzle-orm";
23924
24042
  async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
23925
24043
  const byId = /* @__PURE__ */ new Map();
23926
24044
  for (const r of responses) byId.set(r.messageId, r);
@@ -23940,8 +24058,8 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
23940
24058
  await tx.insert(phaseUsage).values({ itemId: itemId2, phaseIdx, tokensUp, tokensDown }).onConflictDoUpdate({
23941
24059
  target: [phaseUsage.itemId, phaseUsage.phaseIdx],
23942
24060
  set: {
23943
- tokensUp: sql13`${phaseUsage.tokensUp} + ${tokensUp}`,
23944
- tokensDown: sql13`${phaseUsage.tokensDown} + ${tokensDown}`
24061
+ tokensUp: sql18`${phaseUsage.tokensUp} + ${tokensUp}`,
24062
+ tokensDown: sql18`${phaseUsage.tokensDown} + ${tokensDown}`
23945
24063
  }
23946
24064
  });
23947
24065
  return { tokensUp, tokensDown };
@@ -23949,17 +24067,17 @@ async function recordPhaseTranscriptUsage(db, itemId2, phaseIdx, responses) {
23949
24067
  }
23950
24068
 
23951
24069
  // src/shared/db/recordWindowTokens.ts
23952
- import { and as and20, eq as eq38, sql as sql14 } from "drizzle-orm";
24070
+ import { and as and21, eq as eq39, sql as sql19 } from "drizzle-orm";
23953
24071
  async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
23954
24072
  if (tokensUp <= 0 && tokensDown <= 0) return;
23955
24073
  await db.update(usagePeaks).set({
23956
- tokensUp: sql14`${usagePeaks.tokensUp} + ${tokensUp}`,
23957
- tokensDown: sql14`${usagePeaks.tokensDown} + ${tokensDown}`
24074
+ tokensUp: sql19`${usagePeaks.tokensUp} + ${tokensUp}`,
24075
+ tokensDown: sql19`${usagePeaks.tokensDown} + ${tokensDown}`
23958
24076
  }).where(
23959
- and20(
23960
- eq38(usagePeaks.window, window),
23961
- eq38(usagePeaks.resetsAt, resetsAt),
23962
- eq38(usagePeaks.segment, 0)
24077
+ and21(
24078
+ eq39(usagePeaks.window, window),
24079
+ eq39(usagePeaks.resetsAt, resetsAt),
24080
+ eq39(usagePeaks.segment, 0)
23963
24081
  )
23964
24082
  );
23965
24083
  }
@@ -23998,8 +24116,19 @@ async function persistPhaseTokens(itemId2, phaseIdx, transcriptPath, usedPct, wi
23998
24116
  try {
23999
24117
  if (!process.env.ASSIST_DATABASE_URL && !loadConfig().database.url) return;
24000
24118
  const db = await getDb();
24001
- if (usedPct !== void 0)
24119
+ if (usedPct !== void 0) {
24002
24120
  await recordPhasePeakContext(db, itemId2, phaseIdx, usedPct);
24121
+ for (const { window, resetsAt } of windows) {
24122
+ await recordPhaseCycleContext(
24123
+ db,
24124
+ itemId2,
24125
+ phaseIdx,
24126
+ window,
24127
+ resetsAt,
24128
+ usedPct
24129
+ );
24130
+ }
24131
+ }
24003
24132
  const responses = await readTranscriptUsage(transcriptPath);
24004
24133
  if (responses.length === 0) return;
24005
24134
  const { tokensUp, tokensDown } = await recordPhaseTranscriptUsage(
@@ -24052,10 +24181,10 @@ function applyReviewPause(session, activity2) {
24052
24181
  }
24053
24182
 
24054
24183
  // src/shared/db/getPhaseActiveMs.ts
24055
- import { and as and21, eq as eq39 } from "drizzle-orm";
24184
+ import { and as and22, eq as eq40 } from "drizzle-orm";
24056
24185
  async function getPhaseActiveMs(db, itemId2, phaseIdx) {
24057
24186
  const [row] = await db.select({ activeMs: phaseUsage.activeMs }).from(phaseUsage).where(
24058
- and21(eq39(phaseUsage.itemId, itemId2), eq39(phaseUsage.phaseIdx, phaseIdx))
24187
+ and22(eq40(phaseUsage.itemId, itemId2), eq40(phaseUsage.phaseIdx, phaseIdx))
24059
24188
  );
24060
24189
  return row?.activeMs ?? 0;
24061
24190
  }
@@ -25373,17 +25502,17 @@ function entryMessages(entry) {
25373
25502
  return [];
25374
25503
  }
25375
25504
  function userMessages(content) {
25376
- if (typeof content === "string") return text10("user", cleanUserText(content));
25505
+ if (typeof content === "string") return text15("user", cleanUserText(content));
25377
25506
  if (!Array.isArray(content)) return [];
25378
- return content.filter((c) => c.type === "text").flatMap((c) => text10("user", cleanUserText(c.text ?? "")));
25507
+ return content.filter((c) => c.type === "text").flatMap((c) => text15("user", cleanUserText(c.text ?? "")));
25379
25508
  }
25380
25509
  function assistantMessages(content) {
25381
- if (typeof content === "string") return text10("assistant", content.trim());
25510
+ if (typeof content === "string") return text15("assistant", content.trim());
25382
25511
  if (!Array.isArray(content)) return [];
25383
25512
  return content.flatMap((c) => assistantItem(c));
25384
25513
  }
25385
25514
  function assistantItem(c) {
25386
- if (c.type === "text") return text10("assistant", (c.text ?? "").trim());
25515
+ if (c.type === "text") return text15("assistant", (c.text ?? "").trim());
25387
25516
  if (c.type === "tool_use")
25388
25517
  return [
25389
25518
  {
@@ -25394,7 +25523,7 @@ function assistantItem(c) {
25394
25523
  ];
25395
25524
  return [];
25396
25525
  }
25397
- function text10(role, value) {
25526
+ function text15(role, value) {
25398
25527
  return value ? [{ role, text: value }] : [];
25399
25528
  }
25400
25529
  function cleanUserText(value) {
@@ -25760,16 +25889,16 @@ function parseUserLine(line) {
25760
25889
  if (entry.type !== "user") return void 0;
25761
25890
  const msg = entry.message;
25762
25891
  const c = msg?.content;
25763
- let text11;
25892
+ let text16;
25764
25893
  if (typeof c === "string") {
25765
- text11 = c;
25894
+ text16 = c;
25766
25895
  } else if (Array.isArray(c)) {
25767
25896
  const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
25768
- text11 = collected || void 0;
25897
+ text16 = collected || void 0;
25769
25898
  }
25770
- if (!text11) return void 0;
25899
+ if (!text16) return void 0;
25771
25900
  return {
25772
- text: text11,
25901
+ text: text16,
25773
25902
  entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
25774
25903
  };
25775
25904
  }
@@ -25798,13 +25927,13 @@ function* iterateUserMessages(filePath, maxBytes = 65536) {
25798
25927
 
25799
25928
  // src/commands/sessions/summarise/extractFirstUserMessage.ts
25800
25929
  function extractFirstUserMessage(filePath) {
25801
- for (const text11 of iterateUserMessages(filePath)) {
25802
- return truncate3(text11);
25930
+ for (const text16 of iterateUserMessages(filePath)) {
25931
+ return truncate3(text16);
25803
25932
  }
25804
25933
  return void 0;
25805
25934
  }
25806
- function truncate3(text11, maxChars = 500) {
25807
- const trimmed = text11.trim();
25935
+ function truncate3(text16, maxChars = 500) {
25936
+ const trimmed = text16.trim();
25808
25937
  if (trimmed.length <= maxChars) return trimmed;
25809
25938
  return `${trimmed.slice(0, maxChars)}\u2026`;
25810
25939
  }
@@ -25812,28 +25941,28 @@ function truncate3(text11, maxChars = 500) {
25812
25941
  // src/commands/sessions/summarise/scanSessionBacklogRefs.ts
25813
25942
  function scanSessionBacklogRefs(filePath) {
25814
25943
  const ids = /* @__PURE__ */ new Set();
25815
- for (const text11 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
25816
- for (const id of extractBacklogIds(text11)) {
25944
+ for (const text16 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
25945
+ for (const id of extractBacklogIds(text16)) {
25817
25946
  ids.add(id);
25818
25947
  }
25819
25948
  }
25820
25949
  return [...ids].sort((a, b) => a - b);
25821
25950
  }
25822
- function extractBacklogIds(text11) {
25951
+ function extractBacklogIds(text16) {
25823
25952
  const ids = [];
25824
- for (const m of text11.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
25953
+ for (const m of text16.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
25825
25954
  ids.push(Number.parseInt(m[1], 10));
25826
25955
  }
25827
- for (const m of text11.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
25956
+ for (const m of text16.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
25828
25957
  ids.push(Number.parseInt(m[1], 10));
25829
25958
  }
25830
- for (const m of text11.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
25959
+ for (const m of text16.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
25831
25960
  ids.push(Number.parseInt(m[1], 10));
25832
25961
  }
25833
- for (const m of text11.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
25962
+ for (const m of text16.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
25834
25963
  ids.push(Number.parseInt(m[1], 10));
25835
25964
  }
25836
- for (const m of text11.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
25965
+ for (const m of text16.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
25837
25966
  ids.push(Number.parseInt(m[1], 10));
25838
25967
  }
25839
25968
  return ids;