claude-issue-solver 1.42.1 → 1.43.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.
@@ -3,6 +3,16 @@ export declare function checkRequirements(): {
3
3
  ok: boolean;
4
4
  missing: string[];
5
5
  };
6
+ /**
7
+ * Generate AppleScript for opening a script in iTerm2.
8
+ * Sends 'n' first to dismiss any oh-my-zsh update prompts, then runs the script with bash.
9
+ */
10
+ export declare function generateITermOpenScript(script: string): string;
11
+ /**
12
+ * Generate AppleScript for opening a script in Terminal.app.
13
+ * Sends 'n' first to dismiss any oh-my-zsh update prompts, then runs the script with bash.
14
+ */
15
+ export declare function generateTerminalOpenScript(script: string): string;
6
16
  export declare function openInNewTerminal(script: string): void;
7
17
  export declare function copyEnvFiles(from: string, to: string): void;
8
18
  export declare function symlinkNodeModules(from: string, to: string): void;
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.slugify = slugify;
37
37
  exports.checkRequirements = checkRequirements;
38
+ exports.generateITermOpenScript = generateITermOpenScript;
39
+ exports.generateTerminalOpenScript = generateTerminalOpenScript;
38
40
  exports.openInNewTerminal = openInNewTerminal;
39
41
  exports.copyEnvFiles = copyEnvFiles;
40
42
  exports.symlinkNodeModules = symlinkNodeModules;
@@ -71,16 +73,14 @@ function checkRequirements() {
71
73
  }
72
74
  return { ok: missing.length === 0, missing };
73
75
  }
74
- function openInNewTerminal(script) {
75
- const platform = os.platform();
76
- if (platform === 'darwin') {
77
- // macOS - try iTerm2 first, then Terminal
78
- // Use /bin/bash explicitly to bypass interactive shell issues (e.g., oh-my-zsh update prompts)
79
- // Send 'n' first to dismiss any oh-my-zsh update prompt, then run the script
80
- const escapedScript = script.replace(/"/g, '\\"');
81
- const bashCommand = `/bin/bash "${escapedScript}"`;
82
- // For iTerm: send 'n' to dismiss any prompt, wait briefly, then run the command
83
- const iTermScript = `
76
+ /**
77
+ * Generate AppleScript for opening a script in iTerm2.
78
+ * Sends 'n' first to dismiss any oh-my-zsh update prompts, then runs the script with bash.
79
+ */
80
+ function generateITermOpenScript(script) {
81
+ const escapedScript = script.replace(/"/g, '\\"');
82
+ const bashCommand = `/bin/bash "${escapedScript}"`;
83
+ return `
84
84
  tell application "iTerm"
85
85
  activate
86
86
  set newWindow to (create window with default profile)
@@ -91,13 +91,27 @@ function openInNewTerminal(script) {
91
91
  end tell
92
92
  end tell
93
93
  `;
94
- // For Terminal: combine dismissing prompt and running command
95
- const terminalScript = `
94
+ }
95
+ /**
96
+ * Generate AppleScript for opening a script in Terminal.app.
97
+ * Sends 'n' first to dismiss any oh-my-zsh update prompts, then runs the script with bash.
98
+ */
99
+ function generateTerminalOpenScript(script) {
100
+ const escapedScript = script.replace(/"/g, '\\"');
101
+ const bashCommand = `/bin/bash "${escapedScript}"`;
102
+ return `
96
103
  tell application "Terminal"
97
104
  activate
98
105
  do script "n; ${bashCommand.replace(/"/g, '\\"')}"
99
106
  end tell
100
107
  `;
108
+ }
109
+ function openInNewTerminal(script) {
110
+ const platform = os.platform();
111
+ if (platform === 'darwin') {
112
+ // macOS - try iTerm2 first, then Terminal
113
+ const iTermScript = generateITermOpenScript(script);
114
+ const terminalScript = generateTerminalOpenScript(script);
101
115
  try {
102
116
  // Check if iTerm is installed
103
117
  if (fs.existsSync('/Applications/iTerm.app')) {
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const helpers_1 = require("./helpers");
5
+ (0, vitest_1.describe)('helpers utilities', () => {
6
+ (0, vitest_1.describe)('slugify', () => {
7
+ (0, vitest_1.it)('should convert text to lowercase slug', () => {
8
+ (0, vitest_1.expect)((0, helpers_1.slugify)('Hello World')).toBe('hello-world');
9
+ });
10
+ (0, vitest_1.it)('should remove brackets prefix', () => {
11
+ (0, vitest_1.expect)((0, helpers_1.slugify)('[Bug] Fix login issue')).toBe('fix-login-issue');
12
+ (0, vitest_1.expect)((0, helpers_1.slugify)('[FAQ] How to reset password')).toBe('how-to-reset-password');
13
+ });
14
+ (0, vitest_1.it)('should remove special characters', () => {
15
+ (0, vitest_1.expect)((0, helpers_1.slugify)('Fix: issue #123!')).toBe('fix-issue-123');
16
+ });
17
+ (0, vitest_1.it)('should remove duplicate consecutive words', () => {
18
+ (0, vitest_1.expect)((0, helpers_1.slugify)('[FAQ] FAQ question')).toBe('faq-question');
19
+ });
20
+ (0, vitest_1.it)('should limit slug to 30 characters', () => {
21
+ const longTitle = 'This is a very long issue title that should be truncated';
22
+ (0, vitest_1.expect)((0, helpers_1.slugify)(longTitle).length).toBeLessThanOrEqual(30);
23
+ });
24
+ });
25
+ (0, vitest_1.describe)('generateITermOpenScript', () => {
26
+ (0, vitest_1.it)('should generate valid AppleScript for iTerm', () => {
27
+ const script = (0, helpers_1.generateITermOpenScript)('/path/to/script.sh');
28
+ (0, vitest_1.expect)(script).toContain('tell application "iTerm"');
29
+ (0, vitest_1.expect)(script).toContain('create window with default profile');
30
+ (0, vitest_1.expect)(script).toContain('write text');
31
+ });
32
+ (0, vitest_1.it)('should send "n" to dismiss oh-my-zsh update prompts', () => {
33
+ const script = (0, helpers_1.generateITermOpenScript)('/path/to/script.sh');
34
+ (0, vitest_1.expect)(script).toContain('write text "n"');
35
+ });
36
+ (0, vitest_1.it)('should include delay after dismissing prompt', () => {
37
+ const script = (0, helpers_1.generateITermOpenScript)('/path/to/script.sh');
38
+ (0, vitest_1.expect)(script).toContain('delay 0.3');
39
+ });
40
+ (0, vitest_1.it)('should use /bin/bash to run the script', () => {
41
+ const script = (0, helpers_1.generateITermOpenScript)('/path/to/script.sh');
42
+ (0, vitest_1.expect)(script).toContain('/bin/bash');
43
+ (0, vitest_1.expect)(script).toContain('/path/to/script.sh');
44
+ });
45
+ (0, vitest_1.it)('should handle double quotes in script path without breaking AppleScript', () => {
46
+ const script = (0, helpers_1.generateITermOpenScript)('/path/to/"quoted"/script.sh');
47
+ // Should still contain the path and be valid AppleScript structure
48
+ (0, vitest_1.expect)(script).toContain('tell application "iTerm"');
49
+ (0, vitest_1.expect)(script).toContain('/bin/bash');
50
+ (0, vitest_1.expect)(script).toContain('quoted');
51
+ });
52
+ (0, vitest_1.it)('should handle paths with spaces', () => {
53
+ const script = (0, helpers_1.generateITermOpenScript)('/path/with spaces/script.sh');
54
+ (0, vitest_1.expect)(script).toContain('/path/with spaces/script.sh');
55
+ });
56
+ });
57
+ (0, vitest_1.describe)('generateTerminalOpenScript', () => {
58
+ (0, vitest_1.it)('should generate valid AppleScript for Terminal.app', () => {
59
+ const script = (0, helpers_1.generateTerminalOpenScript)('/path/to/script.sh');
60
+ (0, vitest_1.expect)(script).toContain('tell application "Terminal"');
61
+ (0, vitest_1.expect)(script).toContain('do script');
62
+ });
63
+ (0, vitest_1.it)('should send "n" to dismiss oh-my-zsh update prompts', () => {
64
+ const script = (0, helpers_1.generateTerminalOpenScript)('/path/to/script.sh');
65
+ (0, vitest_1.expect)(script).toContain('n;');
66
+ });
67
+ (0, vitest_1.it)('should use /bin/bash to run the script', () => {
68
+ const script = (0, helpers_1.generateTerminalOpenScript)('/path/to/script.sh');
69
+ (0, vitest_1.expect)(script).toContain('/bin/bash');
70
+ (0, vitest_1.expect)(script).toContain('/path/to/script.sh');
71
+ });
72
+ (0, vitest_1.it)('should handle double quotes in script path without breaking AppleScript', () => {
73
+ const script = (0, helpers_1.generateTerminalOpenScript)('/path/to/"quoted"/script.sh');
74
+ // Should still contain the path and be valid AppleScript structure
75
+ (0, vitest_1.expect)(script).toContain('tell application "Terminal"');
76
+ (0, vitest_1.expect)(script).toContain('/bin/bash');
77
+ (0, vitest_1.expect)(script).toContain('quoted');
78
+ });
79
+ (0, vitest_1.it)('should handle paths with spaces', () => {
80
+ const script = (0, helpers_1.generateTerminalOpenScript)('/path/with spaces/script.sh');
81
+ (0, vitest_1.expect)(script).toContain('/path/with spaces/script.sh');
82
+ });
83
+ });
84
+ (0, vitest_1.describe)('oh-my-zsh bypass behavior', () => {
85
+ (0, vitest_1.it)('iTerm script should have prompt dismissal before command execution', () => {
86
+ const script = (0, helpers_1.generateITermOpenScript)('/test/script.sh');
87
+ const lines = script.split('\n');
88
+ // Find the indices of the relevant lines
89
+ const dismissIndex = lines.findIndex(line => line.includes('write text "n"'));
90
+ const commandIndex = lines.findIndex(line => line.includes('/bin/bash'));
91
+ // Dismissal should come before command
92
+ (0, vitest_1.expect)(dismissIndex).toBeGreaterThan(-1);
93
+ (0, vitest_1.expect)(commandIndex).toBeGreaterThan(-1);
94
+ (0, vitest_1.expect)(dismissIndex).toBeLessThan(commandIndex);
95
+ });
96
+ (0, vitest_1.it)('Terminal script should combine dismiss and command in single do script', () => {
97
+ const script = (0, helpers_1.generateTerminalOpenScript)('/test/script.sh');
98
+ // Should have "n; /bin/bash..." in a single do script call
99
+ (0, vitest_1.expect)(script).toMatch(/do script "n;.*\/bin\/bash/);
100
+ });
101
+ });
102
+ });
@@ -10,6 +10,7 @@ export declare function getSearchPatterns(options: CloseTerminalOptions): string
10
10
  /**
11
11
  * Generate AppleScript to close iTerm2 windows/tabs matching patterns
12
12
  * Uses a two-pass approach: first collect IDs, then close them
13
+ * Matches both window names AND session working directories for reliability
13
14
  */
14
15
  export declare function generateITermCloseScript(patterns: string[]): string;
15
16
  /**
@@ -24,6 +25,11 @@ export declare function generateVSCodeCloseScript(patterns: string[]): string;
24
25
  * Execute AppleScript and handle errors gracefully
25
26
  */
26
27
  export declare function executeAppleScript(script: string, timeout?: number): boolean;
28
+ /**
29
+ * Find and terminate shell processes running in the given directory
30
+ * This is a fallback approach when AppleScript matching fails
31
+ */
32
+ export declare function killProcessesInDirectory(dirPath: string): boolean;
27
33
  /**
28
34
  * Close terminal windows and VS Code windows associated with a worktree
29
35
  * Returns an object indicating which applications had windows closed
@@ -32,4 +38,5 @@ export declare function closeWindowsForWorktree(options: CloseTerminalOptions):
32
38
  iTerm: boolean;
33
39
  terminal: boolean;
34
40
  vscode: boolean;
41
+ processes: boolean;
35
42
  };
@@ -38,6 +38,7 @@ exports.generateITermCloseScript = generateITermCloseScript;
38
38
  exports.generateTerminalCloseScript = generateTerminalCloseScript;
39
39
  exports.generateVSCodeCloseScript = generateVSCodeCloseScript;
40
40
  exports.executeAppleScript = executeAppleScript;
41
+ exports.killProcessesInDirectory = killProcessesInDirectory;
41
42
  exports.closeWindowsForWorktree = closeWindowsForWorktree;
42
43
  const child_process_1 = require("child_process");
43
44
  const os = __importStar(require("os"));
@@ -48,6 +49,10 @@ function getSearchPatterns(options) {
48
49
  const { folderPath, issueNumber, prNumber } = options;
49
50
  const folderName = folderPath.split('/').pop() || '';
50
51
  const patterns = [];
52
+ // Full folder path (most reliable for working directory matching)
53
+ if (folderPath) {
54
+ patterns.push(folderPath);
55
+ }
51
56
  // Folder name pattern (e.g., "project-issue-38-slug")
52
57
  if (folderName) {
53
58
  patterns.push(folderName);
@@ -66,6 +71,7 @@ function getSearchPatterns(options) {
66
71
  /**
67
72
  * Generate AppleScript to close iTerm2 windows/tabs matching patterns
68
73
  * Uses a two-pass approach: first collect IDs, then close them
74
+ * Matches both window names AND session working directories for reliability
69
75
  */
70
76
  function generateITermCloseScript(patterns) {
71
77
  // Escape patterns for AppleScript string comparison
@@ -73,51 +79,39 @@ function generateITermCloseScript(patterns) {
73
79
  return `
74
80
  tell application "iTerm"
75
81
  set windowsToClose to {}
76
- set sessionsToClose to {}
77
82
 
78
- -- First pass: collect windows and sessions to close
83
+ -- First pass: collect windows to close (by name or by session working directory)
79
84
  repeat with w in windows
80
85
  try
81
86
  set windowName to name of w
82
87
  set windowId to id of w
83
- ${escapedPatterns.map((p) => `if windowName contains "${p}" then set end of windowsToClose to windowId`).join('\n ')}
84
- end try
88
+ set shouldClose to false
85
89
 
86
- -- Check tabs and sessions
87
- repeat with t in tabs of w
88
- repeat with s in sessions of t
89
- try
90
- set sessionName to name of s
91
- set sessionId to unique id of s
92
- ${escapedPatterns.map((p) => `if sessionName contains "${p}" then set end of sessionsToClose to {windowId, sessionId}`).join('\n ')}
93
- end try
94
- end repeat
95
- end repeat
96
- end repeat
90
+ -- Match by window name
91
+ ${escapedPatterns.map((p) => `if windowName contains "${p}" then set shouldClose to true`).join('\n ')}
97
92
 
98
- -- Second pass: close sessions first (from windows not being fully closed)
99
- repeat with sessionInfo in sessionsToClose
100
- try
101
- set targetWindowId to item 1 of sessionInfo
102
- set targetSessionId to item 2 of sessionInfo
103
- -- Only close session if its window isn't being closed entirely
104
- if windowsToClose does not contain targetWindowId then
105
- repeat with w in windows
106
- if id of w is targetWindowId then
107
- repeat with t in tabs of w
108
- repeat with s in sessions of t
109
- if unique id of s is targetSessionId then
110
- close s
111
- end if
112
- end repeat
113
- end repeat
114
- end if
93
+ -- Match by session working directory path (more reliable)
94
+ if not shouldClose then
95
+ repeat with t in tabs of w
96
+ repeat with s in sessions of t
97
+ try
98
+ set sessionPath to ""
99
+ try
100
+ set sessionPath to path of s
101
+ end try
102
+ ${escapedPatterns.map((p) => `if sessionPath contains "${p}" then set shouldClose to true`).join('\n ')}
103
+ end try
104
+ end repeat
115
105
  end repeat
116
106
  end if
107
+
108
+ if shouldClose and windowsToClose does not contain windowId then
109
+ set end of windowsToClose to windowId
110
+ end if
117
111
  end try
118
112
  end repeat
119
113
 
120
- -- Third pass: close entire windows
114
+ -- Second pass: close windows
121
115
  repeat with targetWindowId in windowsToClose
122
116
  try
123
117
  repeat with w in windows
@@ -214,13 +208,60 @@ function executeAppleScript(script, timeout = 5000) {
214
208
  return false;
215
209
  }
216
210
  }
211
+ /**
212
+ * Find and terminate shell processes running in the given directory
213
+ * This is a fallback approach when AppleScript matching fails
214
+ */
215
+ function killProcessesInDirectory(dirPath) {
216
+ if (os.platform() !== 'darwin' && os.platform() !== 'linux') {
217
+ return false;
218
+ }
219
+ try {
220
+ // Use lsof to find processes with their current working directory in the target path
221
+ // +D flag finds processes with files open in the directory (including cwd)
222
+ const output = (0, child_process_1.execSync)(`lsof +D "${dirPath}" 2>/dev/null || true`, {
223
+ encoding: 'utf8',
224
+ timeout: 5000,
225
+ });
226
+ if (!output.trim()) {
227
+ return false;
228
+ }
229
+ // Parse lsof output to get PIDs of shell processes
230
+ const lines = output.split('\n').slice(1); // Skip header
231
+ const pids = new Set();
232
+ for (const line of lines) {
233
+ const parts = line.split(/\s+/);
234
+ if (parts.length >= 2) {
235
+ const command = parts[0].toLowerCase();
236
+ const pid = parts[1];
237
+ // Only kill shell processes and their children, not system processes
238
+ if (['bash', 'zsh', 'sh', 'fish', 'claude', 'node'].some(s => command.includes(s))) {
239
+ pids.add(pid);
240
+ }
241
+ }
242
+ }
243
+ // Send SIGTERM to each process
244
+ for (const pid of pids) {
245
+ try {
246
+ (0, child_process_1.execSync)(`kill -TERM ${pid} 2>/dev/null || true`, { stdio: 'pipe' });
247
+ }
248
+ catch {
249
+ // Process may have already exited
250
+ }
251
+ }
252
+ return pids.size > 0;
253
+ }
254
+ catch {
255
+ return false;
256
+ }
257
+ }
217
258
  /**
218
259
  * Close terminal windows and VS Code windows associated with a worktree
219
260
  * Returns an object indicating which applications had windows closed
220
261
  */
221
262
  function closeWindowsForWorktree(options) {
222
263
  if (os.platform() !== 'darwin') {
223
- return { iTerm: false, terminal: false, vscode: false };
264
+ return { iTerm: false, terminal: false, vscode: false, processes: false };
224
265
  }
225
266
  const patterns = getSearchPatterns(options);
226
267
  // Try to close iTerm2 windows/sessions
@@ -232,9 +273,12 @@ function closeWindowsForWorktree(options) {
232
273
  // Try to close VS Code windows
233
274
  const vscodeScript = generateVSCodeCloseScript(patterns);
234
275
  const vscodeResult = executeAppleScript(vscodeScript, 10000);
276
+ // Fallback: kill processes running in the worktree directory
277
+ const processResult = killProcessesInDirectory(options.folderPath);
235
278
  return {
236
279
  iTerm: iTermResult,
237
280
  terminal: terminalResult,
238
281
  vscode: vscodeResult,
282
+ processes: processResult,
239
283
  };
240
284
  }
@@ -10,10 +10,21 @@ const terminal_1 = require("./terminal");
10
10
  issueNumber: '42',
11
11
  };
12
12
  const patterns = (0, terminal_1.getSearchPatterns)(options);
13
+ // Should include full path for working directory matching
14
+ (0, vitest_1.expect)(patterns).toContain('/Users/test/project-issue-42-fix-bug');
13
15
  (0, vitest_1.expect)(patterns).toContain('project-issue-42-fix-bug');
14
16
  (0, vitest_1.expect)(patterns).toContain('Issue #42');
15
17
  (0, vitest_1.expect)(patterns).toContain('issue-42-');
16
18
  });
19
+ (0, vitest_1.it)('should include full folder path for working directory matching', () => {
20
+ const options = {
21
+ folderPath: '/Users/dev/myproject-issue-123-feature',
22
+ issueNumber: '123',
23
+ };
24
+ const patterns = (0, terminal_1.getSearchPatterns)(options);
25
+ // Full path should be first for best matching
26
+ (0, vitest_1.expect)(patterns[0]).toBe('/Users/dev/myproject-issue-123-feature');
27
+ });
17
28
  (0, vitest_1.it)('should include PR patterns when prNumber is provided', () => {
18
29
  const options = {
19
30
  folderPath: '/Users/test/project-issue-42-fix-bug',
@@ -51,7 +62,6 @@ const terminal_1 = require("./terminal");
51
62
  (0, vitest_1.expect)(script).toContain('project-issue-42');
52
63
  (0, vitest_1.expect)(script).toContain('Issue #42');
53
64
  (0, vitest_1.expect)(script).toContain('windowsToClose');
54
- (0, vitest_1.expect)(script).toContain('sessionsToClose');
55
65
  });
56
66
  (0, vitest_1.it)('should escape double quotes in patterns', () => {
57
67
  const patterns = ['Issue "quoted"'];
@@ -61,12 +71,18 @@ const terminal_1 = require("./terminal");
61
71
  (0, vitest_1.it)('should use two-pass approach for closing', () => {
62
72
  const patterns = ['test'];
63
73
  const script = (0, terminal_1.generateITermCloseScript)(patterns);
64
- // First pass collects
74
+ // First pass collects windows to close
65
75
  (0, vitest_1.expect)(script).toContain('First pass: collect');
66
- // Second pass closes sessions
67
- (0, vitest_1.expect)(script).toContain('Second pass: close sessions');
68
- // Third pass closes windows
69
- (0, vitest_1.expect)(script).toContain('Third pass: close entire windows');
76
+ // Second pass closes windows
77
+ (0, vitest_1.expect)(script).toContain('Second pass: close windows');
78
+ });
79
+ (0, vitest_1.it)('should match by session working directory path', () => {
80
+ const patterns = ['/Users/test/worktree'];
81
+ const script = (0, terminal_1.generateITermCloseScript)(patterns);
82
+ // Should include path matching
83
+ (0, vitest_1.expect)(script).toContain('set sessionPath to');
84
+ (0, vitest_1.expect)(script).toContain('path of s');
85
+ (0, vitest_1.expect)(script).toContain('sessionPath contains');
70
86
  });
71
87
  });
72
88
  (0, vitest_1.describe)('generateTerminalCloseScript', () => {
@@ -116,9 +132,11 @@ const terminal_1 = require("./terminal");
116
132
  (0, vitest_1.expect)(result).toHaveProperty('iTerm');
117
133
  (0, vitest_1.expect)(result).toHaveProperty('terminal');
118
134
  (0, vitest_1.expect)(result).toHaveProperty('vscode');
135
+ (0, vitest_1.expect)(result).toHaveProperty('processes');
119
136
  (0, vitest_1.expect)(typeof result.iTerm).toBe('boolean');
120
137
  (0, vitest_1.expect)(typeof result.terminal).toBe('boolean');
121
138
  (0, vitest_1.expect)(typeof result.vscode).toBe('boolean');
139
+ (0, vitest_1.expect)(typeof result.processes).toBe('boolean');
122
140
  });
123
141
  (0, vitest_1.it)('should handle prNumber parameter', () => {
124
142
  const result = (0, terminal_1.closeWindowsForWorktree)({
@@ -129,6 +147,7 @@ const terminal_1 = require("./terminal");
129
147
  (0, vitest_1.expect)(result).toHaveProperty('iTerm');
130
148
  (0, vitest_1.expect)(result).toHaveProperty('terminal');
131
149
  (0, vitest_1.expect)(result).toHaveProperty('vscode');
150
+ (0, vitest_1.expect)(result).toHaveProperty('processes');
132
151
  });
133
152
  });
134
153
  (0, vitest_1.describe)('pattern matching edge cases', () => {
@@ -175,7 +194,8 @@ const terminal_1 = require("./terminal");
175
194
  const script = (0, terminal_1.generateITermCloseScript)(patterns);
176
195
  // Script should be syntactically valid (quotes should be escaped)
177
196
  (0, vitest_1.expect)(script).toContain('test\\"pattern');
178
- (0, vitest_1.expect)(script).not.toContain('""'); // No empty quotes from bad escaping
197
+ // Should not have broken string like contains "" (empty pattern)
198
+ (0, vitest_1.expect)(script).not.toMatch(/contains ""/);
179
199
  });
180
200
  (0, vitest_1.it)('should not have nested quotes issues in Terminal script', () => {
181
201
  const patterns = ['test"pattern'];
@@ -188,4 +208,14 @@ const terminal_1 = require("./terminal");
188
208
  (0, vitest_1.expect)(script).toContain('test\\"pattern');
189
209
  });
190
210
  });
211
+ (0, vitest_1.describe)('killProcessesInDirectory', () => {
212
+ (0, vitest_1.it)('should return false for non-existent directory', () => {
213
+ const result = (0, terminal_1.killProcessesInDirectory)('/nonexistent/path/that/does/not/exist');
214
+ (0, vitest_1.expect)(result).toBe(false);
215
+ });
216
+ (0, vitest_1.it)('should return boolean result', () => {
217
+ const result = (0, terminal_1.killProcessesInDirectory)('/tmp');
218
+ (0, vitest_1.expect)(typeof result).toBe('boolean');
219
+ });
220
+ });
191
221
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-issue-solver",
3
- "version": "1.42.1",
3
+ "version": "1.43.1",
4
4
  "description": "Automatically solve GitHub issues using Claude Code",
5
5
  "main": "dist/index.js",
6
6
  "bin": {