@staff0rd/assist 0.618.1 → 0.620.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.618.1",
9
+ version: "0.620.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -11341,8 +11341,8 @@ function subsequenceScore(text18, query) {
11341
11341
  function scoreFilePath(path90, query) {
11342
11342
  const needle = query.trim().toLowerCase();
11343
11343
  if (!needle) return 0;
11344
- const basename26 = path90.slice(path90.lastIndexOf("/") + 1);
11345
- const inBasename = subsequenceScore(basename26, needle);
11344
+ const basename27 = path90.slice(path90.lastIndexOf("/") + 1);
11345
+ const inBasename = subsequenceScore(basename27, needle);
11346
11346
  if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
11347
11347
  return subsequenceScore(path90, needle);
11348
11348
  }
@@ -18132,11 +18132,11 @@ function pushTargetForRenamedUpstream(trunkMode) {
18132
18132
  const remote = gitOrNull2(
18133
18133
  `git config --get branch.${shellQuote(branch2)}.remote`
18134
18134
  );
18135
- const merge = gitOrNull2(
18135
+ const merge2 = gitOrNull2(
18136
18136
  `git config --get branch.${shellQuote(branch2)}.merge`
18137
18137
  );
18138
- if (!remote || !merge) return null;
18139
- const upstream = merge.startsWith(HEADS_PREFIX) ? merge.slice(HEADS_PREFIX.length) : merge;
18138
+ if (!remote || !merge2) return null;
18139
+ const upstream = merge2.startsWith(HEADS_PREFIX) ? merge2.slice(HEADS_PREFIX.length) : merge2;
18140
18140
  if (upstream === branch2) return null;
18141
18141
  return trunkMode ? landOnTrackedMainline(remote, upstream) : raiseOwnRemoteBranch(remote, branch2);
18142
18142
  }
@@ -28625,8 +28625,8 @@ function findRootParent(file, importedBy, visited) {
28625
28625
  function clusterFiles(graph) {
28626
28626
  const clusters = /* @__PURE__ */ new Map();
28627
28627
  for (const file of graph.files) {
28628
- const basename26 = path61.basename(file, path61.extname(file));
28629
- if (basename26 === "index") continue;
28628
+ const basename27 = path61.basename(file, path61.extname(file));
28629
+ if (basename27 === "index") continue;
28630
28630
  const importers = graph.importedBy.get(file);
28631
28631
  if (!importers || importers.size !== 1) continue;
28632
28632
  const parent = [...importers][0];
@@ -32437,9 +32437,28 @@ function formatCue(cue) {
32437
32437
  return `${timing}
32438
32438
  ${text18}`;
32439
32439
  }
32440
+ function formatClock(ms) {
32441
+ return formatTimestamp2(ms).slice(0, 8);
32442
+ }
32443
+ function formatNoteBlock(lines2) {
32444
+ return lines2.length ? [lines2.map((line) => `NOTE ${line}`).join("\n")] : [];
32445
+ }
32446
+ function formatPassage(passage) {
32447
+ return [
32448
+ `NOTE source: ${passage.source} @ ${formatClock(passage.sourceStartMs)}`,
32449
+ ...passage.cues.map(formatCue)
32450
+ ];
32451
+ }
32440
32452
  function formatVtt(cues) {
32441
32453
  return ["WEBVTT", ...cues.map(formatCue)].join("\n\n");
32442
32454
  }
32455
+ function formatVttPassages(passages, notes = []) {
32456
+ return [
32457
+ "WEBVTT",
32458
+ ...formatNoteBlock(notes),
32459
+ ...passages.flatMap(formatPassage)
32460
+ ].join("\n\n");
32461
+ }
32443
32462
 
32444
32463
  // src/commands/transcript/convert/readCleanedCues.ts
32445
32464
  import { readFileSync as readFileSync55 } from "fs";
@@ -32558,9 +32577,169 @@ function list4() {
32558
32577
  }
32559
32578
  }
32560
32579
 
32580
+ // src/commands/transcript/merge.ts
32581
+ import { existsSync as existsSync73, writeFileSync as writeFileSync46 } from "fs";
32582
+ import { basename as basename21 } from "path";
32583
+
32584
+ // src/commands/transcript/failTranscript.ts
32585
+ function failTranscript(message3) {
32586
+ console.error(`Error: ${message3}`);
32587
+ process.exit(1);
32588
+ }
32589
+
32590
+ // src/commands/transcript/headerNotes.ts
32591
+ function removedNote(removed) {
32592
+ if (removed.length === 0) return [];
32593
+ const distinct = [...new Set(removed)];
32594
+ const noun = removed.length === 1 ? "passage" : "passages";
32595
+ return [`${removed.length} ${noun} removed: ${distinct.join(", ")}`];
32596
+ }
32597
+ function headerNotes(sources, removed) {
32598
+ return [
32599
+ `Collapsed ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)} from:`,
32600
+ ...sources.map((source) => ` ${source.name}`),
32601
+ ...removedNote(removed)
32602
+ ];
32603
+ }
32604
+
32605
+ // src/commands/transcript/rebasePassages.ts
32606
+ var JOIN_GAP_MS = 1e3;
32607
+ function rebasePassages(passages) {
32608
+ let cursorMs = 0;
32609
+ return passages.map((passage) => {
32610
+ const cues = shift(passage.cues, cursorMs - passage.sourceStartMs);
32611
+ cursorMs = lastEndMs(cues) + JOIN_GAP_MS;
32612
+ return { ...passage, cues };
32613
+ });
32614
+ }
32615
+ function shift(cues, offsetMs) {
32616
+ return cues.map((cue) => ({
32617
+ ...cue,
32618
+ startMs: cue.startMs + offsetMs,
32619
+ endMs: cue.endMs + offsetMs
32620
+ }));
32621
+ }
32622
+ function lastEndMs(cues) {
32623
+ return Math.max(...cues.map((cue) => cue.endMs));
32624
+ }
32625
+
32626
+ // src/commands/transcript/selectPassages.ts
32627
+ var CLOCK = /^(?:(\d{1,3}):)?(\d{1,2}):(\d{1,2})(?:\.(\d{1,3}))?$/;
32628
+ function describeRange(range) {
32629
+ return `${range.from} --> ${range.to} in ${range.file}`;
32630
+ }
32631
+ function parseClock(value, range) {
32632
+ const match = value.match(CLOCK);
32633
+ if (!match) {
32634
+ failTranscript(
32635
+ `malformed timestamp "${value}" in selection range ${describeRange(range)}`
32636
+ );
32637
+ }
32638
+ const [, hours, minutes, seconds, millis] = match;
32639
+ return (Number(hours ?? 0) * 3600 + Number(minutes) * 60 + Number(seconds)) * 1e3 + Number((millis ?? "").padEnd(3, "0"));
32640
+ }
32641
+ function findSource(sources, range) {
32642
+ const match = sources.find(
32643
+ (source) => source.path === range.file || source.name === range.file
32644
+ );
32645
+ return match ?? failTranscript(`selection names a file that was not given: ${range.file}`);
32646
+ }
32647
+ function spanOf(source) {
32648
+ return {
32649
+ startMs: source.cues[0].startMs,
32650
+ endMs: Math.max(...source.cues.map((cue) => cue.endMs))
32651
+ };
32652
+ }
32653
+ function boundsOf(source, range) {
32654
+ const fromMs = parseClock(range.from, range);
32655
+ const toMs = parseClock(range.to, range);
32656
+ if (toMs < fromMs) {
32657
+ failTranscript(
32658
+ `selection range ${describeRange(range)} ends before it starts`
32659
+ );
32660
+ }
32661
+ const span = spanOf(source);
32662
+ if (fromMs > span.endMs || toMs < span.startMs) {
32663
+ failTranscript(
32664
+ `selection range ${describeRange(range)} lies outside that file's cues`
32665
+ );
32666
+ }
32667
+ return { fromMs, toMs };
32668
+ }
32669
+ function cuesInRange(source, range) {
32670
+ const { fromMs, toMs } = boundsOf(source, range);
32671
+ return source.cues.filter(
32672
+ (cue) => cue.startMs >= fromMs && cue.startMs <= toMs
32673
+ );
32674
+ }
32675
+ function toPassage(source, cues) {
32676
+ return { source: source.name, sourceStartMs: cues[0].startMs, cues };
32677
+ }
32678
+ function selectPassages(sources, selection) {
32679
+ const passages = selection.keep.flatMap((range) => {
32680
+ const source = findSource(sources, range);
32681
+ const cues = cuesInRange(source, range);
32682
+ return cues.length ? [toPassage(source, cues)] : [];
32683
+ });
32684
+ if (passages.length === 0) {
32685
+ failTranscript("selection kept no cues from any source");
32686
+ }
32687
+ return passages;
32688
+ }
32689
+
32690
+ // src/commands/transcript/selectionSchema.ts
32691
+ import { z as z9 } from "zod";
32692
+ var selectionSchema = z9.strictObject({
32693
+ keep: z9.array(
32694
+ z9.strictObject({
32695
+ file: z9.string().trim().min(1, "file is required"),
32696
+ from: z9.string().trim().min(1, "from is required"),
32697
+ to: z9.string().trim().min(1, "to is required")
32698
+ })
32699
+ ).min(1, "a selection needs at least one keep range"),
32700
+ removed: z9.array(z9.string().trim().min(1)).default([])
32701
+ });
32702
+
32703
+ // src/commands/transcript/merge.ts
32704
+ function readSource2(file) {
32705
+ if (!existsSync73(file)) failTranscript(`VTT file not found: ${file}`);
32706
+ const cues = readCleanedCues(file);
32707
+ if (cues.length === 0) failTranscript(`no cues found in: ${file}`);
32708
+ return { path: file, name: basename21(file), cues };
32709
+ }
32710
+ function wholePassages(sources) {
32711
+ return sources.map((source) => ({
32712
+ source: source.name,
32713
+ sourceStartMs: source.cues[0].startMs,
32714
+ cues: source.cues
32715
+ }));
32716
+ }
32717
+ async function readSelection(source) {
32718
+ if (!source) return void 0;
32719
+ return readJsonPayload(source, selectionSchema, "transcript selection");
32720
+ }
32721
+ async function merge(files, options2 = {}) {
32722
+ const sources = files.map(readSource2);
32723
+ const selection = await readSelection(options2.select);
32724
+ const passages = rebasePassages(
32725
+ selection ? selectPassages(sources, selection) : wholePassages(sources)
32726
+ );
32727
+ const document = formatVttPassages(
32728
+ passages,
32729
+ headerNotes(sources, selection?.removed ?? [])
32730
+ );
32731
+ if (!options2.out) {
32732
+ console.log(document);
32733
+ return;
32734
+ }
32735
+ writeFileSync46(options2.out, `${document}
32736
+ `, "utf8");
32737
+ console.log(`Merged transcript: ${options2.out}`);
32738
+ }
32739
+
32561
32740
  // src/commands/transcript/move.ts
32562
- import { existsSync as existsSync73, mkdirSync as mkdirSync28, renameSync as renameSync2, writeFileSync as writeFileSync46 } from "fs";
32563
- import { basename as basename21, join as join85 } from "path";
32741
+ import { existsSync as existsSync74, mkdirSync as mkdirSync28, renameSync as renameSync2, writeFileSync as writeFileSync47 } from "fs";
32742
+ import { basename as basename22, join as join85 } from "path";
32564
32743
 
32565
32744
  // src/commands/transcript/convertVttToMarkdown.ts
32566
32745
  function convertVttToMarkdown(inputPath) {
@@ -32581,18 +32760,18 @@ function move(file, options2) {
32581
32760
  process.exit(1);
32582
32761
  }
32583
32762
  const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
32584
- const filename = basename21(file);
32763
+ const filename = basename22(file);
32585
32764
  const sourcePath = join85(vttDir, filename);
32586
- if (!existsSync73(sourcePath)) {
32765
+ if (!existsSync74(sourcePath)) {
32587
32766
  console.error(`Error: VTT file not found: ${sourcePath}`);
32588
32767
  process.exit(1);
32589
32768
  }
32590
- const base = basename21(filename, ".vtt").replace(/ Transcription$/, "");
32769
+ const base = basename22(filename, ".vtt").replace(/ Transcription$/, "");
32591
32770
  const outputName = `${date} ${base}.md`;
32592
32771
  const formattedDir = join85(transcriptsDir, client);
32593
32772
  mkdirSync28(formattedDir, { recursive: true });
32594
32773
  const formattedPath = join85(formattedDir, outputName);
32595
- writeFileSync46(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
32774
+ writeFileSync47(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
32596
32775
  archiveRawVtt(vttDir, sourcePath, filename);
32597
32776
  const summaryPath = join85(summaryDir, client, outputName);
32598
32777
  console.log(`Formatted transcript: ${formattedPath}`);
@@ -32606,6 +32785,12 @@ function registerTranscript(program2) {
32606
32785
  transcriptCommand.command("configure").description("Configure transcript directories").action(configure);
32607
32786
  transcriptCommand.command("list").description("List raw .vtt filenames waiting in the pick-up directory").action(list4);
32608
32787
  transcriptCommand.command("clean <path>").description("Clean any .vtt file and write the result to stdout").option("--format <md|vtt>", "output format", "md").action(clean);
32788
+ transcriptCommand.command("merge <path...>").description(
32789
+ "Collapse several .vtt files into one transcript with NOTE provenance"
32790
+ ).option("--out <path>", "write the merged transcript to this path").option(
32791
+ "--select <file|->",
32792
+ "keep/removed JSON naming the passages to keep (- for stdin)"
32793
+ ).action(merge);
32609
32794
  transcriptCommand.command("move <file>").description(
32610
32795
  "Convert a raw .vtt to a dated markdown transcript and archive the original"
32611
32796
  ).requiredOption("--date <YYYY-MM-DD>", "meeting date").requiredOption("--client <name>", "client name").action(move);
@@ -32713,9 +32898,9 @@ function devices() {
32713
32898
  }
32714
32899
 
32715
32900
  // src/commands/voice/logs.ts
32716
- import { existsSync as existsSync74, readFileSync as readFileSync56 } from "fs";
32901
+ import { existsSync as existsSync75, readFileSync as readFileSync56 } from "fs";
32717
32902
  function logs(options2) {
32718
- if (!existsSync74(voicePaths.log)) {
32903
+ if (!existsSync75(voicePaths.log)) {
32719
32904
  console.log("No voice log file found");
32720
32905
  return;
32721
32906
  }
@@ -32747,7 +32932,7 @@ import { join as join89 } from "path";
32747
32932
 
32748
32933
  // src/commands/voice/checkLockFile.ts
32749
32934
  import { execSync as execSync59 } from "child_process";
32750
- import { existsSync as existsSync75, mkdirSync as mkdirSync29, readFileSync as readFileSync57, writeFileSync as writeFileSync47 } from "fs";
32935
+ import { existsSync as existsSync76, mkdirSync as mkdirSync29, readFileSync as readFileSync57, writeFileSync as writeFileSync48 } from "fs";
32751
32936
  import { join as join88 } from "path";
32752
32937
  function isProcessAlive2(pid) {
32753
32938
  try {
@@ -32759,7 +32944,7 @@ function isProcessAlive2(pid) {
32759
32944
  }
32760
32945
  function checkLockFile() {
32761
32946
  const lockFile = getLockFile();
32762
- if (!existsSync75(lockFile)) return;
32947
+ if (!existsSync76(lockFile)) return;
32763
32948
  try {
32764
32949
  const lock2 = JSON.parse(readFileSync57(lockFile, "utf8"));
32765
32950
  if (lock2.pid && isProcessAlive2(lock2.pid)) {
@@ -32772,7 +32957,7 @@ function checkLockFile() {
32772
32957
  }
32773
32958
  }
32774
32959
  function bootstrapVenv() {
32775
- if (existsSync75(getVenvPython())) return;
32960
+ if (existsSync76(getVenvPython())) return;
32776
32961
  console.log("Setting up Python environment...");
32777
32962
  const pythonDir = getPythonDir();
32778
32963
  execSync59(
@@ -32786,7 +32971,7 @@ function bootstrapVenv() {
32786
32971
  function writeLockFile(pid) {
32787
32972
  const lockFile = getLockFile();
32788
32973
  mkdirSync29(join88(lockFile, ".."), { recursive: true });
32789
- writeFileSync47(
32974
+ writeFileSync48(
32790
32975
  lockFile,
32791
32976
  JSON.stringify({
32792
32977
  pid,
@@ -32814,7 +32999,7 @@ function setup() {
32814
32999
 
32815
33000
  // src/commands/voice/start.ts
32816
33001
  import { spawn as spawn8 } from "child_process";
32817
- import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync48 } from "fs";
33002
+ import { mkdirSync as mkdirSync31, writeFileSync as writeFileSync49 } from "fs";
32818
33003
  import { join as join90 } from "path";
32819
33004
 
32820
33005
  // src/commands/voice/buildDaemonEnv.ts
@@ -32843,7 +33028,7 @@ function spawnBackground(python, script, env) {
32843
33028
  console.error("Failed to start voice daemon");
32844
33029
  process.exit(1);
32845
33030
  }
32846
- writeFileSync48(voicePaths.pid, String(pid));
33031
+ writeFileSync49(voicePaths.pid, String(pid));
32847
33032
  writeLockFile(pid);
32848
33033
  console.log(`Voice daemon started (PID ${pid})`);
32849
33034
  }
@@ -32863,7 +33048,7 @@ function start2(options2) {
32863
33048
  }
32864
33049
 
32865
33050
  // src/commands/voice/status.ts
32866
- import { existsSync as existsSync76, readFileSync as readFileSync58 } from "fs";
33051
+ import { existsSync as existsSync77, readFileSync as readFileSync58 } from "fs";
32867
33052
  function isProcessAlive3(pid) {
32868
33053
  try {
32869
33054
  process.kill(pid, 0);
@@ -32873,12 +33058,12 @@ function isProcessAlive3(pid) {
32873
33058
  }
32874
33059
  }
32875
33060
  function readRecentLogs(count8) {
32876
- if (!existsSync76(voicePaths.log)) return [];
33061
+ if (!existsSync77(voicePaths.log)) return [];
32877
33062
  const lines2 = readFileSync58(voicePaths.log, "utf8").trim().split("\n");
32878
33063
  return lines2.slice(-count8);
32879
33064
  }
32880
33065
  function status2() {
32881
- if (!existsSync76(voicePaths.pid)) {
33066
+ if (!existsSync77(voicePaths.pid)) {
32882
33067
  console.log("Voice daemon: not running (no PID file)");
32883
33068
  return;
32884
33069
  }
@@ -32901,9 +33086,9 @@ function status2() {
32901
33086
  }
32902
33087
 
32903
33088
  // src/commands/voice/stop.ts
32904
- import { existsSync as existsSync77, readFileSync as readFileSync59, unlinkSync as unlinkSync20 } from "fs";
33089
+ import { existsSync as existsSync78, readFileSync as readFileSync59, unlinkSync as unlinkSync20 } from "fs";
32905
33090
  function stop2() {
32906
- if (!existsSync77(voicePaths.pid)) {
33091
+ if (!existsSync78(voicePaths.pid)) {
32907
33092
  console.log("Voice daemon is not running (no PID file)");
32908
33093
  return;
32909
33094
  }
@@ -32920,7 +33105,7 @@ function stop2() {
32920
33105
  }
32921
33106
  try {
32922
33107
  const lockFile = getLockFile();
32923
- if (existsSync77(lockFile)) unlinkSync20(lockFile);
33108
+ if (existsSync78(lockFile)) unlinkSync20(lockFile);
32924
33109
  } catch {
32925
33110
  }
32926
33111
  console.log("Voice daemon stopped");
@@ -33239,9 +33424,9 @@ function stashDirtyTree(cwd) {
33239
33424
  function mergeBehindBranch(cwd) {
33240
33425
  const stash = stashDirtyTree(cwd);
33241
33426
  if (!stash.ok) return { kind: "blocked", reason: stash.reason };
33242
- const merge = attemptGit(["merge", "--ff-only", "@{u}"], cwd);
33427
+ const merge2 = attemptGit(["merge", "--ff-only", "@{u}"], cwd);
33243
33428
  const restore2 = stash.stashed ? attemptGit(["stash", "pop"], cwd) : { ok: true };
33244
- if (!merge.ok) return { kind: "blocked", reason: merge.reason };
33429
+ if (!merge2.ok) return { kind: "blocked", reason: merge2.reason };
33245
33430
  if (!restore2.ok) return { kind: "blocked", reason: restore2.reason };
33246
33431
  return fastForwarded(cwd);
33247
33432
  }
@@ -33325,7 +33510,7 @@ function resolveParams(params, cliArgs) {
33325
33510
  }
33326
33511
 
33327
33512
  // src/commands/run/resolveRunCwd.ts
33328
- import { existsSync as existsSync78 } from "fs";
33513
+ import { existsSync as existsSync79 } from "fs";
33329
33514
  import { resolve as resolve19 } from "path";
33330
33515
  var MissingRunCwdError = class extends Error {
33331
33516
  constructor(runName, cwd) {
@@ -33338,17 +33523,17 @@ var MissingRunCwdError = class extends Error {
33338
33523
  function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
33339
33524
  if (!config.cwd) return void 0;
33340
33525
  const cwd = resolve19(baseDir, config.cwd);
33341
- if (!existsSync78(cwd)) throw new MissingRunCwdError(config.name, cwd);
33526
+ if (!existsSync79(cwd)) throw new MissingRunCwdError(config.name, cwd);
33342
33527
  return cwd;
33343
33528
  }
33344
33529
 
33345
33530
  // src/commands/run/runCommandToCompletion.ts
33346
33531
  import { spawn as spawn9 } from "child_process";
33347
- import { existsSync as existsSync80 } from "fs";
33532
+ import { existsSync as existsSync81 } from "fs";
33348
33533
 
33349
33534
  // src/commands/run/resolveCommand.ts
33350
33535
  import { execFileSync as execFileSync17 } from "child_process";
33351
- import { existsSync as existsSync79 } from "fs";
33536
+ import { existsSync as existsSync80 } from "fs";
33352
33537
  import { dirname as dirname37, join as join92, resolve as resolve20 } from "path";
33353
33538
  function resolveCommand2(command) {
33354
33539
  if (process.platform !== "win32" || command !== "bash") return command;
@@ -33356,7 +33541,7 @@ function resolveCommand2(command) {
33356
33541
  const gitPath = execFileSync17("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
33357
33542
  const gitRoot = resolve20(dirname37(gitPath), "..");
33358
33543
  const gitBash = join92(gitRoot, "bin", "bash.exe");
33359
- if (existsSync79(gitBash)) return gitBash;
33544
+ if (existsSync80(gitBash)) return gitBash;
33360
33545
  } catch {
33361
33546
  return command;
33362
33547
  }
@@ -33366,7 +33551,7 @@ function resolveCommand2(command) {
33366
33551
  // src/commands/run/runCommandToCompletion.ts
33367
33552
  function runCommandToCompletion(command, args, env, cwd, quiet) {
33368
33553
  return new Promise((resolveResult) => {
33369
- if (cwd && !existsSync80(cwd)) {
33554
+ if (cwd && !existsSync81(cwd)) {
33370
33555
  resolveResult({
33371
33556
  kind: "failed",
33372
33557
  message: `Failed to execute command: cwd ${cwd} does not exist`
@@ -33944,7 +34129,7 @@ async function run3(name, args) {
33944
34129
  }
33945
34130
 
33946
34131
  // src/commands/run/add.ts
33947
- import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync49 } from "fs";
34132
+ import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync50 } from "fs";
33948
34133
  import { join as join94 } from "path";
33949
34134
 
33950
34135
  // src/commands/run/extractOption.ts
@@ -34015,7 +34200,7 @@ description: Run ${name}
34015
34200
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
34016
34201
  `;
34017
34202
  const filePath = join94(dir, `${name}.md`);
34018
- writeFileSync49(filePath, content);
34203
+ writeFileSync50(filePath, content);
34019
34204
  console.log(`Created command file: ${filePath}`);
34020
34205
  }
34021
34206
  function add3() {
@@ -34070,7 +34255,7 @@ function link2() {
34070
34255
  }
34071
34256
 
34072
34257
  // src/commands/run/remove.ts
34073
- import { existsSync as existsSync81, unlinkSync as unlinkSync21 } from "fs";
34258
+ import { existsSync as existsSync82, unlinkSync as unlinkSync21 } from "fs";
34074
34259
  import { join as join95 } from "path";
34075
34260
  function findRemoveIndex() {
34076
34261
  const idx = process.argv.indexOf("remove");
@@ -34087,7 +34272,7 @@ function parseRemoveName() {
34087
34272
  }
34088
34273
  function deleteCommandFile(name) {
34089
34274
  const filePath = join95(".claude", "commands", `${name}.md`);
34090
- if (existsSync81(filePath)) {
34275
+ if (existsSync82(filePath)) {
34091
34276
  unlinkSync21(filePath);
34092
34277
  console.log(`Deleted command file: ${filePath}`);
34093
34278
  }
@@ -34132,7 +34317,7 @@ function registerRun(program2) {
34132
34317
 
34133
34318
  // src/commands/screenshot/index.ts
34134
34319
  import { execSync as execSync61 } from "child_process";
34135
- import { existsSync as existsSync82, mkdirSync as mkdirSync33, unlinkSync as unlinkSync22, writeFileSync as writeFileSync50 } from "fs";
34320
+ import { existsSync as existsSync83, mkdirSync as mkdirSync33, unlinkSync as unlinkSync22, writeFileSync as writeFileSync51 } from "fs";
34136
34321
  import { tmpdir as tmpdir9 } from "os";
34137
34322
  import { join as join96, resolve as resolve21 } from "path";
34138
34323
  import chalk227 from "chalk";
@@ -34264,7 +34449,7 @@ Write-Output $OutputPath
34264
34449
 
34265
34450
  // src/commands/screenshot/index.ts
34266
34451
  function buildOutputPath(outputDir, processName) {
34267
- if (!existsSync82(outputDir)) {
34452
+ if (!existsSync83(outputDir)) {
34268
34453
  mkdirSync33(outputDir, { recursive: true });
34269
34454
  }
34270
34455
  const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
@@ -34272,7 +34457,7 @@ function buildOutputPath(outputDir, processName) {
34272
34457
  }
34273
34458
  function runPowerShellScript(processName, outputPath) {
34274
34459
  const scriptPath = join96(tmpdir9(), `assist-screenshot-${Date.now()}.ps1`);
34275
- writeFileSync50(scriptPath, captureWindowPs1, "utf8");
34460
+ writeFileSync51(scriptPath, captureWindowPs1, "utf8");
34276
34461
  try {
34277
34462
  execSync61(
34278
34463
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
@@ -34522,9 +34707,9 @@ function createAutoExit(exit, graceMs = DEFAULT_GRACE_MS) {
34522
34707
  }
34523
34708
 
34524
34709
  // src/commands/sessions/daemon/loadActiveSelection.ts
34525
- import { z as z9 } from "zod";
34710
+ import { z as z10 } from "zod";
34526
34711
  var ACTIVE_FILE = "active.json";
34527
- var activeSelectionSchema = z9.record(z9.string(), z9.string());
34712
+ var activeSelectionSchema = z10.record(z10.string(), z10.string());
34528
34713
  function loadActiveSelection() {
34529
34714
  const parsed = activeSelectionSchema.safeParse(
34530
34715
  loadJson(ACTIVE_FILE)
@@ -34609,12 +34794,12 @@ function toSessionRunInfo({
34609
34794
  }
34610
34795
 
34611
34796
  // src/commands/sessions/daemon/worktree/joinRefusal.ts
34612
- import { existsSync as existsSync83 } from "fs";
34797
+ import { existsSync as existsSync84 } from "fs";
34613
34798
  function joinRefusal(session) {
34614
34799
  if (session.commandType === "run") return "a server run has no agent stream";
34615
34800
  if (session.closing === true) return "the session is closing";
34616
34801
  if (!session.cwd) return "the session has no working directory";
34617
- if (!existsSync83(session.cwd))
34802
+ if (!existsSync84(session.cwd))
34618
34803
  return "the session's workspace no longer exists";
34619
34804
  return void 0;
34620
34805
  }
@@ -34778,11 +34963,11 @@ function sessionBase(id, status3) {
34778
34963
  }
34779
34964
 
34780
34965
  // src/commands/sessions/daemon/spawnPty.ts
34781
- import { existsSync as existsSync85 } from "fs";
34966
+ import { existsSync as existsSync86 } from "fs";
34782
34967
  import * as pty from "node-pty";
34783
34968
 
34784
34969
  // src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
34785
- import { chmodSync, existsSync as existsSync84, statSync as statSync13 } from "fs";
34970
+ import { chmodSync, existsSync as existsSync85, statSync as statSync13 } from "fs";
34786
34971
  import { createRequire as createRequire3 } from "module";
34787
34972
  import path85 from "path";
34788
34973
  var require4 = createRequire3(import.meta.url);
@@ -34797,7 +34982,7 @@ function ensureSpawnHelperExecutable() {
34797
34982
  `${process.platform}-${process.arch}`,
34798
34983
  "spawn-helper"
34799
34984
  );
34800
- if (!existsSync84(helper)) return;
34985
+ if (!existsSync85(helper)) return;
34801
34986
  const mode = statSync13(helper).mode;
34802
34987
  if ((mode & 73) === 0) chmodSync(helper, mode | 493);
34803
34988
  }
@@ -34833,7 +35018,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
34833
35018
  });
34834
35019
  }
34835
35020
  function refuseMissingCwd(cwd, sessionId) {
34836
- if (!cwd || existsSync85(cwd)) return;
35021
+ if (!cwd || existsSync86(cwd)) return;
34837
35022
  daemonLog(
34838
35023
  `${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
34839
35024
  );
@@ -35015,11 +35200,11 @@ function setStatus2(session, newStatus) {
35015
35200
  }
35016
35201
 
35017
35202
  // src/commands/sessions/daemon/worktree/reapWorktree.ts
35018
- import { existsSync as existsSync87 } from "fs";
35019
- import { basename as basename22 } from "path";
35203
+ import { existsSync as existsSync88 } from "fs";
35204
+ import { basename as basename23 } from "path";
35020
35205
 
35021
35206
  // src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
35022
- import { existsSync as existsSync86 } from "fs";
35207
+ import { existsSync as existsSync87 } from "fs";
35023
35208
  import { join as join99 } from "path";
35024
35209
 
35025
35210
  // src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
@@ -35089,7 +35274,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
35089
35274
  );
35090
35275
  }
35091
35276
  function strandedReason(worktreePath, cause) {
35092
- if (!existsSync86(join99(worktreePath, ".git")))
35277
+ if (!existsSync87(join99(worktreePath, ".git")))
35093
35278
  return "its .git link is already gone";
35094
35279
  if (/not a working tree|not a git repository/i.test(reason2(cause)))
35095
35280
  return "git no longer recognises it as a working tree";
@@ -35141,7 +35326,7 @@ function reason3(error) {
35141
35326
 
35142
35327
  // src/commands/sessions/daemon/worktree/reapWorktree.ts
35143
35328
  async function reapWorktree(worktreePath, force = false) {
35144
- if (!existsSync87(worktreePath)) {
35329
+ if (!existsSync88(worktreePath)) {
35145
35330
  forgetWorktree(worktreePath);
35146
35331
  daemonLog(
35147
35332
  `worktree ${worktreePath} already gone; its record was forgotten`
@@ -35159,14 +35344,14 @@ async function reapWorktree(worktreePath, force = false) {
35159
35344
  const clone = owningClone(worktreePath);
35160
35345
  const removal = await removeTree(clone, worktreePath, force);
35161
35346
  if (!removal.removed) return removal;
35162
- await deleteWorktreeBranch(clone, basename22(worktreePath));
35347
+ await deleteWorktreeBranch(clone, basename23(worktreePath));
35163
35348
  forgetWorktree(worktreePath);
35164
35349
  daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
35165
35350
  return removal;
35166
35351
  }
35167
35352
  function owningClone(worktreePath) {
35168
35353
  const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
35169
- if (recorded && existsSync87(recorded)) return recorded;
35354
+ if (recorded && existsSync88(recorded)) return recorded;
35170
35355
  const detected = mainWorktree(worktreePath);
35171
35356
  if (detected) return detected;
35172
35357
  daemonLog(
@@ -35297,12 +35482,12 @@ function closeGateApplies(sessions, session) {
35297
35482
  }
35298
35483
 
35299
35484
  // src/commands/sessions/daemon/worktree/watchGitState.ts
35300
- import { existsSync as existsSync88, watch } from "fs";
35485
+ import { existsSync as existsSync89, watch } from "fs";
35301
35486
  var DEBOUNCE_MS = 500;
35302
35487
  var POLL_MS = 3e4;
35303
35488
  function watchGitState(cwd, onChange) {
35304
35489
  const common = gitCommonDir(cwd);
35305
- if (!common || !existsSync88(common)) return void 0;
35490
+ if (!common || !existsSync89(common)) return void 0;
35306
35491
  const watchers = [
35307
35492
  watchGitDir(common, onChange),
35308
35493
  pollGitState(cwd, onChange)
@@ -35792,10 +35977,10 @@ function emitSessionOutput(session, clients, data) {
35792
35977
  }
35793
35978
 
35794
35979
  // src/commands/sessions/daemon/exitReason.ts
35795
- import { existsSync as existsSync89 } from "fs";
35980
+ import { existsSync as existsSync90 } from "fs";
35796
35981
  import { resolve as resolve22 } from "path";
35797
35982
  function exitDetail(session) {
35798
- if (session.cwd && !existsSync89(session.cwd))
35983
+ if (session.cwd && !existsSync90(session.cwd))
35799
35984
  return `working directory ${session.cwd} no longer exists`;
35800
35985
  return missingRunConfigCwd(session);
35801
35986
  }
@@ -35809,7 +35994,7 @@ function missingRunConfigCwd(session) {
35809
35994
  const config = resolveRunConfig(session.runName, dir);
35810
35995
  if (!config?.cwd) return void 0;
35811
35996
  const configured = resolve22(runConfigBaseDirFrom(dir), config.cwd);
35812
- if (existsSync89(configured)) return void 0;
35997
+ if (existsSync90(configured)) return void 0;
35813
35998
  return `run config "${config.name}": cwd ${configured} does not exist`;
35814
35999
  }
35815
36000
 
@@ -35850,7 +36035,7 @@ function handleFailedResume(session, exitCode, onStatusChange) {
35850
36035
  }
35851
36036
 
35852
36037
  // src/commands/sessions/daemon/watchActivity.ts
35853
- import { existsSync as existsSync90, mkdirSync as mkdirSync34, watch as watch2 } from "fs";
36038
+ import { existsSync as existsSync91, mkdirSync as mkdirSync34, watch as watch2 } from "fs";
35854
36039
  import { dirname as dirname39 } from "path";
35855
36040
 
35856
36041
  // src/commands/sessions/daemon/applyActivityToSession.ts
@@ -35936,7 +36121,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
35936
36121
  if (timer) clearTimeout(timer);
35937
36122
  timer = setTimeout(read3, DEBOUNCE_MS2);
35938
36123
  });
35939
- if (existsSync90(path90)) read3();
36124
+ if (existsSync91(path90)) read3();
35940
36125
  }
35941
36126
  function refreshActivity(session) {
35942
36127
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -37659,8 +37844,8 @@ function rearmStoppedSessions(sessions, notify2) {
37659
37844
  }
37660
37845
 
37661
37846
  // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
37662
- import { existsSync as existsSync93 } from "fs";
37663
- import { basename as basename24 } from "path";
37847
+ import { existsSync as existsSync94 } from "fs";
37848
+ import { basename as basename25 } from "path";
37664
37849
 
37665
37850
  // src/commands/sessions/daemon/worktree/accountedTrees.ts
37666
37851
  function accountedTrees(sessions) {
@@ -37714,9 +37899,9 @@ function bindResumedWorktree(session, cwd, notify2) {
37714
37899
  }
37715
37900
 
37716
37901
  // src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
37717
- import { existsSync as existsSync92 } from "fs";
37902
+ import { existsSync as existsSync93 } from "fs";
37718
37903
  async function reclaimVanishedWorktrees(clone, paths) {
37719
- if (!existsSync92(clone)) {
37904
+ if (!existsSync93(clone)) {
37720
37905
  for (const { path: path90 } of paths) forgetWorktree(path90);
37721
37906
  daemonLog(
37722
37907
  `clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
@@ -37802,7 +37987,7 @@ function capped(lines2) {
37802
37987
  }
37803
37988
 
37804
37989
  // src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
37805
- import { basename as basename23 } from "path";
37990
+ import { basename as basename24 } from "path";
37806
37991
  function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
37807
37992
  const { orphan, reason: reason4, held } = recovered;
37808
37993
  let id;
@@ -37825,7 +38010,7 @@ function orphanedSession(id, recovered) {
37825
38010
  const { orphan, reason: reason4, held } = recovered;
37826
38011
  return {
37827
38012
  ...sessionBase(id, "stopped"),
37828
- name: `recovered ${basename23(orphan.path)}`,
38013
+ name: `recovered ${basename24(orphan.path)}`,
37829
38014
  subtitle: `${held.summary} in ${orphan.path}`,
37830
38015
  commandType: "claude",
37831
38016
  pty: null,
@@ -37882,11 +38067,11 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
37882
38067
  );
37883
38068
  continue;
37884
38069
  }
37885
- if (!existsSync93(path90)) {
38070
+ if (!existsSync94(path90)) {
37886
38071
  logVanishedTree(sessions, path90);
37887
38072
  vanished.set(clone, [
37888
38073
  ...vanished.get(clone) ?? [],
37889
- { path: path90, branch: basename24(path90) }
38074
+ { path: path90, branch: basename25(path90) }
37890
38075
  ]);
37891
38076
  continue;
37892
38077
  }
@@ -38527,13 +38712,13 @@ async function defaultConnect() {
38527
38712
  }
38528
38713
 
38529
38714
  // src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
38530
- import { existsSync as existsSync94, readFileSync as readFileSync63 } from "fs";
38715
+ import { existsSync as existsSync95, readFileSync as readFileSync63 } from "fs";
38531
38716
  import { posix as posix3 } from "path";
38532
38717
  function hasPersistedWindowsSessions() {
38533
38718
  const sessionsFile = windowsSessionsFileFromWsl();
38534
38719
  if (!sessionsFile) return false;
38535
38720
  try {
38536
- if (!existsSync94(sessionsFile)) return false;
38721
+ if (!existsSync95(sessionsFile)) return false;
38537
38722
  const data = JSON.parse(readFileSync63(sessionsFile, "utf8"));
38538
38723
  return Array.isArray(data) && data.length > 0;
38539
38724
  } catch (error) {
@@ -39268,7 +39453,7 @@ function setAutoAdvance(sessions, id, enabled) {
39268
39453
  }
39269
39454
 
39270
39455
  // src/commands/sessions/daemon/worktree/resumeInTree.ts
39271
- import { existsSync as existsSync97 } from "fs";
39456
+ import { existsSync as existsSync98 } from "fs";
39272
39457
 
39273
39458
  // src/commands/sessions/daemon/resumeSession.ts
39274
39459
  function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
@@ -39299,10 +39484,10 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
39299
39484
  }
39300
39485
 
39301
39486
  // src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
39302
- import { existsSync as existsSync96 } from "fs";
39487
+ import { existsSync as existsSync97 } from "fs";
39303
39488
 
39304
39489
  // src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
39305
- import { copyFileSync as copyFileSync7, existsSync as existsSync95, mkdirSync as mkdirSync36 } from "fs";
39490
+ import { copyFileSync as copyFileSync7, existsSync as existsSync96, mkdirSync as mkdirSync36 } from "fs";
39306
39491
  import { join as join101 } from "path";
39307
39492
  function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
39308
39493
  const dir = projectDirForCwd(toCwd);
@@ -39313,7 +39498,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
39313
39498
  return;
39314
39499
  }
39315
39500
  const dest = join101(dir, `${claudeSessionId}.jsonl`);
39316
- if (existsSync95(dest)) {
39501
+ if (existsSync96(dest)) {
39317
39502
  daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
39318
39503
  return;
39319
39504
  }
@@ -39364,7 +39549,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name, harness
39364
39549
  }
39365
39550
  function cloneForReapedTree(missingCwd) {
39366
39551
  const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
39367
- if (!clone || !existsSync96(clone))
39552
+ if (!clone || !existsSync97(clone))
39368
39553
  throw new Error(
39369
39554
  `working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
39370
39555
  );
@@ -39373,7 +39558,7 @@ function cloneForReapedTree(missingCwd) {
39373
39558
 
39374
39559
  // src/commands/sessions/daemon/worktree/resumeInTree.ts
39375
39560
  function resumeInTree(ctx, sessionId, cwd, name, harness) {
39376
- if (!existsSync97(cwd))
39561
+ if (!existsSync98(cwd))
39377
39562
  return resumeInReplacementTree(ctx, sessionId, cwd, name, harness);
39378
39563
  const id = ctx.spawnWith(
39379
39564
  (sid) => resumeSession(sid, sessionId, cwd, name, void 0, harness)
@@ -39956,7 +40141,7 @@ function handleConnection(socket, manager) {
39956
40141
  }
39957
40142
 
39958
40143
  // src/commands/sessions/daemon/onListening.ts
39959
- import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync51 } from "fs";
40144
+ import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync52 } from "fs";
39960
40145
 
39961
40146
  // src/commands/sessions/daemon/startPidFileWatchdog.ts
39962
40147
  import { readFileSync as readFileSync64 } from "fs";
@@ -39978,7 +40163,7 @@ function ownsPidFile() {
39978
40163
 
39979
40164
  // src/commands/sessions/daemon/onListening.ts
39980
40165
  function onListening(manager, checkAutoExit) {
39981
- writeFileSync51(daemonPaths.pid, String(process.pid));
40166
+ writeFileSync52(daemonPaths.pid, String(process.pid));
39982
40167
  startPidFileWatchdog(() => {
39983
40168
  daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
39984
40169
  void manager.flushActiveMs().finally(() => {