@staff0rd/assist 0.548.1 → 0.549.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.548.1",
9
+ version: "0.549.1",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -3421,6 +3421,312 @@ function isBicepFile(filePath) {
3421
3421
  return BICEP_EXTENSIONS.some((ext) => filePath.endsWith(ext));
3422
3422
  }
3423
3423
 
3424
+ // src/shared/isCsharpFile.ts
3425
+ var CSHARP_EXTENSIONS = [".cs", ".csx"];
3426
+ function isCsharpFile(filePath) {
3427
+ if (!filePath) return false;
3428
+ return CSHARP_EXTENSIONS.some((ext) => filePath.endsWith(ext));
3429
+ }
3430
+
3431
+ // src/shared/isGeneratedCsharpFile.ts
3432
+ var GENERATED_SUFFIXES = [".g.cs", ".designer.cs"];
3433
+ var BUILD_OUTPUT_DIR = /(^|[/\\])obj[/\\]/;
3434
+ var AUTO_GENERATED_MARKER = "<auto-generated";
3435
+ var HEADER_LINES = 10;
3436
+ function hasAutoGeneratedHeader(content) {
3437
+ return content.split("\n", HEADER_LINES).some((line) => line.toLowerCase().includes(AUTO_GENERATED_MARKER));
3438
+ }
3439
+ function isGeneratedCsharpFile(filePath, content) {
3440
+ if (!isCsharpFile(filePath) || !filePath) return false;
3441
+ const lower = filePath.toLowerCase();
3442
+ if (GENERATED_SUFFIXES.some((suffix) => lower.endsWith(suffix))) return true;
3443
+ if (BUILD_OUTPUT_DIR.test(lower)) return true;
3444
+ return content !== void 0 && hasAutoGeneratedHeader(content);
3445
+ }
3446
+
3447
+ // src/shared/isRazorFile.ts
3448
+ var RAZOR_EXTENSIONS = [".razor", ".cshtml"];
3449
+ function isRazorFile(filePath) {
3450
+ if (!filePath) return false;
3451
+ return RAZOR_EXTENSIONS.some((ext) => filePath.endsWith(ext));
3452
+ }
3453
+
3454
+ // src/shared/lineCounter.ts
3455
+ function lineCounter(content) {
3456
+ let scanned = 0;
3457
+ let line = 1;
3458
+ return (offset) => {
3459
+ for (; scanned < offset; scanned++) {
3460
+ if (content[scanned] === "\n") line++;
3461
+ }
3462
+ return line;
3463
+ };
3464
+ }
3465
+
3466
+ // src/shared/readRazorComment.ts
3467
+ var RAZOR_OPEN = "@*";
3468
+ var RAZOR_CLOSE = "*@";
3469
+ var HTML_OPEN = "<!--";
3470
+ var HTML_CLOSE = "-->";
3471
+ function read(content, index3, open, close) {
3472
+ const found = content.indexOf(close, index3 + open.length);
3473
+ const end = found === -1 ? content.length : found + close.length;
3474
+ return { end, text: content.slice(index3, end) };
3475
+ }
3476
+ function readRazorComment(content, index3) {
3477
+ if (content.startsWith(RAZOR_OPEN, index3))
3478
+ return read(content, index3, RAZOR_OPEN, RAZOR_CLOSE);
3479
+ if (content.startsWith(HTML_OPEN, index3))
3480
+ return read(content, index3, HTML_OPEN, HTML_CLOSE);
3481
+ return void 0;
3482
+ }
3483
+
3484
+ // src/shared/skipCsharpCharLiteral.ts
3485
+ var CHAR_LITERAL_MAX_LENGTH = 12;
3486
+ function skipCsharpCharLiteral(content, index3) {
3487
+ const limit = Math.min(content.length, index3 + CHAR_LITERAL_MAX_LENGTH);
3488
+ let cursor = index3 + 1;
3489
+ while (cursor < limit) {
3490
+ const char = content[cursor];
3491
+ if (char === "\n") break;
3492
+ if (char === "\\") {
3493
+ cursor += 2;
3494
+ continue;
3495
+ }
3496
+ if (char === "'") return cursor + 1;
3497
+ cursor++;
3498
+ }
3499
+ return index3 + 1;
3500
+ }
3501
+
3502
+ // src/shared/readCsharpStringStart.ts
3503
+ function readCsharpStringStart(content, index3) {
3504
+ let cursor = index3;
3505
+ let verbatim = false;
3506
+ let interpolated = false;
3507
+ while (content[cursor] === "@" || content[cursor] === "$") {
3508
+ if (content[cursor] === "@") verbatim = true;
3509
+ else interpolated = true;
3510
+ cursor++;
3511
+ }
3512
+ if (content[cursor] !== '"') return void 0;
3513
+ let quoteRun = 0;
3514
+ while (content[cursor + quoteRun] === '"') quoteRun++;
3515
+ return { quote: cursor, verbatim, interpolated, quoteRun };
3516
+ }
3517
+
3518
+ // src/shared/skipCsharpRawString.ts
3519
+ function skipCsharpRawString(content, quote, quoteRun) {
3520
+ let cursor = quote + quoteRun;
3521
+ while (cursor < content.length) {
3522
+ if (content[cursor] !== '"') {
3523
+ cursor++;
3524
+ continue;
3525
+ }
3526
+ let run4 = 0;
3527
+ while (content[cursor + run4] === '"') run4++;
3528
+ if (run4 >= quoteRun) return cursor + run4;
3529
+ cursor += run4;
3530
+ }
3531
+ return content.length;
3532
+ }
3533
+
3534
+ // src/shared/skipCsharpString.ts
3535
+ function skipInterpolationHole(content, index3) {
3536
+ let cursor = index3;
3537
+ let depth = 1;
3538
+ while (cursor < content.length) {
3539
+ const char = content[cursor];
3540
+ if (char === "{") depth++;
3541
+ else if (char === "}" && --depth === 0) return cursor + 1;
3542
+ else if (char === "'") {
3543
+ cursor = skipCsharpCharLiteral(content, cursor);
3544
+ continue;
3545
+ } else {
3546
+ const nested = skipCsharpString(content, cursor);
3547
+ if (nested !== void 0) {
3548
+ cursor = nested;
3549
+ continue;
3550
+ }
3551
+ }
3552
+ cursor++;
3553
+ }
3554
+ return content.length;
3555
+ }
3556
+ function skipDelimitedString(content, start3) {
3557
+ const { quote, verbatim, interpolated } = start3;
3558
+ let cursor = quote + 1;
3559
+ while (cursor < content.length) {
3560
+ const char = content[cursor];
3561
+ if (char === "\\" && !verbatim) cursor += 2;
3562
+ else if (char === "\n" && !verbatim) return cursor;
3563
+ else if (char === '"') {
3564
+ if (!verbatim || content[cursor + 1] !== '"') return cursor + 1;
3565
+ cursor += 2;
3566
+ } else if (interpolated && char === "{")
3567
+ cursor = content[cursor + 1] === "{" ? cursor + 2 : skipInterpolationHole(content, cursor + 1);
3568
+ else cursor++;
3569
+ }
3570
+ return content.length;
3571
+ }
3572
+ function skipCsharpString(content, index3) {
3573
+ const start3 = readCsharpStringStart(content, index3);
3574
+ if (!start3) return void 0;
3575
+ if (!start3.verbatim && start3.quoteRun >= 3)
3576
+ return skipCsharpRawString(content, start3.quote, start3.quoteRun);
3577
+ return skipDelimitedString(content, start3);
3578
+ }
3579
+
3580
+ // src/shared/stepRazorCode.ts
3581
+ function stepRazorCode(content, index3) {
3582
+ const char = content[index3];
3583
+ if (char === "{") return { next: index3 + 1, depthChange: 1 };
3584
+ if (char === "}") return { next: index3 + 1, depthChange: -1 };
3585
+ if (char === "'")
3586
+ return { next: skipCsharpCharLiteral(content, index3), depthChange: 0 };
3587
+ const afterString = skipCsharpString(content, index3);
3588
+ return { next: afterString ?? index3 + 1, depthChange: 0 };
3589
+ }
3590
+
3591
+ // src/shared/readRazorCodeBlockStart.ts
3592
+ var CODE_KEYWORDS = ["code", "functions"];
3593
+ var WHITESPACE = /* @__PURE__ */ new Set([" ", " ", "\r", "\n"]);
3594
+ function readRazorCodeBlockStart(content, index3) {
3595
+ if (content[index3] !== "@") return void 0;
3596
+ let cursor = index3 + 1;
3597
+ const keyword = CODE_KEYWORDS.find(
3598
+ (word) => content.startsWith(word, cursor)
3599
+ );
3600
+ if (keyword) {
3601
+ cursor += keyword.length;
3602
+ while (WHITESPACE.has(content[cursor] ?? "")) cursor++;
3603
+ }
3604
+ return content[cursor] === "{" ? cursor + 1 : void 0;
3605
+ }
3606
+
3607
+ // src/shared/skipHtmlTag.ts
3608
+ var TAG_NAME_START = /[A-Za-z/]/;
3609
+ function skipHtmlTag(content, index3) {
3610
+ if (content[index3] !== "<") return void 0;
3611
+ if (!TAG_NAME_START.test(content[index3 + 1] ?? "")) return void 0;
3612
+ let cursor = index3 + 1;
3613
+ while (cursor < content.length) {
3614
+ const char = content[cursor];
3615
+ if (char === '"' || char === "'") {
3616
+ const close = content.indexOf(char, cursor + 1);
3617
+ if (close === -1) return void 0;
3618
+ cursor = close + 1;
3619
+ } else if (char === ">") return cursor + 1;
3620
+ else cursor++;
3621
+ }
3622
+ return void 0;
3623
+ }
3624
+
3625
+ // src/shared/skipRawTextElement.ts
3626
+ var RAW_TEXT_TAGS = ["script", "style"];
3627
+ var TAG_NAME_END = /[^A-Za-z0-9-]/;
3628
+ function openedTag(content, tagStart, tagEnd) {
3629
+ if (content.slice(tagStart, tagEnd).endsWith("/>")) return "";
3630
+ const name = content.slice(tagStart + 1, tagEnd).toLowerCase();
3631
+ return RAW_TEXT_TAGS.find(
3632
+ (tag) => name.startsWith(tag) && TAG_NAME_END.test(name[tag.length] ?? ">")
3633
+ ) ?? "";
3634
+ }
3635
+ function skipRawTextElement(content, tagStart, tagEnd) {
3636
+ const tag = openedTag(content, tagStart, tagEnd);
3637
+ if (!tag) return tagEnd;
3638
+ const close = new RegExp(`</${tag}`, "i").exec(content.slice(tagEnd));
3639
+ return close ? tagEnd + close.index : tagEnd;
3640
+ }
3641
+
3642
+ // src/shared/skipRazorExpression.ts
3643
+ var IDENT_START = /[A-Za-z_]/;
3644
+ var IDENT_PART = /[A-Za-z0-9_]/;
3645
+ var GROUP_CLOSE = { "(": ")", "[": "]" };
3646
+ function skipGroup(content, index3) {
3647
+ const open = content[index3];
3648
+ const close = GROUP_CLOSE[open];
3649
+ let cursor = index3 + 1;
3650
+ let depth = 1;
3651
+ while (cursor < content.length) {
3652
+ const char = content[cursor];
3653
+ if (char === open) depth++;
3654
+ else if (char === close && --depth === 0) return cursor + 1;
3655
+ else if (char === "'") {
3656
+ cursor = skipCsharpCharLiteral(content, cursor);
3657
+ continue;
3658
+ } else {
3659
+ const afterString = skipCsharpString(content, cursor);
3660
+ if (afterString !== void 0) {
3661
+ cursor = afterString;
3662
+ continue;
3663
+ }
3664
+ }
3665
+ cursor++;
3666
+ }
3667
+ return void 0;
3668
+ }
3669
+ function skipRazorExpression(content, index3) {
3670
+ if (content[index3] !== "@") return void 0;
3671
+ const first = content[index3 + 1] ?? "";
3672
+ if (!IDENT_START.test(first) && !GROUP_CLOSE[first]) return void 0;
3673
+ let cursor = index3 + 1;
3674
+ while (cursor < content.length) {
3675
+ const char = content[cursor];
3676
+ if (IDENT_PART.test(char)) cursor++;
3677
+ else if (char === "." && IDENT_START.test(content[cursor + 1] ?? ""))
3678
+ cursor++;
3679
+ else if (GROUP_CLOSE[char]) {
3680
+ const afterGroup = skipGroup(content, cursor);
3681
+ if (afterGroup === void 0) return cursor;
3682
+ cursor = afterGroup;
3683
+ } else break;
3684
+ }
3685
+ return cursor;
3686
+ }
3687
+
3688
+ // src/shared/stepRazorMarkup.ts
3689
+ function stepRazorMarkup(content, index3) {
3690
+ const blockBody = readRazorCodeBlockStart(content, index3);
3691
+ if (blockBody !== void 0) return { next: blockBody, enteredCode: true };
3692
+ const expressionEnd = skipRazorExpression(content, index3);
3693
+ if (expressionEnd !== void 0)
3694
+ return { next: expressionEnd, enteredCode: false };
3695
+ const tagEnd = skipHtmlTag(content, index3);
3696
+ const next3 = tagEnd === void 0 ? index3 + 1 : skipRawTextElement(content, index3, tagEnd);
3697
+ return { next: next3, enteredCode: false };
3698
+ }
3699
+
3700
+ // src/shared/extractRazorComments.ts
3701
+ function extractRazorComments(content) {
3702
+ const comments3 = [];
3703
+ const lineOf = lineCounter(content);
3704
+ let index3 = 0;
3705
+ let codeDepth = 0;
3706
+ while (index3 < content.length) {
3707
+ if (content[index3] === "@" && content[index3 + 1] === "@") {
3708
+ index3 += 2;
3709
+ continue;
3710
+ }
3711
+ const comment3 = readRazorComment(content, index3);
3712
+ if (comment3) {
3713
+ comments3.push({ line: lineOf(index3), text: comment3.text });
3714
+ index3 = comment3.end;
3715
+ continue;
3716
+ }
3717
+ if (codeDepth > 0) {
3718
+ const step3 = stepRazorCode(content, index3);
3719
+ codeDepth += step3.depthChange;
3720
+ index3 = step3.next;
3721
+ continue;
3722
+ }
3723
+ const step2 = stepRazorMarkup(content, index3);
3724
+ if (step2.enteredCode) codeDepth = 1;
3725
+ index3 = step2.next;
3726
+ }
3727
+ return comments3;
3728
+ }
3729
+
3424
3730
  // src/commands/verify/blockCodeComments/collectBicepComments.ts
3425
3731
  function blankNonNewline(text17) {
3426
3732
  return text17.replace(/[^\n]/g, " ");
@@ -3444,6 +3750,84 @@ function collectBicepComments(content) {
3444
3750
  return comments3;
3445
3751
  }
3446
3752
 
3753
+ // src/shared/csharpHeaderLineCount.ts
3754
+ function closesBlock(trimmed, from) {
3755
+ return trimmed.includes("*/", from);
3756
+ }
3757
+ function csharpHeaderLineCount(content) {
3758
+ const lines2 = content.split("\n");
3759
+ let count8 = 0;
3760
+ let inBlock = false;
3761
+ while (count8 < lines2.length) {
3762
+ const trimmed = lines2[count8].trim();
3763
+ if (inBlock) {
3764
+ inBlock = !closesBlock(trimmed, 0);
3765
+ } else if (trimmed.startsWith("/*")) {
3766
+ inBlock = !closesBlock(trimmed, 2);
3767
+ } else if (trimmed !== "" && !trimmed.startsWith("//")) {
3768
+ break;
3769
+ }
3770
+ count8++;
3771
+ }
3772
+ return count8;
3773
+ }
3774
+
3775
+ // src/shared/readCsharpComment.ts
3776
+ function readCsharpComment(content, index3) {
3777
+ if (content[index3] !== "/") return void 0;
3778
+ if (content[index3 + 1] === "/") {
3779
+ const lineEnd = content.indexOf("\n", index3);
3780
+ const end = lineEnd === -1 ? content.length : lineEnd;
3781
+ return { end, text: content.slice(index3, end) };
3782
+ }
3783
+ if (content[index3 + 1] === "*") {
3784
+ const close = content.indexOf("*/", index3 + 2);
3785
+ const end = close === -1 ? content.length : close + 2;
3786
+ return { end, text: content.slice(index3, end) };
3787
+ }
3788
+ return void 0;
3789
+ }
3790
+
3791
+ // src/shared/extractCsharpComments.ts
3792
+ var WHITESPACE2 = /* @__PURE__ */ new Set([" ", " ", "\r"]);
3793
+ function extractCsharpComments(content) {
3794
+ const comments3 = [];
3795
+ const lineOf = lineCounter(content);
3796
+ let index3 = 0;
3797
+ let atLineStart = true;
3798
+ while (index3 < content.length) {
3799
+ const char = content[index3];
3800
+ if (char === "\n") {
3801
+ atLineStart = true;
3802
+ index3++;
3803
+ } else if (WHITESPACE2.has(char)) {
3804
+ index3++;
3805
+ } else if (atLineStart && char === "#") {
3806
+ const lineEnd = content.indexOf("\n", index3);
3807
+ index3 = lineEnd === -1 ? content.length : lineEnd;
3808
+ } else {
3809
+ atLineStart = false;
3810
+ const comment3 = readCsharpComment(content, index3);
3811
+ const afterString = comment3 ? void 0 : skipCsharpString(content, index3);
3812
+ if (comment3) {
3813
+ comments3.push({ line: lineOf(index3), text: comment3.text });
3814
+ index3 = comment3.end;
3815
+ } else if (char === "'") index3 = skipCsharpCharLiteral(content, index3);
3816
+ else if (afterString !== void 0) index3 = afterString;
3817
+ else index3++;
3818
+ }
3819
+ }
3820
+ return comments3;
3821
+ }
3822
+
3823
+ // src/commands/verify/blockCodeComments/collectCsharpComments.ts
3824
+ function collectCsharpComments(content) {
3825
+ const headerLines = csharpHeaderLineCount(content);
3826
+ return extractCsharpComments(content).filter(
3827
+ (comment3) => comment3.line > headerLines
3828
+ );
3829
+ }
3830
+
3447
3831
  // src/commands/verify/blockCodeComments/collectHashComments.ts
3448
3832
  function blankNonNewline2(text17) {
3449
3833
  return text17.replace(/[^\n]/g, " ");
@@ -3521,6 +3905,10 @@ var MACHINE_DIRECTIVES = [
3521
3905
  "v8 ignore",
3522
3906
  "c8 ignore",
3523
3907
  "@vitest-environment",
3908
+ "resharper disable",
3909
+ "resharper restore",
3910
+ "noinspection",
3911
+ "<auto-generated",
3524
3912
  MAINTAINABILITY_OVERRIDE_MARKER
3525
3913
  ];
3526
3914
  function isCommentExempt(text17) {
@@ -3556,7 +3944,7 @@ function collectYamlComments(content) {
3556
3944
  return comments3;
3557
3945
  }
3558
3946
 
3559
- // src/commands/verify/blockCodeComments/collectFileComments.ts
3947
+ // src/commands/verify/blockCodeComments/toFindings.ts
3560
3948
  function toFindings(file, lines2, raw, exempt) {
3561
3949
  const findings = [];
3562
3950
  for (const { line, text: text17 } of raw) {
@@ -3566,19 +3954,28 @@ function toFindings(file, lines2, raw, exempt) {
3566
3954
  }
3567
3955
  return findings;
3568
3956
  }
3957
+
3958
+ // src/commands/verify/blockCodeComments/collectFileComments.ts
3569
3959
  function collectFileComments(file, lines2, project) {
3570
- const read = () => fs14.readFileSync(file, "utf8");
3960
+ const read2 = () => fs14.readFileSync(file, "utf8");
3571
3961
  if (isYamlFile(file))
3572
- return toFindings(file, lines2, collectYamlComments(read()), false);
3962
+ return toFindings(file, lines2, collectYamlComments(read2()), false);
3573
3963
  if (isDockerfile(file) || isEnvFile(file) || isShellFile(file))
3574
3964
  return toFindings(
3575
3965
  file,
3576
3966
  lines2,
3577
- collectHashComments(read(), { skipHeader: isShellFile(file) }),
3967
+ collectHashComments(read2(), { skipHeader: isShellFile(file) }),
3578
3968
  true
3579
3969
  );
3580
3970
  if (isBicepFile(file))
3581
- return toFindings(file, lines2, collectBicepComments(read()), true);
3971
+ return toFindings(file, lines2, collectBicepComments(read2()), true);
3972
+ if (isCsharpFile(file)) {
3973
+ const content = read2();
3974
+ if (isGeneratedCsharpFile(file, content)) return [];
3975
+ return toFindings(file, lines2, collectCsharpComments(content), true);
3976
+ }
3977
+ if (isRazorFile(file))
3978
+ return toFindings(file, lines2, extractRazorComments(read2()), true);
3582
3979
  return collectSourceFindings(file, lines2, project);
3583
3980
  }
3584
3981
 
@@ -3628,7 +4025,11 @@ var SCANNED_EXTENSIONS = [
3628
4025
  ".yml",
3629
4026
  ".yaml",
3630
4027
  ".bicep",
3631
- ".bicepparam"
4028
+ ".bicepparam",
4029
+ ".cs",
4030
+ ".csx",
4031
+ ".razor",
4032
+ ".cshtml"
3632
4033
  ];
3633
4034
  function shouldScan(file, ignoreGlobs) {
3634
4035
  if (!SCANNED_EXTENSIONS.some((ext) => file.endsWith(ext)) && !isHashCommentFile(file))
@@ -19177,6 +19578,58 @@ function registerDotnet(program2) {
19177
19578
  // src/commands/editHook/index.ts
19178
19579
  import fs23 from "fs";
19179
19580
 
19581
+ // src/commands/editHook/introducedComments.ts
19582
+ function introducedComments(added, removed) {
19583
+ const counts = /* @__PURE__ */ new Map();
19584
+ for (const comment3 of removed) {
19585
+ counts.set(comment3, (counts.get(comment3) ?? 0) + 1);
19586
+ }
19587
+ const candidates = [];
19588
+ for (const comment3 of added) {
19589
+ const remaining = counts.get(comment3) ?? 0;
19590
+ if (remaining > 0) counts.set(comment3, remaining - 1);
19591
+ else candidates.push(comment3);
19592
+ }
19593
+ const removedWords = new Set(removed.flatMap(commentWords));
19594
+ return candidates.filter((comment3) => {
19595
+ const words = commentWords(comment3);
19596
+ if (words.length === 0) return true;
19597
+ return !words.every((word) => removedWords.has(word));
19598
+ });
19599
+ }
19600
+ function commentWords(comment3) {
19601
+ return comment3.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 0);
19602
+ }
19603
+
19604
+ // src/commands/editHook/partitionStrings.ts
19605
+ function defined(values) {
19606
+ return values.filter((value) => value != null);
19607
+ }
19608
+ function partitionStrings(input, existingContent) {
19609
+ const { tool_name, tool_input } = input;
19610
+ switch (tool_name) {
19611
+ case "Edit":
19612
+ return {
19613
+ added: defined([tool_input.new_string]),
19614
+ removed: defined([tool_input.old_string])
19615
+ };
19616
+ case "MultiEdit": {
19617
+ const edits = tool_input.edits ?? [];
19618
+ return {
19619
+ added: defined(edits.map((e) => e.new_string)),
19620
+ removed: defined(edits.map((e) => e.old_string))
19621
+ };
19622
+ }
19623
+ case "Write":
19624
+ return {
19625
+ added: defined([tool_input.content]),
19626
+ removed: defined([existingContent])
19627
+ };
19628
+ default:
19629
+ return { added: [], removed: [] };
19630
+ }
19631
+ }
19632
+
19180
19633
  // src/commands/editHook/extractComments.ts
19181
19634
  var SOURCE_EXTENSIONS = [
19182
19635
  ".ts",
@@ -19213,6 +19666,21 @@ function extractComments(text17) {
19213
19666
  return comments3.map((comment3) => comment3.replace(/\s+/g, " ").trim()).filter((comment3) => comment3.length > 0).filter((comment3) => !isCommentExempt(comment3));
19214
19667
  }
19215
19668
 
19669
+ // src/commands/editHook/commentTexts.ts
19670
+ function commentTexts(comments3) {
19671
+ return comments3.map((comment3) => comment3.text.replace(/\s+/g, " ").trim()).filter((comment3) => comment3.length > 0).filter((comment3) => !isCommentExempt(comment3));
19672
+ }
19673
+
19674
+ // src/commands/editHook/extractCsharpCommentTexts.ts
19675
+ function extractCsharpCommentTexts(text17) {
19676
+ return commentTexts(extractCsharpComments(text17));
19677
+ }
19678
+
19679
+ // src/commands/editHook/extractRazorCommentTexts.ts
19680
+ function extractRazorCommentTexts(text17) {
19681
+ return commentTexts(extractRazorComments(text17));
19682
+ }
19683
+
19216
19684
  // src/commands/editHook/extractYamlComments.ts
19217
19685
  function blankNonNewline4(text17) {
19218
19686
  return text17.replace(/[^\n]/g, " ");
@@ -19243,27 +19711,19 @@ function extractShellComments(text17) {
19243
19711
  return extractYamlComments(lines2.slice(firstCodeLine).join("\n"));
19244
19712
  }
19245
19713
 
19246
- // src/commands/editHook/introducedComments.ts
19247
- function introducedComments(added, removed) {
19248
- const counts = /* @__PURE__ */ new Map();
19249
- for (const comment3 of removed) {
19250
- counts.set(comment3, (counts.get(comment3) ?? 0) + 1);
19251
- }
19252
- const candidates = [];
19253
- for (const comment3 of added) {
19254
- const remaining = counts.get(comment3) ?? 0;
19255
- if (remaining > 0) counts.set(comment3, remaining - 1);
19256
- else candidates.push(comment3);
19257
- }
19258
- const removedWords = new Set(removed.flatMap(commentWords));
19259
- return candidates.filter((comment3) => {
19260
- const words = commentWords(comment3);
19261
- if (words.length === 0) return true;
19262
- return !words.every((word) => removedWords.has(word));
19263
- });
19264
- }
19265
- function commentWords(comment3) {
19266
- return comment3.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 0);
19714
+ // src/commands/editHook/selectCommentExtractor.ts
19715
+ function selectCommentExtractor(filePath) {
19716
+ if (isHashCommentFile(filePath))
19717
+ return {
19718
+ extract: isShellFile(filePath) ? extractShellComments : extractYamlComments,
19719
+ marker: "#"
19720
+ };
19721
+ if (isCsharpFile(filePath))
19722
+ return { extract: extractCsharpCommentTexts, marker: "//" };
19723
+ if (isRazorFile(filePath))
19724
+ return { extract: extractRazorCommentTexts, marker: "//" };
19725
+ if (isSourceFile(filePath)) return { extract: extractComments, marker: "//" };
19726
+ return void 0;
19267
19727
  }
19268
19728
 
19269
19729
  // src/commands/editHook/decideCommentGuard.ts
@@ -19271,44 +19731,17 @@ function denyReason(marker) {
19271
19731
  const blockClause = marker === "//" ? ", no block comments" : "";
19272
19732
  return `This edit introduces a code comment (${marker}), which is blocked by the comment gate. Comments are a last resort \u2014 prefer a clearer name, a smaller function, or a test that makes the comment unnecessary. The comment must not appear in your edit itself. If this one line genuinely earns its keep, use the escape hatch: run \`assist code-comment set <file> <line> "<text>"\` (single line, max 50 chars${blockClause}) to get a pin, then \`assist code-comment confirm <pin>\` to insert it.`;
19273
19733
  }
19274
- function defined(values) {
19275
- return values.filter((value) => value != null);
19276
- }
19277
- function partitionStrings(input, existingContent) {
19278
- const { tool_name, tool_input } = input;
19279
- switch (tool_name) {
19280
- case "Edit":
19281
- return {
19282
- added: defined([tool_input.new_string]),
19283
- removed: defined([tool_input.old_string])
19284
- };
19285
- case "MultiEdit": {
19286
- const edits = tool_input.edits ?? [];
19287
- return {
19288
- added: defined(edits.map((e) => e.new_string)),
19289
- removed: defined(edits.map((e) => e.old_string))
19290
- };
19291
- }
19292
- case "Write":
19293
- return {
19294
- added: defined([tool_input.content]),
19295
- removed: defined([existingContent])
19296
- };
19297
- default:
19298
- return { added: [], removed: [] };
19299
- }
19300
- }
19301
19734
  function decideCommentGuard(input, existingContent) {
19302
- const filePath = input.tool_input.file_path;
19303
- const hash = isHashCommentFile(filePath);
19304
- if (!isSourceFile(filePath) && !hash) return void 0;
19305
- const extract2 = hash ? isShellFile(filePath) ? extractShellComments : extractYamlComments : extractComments;
19735
+ const { file_path, content } = input.tool_input;
19736
+ if (isGeneratedCsharpFile(file_path, content)) return void 0;
19737
+ const gate = selectCommentExtractor(file_path);
19738
+ if (!gate) return void 0;
19306
19739
  const { added, removed } = partitionStrings(input, existingContent);
19307
19740
  const introduced = introducedComments(
19308
- added.flatMap(extract2),
19309
- removed.flatMap(extract2)
19741
+ added.flatMap(gate.extract),
19742
+ removed.flatMap(gate.extract)
19310
19743
  );
19311
- return introduced.length > 0 ? denyReason(hash ? "#" : "//") : void 0;
19744
+ return introduced.length > 0 ? denyReason(gate.marker) : void 0;
19312
19745
  }
19313
19746
 
19314
19747
  // src/commands/dbMigration/consumeMigrationApproval.ts
@@ -22034,10 +22467,10 @@ async function edit(options2) {
22034
22467
  }
22035
22468
 
22036
22469
  // src/commands/prs/fixed.ts
22037
- import { execSync as execSync46 } from "child_process";
22470
+ import { execSync as execSync45 } from "child_process";
22038
22471
 
22039
22472
  // src/commands/prs/resolveCommentWithReply.ts
22040
- import { execSync as execSync45 } from "child_process";
22473
+ import { execSync as execSync44 } from "child_process";
22041
22474
  import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync33 } from "fs";
22042
22475
  import { tmpdir as tmpdir6 } from "os";
22043
22476
  import { join as join57 } from "path";
@@ -22078,12 +22511,22 @@ function deleteCommentsCache(org, repo, prNumber) {
22078
22511
  }
22079
22512
 
22080
22513
  // src/commands/prs/replyToComment.ts
22081
- import { execSync as execSync44 } from "child_process";
22514
+ import { spawnSync as spawnSync5 } from "child_process";
22082
22515
  function replyToComment(org, repo, prNumber, commentId, message3) {
22083
- execSync44(
22084
- `gh api repos/${org}/${repo}/pulls/${prNumber}/comments -f body="${message3.replace(/"/g, String.raw`\"`)}" -F in_reply_to=${commentId}`,
22085
- { stdio: ["inherit", "pipe", "inherit"] }
22516
+ const result = spawnSync5(
22517
+ "gh",
22518
+ [
22519
+ "api",
22520
+ `repos/${org}/${repo}/pulls/${prNumber}/comments`,
22521
+ "-f",
22522
+ `body=${message3}`,
22523
+ "-F",
22524
+ `in_reply_to=${commentId}`
22525
+ ],
22526
+ { encoding: "utf8", windowsHide: true }
22086
22527
  );
22528
+ if (result.error) throw result.error;
22529
+ if (result.status !== 0) throw new Error(result.stderr || result.stdout);
22087
22530
  }
22088
22531
 
22089
22532
  // src/commands/prs/resolveCommentWithReply.ts
@@ -22092,7 +22535,7 @@ function resolveThread(threadId) {
22092
22535
  const queryFile = join57(tmpdir6(), `gh-mutation-${Date.now()}.graphql`);
22093
22536
  writeFileSync33(queryFile, mutation);
22094
22537
  try {
22095
- execSync45(
22538
+ execSync44(
22096
22539
  `gh api graphql -F query=@${queryFile} -f threadId="${threadId}"`,
22097
22540
  { stdio: ["inherit", "pipe", "inherit"] }
22098
22541
  );
@@ -22144,7 +22587,7 @@ function resolveCommentWithReply(commentId, message3) {
22144
22587
  // src/commands/prs/fixed.ts
22145
22588
  function verifySha(sha) {
22146
22589
  try {
22147
- return execSync46(`git rev-parse --verify ${sha}`, {
22590
+ return execSync45(`git rev-parse --verify ${sha}`, {
22148
22591
  encoding: "utf8"
22149
22592
  }).trim();
22150
22593
  } catch {
@@ -22171,7 +22614,7 @@ function fixed(commentId, sha) {
22171
22614
  }
22172
22615
 
22173
22616
  // src/commands/prs/fetchThreadIds.ts
22174
- import { execSync as execSync47 } from "child_process";
22617
+ import { execSync as execSync46 } from "child_process";
22175
22618
  import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync34 } from "fs";
22176
22619
  import { tmpdir as tmpdir7 } from "os";
22177
22620
  import { join as join58 } from "path";
@@ -22180,7 +22623,7 @@ function fetchThreadIds(org, repo, prNumber) {
22180
22623
  const queryFile = join58(tmpdir7(), `gh-query-${Date.now()}.graphql`);
22181
22624
  writeFileSync34(queryFile, THREAD_QUERY);
22182
22625
  try {
22183
- const result = execSync47(
22626
+ const result = execSync46(
22184
22627
  `gh api graphql -F query=@${queryFile} -F owner="${org}" -F repo="${repo}" -F prNumber=${prNumber}`,
22185
22628
  { encoding: "utf8" }
22186
22629
  );
@@ -22202,9 +22645,9 @@ function fetchThreadIds(org, repo, prNumber) {
22202
22645
  }
22203
22646
 
22204
22647
  // src/commands/prs/listComments/fetchReviewComments.ts
22205
- import { execSync as execSync48 } from "child_process";
22648
+ import { execSync as execSync47 } from "child_process";
22206
22649
  function fetchJson(endpoint) {
22207
- const result = execSync48(`gh api --paginate ${endpoint}`, {
22650
+ const result = execSync47(`gh api --paginate ${endpoint}`, {
22208
22651
  encoding: "utf8"
22209
22652
  });
22210
22653
  if (!result.trim()) return [];
@@ -22480,7 +22923,7 @@ async function listComments() {
22480
22923
  }
22481
22924
 
22482
22925
  // src/commands/prs/prs/index.ts
22483
- import { execSync as execSync49 } from "child_process";
22926
+ import { execSync as execSync48 } from "child_process";
22484
22927
 
22485
22928
  // src/commands/prs/prs/displayPaginated/index.ts
22486
22929
  import enquirer9 from "enquirer";
@@ -22587,7 +23030,7 @@ async function prs(options2) {
22587
23030
  const state = options2.open ? "open" : options2.closed ? "closed" : "all";
22588
23031
  try {
22589
23032
  const { org, repo } = getRepoInfo();
22590
- const result = execSync49(
23033
+ const result = execSync48(
22591
23034
  `gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100 -R ${org}/${repo}`,
22592
23035
  { encoding: "utf8" }
22593
23036
  );
@@ -22658,16 +23101,16 @@ function buildCreateArgs(title, body, options2) {
22658
23101
  }
22659
23102
 
22660
23103
  // src/commands/prs/readSessionPrRef.ts
22661
- import { execSync as execSync50 } from "child_process";
23104
+ import { execSync as execSync49 } from "child_process";
22662
23105
  function readSessionPrRef() {
22663
23106
  try {
22664
- const branch2 = execSync50("git rev-parse --abbrev-ref HEAD", {
23107
+ const branch2 = execSync49("git rev-parse --abbrev-ref HEAD", {
22665
23108
  encoding: "utf8",
22666
23109
  stdio: ["pipe", "pipe", "pipe"]
22667
23110
  }).trim();
22668
23111
  if (!branch2 || branch2 === "HEAD") return null;
22669
23112
  const pr = JSON.parse(
22670
- execSync50(`gh pr view ${branch2} --json number,title,url,state`, {
23113
+ execSync49(`gh pr view ${branch2} --json number,title,url,state`, {
22671
23114
  encoding: "utf8",
22672
23115
  stdio: ["pipe", "pipe", "pipe"]
22673
23116
  })
@@ -22924,7 +23367,7 @@ function reply(commentId, body) {
22924
23367
  }
22925
23368
 
22926
23369
  // src/commands/prs/wontfix.ts
22927
- import { execSync as execSync51 } from "child_process";
23370
+ import { execSync as execSync50 } from "child_process";
22928
23371
  function validateReason(reason4) {
22929
23372
  const lowerReason = reason4.toLowerCase();
22930
23373
  if (lowerReason.includes("claude") || lowerReason.includes("opus")) {
@@ -22941,7 +23384,7 @@ function validateShaReferences(reason4) {
22941
23384
  const invalidShas = [];
22942
23385
  for (const sha of shas) {
22943
23386
  try {
22944
- execSync51(`git cat-file -t ${sha}`, { stdio: "pipe" });
23387
+ execSync50(`git cat-file -t ${sha}`, { stdio: "pipe" });
22945
23388
  } catch {
22946
23389
  invalidShas.push(sha);
22947
23390
  }
@@ -22968,6 +23411,45 @@ function wontfix(commentId, reason4) {
22968
23411
  }
22969
23412
  }
22970
23413
 
23414
+ // src/commands/prs/readBodyArgument.ts
23415
+ async function readBodyArgument(value) {
23416
+ if (value !== "-") return value;
23417
+ const body = (await readStdinBuffer()).toString("utf8").replace(/\n+$/, "");
23418
+ if (body.trim().length === 0) {
23419
+ console.error("Error: No body was provided on stdin.");
23420
+ process.exit(1);
23421
+ }
23422
+ return body;
23423
+ }
23424
+
23425
+ // src/commands/registerPrsComments.ts
23426
+ function registerPrsComments(prsCommand) {
23427
+ prsCommand.command("list-comments").description("List all comments on the current branch's pull request").action(() => {
23428
+ listComments().then(printComments2);
23429
+ });
23430
+ prsCommand.command("fixed <comment-id> <sha>").description("Reply with commit link and resolve thread").action((commentId, sha) => {
23431
+ fixed(Number.parseInt(commentId, 10), sha);
23432
+ });
23433
+ prsCommand.command("wontfix <comment-id> <reason>").description(
23434
+ "Reply with reason and resolve thread (reason of - reads it from stdin)"
23435
+ ).action(async (commentId, reason4) => {
23436
+ wontfix(
23437
+ Number.parseInt(commentId, 10),
23438
+ await readBodyArgument(reason4)
23439
+ );
23440
+ });
23441
+ prsCommand.command("reply <comment-id> <body>").description(
23442
+ "Reply to a comment thread without resolving it (body of - reads it from stdin)"
23443
+ ).action(async (commentId, body) => {
23444
+ reply(Number.parseInt(commentId, 10), await readBodyArgument(body));
23445
+ });
23446
+ prsCommand.command("comment <path> <line> <body>").description(
23447
+ "Add a line comment to the pending review (body of - reads it from stdin)"
23448
+ ).action(async (path73, line, body) => {
23449
+ comment2(path73, Number.parseInt(line, 10), await readBodyArgument(body));
23450
+ });
23451
+ }
23452
+
22971
23453
  // src/commands/prs/prConcisenessGuidance.ts
22972
23454
  var prConcisenessGuidance = `Brevity budget \u2014 one paragraph per section, and these are ceilings, not targets:
22973
23455
 
@@ -23173,21 +23655,7 @@ function registerPrs(program2) {
23173
23655
  const prsCommand = program2.command("prs").description("Pull request utilities").option("--open", "List only open pull requests").option("--closed", "List only closed pull requests").action(prs);
23174
23656
  registerPrsRaise(prsCommand);
23175
23657
  registerPrsEdit(prsCommand);
23176
- prsCommand.command("list-comments").description("List all comments on the current branch's pull request").action(() => {
23177
- listComments().then(printComments2);
23178
- });
23179
- prsCommand.command("fixed <comment-id> <sha>").description("Reply with commit link and resolve thread").action((commentId, sha) => {
23180
- fixed(Number.parseInt(commentId, 10), sha);
23181
- });
23182
- prsCommand.command("wontfix <comment-id> <reason>").description("Reply with reason and resolve thread").action((commentId, reason4) => {
23183
- wontfix(Number.parseInt(commentId, 10), reason4);
23184
- });
23185
- prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
23186
- reply(Number.parseInt(commentId, 10), body);
23187
- });
23188
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path73, line, body) => {
23189
- comment2(path73, Number.parseInt(line, 10), body);
23190
- });
23658
+ registerPrsComments(prsCommand);
23191
23659
  configHelp(prsCommand, prsConfigHelp);
23192
23660
  }
23193
23661
 
@@ -23261,10 +23729,10 @@ import chalk174 from "chalk";
23261
23729
  import Enquirer2 from "enquirer";
23262
23730
 
23263
23731
  // src/commands/ravendb/searchItems.ts
23264
- import { execSync as execSync52 } from "child_process";
23732
+ import { execSync as execSync51 } from "child_process";
23265
23733
  import chalk173 from "chalk";
23266
23734
  function opExec(args) {
23267
- return execSync52(`op ${args}`, {
23735
+ return execSync51(`op ${args}`, {
23268
23736
  encoding: "utf8",
23269
23737
  stdio: ["pipe", "pipe", "pipe"]
23270
23738
  }).trim();
@@ -23416,7 +23884,7 @@ ${errorText}`
23416
23884
  }
23417
23885
 
23418
23886
  // src/commands/ravendb/resolveOpSecret.ts
23419
- import { execSync as execSync53 } from "child_process";
23887
+ import { execSync as execSync52 } from "child_process";
23420
23888
  import chalk178 from "chalk";
23421
23889
  function resolveOpSecret(reference) {
23422
23890
  if (!reference.startsWith("op://")) {
@@ -23424,7 +23892,7 @@ function resolveOpSecret(reference) {
23424
23892
  process.exit(1);
23425
23893
  }
23426
23894
  try {
23427
- return execSync53(`op read "${reference}"`, {
23895
+ return execSync52(`op read "${reference}"`, {
23428
23896
  encoding: "utf8",
23429
23897
  stdio: ["pipe", "pipe", "pipe"]
23430
23898
  }).trim();
@@ -23674,7 +24142,7 @@ Refactor check failed:
23674
24142
  }
23675
24143
 
23676
24144
  // src/commands/refactor/check/getViolations/index.ts
23677
- import { execSync as execSync54 } from "child_process";
24145
+ import { execSync as execSync53 } from "child_process";
23678
24146
  import fs25 from "fs";
23679
24147
  import { minimatch as minimatch6 } from "minimatch";
23680
24148
 
@@ -23724,7 +24192,7 @@ function getGitFiles(options2) {
23724
24192
  }
23725
24193
  const files = /* @__PURE__ */ new Set();
23726
24194
  if (options2.staged || options2.modified) {
23727
- const staged = execSync54("git diff --cached --name-only", {
24195
+ const staged = execSync53("git diff --cached --name-only", {
23728
24196
  encoding: "utf8"
23729
24197
  });
23730
24198
  for (const file of staged.trim().split("\n").filter(Boolean)) {
@@ -23732,7 +24200,7 @@ function getGitFiles(options2) {
23732
24200
  }
23733
24201
  }
23734
24202
  if (options2.unstaged || options2.modified) {
23735
- const unstaged = execSync54("git diff --name-only", { encoding: "utf8" });
24203
+ const unstaged = execSync53("git diff --name-only", { encoding: "utf8" });
23736
24204
  for (const file of unstaged.trim().split("\n").filter(Boolean)) {
23737
24205
  files.add(file);
23738
24206
  }
@@ -25430,9 +25898,9 @@ function buildReviewPaths(repoRoot2, key) {
25430
25898
  }
25431
25899
 
25432
25900
  // src/commands/review/fetchExistingComments.ts
25433
- import { execSync as execSync55 } from "child_process";
25901
+ import { execSync as execSync54 } from "child_process";
25434
25902
  function fetchRawComments(org, repo, prNumber) {
25435
- const out = execSync55(
25903
+ const out = execSync54(
25436
25904
  `gh api --paginate repos/${org}/${repo}/pulls/${prNumber}/comments`,
25437
25905
  { encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }
25438
25906
  );
@@ -25463,14 +25931,14 @@ function fetchExistingComments() {
25463
25931
  }
25464
25932
 
25465
25933
  // src/commands/review/gatherContext.ts
25466
- import { execSync as execSync58 } from "child_process";
25934
+ import { execSync as execSync57 } from "child_process";
25467
25935
 
25468
25936
  // src/commands/review/fetchPrDiff.ts
25469
- import { execSync as execSync56 } from "child_process";
25937
+ import { execSync as execSync55 } from "child_process";
25470
25938
  function fetchPrDiff(prNumber, baseSha, headSha) {
25471
25939
  const { org, repo } = getRepoInfo();
25472
25940
  try {
25473
- return execSync56(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
25941
+ return execSync55(`gh pr diff ${prNumber} -R ${org}/${repo}`, {
25474
25942
  encoding: "utf8",
25475
25943
  maxBuffer: 256 * 1024 * 1024,
25476
25944
  stdio: ["ignore", "pipe", "pipe"]
@@ -25485,19 +25953,19 @@ function isDiffTooLarge(error) {
25485
25953
  }
25486
25954
  function fetchDiffViaGit(baseSha, headSha) {
25487
25955
  try {
25488
- execSync56(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
25956
+ execSync55(`git fetch origin ${baseSha} ${headSha}`, { stdio: "ignore" });
25489
25957
  } catch {
25490
25958
  }
25491
- return execSync56(`git diff ${baseSha}...${headSha}`, {
25959
+ return execSync55(`git diff ${baseSha}...${headSha}`, {
25492
25960
  encoding: "utf8",
25493
25961
  maxBuffer: 256 * 1024 * 1024
25494
25962
  });
25495
25963
  }
25496
25964
 
25497
25965
  // src/commands/review/fetchPrDiffInfo.ts
25498
- import { execSync as execSync57 } from "child_process";
25966
+ import { execSync as execSync56 } from "child_process";
25499
25967
  function getCurrentBranch3() {
25500
- return execSync57("git rev-parse --abbrev-ref HEAD", {
25968
+ return execSync56("git rev-parse --abbrev-ref HEAD", {
25501
25969
  encoding: "utf8"
25502
25970
  }).trim();
25503
25971
  }
@@ -25505,7 +25973,7 @@ function fetchPrDiffInfo() {
25505
25973
  const { org, repo } = getRepoInfo();
25506
25974
  const branch2 = getCurrentBranch3();
25507
25975
  const fields = "number,baseRefName,baseRefOid,headRefName,headRefOid";
25508
- const raw = execSync57(
25976
+ const raw = execSync56(
25509
25977
  `gh pr list --state open --head ${branch2} --json ${fields} -R ${org}/${repo}`,
25510
25978
  {
25511
25979
  encoding: "utf8",
@@ -25530,7 +25998,7 @@ function fetchPrDiffInfo() {
25530
25998
  }
25531
25999
  function fetchPrChangedFiles(prNumber) {
25532
26000
  const { org, repo } = getRepoInfo();
25533
- const out = execSync57(
26001
+ const out = execSync56(
25534
26002
  `gh api repos/${org}/${repo}/pulls/${prNumber}/files --paginate --jq ".[].filename"`,
25535
26003
  {
25536
26004
  encoding: "utf8",
@@ -25542,11 +26010,11 @@ function fetchPrChangedFiles(prNumber) {
25542
26010
 
25543
26011
  // src/commands/review/gatherContext.ts
25544
26012
  function gatherContext() {
25545
- const branch2 = execSync58("git rev-parse --abbrev-ref HEAD", {
26013
+ const branch2 = execSync57("git rev-parse --abbrev-ref HEAD", {
25546
26014
  encoding: "utf8"
25547
26015
  }).trim();
25548
- const sha = execSync58("git rev-parse HEAD", { encoding: "utf8" }).trim();
25549
- const shortSha = execSync58("git rev-parse --short=7 HEAD", {
26016
+ const sha = execSync57("git rev-parse HEAD", { encoding: "utf8" }).trim();
26017
+ const shortSha = execSync57("git rev-parse --short=7 HEAD", {
25550
26018
  encoding: "utf8"
25551
26019
  }).trim();
25552
26020
  const prInfo = fetchPrDiffInfo();
@@ -26280,9 +26748,9 @@ var MultiSpinner = class {
26280
26748
  };
26281
26749
 
26282
26750
  // src/commands/review/ensureCodexAvailable.ts
26283
- import { spawnSync as spawnSync5 } from "child_process";
26751
+ import { spawnSync as spawnSync6 } from "child_process";
26284
26752
  function runNpmInstall() {
26285
- const result = spawnSync5("npm", ["install", "-g", "@openai/codex"], {
26753
+ const result = spawnSync6("npm", ["install", "-g", "@openai/codex"], {
26286
26754
  stdio: "inherit",
26287
26755
  shell: true
26288
26756
  });
@@ -28635,7 +29103,7 @@ function registerVerify(program2) {
28635
29103
  }
28636
29104
 
28637
29105
  // src/commands/voice/devices.ts
28638
- import { spawnSync as spawnSync6 } from "child_process";
29106
+ import { spawnSync as spawnSync7 } from "child_process";
28639
29107
  import { join as join74 } from "path";
28640
29108
 
28641
29109
  // src/commands/voice/shared.ts
@@ -28668,7 +29136,7 @@ function getLockFile() {
28668
29136
  // src/commands/voice/devices.ts
28669
29137
  function devices() {
28670
29138
  const script = join74(getPythonDir(), "list_devices.py");
28671
- spawnSync6(getVenvPython(), [script], { stdio: "inherit" });
29139
+ spawnSync7(getVenvPython(), [script], { stdio: "inherit" });
28672
29140
  }
28673
29141
 
28674
29142
  // src/commands/voice/logs.ts
@@ -28700,12 +29168,12 @@ function logs(options2) {
28700
29168
  }
28701
29169
 
28702
29170
  // src/commands/voice/setup.ts
28703
- import { spawnSync as spawnSync7 } from "child_process";
29171
+ import { spawnSync as spawnSync8 } from "child_process";
28704
29172
  import { mkdirSync as mkdirSync27 } from "fs";
28705
29173
  import { join as join76 } from "path";
28706
29174
 
28707
29175
  // src/commands/voice/checkLockFile.ts
28708
- import { execSync as execSync59 } from "child_process";
29176
+ import { execSync as execSync58 } from "child_process";
28709
29177
  import { existsSync as existsSync60, mkdirSync as mkdirSync26, readFileSync as readFileSync49, writeFileSync as writeFileSync42 } from "fs";
28710
29178
  import { join as join75 } from "path";
28711
29179
  function isProcessAlive2(pid) {
@@ -28734,7 +29202,7 @@ function bootstrapVenv() {
28734
29202
  if (existsSync60(getVenvPython())) return;
28735
29203
  console.log("Setting up Python environment...");
28736
29204
  const pythonDir = getPythonDir();
28737
- execSync59(
29205
+ execSync58(
28738
29206
  `uv sync --project "${pythonDir}" --extra runtime --no-install-project`,
28739
29207
  {
28740
29208
  stdio: "inherit",
@@ -28761,7 +29229,7 @@ function setup() {
28761
29229
  bootstrapVenv();
28762
29230
  console.log("\nDownloading models...\n");
28763
29231
  const script = join76(getPythonDir(), "setup_models.py");
28764
- const result = spawnSync7(getVenvPython(), [script], {
29232
+ const result = spawnSync8(getVenvPython(), [script], {
28765
29233
  stdio: "inherit",
28766
29234
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
28767
29235
  });
@@ -29317,11 +29785,11 @@ function runCommandToCompletion(command, args, env, cwd, quiet) {
29317
29785
  }
29318
29786
 
29319
29787
  // src/commands/run/runPreCommands.ts
29320
- import { execSync as execSync60 } from "child_process";
29788
+ import { execSync as execSync59 } from "child_process";
29321
29789
  function runPreCommands(pre, cwd) {
29322
29790
  for (const cmd of pre) {
29323
29791
  try {
29324
- execSync60(cmd, { stdio: "inherit", cwd });
29792
+ execSync59(cmd, { stdio: "inherit", cwd });
29325
29793
  } catch (error) {
29326
29794
  const code = error && typeof error === "object" && "status" in error ? error.status : 1;
29327
29795
  process.exit(code);
@@ -30013,7 +30481,7 @@ function registerRun(program2) {
30013
30481
  }
30014
30482
 
30015
30483
  // src/commands/screenshot/index.ts
30016
- import { execSync as execSync61 } from "child_process";
30484
+ import { execSync as execSync60 } from "child_process";
30017
30485
  import { existsSync as existsSync67, mkdirSync as mkdirSync30, unlinkSync as unlinkSync22, writeFileSync as writeFileSync45 } from "fs";
30018
30486
  import { tmpdir as tmpdir8 } from "os";
30019
30487
  import { join as join83, resolve as resolve19 } from "path";
@@ -30156,7 +30624,7 @@ function runPowerShellScript(processName, outputPath) {
30156
30624
  const scriptPath = join83(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
30157
30625
  writeFileSync45(scriptPath, captureWindowPs1, "utf8");
30158
30626
  try {
30159
- execSync61(
30627
+ execSync60(
30160
30628
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
30161
30629
  { stdio: ["ignore", "pipe", "pipe"], encoding: "utf8" }
30162
30630
  );
@@ -31730,7 +32198,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
31730
32198
  }
31731
32199
  reconcileActivity(session.id, session.activity);
31732
32200
  let timer = null;
31733
- const read = () => {
32201
+ const read2 = () => {
31734
32202
  timer = null;
31735
32203
  const activity2 = readActivity(path73);
31736
32204
  if (!activity2) return;
@@ -31743,9 +32211,9 @@ function watchActivity(session, notify2, onClaudeSessionId) {
31743
32211
  session.activityWatcher = watch2(dir, (_event, filename) => {
31744
32212
  if (filename && !path73.endsWith(filename)) return;
31745
32213
  if (timer) clearTimeout(timer);
31746
- timer = setTimeout(read, DEBOUNCE_MS2);
32214
+ timer = setTimeout(read2, DEBOUNCE_MS2);
31747
32215
  });
31748
- if (existsSync75(path73)) read();
32216
+ if (existsSync75(path73)) read2();
31749
32217
  }
31750
32218
  function refreshActivity(session) {
31751
32219
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -35652,7 +36120,7 @@ async function statusLine() {
35652
36120
  }
35653
36121
 
35654
36122
  // src/commands/update.ts
35655
- import { execSync as execSync62 } from "child_process";
36123
+ import { execSync as execSync61 } from "child_process";
35656
36124
  import * as path72 from "path";
35657
36125
 
35658
36126
  // src/commands/restartDaemonAfterUpdate.ts
@@ -35676,7 +36144,7 @@ function isGlobalNpmInstall(dir) {
35676
36144
  if (resolved.split(path72.sep).includes("node_modules")) {
35677
36145
  return true;
35678
36146
  }
35679
- const globalPrefix = execSync62("npm prefix -g", { stdio: "pipe" }).toString().trim();
36147
+ const globalPrefix = execSync61("npm prefix -g", { stdio: "pipe" }).toString().trim();
35680
36148
  return resolved.toLowerCase().startsWith(path72.resolve(globalPrefix).toLowerCase());
35681
36149
  } catch {
35682
36150
  return false;
@@ -35687,18 +36155,18 @@ async function update2() {
35687
36155
  console.log(`Assist is installed at: ${installDir}`);
35688
36156
  if (isGitRepo(installDir)) {
35689
36157
  console.log("Detected git repo installation, pulling latest...");
35690
- execSync62("git pull", { cwd: installDir, stdio: "inherit" });
36158
+ execSync61("git pull", { cwd: installDir, stdio: "inherit" });
35691
36159
  console.log("Installing dependencies...");
35692
- execSync62("npm i", { cwd: installDir, stdio: "inherit" });
36160
+ execSync61("npm i", { cwd: installDir, stdio: "inherit" });
35693
36161
  console.log("Building...");
35694
- execSync62("npm run build", { cwd: installDir, stdio: "inherit" });
36162
+ execSync61("npm run build", { cwd: installDir, stdio: "inherit" });
35695
36163
  console.log("Syncing commands...");
35696
- execSync62("assist sync", { stdio: "inherit" });
36164
+ execSync61("assist sync", { stdio: "inherit" });
35697
36165
  } else if (isGlobalNpmInstall(installDir)) {
35698
36166
  console.log("Detected global npm installation, updating...");
35699
- execSync62("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
36167
+ execSync61("npm i -g @staff0rd/assist@latest", { stdio: "inherit" });
35700
36168
  console.log("Syncing commands...");
35701
- execSync62("assist sync", { stdio: "inherit" });
36169
+ execSync61("assist sync", { stdio: "inherit" });
35702
36170
  } else {
35703
36171
  console.error(
35704
36172
  "Could not determine installation method. Expected a git repo or global npm install."