@staff0rd/assist 0.402.0 → 0.403.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.402.0",
9
+ version: "0.403.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -1577,6 +1577,95 @@ function stageAndCommit(files, message) {
1577
1577
  return commitStaged(message);
1578
1578
  }
1579
1579
 
1580
+ // src/commands/sessions/summarise/iterateUserMessages.ts
1581
+ import * as fs from "fs";
1582
+
1583
+ // src/commands/sessions/summarise/parseUserLine.ts
1584
+ function parseUserLine(line) {
1585
+ let entry;
1586
+ try {
1587
+ entry = JSON.parse(line);
1588
+ } catch {
1589
+ return void 0;
1590
+ }
1591
+ if (entry.type !== "user") return void 0;
1592
+ const msg = entry.message;
1593
+ const c = msg?.content;
1594
+ let text17;
1595
+ if (typeof c === "string") {
1596
+ text17 = c;
1597
+ } else if (Array.isArray(c)) {
1598
+ const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
1599
+ text17 = collected || void 0;
1600
+ }
1601
+ if (!text17) return void 0;
1602
+ return {
1603
+ text: text17,
1604
+ entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
1605
+ };
1606
+ }
1607
+
1608
+ // src/commands/sessions/summarise/iterateUserMessages.ts
1609
+ function* iterateUserMessages(filePath, maxBytes = 65536) {
1610
+ let content;
1611
+ try {
1612
+ const fd = fs.openSync(filePath, "r");
1613
+ try {
1614
+ const buf = Buffer.alloc(maxBytes);
1615
+ const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
1616
+ content = buf.toString("utf8", 0, bytesRead);
1617
+ } finally {
1618
+ fs.closeSync(fd);
1619
+ }
1620
+ } catch {
1621
+ return;
1622
+ }
1623
+ for (const line of content.split("\n")) {
1624
+ if (!line) continue;
1625
+ const entry = parseUserLine(line);
1626
+ if (entry) yield entry.text;
1627
+ }
1628
+ }
1629
+
1630
+ // src/commands/sessions/summarise/scanSessionBacklogRefs.ts
1631
+ function scanSessionBacklogRefs(filePath) {
1632
+ const ids = /* @__PURE__ */ new Set();
1633
+ for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
1634
+ for (const id of extractBacklogIds(text17)) {
1635
+ ids.add(id);
1636
+ }
1637
+ }
1638
+ return [...ids].sort((a, b) => a - b);
1639
+ }
1640
+ function extractBacklogIds(text17) {
1641
+ const ids = [];
1642
+ for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
1643
+ ids.push(Number.parseInt(m[1], 10));
1644
+ }
1645
+ for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
1646
+ ids.push(Number.parseInt(m[1], 10));
1647
+ }
1648
+ for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
1649
+ ids.push(Number.parseInt(m[1], 10));
1650
+ }
1651
+ for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
1652
+ ids.push(Number.parseInt(m[1], 10));
1653
+ }
1654
+ for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
1655
+ ids.push(Number.parseInt(m[1], 10));
1656
+ }
1657
+ return ids;
1658
+ }
1659
+
1660
+ // src/shared/findBacklogRefs.ts
1661
+ function findBacklogRefs(text17) {
1662
+ return [...new Set(extractBacklogIds(text17))];
1663
+ }
1664
+ function backlogRefError(subject, context, ids) {
1665
+ const refs = ids.map((id) => `a${id}`).join(", ");
1666
+ return `Error: ${subject} must not reference assist backlog items (found ${refs}). Do not include assist references or backlog numbers in ${context} \u2014 the backlog item links to your work, not the other way around.`;
1667
+ }
1668
+
1580
1669
  // src/commands/commit/validateMessage.ts
1581
1670
  var MAX_MESSAGE_LENGTH = 50;
1582
1671
  var CONVENTIONAL_COMMIT_REGEX = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(!)?(\(.+\))?!?: .+$/;
@@ -1585,6 +1674,13 @@ function validateMessage(message, config) {
1585
1674
  console.error("Error: Commit message must not reference Claude");
1586
1675
  process.exit(1);
1587
1676
  }
1677
+ const backlogIds = findBacklogRefs(message);
1678
+ if (backlogIds.length > 0) {
1679
+ console.error(
1680
+ backlogRefError("Commit message", "commit messages", backlogIds)
1681
+ );
1682
+ process.exit(1);
1683
+ }
1588
1684
  if (config.commit?.conventional && !CONVENTIONAL_COMMIT_REGEX.test(message)) {
1589
1685
  console.error(
1590
1686
  "Error: Commit message must follow conventional commit format (e.g., 'feat: add feature', 'fix(scope): fix bug')"
@@ -1700,18 +1796,18 @@ async function promptMultiselect(message, options2) {
1700
1796
  }
1701
1797
 
1702
1798
  // src/shared/readPackageJson.ts
1703
- import * as fs from "fs";
1799
+ import * as fs2 from "fs";
1704
1800
  import * as path from "path";
1705
1801
  import chalk5 from "chalk";
1706
1802
  function findPackageJson() {
1707
1803
  const packageJsonPath = path.join(process.cwd(), "package.json");
1708
- if (fs.existsSync(packageJsonPath)) {
1804
+ if (fs2.existsSync(packageJsonPath)) {
1709
1805
  return packageJsonPath;
1710
1806
  }
1711
1807
  return null;
1712
1808
  }
1713
1809
  function readPackageJson(filePath) {
1714
- return JSON.parse(fs.readFileSync(filePath, "utf8"));
1810
+ return JSON.parse(fs2.readFileSync(filePath, "utf8"));
1715
1811
  }
1716
1812
  function requirePackageJson() {
1717
1813
  const packageJsonPath = findPackageJson();
@@ -1726,8 +1822,8 @@ function findPackageJsonWithVerifyScripts(startDir) {
1726
1822
  let currentDir = startDir;
1727
1823
  while (true) {
1728
1824
  const packageJsonPath = path.join(currentDir, "package.json");
1729
- if (fs.existsSync(packageJsonPath)) {
1730
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
1825
+ if (fs2.existsSync(packageJsonPath)) {
1826
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
1731
1827
  const scripts = packageJson.scripts || {};
1732
1828
  const verifyScripts = Object.keys(scripts).filter(
1733
1829
  (name) => name.startsWith("verify:")
@@ -2389,28 +2485,28 @@ async function init3(options2 = {}) {
2389
2485
  import chalk23 from "chalk";
2390
2486
 
2391
2487
  // src/commands/vscode/init/createLaunchJson.ts
2392
- import * as fs2 from "fs";
2488
+ import * as fs3 from "fs";
2393
2489
  import * as path8 from "path";
2394
2490
  import chalk20 from "chalk";
2395
2491
  function ensureVscodeFolder() {
2396
2492
  const vscodeDir = path8.join(process.cwd(), ".vscode");
2397
- if (!fs2.existsSync(vscodeDir)) {
2398
- fs2.mkdirSync(vscodeDir);
2493
+ if (!fs3.existsSync(vscodeDir)) {
2494
+ fs3.mkdirSync(vscodeDir);
2399
2495
  console.log(chalk20.dim("Created .vscode folder"));
2400
2496
  }
2401
2497
  }
2402
2498
  function removeVscodeFromGitignore() {
2403
2499
  const gitignorePath = path8.join(process.cwd(), ".gitignore");
2404
- if (!fs2.existsSync(gitignorePath)) {
2500
+ if (!fs3.existsSync(gitignorePath)) {
2405
2501
  return;
2406
2502
  }
2407
- const content = fs2.readFileSync(gitignorePath, "utf8");
2503
+ const content = fs3.readFileSync(gitignorePath, "utf8");
2408
2504
  const lines = content.split("\n");
2409
2505
  const filteredLines = lines.filter(
2410
2506
  (line) => !line.trim().toLowerCase().includes(".vscode")
2411
2507
  );
2412
2508
  if (filteredLines.length !== lines.length) {
2413
- fs2.writeFileSync(gitignorePath, filteredLines.join("\n"));
2509
+ fs3.writeFileSync(gitignorePath, filteredLines.join("\n"));
2414
2510
  console.log(chalk20.dim("Removed .vscode references from .gitignore"));
2415
2511
  }
2416
2512
  }
@@ -2428,20 +2524,20 @@ function createLaunchJson(type) {
2428
2524
  ]
2429
2525
  };
2430
2526
  const launchPath = path8.join(process.cwd(), ".vscode", "launch.json");
2431
- fs2.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
2527
+ fs3.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
2432
2528
  `);
2433
2529
  console.log(chalk20.green("Created .vscode/launch.json"));
2434
2530
  }
2435
2531
 
2436
2532
  // src/commands/vscode/init/detectVscodeSetup.ts
2437
- import * as fs3 from "fs";
2533
+ import * as fs4 from "fs";
2438
2534
  import * as path9 from "path";
2439
2535
  function detectVscodeSetup(pkg) {
2440
2536
  const vscodeDir = path9.join(process.cwd(), ".vscode");
2441
2537
  return {
2442
- hasVscodeFolder: fs3.existsSync(vscodeDir),
2443
- hasLaunchJson: fs3.existsSync(path9.join(vscodeDir, "launch.json")),
2444
- hasSettingsJson: fs3.existsSync(path9.join(vscodeDir, "settings.json")),
2538
+ hasVscodeFolder: fs4.existsSync(vscodeDir),
2539
+ hasLaunchJson: fs4.existsSync(path9.join(vscodeDir, "launch.json")),
2540
+ hasSettingsJson: fs4.existsSync(path9.join(vscodeDir, "settings.json")),
2445
2541
  hasVite: !!pkg.devDependencies?.vite || !!pkg.dependencies?.vite,
2446
2542
  hasTsup: !!pkg.devDependencies?.tsup || !!pkg.dependencies?.tsup
2447
2543
  };
@@ -2473,16 +2569,16 @@ function getAvailableOptions2(setup2) {
2473
2569
  }
2474
2570
 
2475
2571
  // src/commands/vscode/init/createSettingsJson.ts
2476
- import * as fs5 from "fs";
2572
+ import * as fs6 from "fs";
2477
2573
  import * as path10 from "path";
2478
2574
  import chalk21 from "chalk";
2479
2575
 
2480
2576
  // src/commands/vscode/init/readVscodeJson.ts
2481
- import * as fs4 from "fs";
2577
+ import * as fs5 from "fs";
2482
2578
  function readVscodeJson(filePath) {
2483
- if (!fs4.existsSync(filePath)) return {};
2579
+ if (!fs5.existsSync(filePath)) return {};
2484
2580
  try {
2485
- return JSON.parse(fs4.readFileSync(filePath, "utf8"));
2581
+ return JSON.parse(fs5.readFileSync(filePath, "utf8"));
2486
2582
  } catch {
2487
2583
  return {};
2488
2584
  }
@@ -2501,7 +2597,7 @@ function createSettingsJson() {
2501
2597
  "source.fixAll.oxc": "explicit"
2502
2598
  }
2503
2599
  };
2504
- fs5.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
2600
+ fs6.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
2505
2601
  `);
2506
2602
  console.log(chalk21.green("Created .vscode/settings.json"));
2507
2603
  }
@@ -2512,7 +2608,7 @@ function existingCodeActions(actions) {
2512
2608
  }
2513
2609
 
2514
2610
  // src/commands/vscode/init/createExtensionsJson.ts
2515
- import * as fs6 from "fs";
2611
+ import * as fs7 from "fs";
2516
2612
  import * as path11 from "path";
2517
2613
  import chalk22 from "chalk";
2518
2614
  function createExtensionsJson() {
@@ -2521,7 +2617,7 @@ function createExtensionsJson() {
2521
2617
  const previous = Array.isArray(existing.recommendations) ? existing.recommendations : [];
2522
2618
  const recommendations = previous.includes("oxc.oxc-vscode") ? previous : [...previous, "oxc.oxc-vscode"];
2523
2619
  const extensions = { ...existing, recommendations };
2524
- fs6.writeFileSync(
2620
+ fs7.writeFileSync(
2525
2621
  extensionsPath,
2526
2622
  `${JSON.stringify(extensions, null, " ")}
2527
2623
  `
@@ -2578,20 +2674,20 @@ import path17 from "path";
2578
2674
  import chalk25 from "chalk";
2579
2675
 
2580
2676
  // src/commands/lint/lint/checkFileNames.ts
2581
- import fs8 from "fs";
2677
+ import fs9 from "fs";
2582
2678
  import path13 from "path";
2583
2679
 
2584
2680
  // src/shared/findSourceFiles.ts
2585
- import fs7 from "fs";
2681
+ import fs8 from "fs";
2586
2682
  import path12 from "path";
2587
2683
  var EXTENSIONS = [".ts", ".tsx"];
2588
2684
  function findSourceFiles(dir, options2 = {}) {
2589
2685
  const { includeTests = true } = options2;
2590
2686
  const results = [];
2591
- if (!fs7.existsSync(dir)) {
2687
+ if (!fs8.existsSync(dir)) {
2592
2688
  return results;
2593
2689
  }
2594
- const entries = fs7.readdirSync(dir, { withFileTypes: true });
2690
+ const entries = fs8.readdirSync(dir, { withFileTypes: true });
2595
2691
  for (const entry of entries) {
2596
2692
  const fullPath = path12.join(dir, entry.name);
2597
2693
  if (entry.isDirectory() && entry.name !== "node_modules") {
@@ -2641,7 +2737,7 @@ function checkFileNames() {
2641
2737
  const nameWithoutExt = fileName.replace(/\.(ts|tsx)$/, "");
2642
2738
  if (/\.(stories|test)\.(ts|tsx)$/.test(fileName)) continue;
2643
2739
  if (/^[A-Z]/.test(nameWithoutExt)) {
2644
- const content = fs8.readFileSync(filePath, "utf8");
2740
+ const content = fs9.readFileSync(filePath, "utf8");
2645
2741
  if (!hasClassOrComponent(content) && !hasMatchingTypeExport(content, nameWithoutExt)) {
2646
2742
  violations.push({
2647
2743
  filePath,
@@ -2658,7 +2754,7 @@ function checkFileNames() {
2658
2754
  import chalk24 from "chalk";
2659
2755
 
2660
2756
  // src/commands/lint/lint/applyMoves.ts
2661
- import fs9 from "fs";
2757
+ import fs10 from "fs";
2662
2758
  import path15 from "path";
2663
2759
 
2664
2760
  // src/commands/lint/lint/renameExports.ts
@@ -2694,8 +2790,8 @@ function isCaseOnly(a, b) {
2694
2790
  }
2695
2791
  function moveCaseInsensitive(absSource, absDest) {
2696
2792
  const tmp = `${absSource}.tmp`;
2697
- fs9.renameSync(absSource, tmp);
2698
- fs9.renameSync(tmp, absDest);
2793
+ fs10.renameSync(absSource, tmp);
2794
+ fs10.renameSync(tmp, absDest);
2699
2795
  }
2700
2796
  function applyMoves(project, moves, cwd, emit4) {
2701
2797
  for (const { sourcePath, destPath } of moves) {
@@ -2715,19 +2811,19 @@ function applyMoves(project, moves, cwd, emit4) {
2715
2811
  for (const { sourcePath, destPath } of moves) {
2716
2812
  const absSource = path15.resolve(sourcePath);
2717
2813
  const absDest = path15.resolve(destPath);
2718
- if (isCaseOnly(absSource, absDest) && fs9.existsSync(absSource)) {
2814
+ if (isCaseOnly(absSource, absDest) && fs10.existsSync(absSource)) {
2719
2815
  moveCaseInsensitive(absSource, absDest);
2720
2816
  }
2721
2817
  }
2722
2818
  }
2723
2819
 
2724
2820
  // src/commands/lint/lint/createLintProject.ts
2725
- import fs10 from "fs";
2821
+ import fs11 from "fs";
2726
2822
  import path16 from "path";
2727
2823
  import { Project } from "ts-morph";
2728
2824
  function createLintProject() {
2729
2825
  const tsConfigPath = path16.resolve("tsconfig.json");
2730
- const project = fs10.existsSync(tsConfigPath) ? new Project({
2826
+ const project = fs11.existsSync(tsConfigPath) ? new Project({
2731
2827
  tsConfigFilePath: tsConfigPath,
2732
2828
  skipAddingFilesFromTsConfig: true
2733
2829
  }) : new Project();
@@ -2784,7 +2880,7 @@ function runFileNameCheck(fix = false) {
2784
2880
  }
2785
2881
 
2786
2882
  // src/commands/lint/lint/runImportExtensionCheck.ts
2787
- import fs11 from "fs";
2883
+ import fs12 from "fs";
2788
2884
 
2789
2885
  // src/commands/lint/shared.ts
2790
2886
  import chalk26 from "chalk";
@@ -2810,7 +2906,7 @@ ${checkName} failed:
2810
2906
 
2811
2907
  // src/commands/lint/lint/runImportExtensionCheck.ts
2812
2908
  function checkForImportExtensions(filePath) {
2813
- const content = fs11.readFileSync(filePath, "utf8");
2909
+ const content = fs12.readFileSync(filePath, "utf8");
2814
2910
  const lines = content.split("\n");
2815
2911
  const violations = [];
2816
2912
  const importExtensionPattern = /from\s+["']\..*\.(js|ts)["']/;
@@ -2844,9 +2940,9 @@ function runImportExtensionCheck() {
2844
2940
  }
2845
2941
 
2846
2942
  // src/commands/lint/lint/runStaticImportCheck.ts
2847
- import fs12 from "fs";
2943
+ import fs13 from "fs";
2848
2944
  function checkForDynamicImports(filePath) {
2849
- const content = fs12.readFileSync(filePath, "utf8");
2945
+ const content = fs13.readFileSync(filePath, "utf8");
2850
2946
  const lines = content.split("\n");
2851
2947
  const violations = [];
2852
2948
  const requirePattern = /\brequire\s*\(/;
@@ -2896,7 +2992,7 @@ import { basename as basename2, resolve as resolve5 } from "path";
2896
2992
 
2897
2993
  // src/commands/verify/blockComments/findComments.ts
2898
2994
  import { execSync as execSync10 } from "child_process";
2899
- import fs14 from "fs";
2995
+ import fs15 from "fs";
2900
2996
  import { minimatch } from "minimatch";
2901
2997
  import { Project as Project2 } from "ts-morph";
2902
2998
 
@@ -2930,7 +3026,7 @@ function isHashCommentFile(filePath) {
2930
3026
  }
2931
3027
 
2932
3028
  // src/commands/verify/blockComments/collectFileComments.ts
2933
- import fs13 from "fs";
3029
+ import fs14 from "fs";
2934
3030
 
2935
3031
  // src/shared/isBicepFile.ts
2936
3032
  var BICEP_EXTENSIONS = [".bicep", ".bicepparam"];
@@ -3085,7 +3181,7 @@ function toFindings(file, lines, raw, exempt) {
3085
3181
  return findings;
3086
3182
  }
3087
3183
  function collectFileComments(file, lines, project) {
3088
- const read = () => fs13.readFileSync(file, "utf8");
3184
+ const read = () => fs14.readFileSync(file, "utf8");
3089
3185
  if (isYamlFile(file))
3090
3186
  return toFindings(file, lines, collectYamlComments(read()), false);
3091
3187
  if (isDockerfile(file) || isEnvFile(file) || isShellFile(file))
@@ -3152,7 +3248,7 @@ function shouldScan(file, ignoreGlobs) {
3152
3248
  if (!SCANNED_EXTENSIONS.some((ext) => file.endsWith(ext)) && !isHashCommentFile(file))
3153
3249
  return false;
3154
3250
  if (ignoreGlobs.some((glob) => minimatch(file, glob))) return false;
3155
- return fs14.existsSync(file);
3251
+ return fs15.existsSync(file);
3156
3252
  }
3157
3253
  function findComments(options2) {
3158
3254
  const diff2 = execSync10("git diff HEAD", {
@@ -4230,7 +4326,7 @@ function detectPlatform() {
4230
4326
 
4231
4327
  // src/commands/notify/showNotification/showWindowsNotificationFromWsl.ts
4232
4328
  import { spawn as spawn2 } from "child_process";
4233
- import fs15 from "fs";
4329
+ import fs16 from "fs";
4234
4330
  import { createRequire } from "module";
4235
4331
  import path21 from "path";
4236
4332
  var require2 = createRequire(import.meta.url);
@@ -4242,7 +4338,7 @@ function showWindowsNotificationFromWsl(options2) {
4242
4338
  const { title, message, sound } = options2;
4243
4339
  const snoreToastPath = getSnoreToastPath();
4244
4340
  try {
4245
- fs15.chmodSync(snoreToastPath, 493);
4341
+ fs16.chmodSync(snoreToastPath, 493);
4246
4342
  } catch {
4247
4343
  }
4248
4344
  const args = ["-t", title, "-m", message];
@@ -6684,12 +6780,12 @@ import chalk42 from "chalk";
6684
6780
  import * as path24 from "path";
6685
6781
 
6686
6782
  // src/commands/sessions/shared/discoverSessions.ts
6687
- import * as fs17 from "fs";
6783
+ import * as fs18 from "fs";
6688
6784
  import * as os2 from "os";
6689
6785
  import * as path23 from "path";
6690
6786
 
6691
6787
  // src/commands/sessions/shared/parseSessionFile.ts
6692
- import * as fs16 from "fs";
6788
+ import * as fs17 from "fs";
6693
6789
  import * as path22 from "path";
6694
6790
 
6695
6791
  // src/commands/sessions/shared/deriveHistoryFields.ts
@@ -6787,10 +6883,10 @@ function matchMarker(text17, tag) {
6787
6883
  async function parseSessionFile(filePath, origin = "wsl") {
6788
6884
  let handle;
6789
6885
  try {
6790
- handle = await fs16.promises.open(filePath, "r");
6886
+ handle = await fs17.promises.open(filePath, "r");
6791
6887
  const meta = extractSessionMeta(await readHeadLines(handle));
6792
6888
  if (!meta.sessionId) return null;
6793
- const timestamp6 = meta.timestamp || (await fs16.promises.stat(filePath)).mtime.toISOString();
6889
+ const timestamp6 = meta.timestamp || (await fs17.promises.stat(filePath)).mtime.toISOString();
6794
6890
  return {
6795
6891
  sessionId: meta.sessionId,
6796
6892
  name: meta.name || `Session ${meta.sessionId.slice(0, 8)}`,
@@ -6836,7 +6932,7 @@ async function discoverSessionJsonlPaths() {
6836
6932
  sessionRoots().map(async ({ dir, origin }) => {
6837
6933
  let projectDirs;
6838
6934
  try {
6839
- projectDirs = await fs17.promises.readdir(dir);
6935
+ projectDirs = await fs18.promises.readdir(dir);
6840
6936
  } catch {
6841
6937
  return;
6842
6938
  }
@@ -6845,7 +6941,7 @@ async function discoverSessionJsonlPaths() {
6845
6941
  const dirPath = path23.join(dir, dirName);
6846
6942
  let entries;
6847
6943
  try {
6848
- entries = await fs17.promises.readdir(dirPath);
6944
+ entries = await fs18.promises.readdir(dirPath);
6849
6945
  } catch {
6850
6946
  return;
6851
6947
  }
@@ -7618,9 +7714,9 @@ function startWebServer(label2, port, handler, initialPath, open = true) {
7618
7714
  // src/commands/sessions/daemon/ensureDaemonRunning.ts
7619
7715
  import { spawn as spawn4 } from "child_process";
7620
7716
  import {
7621
- closeSync,
7717
+ closeSync as closeSync2,
7622
7718
  mkdirSync as mkdirSync10,
7623
- openSync,
7719
+ openSync as openSync2,
7624
7720
  statSync,
7625
7721
  unlinkSync as unlinkSync5,
7626
7722
  writeSync
@@ -7660,9 +7756,9 @@ function acquireSpawnLock() {
7660
7756
  }
7661
7757
  function tryCreateLock() {
7662
7758
  try {
7663
- const fd = openSync(daemonPaths.spawnLock, "wx");
7759
+ const fd = openSync2(daemonPaths.spawnLock, "wx");
7664
7760
  writeSync(fd, String(process.pid));
7665
- closeSync(fd);
7761
+ closeSync2(fd);
7666
7762
  return true;
7667
7763
  } catch {
7668
7764
  return false;
@@ -7682,7 +7778,7 @@ function releaseSpawnLock() {
7682
7778
  }
7683
7779
  }
7684
7780
  function spawnDaemon(reason) {
7685
- const log = openSync(daemonPaths.log, "a");
7781
+ const log = openSync2(daemonPaths.log, "a");
7686
7782
  const child = spawn4(process.execPath, [process.argv[1], "daemon", "run"], {
7687
7783
  detached: true,
7688
7784
  stdio: ["ignore", log, log],
@@ -12773,13 +12869,13 @@ import chalk119 from "chalk";
12773
12869
  import chalk112 from "chalk";
12774
12870
 
12775
12871
  // src/commands/complexity/shared/index.ts
12776
- import fs19 from "fs";
12872
+ import fs20 from "fs";
12777
12873
  import path27 from "path";
12778
12874
  import chalk111 from "chalk";
12779
12875
  import ts5 from "typescript";
12780
12876
 
12781
12877
  // src/commands/complexity/findSourceFiles.ts
12782
- import fs18 from "fs";
12878
+ import fs19 from "fs";
12783
12879
  import path26 from "path";
12784
12880
  import { minimatch as minimatch5 } from "minimatch";
12785
12881
  function applyIgnoreGlobs(files, extraIgnore = []) {
@@ -12788,11 +12884,11 @@ function applyIgnoreGlobs(files, extraIgnore = []) {
12788
12884
  return files.filter((f) => !ignore3.some((glob) => minimatch5(f, glob)));
12789
12885
  }
12790
12886
  function walk(dir, results) {
12791
- if (!fs18.existsSync(dir)) {
12887
+ if (!fs19.existsSync(dir)) {
12792
12888
  return;
12793
12889
  }
12794
12890
  const extensions = [".ts", ".tsx"];
12795
- const entries = fs18.readdirSync(dir, { withFileTypes: true });
12891
+ const entries = fs19.readdirSync(dir, { withFileTypes: true });
12796
12892
  for (const entry of entries) {
12797
12893
  const fullPath = path26.join(dir, entry.name);
12798
12894
  if (entry.isDirectory()) {
@@ -12813,10 +12909,10 @@ function findSourceFiles2(pattern2, baseDir = ".", extraIgnore = []) {
12813
12909
  extraIgnore
12814
12910
  );
12815
12911
  }
12816
- if (fs18.existsSync(pattern2) && fs18.statSync(pattern2).isFile()) {
12912
+ if (fs19.existsSync(pattern2) && fs19.statSync(pattern2).isFile()) {
12817
12913
  return [pattern2];
12818
12914
  }
12819
- if (fs18.existsSync(pattern2) && fs18.statSync(pattern2).isDirectory()) {
12915
+ if (fs19.existsSync(pattern2) && fs19.statSync(pattern2).isDirectory()) {
12820
12916
  walk(pattern2, results);
12821
12917
  return applyIgnoreGlobs(results, extraIgnore);
12822
12918
  }
@@ -13014,7 +13110,7 @@ function countSloc(content) {
13014
13110
 
13015
13111
  // src/commands/complexity/shared/index.ts
13016
13112
  function createSourceFromFile(filePath) {
13017
- const content = fs19.readFileSync(filePath, "utf8");
13113
+ const content = fs20.readFileSync(filePath, "utf8");
13018
13114
  return ts5.createSourceFile(
13019
13115
  path27.basename(filePath),
13020
13116
  content,
@@ -13174,7 +13270,7 @@ function printMaintainabilityFormula() {
13174
13270
  }
13175
13271
 
13176
13272
  // src/commands/complexity/maintainability/collectFileMetrics.ts
13177
- import fs20 from "fs";
13273
+ import fs21 from "fs";
13178
13274
 
13179
13275
  // src/commands/complexity/maintainability/calculateMaintainabilityIndex.ts
13180
13276
  function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, sloc2) {
@@ -13189,7 +13285,7 @@ function calculateMaintainabilityIndex(halsteadVolume, cyclomaticComplexity, slo
13189
13285
  function collectFileMetrics(files) {
13190
13286
  const fileMetrics = /* @__PURE__ */ new Map();
13191
13287
  for (const file of files) {
13192
- const content = fs20.readFileSync(file, "utf8");
13288
+ const content = fs21.readFileSync(file, "utf8");
13193
13289
  fileMetrics.set(file, {
13194
13290
  sloc: countSloc(content),
13195
13291
  functions: [],
@@ -13245,14 +13341,14 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
13245
13341
  }
13246
13342
 
13247
13343
  // src/commands/complexity/sloc.ts
13248
- import fs21 from "fs";
13344
+ import fs22 from "fs";
13249
13345
  import chalk118 from "chalk";
13250
13346
  async function sloc(pattern2 = "**/*.ts", options2 = {}) {
13251
13347
  withSourceFiles(pattern2, (files) => {
13252
13348
  const results = [];
13253
13349
  let hasViolation = false;
13254
13350
  for (const file of files) {
13255
- const content = fs21.readFileSync(file, "utf8");
13351
+ const content = fs22.readFileSync(file, "utf8");
13256
13352
  const lines = countSloc(content);
13257
13353
  results.push({ file, lines });
13258
13354
  if (options2.threshold !== void 0 && lines > options2.threshold) {
@@ -14147,7 +14243,7 @@ function registerDevlog(program2) {
14147
14243
  }
14148
14244
 
14149
14245
  // src/commands/dotnet/checkBuildLocks.ts
14150
- import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync5 } from "fs";
14246
+ import { closeSync as closeSync3, openSync as openSync3, readdirSync as readdirSync5 } from "fs";
14151
14247
  import { join as join37 } from "path";
14152
14248
  import chalk131 from "chalk";
14153
14249
 
@@ -14178,8 +14274,8 @@ function isLockedDll(debugDir) {
14178
14274
  if (!file.toLowerCase().endsWith(".dll")) continue;
14179
14275
  const dllPath = join37(debugDir, file);
14180
14276
  try {
14181
- const fd = openSync2(dllPath, "r+");
14182
- closeSync2(fd);
14277
+ const fd = openSync3(dllPath, "r+");
14278
+ closeSync3(fd);
14183
14279
  } catch {
14184
14280
  return dllPath;
14185
14281
  }
@@ -14779,7 +14875,7 @@ function registerDotnet(program2) {
14779
14875
  }
14780
14876
 
14781
14877
  // src/commands/editHook/index.ts
14782
- import fs22 from "fs";
14878
+ import fs23 from "fs";
14783
14879
 
14784
14880
  // src/commands/editHook/extractComments.ts
14785
14881
  var SOURCE_EXTENSIONS = [
@@ -14959,7 +15055,7 @@ function tryParseInput2(raw) {
14959
15055
  function readExisting(filePath) {
14960
15056
  if (!filePath) return void 0;
14961
15057
  try {
14962
- return fs22.readFileSync(filePath, "utf8");
15058
+ return fs23.readFileSync(filePath, "utf8");
14963
15059
  } catch {
14964
15060
  return void 0;
14965
15061
  }
@@ -16860,14 +16956,15 @@ ${resolves}` : baseWhy);
16860
16956
  return serializePrBody(parsed);
16861
16957
  }
16862
16958
 
16863
- // src/commands/prs/validatePrContent.ts
16959
+ // src/commands/prs/findWallOfText.ts
16864
16960
  var MAX_PARAGRAPH_CHARS = 600;
16865
16961
  var MAX_PARAGRAPH_SENTENCES = 4;
16866
- function isListLine(line) {
16867
- return /^\s*([-*+]|\d+[.)])\s/.test(line);
16868
- }
16869
- function countSentences(paragraph) {
16870
- return paragraph.match(/[.!?]+(\s|$)/g)?.length ?? 0;
16962
+ function findWallOfText(body) {
16963
+ const wall = splitParagraphs(body).find((p) => isWallOfText(p.lines));
16964
+ if (!wall) {
16965
+ return void 0;
16966
+ }
16967
+ return { section: wall.section, chars: wall.lines.join(" ").trim().length };
16871
16968
  }
16872
16969
  function splitParagraphs(body) {
16873
16970
  const paragraphs = [];
@@ -16900,6 +16997,14 @@ function isWallOfText(lines) {
16900
16997
  const text17 = lines.join(" ").trim();
16901
16998
  return text17.length > MAX_PARAGRAPH_CHARS || countSentences(text17) > MAX_PARAGRAPH_SENTENCES;
16902
16999
  }
17000
+ function countSentences(paragraph) {
17001
+ return paragraph.match(/[.!?]+(\s|$)/g)?.length ?? 0;
17002
+ }
17003
+ function isListLine(line) {
17004
+ return /^\s*([-*+]|\d+[.)])\s/.test(line);
17005
+ }
17006
+
17007
+ // src/commands/prs/validatePrContent.ts
16903
17008
  function validatePrContent(title, body) {
16904
17009
  if (title.toLowerCase().includes("claude")) {
16905
17010
  console.error("Error: PR title must not reference Claude");
@@ -16909,11 +17014,20 @@ function validatePrContent(title, body) {
16909
17014
  console.error("Error: PR body must not reference Claude");
16910
17015
  process.exit(1);
16911
17016
  }
16912
- const wall = splitParagraphs(body).find((p) => isWallOfText(p.lines));
17017
+ const titleBacklogIds = findBacklogRefs(title);
17018
+ if (titleBacklogIds.length > 0) {
17019
+ console.error(backlogRefError("PR title", "PRs", titleBacklogIds));
17020
+ process.exit(1);
17021
+ }
17022
+ const bodyBacklogIds = findBacklogRefs(body);
17023
+ if (bodyBacklogIds.length > 0) {
17024
+ console.error(backlogRefError("PR body", "PRs", bodyBacklogIds));
17025
+ process.exit(1);
17026
+ }
17027
+ const wall = findWallOfText(body);
16913
17028
  if (wall) {
16914
- const chars = wall.lines.join(" ").trim().length;
16915
17029
  console.error(
16916
- `Error: the "${wall.section}" section contains a wall-of-text paragraph (${chars} chars). Be concise \u2014 split it into bullet points or trim it.`
17030
+ `Error: the "${wall.section}" section contains a wall-of-text paragraph (${wall.chars} chars). Be concise \u2014 split it into bullet points or trim it.`
16917
17031
  );
16918
17032
  process.exit(1);
16919
17033
  }
@@ -18116,17 +18230,17 @@ Refactor check failed:
18116
18230
 
18117
18231
  // src/commands/refactor/check/getViolations/index.ts
18118
18232
  import { execSync as execSync49 } from "child_process";
18119
- import fs24 from "fs";
18233
+ import fs25 from "fs";
18120
18234
  import { minimatch as minimatch6 } from "minimatch";
18121
18235
 
18122
18236
  // src/commands/refactor/check/getViolations/getIgnoredFiles.ts
18123
- import fs23 from "fs";
18237
+ import fs24 from "fs";
18124
18238
  var REFACTOR_YML_PATH = "refactor.yml";
18125
18239
  function parseRefactorYml() {
18126
- if (!fs23.existsSync(REFACTOR_YML_PATH)) {
18240
+ if (!fs24.existsSync(REFACTOR_YML_PATH)) {
18127
18241
  return [];
18128
18242
  }
18129
- const content = fs23.readFileSync(REFACTOR_YML_PATH, "utf8");
18243
+ const content = fs24.readFileSync(REFACTOR_YML_PATH, "utf8");
18130
18244
  const entries = [];
18131
18245
  const lines = content.split("\n");
18132
18246
  let currentEntry = {};
@@ -18156,7 +18270,7 @@ function getIgnoredFiles() {
18156
18270
 
18157
18271
  // src/commands/refactor/check/getViolations/index.ts
18158
18272
  function countLines(filePath) {
18159
- const content = fs24.readFileSync(filePath, "utf8");
18273
+ const content = fs25.readFileSync(filePath, "utf8");
18160
18274
  return content.split("\n").length;
18161
18275
  }
18162
18276
  function getGitFiles(options2) {
@@ -18914,12 +19028,12 @@ import chalk170 from "chalk";
18914
19028
  import { Project as Project4 } from "ts-morph";
18915
19029
 
18916
19030
  // src/commands/refactor/extract/findTsConfig.ts
18917
- import fs25 from "fs";
19031
+ import fs26 from "fs";
18918
19032
  import path39 from "path";
18919
19033
  import { Project as Project3 } from "ts-morph";
18920
19034
  function findTsConfig(sourcePath) {
18921
19035
  const rootConfig = path39.resolve("tsconfig.json");
18922
- if (!fs25.existsSync(rootConfig)) return rootConfig;
19036
+ if (!fs26.existsSync(rootConfig)) return rootConfig;
18923
19037
  const tried = /* @__PURE__ */ new Set();
18924
19038
  const candidates = [rootConfig, ...readReferences(rootConfig)];
18925
19039
  for (const candidate of candidates) {
@@ -18927,7 +19041,7 @@ function findTsConfig(sourcePath) {
18927
19041
  tried.add(candidate);
18928
19042
  if (projectIncludes(candidate, sourcePath)) return candidate;
18929
19043
  }
18930
- const siblings = fs25.readdirSync(path39.dirname(rootConfig)).filter((f) => /^tsconfig.*\.json$/.test(f)).map((f) => path39.resolve(path39.dirname(rootConfig), f));
19044
+ const siblings = fs26.readdirSync(path39.dirname(rootConfig)).filter((f) => /^tsconfig.*\.json$/.test(f)).map((f) => path39.resolve(path39.dirname(rootConfig), f));
18931
19045
  for (const sibling of siblings) {
18932
19046
  if (tried.has(sibling)) continue;
18933
19047
  tried.add(sibling);
@@ -18936,8 +19050,8 @@ function findTsConfig(sourcePath) {
18936
19050
  return rootConfig;
18937
19051
  }
18938
19052
  function readReferences(configPath) {
18939
- if (!fs25.existsSync(configPath)) return [];
18940
- const raw = fs25.readFileSync(configPath, "utf8");
19053
+ if (!fs26.existsSync(configPath)) return [];
19054
+ const raw = fs26.readFileSync(configPath, "utf8");
18941
19055
  const stripped = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
18942
19056
  let parsed;
18943
19057
  try {
@@ -18949,8 +19063,8 @@ function readReferences(configPath) {
18949
19063
  const cwd = path39.dirname(configPath);
18950
19064
  return parsed.references.map((ref) => {
18951
19065
  const refPath = path39.resolve(cwd, ref.path);
18952
- return fs25.statSync(refPath, { throwIfNoEntry: false })?.isDirectory() ? path39.join(refPath, "tsconfig.json") : refPath;
18953
- }).filter((p) => fs25.existsSync(p));
19066
+ return fs26.statSync(refPath, { throwIfNoEntry: false })?.isDirectory() ? path39.join(refPath, "tsconfig.json") : refPath;
19067
+ }).filter((p) => fs26.existsSync(p));
18954
19068
  }
18955
19069
  function projectIncludes(configPath, sourcePath) {
18956
19070
  try {
@@ -19000,25 +19114,25 @@ async function extract(file, functionName, destination, options2 = {}) {
19000
19114
  }
19001
19115
 
19002
19116
  // src/commands/refactor/ignore.ts
19003
- import fs26 from "fs";
19117
+ import fs27 from "fs";
19004
19118
  import chalk172 from "chalk";
19005
19119
  var REFACTOR_YML_PATH2 = "refactor.yml";
19006
19120
  function ignore2(file) {
19007
- if (!fs26.existsSync(file)) {
19121
+ if (!fs27.existsSync(file)) {
19008
19122
  console.error(chalk172.red(`Error: File does not exist: ${file}`));
19009
19123
  process.exit(1);
19010
19124
  }
19011
- const content = fs26.readFileSync(file, "utf8");
19125
+ const content = fs27.readFileSync(file, "utf8");
19012
19126
  const lineCount = content.split("\n").length;
19013
19127
  const maxLines = lineCount + 10;
19014
19128
  const entry = `- file: ${file}
19015
19129
  maxLines: ${maxLines}
19016
19130
  `;
19017
- if (fs26.existsSync(REFACTOR_YML_PATH2)) {
19018
- const existing = fs26.readFileSync(REFACTOR_YML_PATH2, "utf8");
19019
- fs26.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
19131
+ if (fs27.existsSync(REFACTOR_YML_PATH2)) {
19132
+ const existing = fs27.readFileSync(REFACTOR_YML_PATH2, "utf8");
19133
+ fs27.writeFileSync(REFACTOR_YML_PATH2, existing + entry);
19020
19134
  } else {
19021
- fs26.writeFileSync(REFACTOR_YML_PATH2, entry);
19135
+ fs27.writeFileSync(REFACTOR_YML_PATH2, entry);
19022
19136
  }
19023
19137
  console.log(
19024
19138
  chalk172.green(
@@ -19028,12 +19142,12 @@ function ignore2(file) {
19028
19142
  }
19029
19143
 
19030
19144
  // src/commands/refactor/rename/index.ts
19031
- import fs29 from "fs";
19145
+ import fs30 from "fs";
19032
19146
  import path46 from "path";
19033
19147
  import chalk175 from "chalk";
19034
19148
 
19035
19149
  // src/commands/refactor/rename/applyRename.ts
19036
- import fs28 from "fs";
19150
+ import fs29 from "fs";
19037
19151
  import path43 from "path";
19038
19152
  import chalk173 from "chalk";
19039
19153
 
@@ -19041,7 +19155,7 @@ import chalk173 from "chalk";
19041
19155
  import path42 from "path";
19042
19156
 
19043
19157
  // src/commands/refactor/restructure/computeRewrites/applyRewrites.ts
19044
- import fs27 from "fs";
19158
+ import fs28 from "fs";
19045
19159
  function getOrCreateList(map, key) {
19046
19160
  const list5 = map.get(key) ?? [];
19047
19161
  if (!map.has(key)) map.set(key, list5);
@@ -19060,7 +19174,7 @@ function rewriteSpecifier(content, oldSpecifier, newSpecifier) {
19060
19174
  return content.replace(pattern2, `$1${newSpecifier}$2`);
19061
19175
  }
19062
19176
  function applyFileRewrites(file, fileRewrites) {
19063
- let content = fs27.readFileSync(file, "utf8");
19177
+ let content = fs28.readFileSync(file, "utf8");
19064
19178
  for (const { oldSpecifier, newSpecifier } of fileRewrites) {
19065
19179
  content = rewriteSpecifier(content, oldSpecifier, newSpecifier);
19066
19180
  }
@@ -19139,12 +19253,12 @@ function computeRewrites(moves, edges, allProjectFiles) {
19139
19253
  function applyRename(rewrites, sourcePath, destPath, cwd) {
19140
19254
  const updatedContents = applyRewrites(rewrites);
19141
19255
  for (const [file, content] of updatedContents) {
19142
- fs28.writeFileSync(file, content, "utf8");
19256
+ fs29.writeFileSync(file, content, "utf8");
19143
19257
  console.log(chalk173.cyan(` Updated imports in ${path43.relative(cwd, file)}`));
19144
19258
  }
19145
19259
  const destDir = path43.dirname(destPath);
19146
- if (!fs28.existsSync(destDir)) fs28.mkdirSync(destDir, { recursive: true });
19147
- fs28.renameSync(sourcePath, destPath);
19260
+ if (!fs29.existsSync(destDir)) fs29.mkdirSync(destDir, { recursive: true });
19261
+ fs29.renameSync(sourcePath, destPath);
19148
19262
  console.log(
19149
19263
  chalk173.white(
19150
19264
  ` Moved ${path43.relative(cwd, sourcePath)} \u2192 ${path43.relative(cwd, destPath)}`
@@ -19252,11 +19366,11 @@ async function rename(source, destination, options2 = {}) {
19252
19366
  const cwd = process.cwd();
19253
19367
  const relSource = path46.relative(cwd, sourcePath);
19254
19368
  const relDest = path46.relative(cwd, destPath);
19255
- if (!fs29.existsSync(sourcePath)) {
19369
+ if (!fs30.existsSync(sourcePath)) {
19256
19370
  console.log(chalk175.red(`File not found: ${source}`));
19257
19371
  process.exit(1);
19258
19372
  }
19259
- if (destPath !== sourcePath && fs29.existsSync(destPath)) {
19373
+ if (destPath !== sourcePath && fs30.existsSync(destPath)) {
19260
19374
  console.log(chalk175.red(`Destination already exists: ${destination}`));
19261
19375
  process.exit(1);
19262
19376
  }
@@ -19481,27 +19595,27 @@ Summary: ${plan2.moves.length} file(s) moved, ${plan2.rewrites.length} imports r
19481
19595
  }
19482
19596
 
19483
19597
  // src/commands/refactor/restructure/executePlan.ts
19484
- import fs30 from "fs";
19598
+ import fs31 from "fs";
19485
19599
  import path51 from "path";
19486
19600
  import chalk178 from "chalk";
19487
19601
  function executePlan(plan2) {
19488
19602
  const updatedContents = applyRewrites(plan2.rewrites);
19489
19603
  for (const [file, content] of updatedContents) {
19490
- fs30.writeFileSync(file, content, "utf8");
19604
+ fs31.writeFileSync(file, content, "utf8");
19491
19605
  console.log(
19492
19606
  chalk178.cyan(` Rewrote imports in ${path51.relative(process.cwd(), file)}`)
19493
19607
  );
19494
19608
  }
19495
19609
  for (const dir of plan2.newDirectories) {
19496
- fs30.mkdirSync(dir, { recursive: true });
19610
+ fs31.mkdirSync(dir, { recursive: true });
19497
19611
  console.log(chalk178.green(` Created ${path51.relative(process.cwd(), dir)}/`));
19498
19612
  }
19499
19613
  for (const move2 of plan2.moves) {
19500
19614
  const targetDir = path51.dirname(move2.to);
19501
- if (!fs30.existsSync(targetDir)) {
19502
- fs30.mkdirSync(targetDir, { recursive: true });
19615
+ if (!fs31.existsSync(targetDir)) {
19616
+ fs31.mkdirSync(targetDir, { recursive: true });
19503
19617
  }
19504
- fs30.renameSync(move2.from, move2.to);
19618
+ fs31.renameSync(move2.from, move2.to);
19505
19619
  console.log(
19506
19620
  chalk178.white(
19507
19621
  ` Moved ${path51.relative(process.cwd(), move2.from)} \u2192 ${path51.relative(process.cwd(), move2.to)}`
@@ -19513,10 +19627,10 @@ function executePlan(plan2) {
19513
19627
  function removeEmptyDirectories(dirs) {
19514
19628
  const unique = [...new Set(dirs)];
19515
19629
  for (const dir of unique) {
19516
- if (!fs30.existsSync(dir)) continue;
19517
- const entries = fs30.readdirSync(dir);
19630
+ if (!fs31.existsSync(dir)) continue;
19631
+ const entries = fs31.readdirSync(dir);
19518
19632
  if (entries.length === 0) {
19519
- fs30.rmdirSync(dir);
19633
+ fs31.rmdirSync(dir);
19520
19634
  console.log(
19521
19635
  chalk178.dim(
19522
19636
  ` Removed empty directory ${path51.relative(process.cwd(), dir)}`
@@ -19530,18 +19644,18 @@ function removeEmptyDirectories(dirs) {
19530
19644
  import path53 from "path";
19531
19645
 
19532
19646
  // src/commands/refactor/restructure/planFileMoves/shared.ts
19533
- import fs31 from "fs";
19647
+ import fs32 from "fs";
19534
19648
  function emptyResult() {
19535
19649
  return { moves: [], directories: [], warnings: [] };
19536
19650
  }
19537
19651
  function checkDirConflict(result, label2, dir) {
19538
- if (!fs31.existsSync(dir)) return false;
19652
+ if (!fs32.existsSync(dir)) return false;
19539
19653
  result.warnings.push(`Skipping ${label2}: directory ${dir} already exists`);
19540
19654
  return true;
19541
19655
  }
19542
19656
 
19543
19657
  // src/commands/refactor/restructure/planFileMoves/planDirectoryMoves.ts
19544
- import fs32 from "fs";
19658
+ import fs33 from "fs";
19545
19659
  import path52 from "path";
19546
19660
  function collectEntry(results, dir, entry) {
19547
19661
  const full = path52.join(dir, entry.name);
@@ -19549,9 +19663,9 @@ function collectEntry(results, dir, entry) {
19549
19663
  results.push(...items2);
19550
19664
  }
19551
19665
  function listFilesRecursive(dir) {
19552
- if (!fs32.existsSync(dir)) return [];
19666
+ if (!fs33.existsSync(dir)) return [];
19553
19667
  const results = [];
19554
- for (const entry of fs32.readdirSync(dir, { withFileTypes: true })) {
19668
+ for (const entry of fs33.readdirSync(dir, { withFileTypes: true })) {
19555
19669
  collectEntry(results, dir, entry);
19556
19670
  }
19557
19671
  return results;
@@ -24231,14 +24345,14 @@ function createAssistSession(id, assistArgs, cwd, meta) {
24231
24345
  import { randomUUID as randomUUID4 } from "crypto";
24232
24346
 
24233
24347
  // src/commands/sessions/daemon/readDesignSystemPrompt.ts
24234
- import * as fs33 from "fs";
24348
+ import * as fs34 from "fs";
24235
24349
  import * as path56 from "path";
24236
24350
  import { fileURLToPath as fileURLToPath8 } from "url";
24237
24351
  var __filename4 = fileURLToPath8(import.meta.url);
24238
24352
  var __dirname6 = path56.dirname(__filename4);
24239
24353
  function readDesignSystemPrompt() {
24240
24354
  const promptPath = path56.join(__dirname6, "..", "claude", "system-prompt.md");
24241
- return fs33.readFileSync(promptPath, "utf8");
24355
+ return fs34.readFileSync(promptPath, "utf8");
24242
24356
  }
24243
24357
 
24244
24358
  // src/commands/sessions/daemon/spawnClaude.ts
@@ -24617,7 +24731,7 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
24617
24731
  }
24618
24732
 
24619
24733
  // src/commands/sessions/shared/transcriptUsage.ts
24620
- import * as fs34 from "fs";
24734
+ import * as fs35 from "fs";
24621
24735
  function transcriptUsage(lines) {
24622
24736
  const byId = /* @__PURE__ */ new Map();
24623
24737
  for (const line of lines) {
@@ -24641,7 +24755,7 @@ function transcriptUsage(lines) {
24641
24755
  return [...byId.values()];
24642
24756
  }
24643
24757
  async function readTranscriptUsage(transcriptPath) {
24644
- const content = await fs34.promises.readFile(transcriptPath, "utf8");
24758
+ const content = await fs35.promises.readFile(transcriptPath, "utf8");
24645
24759
  return transcriptUsage(content.split("\n"));
24646
24760
  }
24647
24761
 
@@ -26099,7 +26213,7 @@ import * as net3 from "net";
26099
26213
  import { createInterface as createInterface9 } from "readline";
26100
26214
 
26101
26215
  // src/commands/sessions/shared/parseTranscript.ts
26102
- import * as fs35 from "fs";
26216
+ import * as fs36 from "fs";
26103
26217
 
26104
26218
  // src/commands/sessions/shared/toolTarget.ts
26105
26219
  function toolTarget(input) {
@@ -26151,7 +26265,7 @@ async function parseTranscript(sessionId) {
26151
26265
  const filePath = await findSessionJsonlPath(sessionId);
26152
26266
  if (!filePath) return [];
26153
26267
  try {
26154
- const raw = await fs35.promises.readFile(filePath, "utf8");
26268
+ const raw = await fs36.promises.readFile(filePath, "utf8");
26155
26269
  return parseTranscriptLines(raw.split("\n"));
26156
26270
  } catch {
26157
26271
  return [];
@@ -26484,13 +26598,13 @@ import * as fs38 from "fs";
26484
26598
  import chalk196 from "chalk";
26485
26599
 
26486
26600
  // src/commands/sessions/summarise/shared.ts
26487
- import * as fs36 from "fs";
26601
+ import * as fs37 from "fs";
26488
26602
  function writeSummary(jsonlPath2, summary) {
26489
- fs36.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
26603
+ fs37.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
26490
26604
  `, "utf8");
26491
26605
  }
26492
26606
  function hasSummary(jsonlPath2) {
26493
- return fs36.existsSync(summaryPathFor(jsonlPath2));
26607
+ return fs37.existsSync(summaryPathFor(jsonlPath2));
26494
26608
  }
26495
26609
  function summaryPathFor(jsonlPath2) {
26496
26610
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -26499,56 +26613,6 @@ function summaryPathFor(jsonlPath2) {
26499
26613
  // src/commands/sessions/summarise/summariseSession.ts
26500
26614
  import { execFileSync as execFileSync12 } from "child_process";
26501
26615
 
26502
- // src/commands/sessions/summarise/iterateUserMessages.ts
26503
- import * as fs37 from "fs";
26504
-
26505
- // src/commands/sessions/summarise/parseUserLine.ts
26506
- function parseUserLine(line) {
26507
- let entry;
26508
- try {
26509
- entry = JSON.parse(line);
26510
- } catch {
26511
- return void 0;
26512
- }
26513
- if (entry.type !== "user") return void 0;
26514
- const msg = entry.message;
26515
- const c = msg?.content;
26516
- let text17;
26517
- if (typeof c === "string") {
26518
- text17 = c;
26519
- } else if (Array.isArray(c)) {
26520
- const collected = c.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n");
26521
- text17 = collected || void 0;
26522
- }
26523
- if (!text17) return void 0;
26524
- return {
26525
- text: text17,
26526
- entrypoint: typeof entry.entrypoint === "string" ? entry.entrypoint : void 0
26527
- };
26528
- }
26529
-
26530
- // src/commands/sessions/summarise/iterateUserMessages.ts
26531
- function* iterateUserMessages(filePath, maxBytes = 65536) {
26532
- let content;
26533
- try {
26534
- const fd = fs37.openSync(filePath, "r");
26535
- try {
26536
- const buf = Buffer.alloc(maxBytes);
26537
- const bytesRead = fs37.readSync(fd, buf, 0, buf.length, 0);
26538
- content = buf.toString("utf8", 0, bytesRead);
26539
- } finally {
26540
- fs37.closeSync(fd);
26541
- }
26542
- } catch {
26543
- return;
26544
- }
26545
- for (const line of content.split("\n")) {
26546
- if (!line) continue;
26547
- const entry = parseUserLine(line);
26548
- if (entry) yield entry.text;
26549
- }
26550
- }
26551
-
26552
26616
  // src/commands/sessions/summarise/extractFirstUserMessage.ts
26553
26617
  function extractFirstUserMessage(filePath) {
26554
26618
  for (const text17 of iterateUserMessages(filePath)) {
@@ -26562,36 +26626,6 @@ function truncate3(text17, maxChars = 500) {
26562
26626
  return `${trimmed.slice(0, maxChars)}\u2026`;
26563
26627
  }
26564
26628
 
26565
- // src/commands/sessions/summarise/scanSessionBacklogRefs.ts
26566
- function scanSessionBacklogRefs(filePath) {
26567
- const ids = /* @__PURE__ */ new Set();
26568
- for (const text17 of iterateUserMessages(filePath, Number.MAX_SAFE_INTEGER)) {
26569
- for (const id of extractBacklogIds(text17)) {
26570
- ids.add(id);
26571
- }
26572
- }
26573
- return [...ids].sort((a, b) => a - b);
26574
- }
26575
- function extractBacklogIds(text17) {
26576
- const ids = [];
26577
- for (const m of text17.matchAll(/backlog\s+run\s+a(\d+)/gi)) {
26578
- ids.push(Number.parseInt(m[1], 10));
26579
- }
26580
- for (const m of text17.matchAll(/backlog\s+(?:item\s+)?a(\d+)/gi)) {
26581
- ids.push(Number.parseInt(m[1], 10));
26582
- }
26583
- for (const m of text17.matchAll(/backlog\s+phase-done\s+a(\d+)/gi)) {
26584
- ids.push(Number.parseInt(m[1], 10));
26585
- }
26586
- for (const m of text17.matchAll(/backlog\s+comment\s+a(\d+)/gi)) {
26587
- ids.push(Number.parseInt(m[1], 10));
26588
- }
26589
- for (const m of text17.matchAll(/(?:^|[\s(])a(\d{1,4})(?=[\s).,;:!?]|$)/gm)) {
26590
- ids.push(Number.parseInt(m[1], 10));
26591
- }
26592
- return ids;
26593
- }
26594
-
26595
26629
  // src/commands/sessions/summarise/summariseSession.ts
26596
26630
  function summariseSession(jsonlPath2) {
26597
26631
  const firstMessage = extractFirstUserMessage(jsonlPath2);