@vibe-agent-toolkit/utils 0.1.40 → 0.1.41-rc.2

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.d.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  * Utilities are added as needed by other packages, not speculatively.
6
6
  */
7
7
  export * from './safe-exec.js';
8
+ export * from './windows-shell.js';
9
+ export * from './spawn-hardened.js';
8
10
  export * from './path-utils.js';
9
11
  export * from './asset-reference.js';
10
12
  export * from './fs-utils.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAI/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,iBAAiB,CAAC;AAGhC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,eAAe,CAAC;AAG9B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,cAAc,CAAC;AAG7B,cAAc,gBAAgB,CAAC;AAI/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,kBAAkB,CAAC;AAGjC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,eAAe,CAAC;AAG9B,cAAc,oBAAoB,CAAC;AAInC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,cAAc,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAG7E,cAAc,uBAAuB,CAAC;AAGtC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,yBAAyB,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,10 @@
6
6
  */
7
7
  // Safe command execution (cross-platform, no shell injection)
8
8
  export * from './safe-exec.js';
9
+ // Windows shell-invocation helpers (.cmd/.bat/.ps1 handling), shared by every spawn wrapper
10
+ export * from './windows-shell.js';
11
+ // Hardened async spawn (streaming stdio + correct Windows .cmd/.bat launching)
12
+ export * from './spawn-hardened.js';
9
13
  // Cross-platform path utilities
10
14
  export * from './path-utils.js';
11
15
  // Asset reference resolution (paths + npm bare specifiers)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,uEAAuE;AACvE,cAAc,cAAc,CAAC;AAE7B,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,yDAAyD;AACzD,cAAc,kBAAkB,CAAC;AAEjC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,2DAA2D;AAC3D,cAAc,eAAe,CAAC;AAE9B,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,uDAAuD;AACvD,uEAAuE;AACvE,OAAO,EAKL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,2EAA2E;AAC3E,cAAc,uBAAuB,CAAC;AAEtC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8DAA8D;AAC9D,cAAc,gBAAgB,CAAC;AAE/B,4FAA4F;AAC5F,cAAc,oBAAoB,CAAC;AAEnC,+EAA+E;AAC/E,cAAc,qBAAqB,CAAC;AAEpC,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,2DAA2D;AAC3D,cAAc,sBAAsB,CAAC;AAErC,uBAAuB;AACvB,cAAc,eAAe,CAAC;AAE9B,wCAAwC;AACxC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,cAAc,wBAAwB,CAAC;AAEvC,uEAAuE;AACvE,cAAc,cAAc,CAAC;AAE7B,8CAA8C;AAC9C,cAAc,gBAAgB,CAAC;AAE/B,2DAA2D;AAC3D,iEAAiE;AACjE,cAAc,oBAAoB,CAAC;AAEnC,yDAAyD;AACzD,cAAc,kBAAkB,CAAC;AAEjC,oDAAoD;AACpD,cAAc,mBAAmB,CAAC;AAElC,4CAA4C;AAC5C,cAAc,wBAAwB,CAAC;AAEvC,2DAA2D;AAC3D,cAAc,eAAe,CAAC;AAE9B,oEAAoE;AACpE,cAAc,oBAAoB,CAAC;AAEnC,uDAAuD;AACvD,uEAAuE;AACvE,OAAO,EAKL,uBAAuB,GAExB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,iBAAiB,EAAoB,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,2EAA2E;AAC3E,cAAc,uBAAuB,CAAC;AAEtC,oEAAoE;AACpE,cAAc,wBAAwB,CAAC;AAEvC,gDAAgD;AAChD,cAAc,mBAAmB,CAAC;AAElC,8EAA8E;AAC9E,cAAc,yBAAyB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"safe-exec.d.ts","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC7E,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,qBAAqB;IACrB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC,SAAgB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;gBAGtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,MAAM,EAAE,MAAM,GAAG,MAAM;CAQ1B;AAqHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,eAAoB,GAC5B,MAAM,GAAG,MAAM,CAmBjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,eAAoB,GAC5B,cAAc,CA4BhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAAoB,GAC/B,MAAM,GAAG,IAAI,CAUf;AAuBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG;IACrD,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CA0CA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,eAAoB,GAC5B,MAAM,GAAG,MAAM,CAyBjB"}
1
+ {"version":3,"file":"safe-exec.d.ts","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAC7E,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,qBAAqB;IACrB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxC,SAAgB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;gBAGtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,MAAM,EAAE,MAAM,GAAG,MAAM;CAQ1B;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,eAAoB,GAC5B,MAAM,GAAG,MAAM,CAmBjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,eAAoB,GAC5B,cAAc,CA4BhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,MAAoB,GAC/B,MAAM,GAAG,IAAI,CAUf;AAuBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG;IACrD,cAAc,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CA0CA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,eAAoB,GAC5B,MAAM,GAAG,MAAM,CAyBjB"}
package/dist/safe-exec.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import which from 'which';
3
+ import { buildWindowsShellLine, shouldUseShell } from './windows-shell.js';
3
4
  /**
4
5
  * Error thrown when command execution fails
5
6
  */
@@ -15,80 +16,6 @@ export class CommandExecutionError extends Error {
15
16
  this.stderr = stderr;
16
17
  }
17
18
  }
18
- /**
19
- * Determine if shell should be used for command execution on Windows
20
- *
21
- * ## Security Context
22
- *
23
- * This package's primary security model is `shell: false` to prevent command injection.
24
- * Windows requires `shell: true` only for shell scripts (.cmd/.bat/.ps1) which require
25
- * a shell interpreter by design (not executable binaries).
26
- *
27
- * ## Node.js on Windows - NO SHELL REQUIRED
28
- *
29
- * **Previous behavior (REMOVED):** Used shell:true for 'node' command
30
- * **Problem discovered:** Node.js DEP0190 deprecation warning - passing args array with
31
- * shell:true leads to incorrect command execution. Exit codes are ignored (always returns 0).
32
- *
33
- * **Testing shows:**
34
- * - ✅ `shell: false` + absolute path from `which.sync('node')` → Works correctly
35
- * - ❌ `shell: true` + args array → Exit codes ignored, security warning
36
- *
37
- * **Root Cause of Previous ENOENT Issues:** Likely resolved in newer Node.js versions.
38
- * Current testing (Node 20+) shows shell:false works correctly with absolute path.
39
- *
40
- * ## Why This Is Secure
41
- *
42
- * 1. **Minimal Shell Usage:** Shell only used for .cmd/.bat/.ps1 files (required)
43
- * 2. **Path Validation:** Command paths resolved via `which.sync()` before execution
44
- * 3. **Array-Based Arguments:** Arguments passed as array, preventing injection
45
- * 4. **Controlled Environment:** Commands from trusted configuration, not user input
46
- * 5. **No String Interpolation:** Never concatenate user input into command strings
47
- *
48
- * ## References
49
- *
50
- * - Node.js deprecation: https://nodejs.org/api/deprecations.html#DEP0190
51
- * - Security tests: `packages/utils/test/safe-exec.test.ts`
52
- * - Windows fix: PR #94 (fix/windows-shell-independence-v2)
53
- *
54
- * @param commandPath - Resolved absolute path to command
55
- * @returns true if shell should be used, false otherwise
56
- */
57
- function shouldUseShell(commandPath) {
58
- if (process.platform !== 'win32') {
59
- return false;
60
- }
61
- // Node.js deprecation warning (DEP0190): Passing args with shell:true leads to incorrect
62
- // command execution and security vulnerabilities. Testing shows shell:false works correctly
63
- // with absolute path from which.sync('node') on Windows.
64
- // Previous ENOENT issues may have been resolved in newer Node.js versions.
65
- //
66
- // REMOVED: if (command === 'node') return true;
67
- // Reason: shell:true causes exit codes to be ignored (always returns 0)
68
- // Fix: Use shell:false with absolute path - works correctly
69
- // Windows shell scripts require shell by design (case-insensitive check)
70
- const lowerPath = commandPath.toLowerCase();
71
- return lowerPath.endsWith('.cmd') || lowerPath.endsWith('.bat') || lowerPath.endsWith('.ps1');
72
- }
73
- /**
74
- * Quote a single argument for a Windows `cmd.exe` command line.
75
- *
76
- * Rules:
77
- * - An arg that's empty, or contains whitespace, quotes, or any of `& | < > ^ ( ) % !`,
78
- * gets wrapped in double quotes.
79
- * - Embedded double quotes become `""` (cmd.exe's escape form inside quoted strings).
80
- *
81
- * This is narrow on purpose: it's only used when we're forced to assemble a shell string
82
- * for `.cmd` / `.bat` wrappers on Windows (DEP0190 path). Callers still control what's
83
- * in `args`, but this keeps a stray space, glob metachar, or paren from getting
84
- * re-interpreted by the shell.
85
- */
86
- function windowsShellQuote(arg) {
87
- if (arg === '' || /["\s&|<>^()%!]/.test(arg)) {
88
- return `"${arg.replaceAll('"', '""')}"`;
89
- }
90
- return arg;
91
- }
92
19
  /**
93
20
  * Resolve command, build spawn options, and execute via spawnSync.
94
21
  *
@@ -114,7 +41,7 @@ function resolveAndSpawn(command, args, options) {
114
41
  if (!useShell) {
115
42
  return spawnSync(execCommand, args, spawnOptions);
116
43
  }
117
- const shellLine = `${execCommand} ${args.map(windowsShellQuote).join(' ')}`;
44
+ const shellLine = buildWindowsShellLine(execCommand, args);
118
45
  // eslint-disable-next-line sonarjs/os-command -- Windows DEP0190 workaround: command resolved via which.sync(); args are per-arg shell-quoted via windowsShellQuote()
119
46
  return spawnSync(shellLine, { ...spawnOptions, shell: true });
120
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"safe-exec.js","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"safe-exec.js","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, protectedEnvNames, type DeclaredEnvInput, type DeclaredEnvResult, type ForwardEnvOptions, } from './env-scrub.js';
2
2
  export { AuthPreflightError, probeAuthStatus, resolveAuth, type AuthMechanism, type AuthMode, type AuthStatusProbe, type AuthStatusResult, type ResolveAuthOptions, type ResolvedAuth, } from './auth-resolver.js';
3
- export { assembleClaudeArgs, spawnHeadlessClaude, type ClaudeSpawnArgs, type SpawnHeadlessOptions, type SpawnResult, } from './spawn-claude.js';
3
+ export { assembleClaudeArgs, killAllActiveClaudeChildren, spawnHeadlessClaude, type ClaudeSpawnArgs, type SpawnHeadlessOptions, type SpawnResult, } from './spawn-claude.js';
4
+ export { detectInvocationFromTranscript, parseStreamJsonTranscript, type ParsedTranscript, } from './transcript.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skill-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skill-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, protectedEnvNames, } from './env-scrub.js';
2
2
  export { AuthPreflightError, probeAuthStatus, resolveAuth, } from './auth-resolver.js';
3
- export { assembleClaudeArgs, spawnHeadlessClaude, } from './spawn-claude.js';
3
+ export { assembleClaudeArgs, killAllActiveClaudeChildren, spawnHeadlessClaude, } from './spawn-claude.js';
4
+ export { detectInvocationFromTranscript, parseStreamJsonTranscript, } from './transcript.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skill-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,GAIlB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,WAAW,GAOZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skill-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,GAIlB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,WAAW,GAOZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,GAIpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,GAE1B,MAAM,iBAAiB,CAAC"}
@@ -32,9 +32,16 @@ export interface SpawnResult {
32
32
  export declare function killProcessTree(child: {
33
33
  pid?: number | undefined;
34
34
  }): void;
35
+ /**
36
+ * SIGKILL every currently in-flight `claude` child (and its process tree, via
37
+ * {@link killProcessTree}) and clear the registry. Idempotent — safe to call
38
+ * when the registry is already empty (e.g. every child has already settled,
39
+ * or this has already been called once on the current error path).
40
+ */
41
+ export declare function killAllActiveClaudeChildren(): void;
35
42
  export interface SpawnHeadlessOptions extends ClaudeSpawnArgs {
36
43
  /**
37
- * The experimenter prompt, held IN MEMORY and streamed to the child's stdin
44
+ * The executor prompt, held IN MEMORY and streamed to the child's stdin
38
45
  * (claude 2.x reads the `-p` prompt from stdin; there is no `--prompt-file`
39
46
  * flag). Kept off argv so the prompt is never inlined (Windows cmd-quoting
40
47
  * safety) AND, deliberately, off disk: the harness stamps a per-run integrity
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../src/skill-test/spawn-claude.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,CAmBlE;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAczE;AAED,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwE1F"}
1
+ {"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../src/skill-test/spawn-claude.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,CAmBlE;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,CAczE;AAoBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAKlD;AAED,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D;;;;;;;;;OASG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAwF1F"}
@@ -1,6 +1,6 @@
1
- import { spawn, spawnSync } from 'node:child_process';
1
+ import { spawnSync } from 'node:child_process';
2
2
  import { Readable } from 'node:stream';
3
- import which from 'which';
3
+ import { spawnHardened } from '../spawn-hardened.js';
4
4
  /**
5
5
  * Pure assembly of the headless `claude -p` argv (spec §9). The prompt is never
6
6
  * inlined as an argv string (Windows cmd-quoting safety) and claude 2.x has no
@@ -60,6 +60,35 @@ export function killProcessTree(child) {
60
60
  // ESRCH (no such process/group): the child and its group are already dead.
61
61
  }
62
62
  }
63
+ /**
64
+ * Registry of currently in-flight `claude` child processes, keyed by the
65
+ * `ChildProcess` object itself. A child is registered immediately after
66
+ * spawn and unregistered wherever it settles (normal 'close', child-process
67
+ * 'error', or the prompt-stream error path) — a normal completed run always
68
+ * leaves this Set empty.
69
+ *
70
+ * This exists for the concurrent pipeline's error path (spec §orphan-reap):
71
+ * when one worker in a bounded pool throws, `Promise.all` rejects without
72
+ * cancelling its siblings, and the top-level handler calls `process.exit(1)`
73
+ * — tearing down the in-process wall/stall watchdog timers before they fire.
74
+ * Without this registry, up to `concurrency - 1` in-flight `claude` sessions
75
+ * would be orphaned (detached process groups) and keep billing tokens until
76
+ * they self-terminate. The orchestrator's error handler calls
77
+ * {@link killAllActiveClaudeChildren} before exiting to reap them.
78
+ */
79
+ const activeClaudeChildren = new Set();
80
+ /**
81
+ * SIGKILL every currently in-flight `claude` child (and its process tree, via
82
+ * {@link killProcessTree}) and clear the registry. Idempotent — safe to call
83
+ * when the registry is already empty (e.g. every child has already settled,
84
+ * or this has already been called once on the current error path).
85
+ */
86
+ export function killAllActiveClaudeChildren() {
87
+ for (const child of activeClaudeChildren) {
88
+ killProcessTree(child);
89
+ }
90
+ activeClaudeChildren.clear();
91
+ }
63
92
  /**
64
93
  * Spawn the headless `claude`. The in-memory prompt is streamed to the child's
65
94
  * stdin so the session reads its prompt and then sees EOF (it cannot block on
@@ -69,11 +98,16 @@ export function killProcessTree(child) {
69
98
  */
70
99
  export async function spawnHeadlessClaude(opts) {
71
100
  // opts.binPath is an internal test seam (see SpawnHeadlessOptions); production
72
- // callers leave it unset and `claude` is resolved on PATH.
73
- const bin = opts.binPath ?? which.sync('claude');
101
+ // callers leave it unset and the bare `claude` name is resolved on PATH by
102
+ // spawnHardened. spawnHardened is REQUIRED here (not a bare spawn): on Windows
103
+ // `claude` resolves to a `claude.cmd` shim, and since CVE-2024-27980 a bare
104
+ // spawn of a `.cmd` throws EINVAL — spawnHardened routes it through the shell.
74
105
  const args = assembleClaudeArgs(opts);
75
106
  return await new Promise((resolve, reject) => {
76
- const child = spawn(bin, args, {
107
+ // `stdio: ['pipe','pipe','pipe']` guarantees all three streams are non-null;
108
+ // spawnHardened is typed to return the generic (nullable-stream) ChildProcess,
109
+ // so narrow to the piped shape here (mirrors Node's own stdio-tuple overload).
110
+ const child = spawnHardened(opts.binPath ?? 'claude', args, {
77
111
  cwd: opts.cwd,
78
112
  env: opts.env,
79
113
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -82,6 +116,9 @@ export async function spawnHeadlessClaude(opts) {
82
116
  // direct child. Windows has no process groups (taskkill handles the tree).
83
117
  detached: process.platform !== 'win32',
84
118
  });
119
+ // Register immediately after spawn so the child is reapable by
120
+ // killAllActiveClaudeChildren() for the entire time it can be in flight.
121
+ activeClaudeChildren.add(child);
85
122
  let timedOut = false;
86
123
  let stalled = false;
87
124
  // Feed the prompt to the child via stdin (claude 2.x has no --prompt-file).
@@ -118,6 +155,10 @@ export async function spawnHeadlessClaude(opts) {
118
155
  // here via 'close'; error paths call it directly) so an unconsumed in-memory
119
156
  // stream is torn down. On a clean run the stream has already ended — no-op.
120
157
  promptStream.destroy();
158
+ // This is the single choke point every settle path (close/error) runs
159
+ // through, so unregistering here guarantees a normally-completed run
160
+ // leaves the registry empty — no reference leak.
161
+ activeClaudeChildren.delete(child);
121
162
  };
122
163
  promptStream.on('error', err => {
123
164
  clearAllTimers();
@@ -131,7 +172,11 @@ export async function spawnHeadlessClaude(opts) {
131
172
  promptStream.pipe(child.stdin);
132
173
  child.stdout.on('data', (d) => { opts.onStdout?.(d.toString()); });
133
174
  child.stderr.on('data', (d) => { opts.onStderr?.(d.toString()); });
134
- child.on('error', err => { clearAllTimers(); reject(err); });
175
+ // Reap on 'error' too: clearAllTimers() unregisters the child, so if 'error'
176
+ // ever fires while the process is actually alive we would otherwise drop it
177
+ // from the reap set without killing it (the exact orphan this file guards
178
+ // against). killProcessTree no-ops on an undefined pid (never-spawned case).
179
+ child.on('error', err => { clearAllTimers(); killProcessTree(child); reject(err); });
135
180
  child.on('close', code => { clearAllTimers(); resolve({ status: code ?? -1, timedOut, stalled }); });
136
181
  });
137
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-claude.js","sourceRoot":"","sources":["../../src/skill-test/spawn-claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spawn-claude.js","sourceRoot":"","sources":["../../src/skill-test/spawn-claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+C,MAAM,oBAAoB,CAAC;AAC5F,OAAO,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAUrD;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,MAAM,IAAI,GAAa;QACrB,IAAI;QACJ,0EAA0E;QAC1E,sEAAsE;QACtE,4DAA4D;QAC5D,iBAAiB,EAAE,aAAa;QAChC,WAAW;QACX,mBAAmB,EAAE,EAAE;QACvB,mBAAmB,EAAE,mBAAmB;QACxC,WAAW,EAAE,IAAI,CAAC,UAAU;KAC7B,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjF,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IAC9F,OAAO,IAAI,CAAC;AACd,CAAC;AAQD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,KAAmC;IACjE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,iNAAiN;YACjN,SAAS,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,+DAA+D;YAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;IAC7E,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAgB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B;IACzC,KAAK,MAAM,KAAK,IAAI,oBAAoB,EAAE,CAAC;QACzC,eAAe,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IACD,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC;AA8BD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA0B;IAClE,+EAA+E;IAC/E,2EAA2E;IAC3E,+EAA+E;IAC/E,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAEtC,OAAO,MAAM,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxD,6EAA6E;QAC7E,+EAA+E;QAC/E,+EAA+E;QAC/E,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE,IAAI,EAAE;YAC1D,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,0EAA0E;YAC1E,sEAAsE;YACtE,2EAA2E;YAC3E,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACvC,CAAsD,CAAC;QACxD,+DAA+D;QAC/D,yEAAyE;QACzE,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,4EAA4E;QAC5E,8EAA8E;QAC9E,8EAA8E;QAC9E,6EAA6E;QAC7E,4CAA4C;QAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QAEzE,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,QAAQ,GAAG,IAAI,CAAC;YAChB,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEnB,kFAAkF;QAClF,IAAI,UAAqD,CAAC;QAC1D,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,MAAM,eAAe,GAAG,GAAS,EAAE;gBACjC,IAAI,UAAU,KAAK,SAAS;oBAAE,YAAY,CAAC,UAAU,CAAC,CAAC;gBACvD,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;oBAC3B,OAAO,GAAG,IAAI,CAAC;oBACf,eAAe,CAAC,KAAK,CAAC,CAAC;gBACzB,CAAC,EAAE,OAAO,CAAC,CAAC;YACd,CAAC,CAAC;YACF,eAAe,EAAE,CAAC;YAElB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,cAAc,GAAG,GAAS,EAAE;YAChC,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,IAAI,UAAU,KAAK,SAAS;gBAAE,YAAY,CAAC,UAAU,CAAC,CAAC;YACvD,wEAAwE;YACxE,6EAA6E;YAC7E,4EAA4E;YAC5E,YAAY,CAAC,OAAO,EAAE,CAAC;YACvB,sEAAsE;YACtE,qEAAqE;YACrE,iDAAiD;YACjD,oBAAoB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC,CAAC;QAEF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YAC7B,cAAc,EAAE,CAAC;YACjB,eAAe,CAAC,KAAK,CAAC,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QACH,0EAA0E;QAC1E,4EAA4E;QAC5E,6BAA6B;QAC7B,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAA0C,CAAC,CAAC,CAAC;QAC1E,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,6EAA6E;QAC7E,4EAA4E;QAC5E,0EAA0E;QAC1E,6EAA6E;QAC7E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Transcript parser for `claude -p --output-format stream-json`. The format
3
+ * is one JSON object per line; we collect the assistant text + tool-use
4
+ * events for the observation record.
5
+ *
6
+ * The stream-json schema is informally documented and may shift between
7
+ * Claude Code releases. This parser is intentionally tolerant of unknown
8
+ * event kinds — anything we don't recognise is appended to `raw`.
9
+ *
10
+ * Shape notes (empirically verified):
11
+ * - `tool_use` content blocks carry `input.command` for Bash calls.
12
+ * - `tool_result` content blocks (on `user` events) carry `is_error`.
13
+ * - `parent_tool_use_id` lives on the TOP-LEVEL event object (not the content
14
+ * block) — `null` for top-level tool calls, the parent's tool_use id for
15
+ * subagent-attributed calls.
16
+ * - The terminal `result` event carries `subtype`, `is_error`, `num_turns`,
17
+ * and `total_cost_usd`.
18
+ */
19
+ export interface ParsedTranscript {
20
+ text: string;
21
+ toolUseEvents: Array<{
22
+ name: string;
23
+ inputSummary: string;
24
+ }>;
25
+ errors: string[];
26
+ raw: string[];
27
+ toolUses: Array<{
28
+ id: string | null;
29
+ name: string;
30
+ command?: string;
31
+ inputSummary: string;
32
+ parentToolUseId: string | null;
33
+ }>;
34
+ toolResults: Array<{
35
+ toolUseId: string | null;
36
+ isError: boolean;
37
+ contentSummary: string;
38
+ }>;
39
+ result?: {
40
+ subtype?: string;
41
+ isError: boolean;
42
+ numTurns?: number;
43
+ totalCostUsd?: number;
44
+ };
45
+ rateLimited: boolean;
46
+ }
47
+ export declare function parseStreamJsonTranscript(streamText: string): ParsedTranscript;
48
+ export declare function detectInvocationFromTranscript(parsed: ParsedTranscript, invocationSignals: readonly string[]): boolean;
49
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC,CAAC;IACH,WAAW,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,WAAW,EAAE,OAAO,CAAC;CACtB;AA4HD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,CA4B9E;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,gBAAgB,EACxB,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAOT"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Transcript parser for `claude -p --output-format stream-json`. The format
3
+ * is one JSON object per line; we collect the assistant text + tool-use
4
+ * events for the observation record.
5
+ *
6
+ * The stream-json schema is informally documented and may shift between
7
+ * Claude Code releases. This parser is intentionally tolerant of unknown
8
+ * event kinds — anything we don't recognise is appended to `raw`.
9
+ *
10
+ * Shape notes (empirically verified):
11
+ * - `tool_use` content blocks carry `input.command` for Bash calls.
12
+ * - `tool_result` content blocks (on `user` events) carry `is_error`.
13
+ * - `parent_tool_use_id` lives on the TOP-LEVEL event object (not the content
14
+ * block) — `null` for top-level tool calls, the parent's tool_use id for
15
+ * subagent-attributed calls.
16
+ * - The terminal `result` event carries `subtype`, `is_error`, `num_turns`,
17
+ * and `total_cost_usd`.
18
+ */
19
+ function summarizeValue(value) {
20
+ try {
21
+ const json = JSON.stringify(value);
22
+ return json.length > 200 ? `${json.slice(0, 197)}...` : json;
23
+ }
24
+ catch {
25
+ return '<unserializable>';
26
+ }
27
+ }
28
+ function extractCommand(input) {
29
+ if (input !== null && typeof input === 'object' && typeof input.command === 'string') {
30
+ return input.command;
31
+ }
32
+ return undefined;
33
+ }
34
+ function consumeAssistantBlocks(blocks, parentToolUseId, out) {
35
+ for (const block of blocks) {
36
+ if (block.type === 'text' && typeof block.text === 'string') {
37
+ out.text += block.text;
38
+ }
39
+ else if (block.type === 'tool_use' && typeof block.name === 'string') {
40
+ const inputSummary = summarizeValue(block.input);
41
+ out.toolUseEvents.push({ name: block.name, inputSummary });
42
+ const command = extractCommand(block.input);
43
+ out.toolUses.push({
44
+ id: typeof block.id === 'string' ? block.id : null,
45
+ name: block.name,
46
+ ...(command === undefined ? {} : { command }),
47
+ inputSummary,
48
+ parentToolUseId,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ function consumeUserBlocks(blocks, out) {
54
+ for (const block of blocks) {
55
+ if (block.type === 'tool_result') {
56
+ out.toolResults.push({
57
+ toolUseId: typeof block.tool_use_id === 'string' ? block.tool_use_id : null,
58
+ isError: block.is_error === true,
59
+ contentSummary: summarizeValue(block.content),
60
+ });
61
+ }
62
+ }
63
+ }
64
+ /** True when the event's `type`/`subtype` mentions rate-limiting, or it carries a `rate_limit_event` field. */
65
+ function detectRateLimit(parsed) {
66
+ const { type, subtype } = parsed;
67
+ if (typeof type === 'string' && type.includes('rate_limit'))
68
+ return true;
69
+ if (typeof subtype === 'string' && subtype.includes('rate_limit'))
70
+ return true;
71
+ return Object.prototype.hasOwnProperty.call(parsed, 'rate_limit_event');
72
+ }
73
+ function consumeResultEvent(parsed, out) {
74
+ // `claude -p --output-format stream-json` reports in-stream failures
75
+ // (max-turns, rate-limit, content-filter, tool error) as a terminal
76
+ // `result` event with is_error:true and a `subtype` discriminator.
77
+ out.result = {
78
+ ...(typeof parsed.subtype === 'string' ? { subtype: parsed.subtype } : {}),
79
+ isError: parsed.is_error === true,
80
+ ...(typeof parsed.num_turns === 'number' ? { numTurns: parsed.num_turns } : {}),
81
+ ...(typeof parsed.total_cost_usd === 'number' ? { totalCostUsd: parsed.total_cost_usd } : {}),
82
+ };
83
+ if (parsed.is_error === true) {
84
+ out.errors.push(`runtime ${parsed.subtype ?? 'error'}`);
85
+ }
86
+ }
87
+ function consumeErrorEvent(parsed, out) {
88
+ // Kept for forward compatibility — the stream-json schema is informally
89
+ // documented and may emit standalone error events in future releases.
90
+ const errMsg = typeof parsed.error === 'string'
91
+ ? parsed.error
92
+ : parsed.error?.message ?? 'unknown error event';
93
+ out.errors.push(errMsg);
94
+ }
95
+ function applyEvent(parsed, out) {
96
+ if (detectRateLimit(parsed)) {
97
+ out.rateLimited = true;
98
+ }
99
+ if (parsed.type === 'assistant' && parsed.message?.content) {
100
+ consumeAssistantBlocks(parsed.message.content, parsed.parent_tool_use_id ?? null, out);
101
+ }
102
+ else if (parsed.type === 'user' && parsed.message?.content) {
103
+ consumeUserBlocks(parsed.message.content, out);
104
+ }
105
+ else if (parsed.type === 'result') {
106
+ consumeResultEvent(parsed, out);
107
+ }
108
+ else if (parsed.type === 'error') {
109
+ consumeErrorEvent(parsed, out);
110
+ }
111
+ }
112
+ export function parseStreamJsonTranscript(streamText) {
113
+ const out = {
114
+ text: '',
115
+ toolUseEvents: [],
116
+ errors: [],
117
+ raw: [],
118
+ toolUses: [],
119
+ toolResults: [],
120
+ rateLimited: false,
121
+ };
122
+ const lines = streamText.split('\n');
123
+ for (const line of lines) {
124
+ const trimmed = line.trim();
125
+ if (trimmed.length === 0)
126
+ continue;
127
+ out.raw.push(trimmed);
128
+ let parsed;
129
+ try {
130
+ parsed = JSON.parse(trimmed);
131
+ }
132
+ catch {
133
+ continue;
134
+ }
135
+ applyEvent(parsed, out);
136
+ }
137
+ return out;
138
+ }
139
+ export function detectInvocationFromTranscript(parsed, invocationSignals) {
140
+ if (parsed.toolUseEvents.length > 0)
141
+ return true;
142
+ if (invocationSignals.length === 0) {
143
+ return parsed.text.trim().length > 0;
144
+ }
145
+ const haystack = parsed.text.toLowerCase();
146
+ return invocationSignals.some((s) => haystack.includes(s.toLowerCase()));
147
+ }
148
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAmBH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,kBAAkB,CAAC;IAC5B,CAAC;AACH,CAAC;AAwBD,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAQ,KAA+B,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChH,OAAQ,KAA6B,CAAC,OAAO,CAAC;IAChD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,sBAAsB,CAC7B,MAAsB,EACtB,eAA8B,EAC9B,GAAqB;IAErB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5D,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QACzB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvE,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACjD,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;YAE3D,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5C,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;gBAClD,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;gBAC7C,YAAY;gBACZ,eAAe;aAChB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAsB,EAAE,GAAqB;IACtE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACjC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC;gBACnB,SAAS,EAAE,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;gBAC3E,OAAO,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI;gBAChC,cAAc,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC;aAC9C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,+GAA+G;AAC/G,SAAS,eAAe,CAAC,MAA+B;IACtD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/E,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAoB,EAAE,GAAqB;IACrE,qEAAqE;IACrE,oEAAoE;IACpE,mEAAmE;IACnE,GAAG,CAAC,MAAM,GAAG;QACX,GAAG,CAAC,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI;QACjC,GAAG,CAAC,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9F,CAAC;IACF,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC7B,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAoB,EAAE,GAAqB;IACpE,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;QAC7C,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,qBAAqB,CAAC;IACnD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,UAAU,CAAC,MAAoB,EAAE,GAAqB;IAC7D,IAAI,eAAe,CAAC,MAAiC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QAC3D,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,kBAAkB,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;QAC7D,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACnC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC1D,MAAM,GAAG,GAAqB;QAC5B,IAAI,EAAE,EAAE;QACR,aAAa,EAAE,EAAE;QACjB,MAAM,EAAE,EAAE;QACV,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,KAAK;KACnB,CAAC;IACF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACnC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,MAAoB,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,MAAwB,EACxB,iBAAoC;IAEpC,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type ChildProcess, type SpawnOptions } from 'node:child_process';
2
+ /**
3
+ * Cross-platform hardened async `spawn`, returning a live {@link ChildProcess} with
4
+ * streaming stdio intact (unlike the sync, buffered {@link ./safe-exec.ts} path).
5
+ *
6
+ * The one thing it does that a bare `child_process.spawn` does not: correctly launch
7
+ * Windows `.cmd`/`.bat`/`.ps1` wrappers. Since the CVE-2024-27980 fix, `spawn` throws
8
+ * `EINVAL` on such a wrapper unless `shell: true` — and npm-installed CLIs (`claude`,
9
+ * `npm`, …) resolve to exactly that on Windows. When shell mode is required we join the
10
+ * command + args into a SINGLE string with per-arg {@link windowsShellQuote} (Node's
11
+ * DEP0190 rejects `shell: true` with a separate args array); everywhere else we spawn
12
+ * `shell: false` with the resolved absolute path, keeping the no-injection guarantee.
13
+ *
14
+ * POSIX is a pure passthrough to `child_process.spawn` (`shouldUseShell` is always
15
+ * false off-Windows), so process-group / `detached` semantics are unchanged there.
16
+ *
17
+ * @param command - Bare command name (PATH-resolved) or an explicit path (used as-is).
18
+ * @param args - Arguments, passed as an array (never string-concatenated on POSIX).
19
+ * @param options - Standard `SpawnOptions` (cwd, env, stdio, detached, …), passed through.
20
+ */
21
+ export declare function spawnHardened(command: string, args: string[], options?: SpawnOptions): ChildProcess;
22
+ //# sourceMappingURL=spawn-hardened.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-hardened.d.ts","sourceRoot":"","sources":["../src/spawn-hardened.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAmBjF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,YAAiB,GACzB,YAAY,CAad"}
@@ -0,0 +1,47 @@
1
+ import { spawn } from 'node:child_process';
2
+ import which from 'which';
3
+ import { isAbsoluteAnyPlatform } from './path-utils.js';
4
+ import { buildWindowsShellLine, shouldUseShell, windowsShellQuote } from './windows-shell.js';
5
+ /**
6
+ * A `command` is treated as an explicit path (used verbatim, never PATH-resolved)
7
+ * when it is absolute or contains a path separator. A bare name (`claude`, `npm`,
8
+ * `git`) is resolved on PATH via `which.sync`. This mirrors — and preserves — the
9
+ * behaviour callers relied on before hardening: an explicit `binPath` is spawned
10
+ * as-given (so a nonexistent path still surfaces as an async `'error'` event, not a
11
+ * synchronous `which` throw), while a bare command is looked up.
12
+ */
13
+ function isPathLike(command) {
14
+ return isAbsoluteAnyPlatform(command) || command.includes('/') || command.includes('\\');
15
+ }
16
+ /**
17
+ * Cross-platform hardened async `spawn`, returning a live {@link ChildProcess} with
18
+ * streaming stdio intact (unlike the sync, buffered {@link ./safe-exec.ts} path).
19
+ *
20
+ * The one thing it does that a bare `child_process.spawn` does not: correctly launch
21
+ * Windows `.cmd`/`.bat`/`.ps1` wrappers. Since the CVE-2024-27980 fix, `spawn` throws
22
+ * `EINVAL` on such a wrapper unless `shell: true` — and npm-installed CLIs (`claude`,
23
+ * `npm`, …) resolve to exactly that on Windows. When shell mode is required we join the
24
+ * command + args into a SINGLE string with per-arg {@link windowsShellQuote} (Node's
25
+ * DEP0190 rejects `shell: true` with a separate args array); everywhere else we spawn
26
+ * `shell: false` with the resolved absolute path, keeping the no-injection guarantee.
27
+ *
28
+ * POSIX is a pure passthrough to `child_process.spawn` (`shouldUseShell` is always
29
+ * false off-Windows), so process-group / `detached` semantics are unchanged there.
30
+ *
31
+ * @param command - Bare command name (PATH-resolved) or an explicit path (used as-is).
32
+ * @param args - Arguments, passed as an array (never string-concatenated on POSIX).
33
+ * @param options - Standard `SpawnOptions` (cwd, env, stdio, detached, …), passed through.
34
+ */
35
+ export function spawnHardened(command, args, options = {}) {
36
+ const resolved = isPathLike(command) ? command : which.sync(command);
37
+ if (!shouldUseShell(resolved)) {
38
+ return spawn(resolved, args, { ...options, shell: false });
39
+ }
40
+ // Windows shell path (.cmd/.bat/.ps1). Use the bare command for a PATH lookup (cmd.exe
41
+ // re-resolves it via PATHEXT); use the quoted resolved path when given an explicit path.
42
+ const shellCommand = isPathLike(command) ? windowsShellQuote(resolved) : command;
43
+ const shellLine = buildWindowsShellLine(shellCommand, args);
44
+ // eslint-disable-next-line sonarjs/os-command -- Windows DEP0190 workaround: command is a PATH-resolved bare name or an explicit path; args are per-arg shell-quoted via windowsShellQuote()
45
+ return spawn(shellLine, { ...options, shell: true });
46
+ }
47
+ //# sourceMappingURL=spawn-hardened.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-hardened.js","sourceRoot":"","sources":["../src/spawn-hardened.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAwC,MAAM,oBAAoB,CAAC;AAEjF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9F;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,qBAAqB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC3F,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,IAAc,EACd,UAAwB,EAAE;IAE1B,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAErE,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,uFAAuF;IACvF,yFAAyF;IACzF,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACjF,MAAM,SAAS,GAAG,qBAAqB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5D,6LAA6L;IAC7L,OAAO,KAAK,CAAC,SAAS,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Windows shell-invocation helpers, shared by every spawn wrapper in this package
3
+ * ({@link ./safe-exec.ts} for the sync `spawnSync` path, {@link ./spawn-hardened.ts}
4
+ * for the async streaming `spawn` path). Extracted so there is exactly ONE Windows
5
+ * `.cmd`/`.bat`/`.ps1` convention across the toolkit — never two subtly-different
6
+ * copies.
7
+ *
8
+ * Background: since the CVE-2024-27980 fix, Node's `child_process.spawn`/`spawnSync`
9
+ * throw `EINVAL` when asked to launch a `.cmd`/`.bat` wrapper without `shell: true`.
10
+ * npm-installed CLIs (`claude`, `npm`, `git` shims, …) resolve to exactly such a
11
+ * wrapper on Windows, so any spawn that omits this handling crashes on Windows only.
12
+ */
13
+ /**
14
+ * Determine if shell should be used for command execution on Windows.
15
+ *
16
+ * ## Security Context
17
+ *
18
+ * This package's primary security model is `shell: false` to prevent command injection.
19
+ * Windows requires `shell: true` only for shell scripts (.cmd/.bat/.ps1) which require
20
+ * a shell interpreter by design (not executable binaries).
21
+ *
22
+ * ## Node.js on Windows - NO SHELL REQUIRED
23
+ *
24
+ * **Previous behavior (REMOVED):** Used shell:true for 'node' command
25
+ * **Problem discovered:** Node.js DEP0190 deprecation warning - passing args array with
26
+ * shell:true leads to incorrect command execution. Exit codes are ignored (always returns 0).
27
+ *
28
+ * **Testing shows:**
29
+ * - ✅ `shell: false` + absolute path from `which.sync('node')` → Works correctly
30
+ * - ❌ `shell: true` + args array → Exit codes ignored, security warning
31
+ *
32
+ * **Root Cause of Previous ENOENT Issues:** Likely resolved in newer Node.js versions.
33
+ * Current testing (Node 20+) shows shell:false works correctly with absolute path.
34
+ *
35
+ * ## Why This Is Secure
36
+ *
37
+ * 1. **Minimal Shell Usage:** Shell only used for .cmd/.bat/.ps1 files (required)
38
+ * 2. **Path Validation:** Command paths resolved via `which.sync()` before execution
39
+ * 3. **Array-Based Arguments:** Arguments passed as array, preventing injection
40
+ * 4. **Controlled Environment:** Commands from trusted configuration, not user input
41
+ * 5. **No String Interpolation:** Never concatenate user input into command strings
42
+ *
43
+ * ## References
44
+ *
45
+ * - Node.js deprecation: https://nodejs.org/api/deprecations.html#DEP0190
46
+ * - Security tests: `packages/utils/test/safe-exec.test.ts`
47
+ * - Windows fix: PR #94 (fix/windows-shell-independence-v2)
48
+ *
49
+ * @param commandPath - Resolved absolute path to command
50
+ * @returns true if shell should be used, false otherwise
51
+ */
52
+ export declare function shouldUseShell(commandPath: string): boolean;
53
+ /**
54
+ * Quote a single argument for a Windows `cmd.exe` command line.
55
+ *
56
+ * Rules:
57
+ * - An arg that's empty, or contains whitespace, quotes, or any of `& | < > ^ ( ) % !`,
58
+ * gets wrapped in double quotes.
59
+ * - Embedded double quotes become `""` (cmd.exe's escape form inside quoted strings).
60
+ *
61
+ * This is narrow on purpose: it's only used when we're forced to assemble a shell string
62
+ * for `.cmd` / `.bat` wrappers on Windows (DEP0190 path). Callers still control what's
63
+ * in `args`, but this keeps a stray space, glob metachar, or paren from getting
64
+ * re-interpreted by the shell.
65
+ */
66
+ export declare function windowsShellQuote(arg: string): string;
67
+ /**
68
+ * Build the single `cmd.exe` command line used when a Windows shim forces shell mode
69
+ * (Node's DEP0190 rejects `shell: true` with a separate args array, so command + args
70
+ * must be one string). `commandToken` is the already-resolved command — a bare PATH
71
+ * name that `cmd.exe` re-resolves via PATHEXT, or a pre-quoted explicit path — and each
72
+ * arg is quoted via {@link windowsShellQuote} so shell metacharacters can't re-interpret.
73
+ */
74
+ export declare function buildWindowsShellLine(commandToken: string, args: string[]): string;
75
+ //# sourceMappingURL=windows-shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-shell.d.ts","sourceRoot":"","sources":["../src/windows-shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAiB3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAElF"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Windows shell-invocation helpers, shared by every spawn wrapper in this package
3
+ * ({@link ./safe-exec.ts} for the sync `spawnSync` path, {@link ./spawn-hardened.ts}
4
+ * for the async streaming `spawn` path). Extracted so there is exactly ONE Windows
5
+ * `.cmd`/`.bat`/`.ps1` convention across the toolkit — never two subtly-different
6
+ * copies.
7
+ *
8
+ * Background: since the CVE-2024-27980 fix, Node's `child_process.spawn`/`spawnSync`
9
+ * throw `EINVAL` when asked to launch a `.cmd`/`.bat` wrapper without `shell: true`.
10
+ * npm-installed CLIs (`claude`, `npm`, `git` shims, …) resolve to exactly such a
11
+ * wrapper on Windows, so any spawn that omits this handling crashes on Windows only.
12
+ */
13
+ /**
14
+ * Determine if shell should be used for command execution on Windows.
15
+ *
16
+ * ## Security Context
17
+ *
18
+ * This package's primary security model is `shell: false` to prevent command injection.
19
+ * Windows requires `shell: true` only for shell scripts (.cmd/.bat/.ps1) which require
20
+ * a shell interpreter by design (not executable binaries).
21
+ *
22
+ * ## Node.js on Windows - NO SHELL REQUIRED
23
+ *
24
+ * **Previous behavior (REMOVED):** Used shell:true for 'node' command
25
+ * **Problem discovered:** Node.js DEP0190 deprecation warning - passing args array with
26
+ * shell:true leads to incorrect command execution. Exit codes are ignored (always returns 0).
27
+ *
28
+ * **Testing shows:**
29
+ * - ✅ `shell: false` + absolute path from `which.sync('node')` → Works correctly
30
+ * - ❌ `shell: true` + args array → Exit codes ignored, security warning
31
+ *
32
+ * **Root Cause of Previous ENOENT Issues:** Likely resolved in newer Node.js versions.
33
+ * Current testing (Node 20+) shows shell:false works correctly with absolute path.
34
+ *
35
+ * ## Why This Is Secure
36
+ *
37
+ * 1. **Minimal Shell Usage:** Shell only used for .cmd/.bat/.ps1 files (required)
38
+ * 2. **Path Validation:** Command paths resolved via `which.sync()` before execution
39
+ * 3. **Array-Based Arguments:** Arguments passed as array, preventing injection
40
+ * 4. **Controlled Environment:** Commands from trusted configuration, not user input
41
+ * 5. **No String Interpolation:** Never concatenate user input into command strings
42
+ *
43
+ * ## References
44
+ *
45
+ * - Node.js deprecation: https://nodejs.org/api/deprecations.html#DEP0190
46
+ * - Security tests: `packages/utils/test/safe-exec.test.ts`
47
+ * - Windows fix: PR #94 (fix/windows-shell-independence-v2)
48
+ *
49
+ * @param commandPath - Resolved absolute path to command
50
+ * @returns true if shell should be used, false otherwise
51
+ */
52
+ export function shouldUseShell(commandPath) {
53
+ if (process.platform !== 'win32') {
54
+ return false;
55
+ }
56
+ // Node.js deprecation warning (DEP0190): Passing args with shell:true leads to incorrect
57
+ // command execution and security vulnerabilities. Testing shows shell:false works correctly
58
+ // with absolute path from which.sync('node') on Windows.
59
+ // Previous ENOENT issues may have been resolved in newer Node.js versions.
60
+ //
61
+ // REMOVED: if (command === 'node') return true;
62
+ // Reason: shell:true causes exit codes to be ignored (always returns 0)
63
+ // Fix: Use shell:false with absolute path - works correctly
64
+ // Windows shell scripts require shell by design (case-insensitive check)
65
+ const lowerPath = commandPath.toLowerCase();
66
+ return lowerPath.endsWith('.cmd') || lowerPath.endsWith('.bat') || lowerPath.endsWith('.ps1');
67
+ }
68
+ /**
69
+ * Quote a single argument for a Windows `cmd.exe` command line.
70
+ *
71
+ * Rules:
72
+ * - An arg that's empty, or contains whitespace, quotes, or any of `& | < > ^ ( ) % !`,
73
+ * gets wrapped in double quotes.
74
+ * - Embedded double quotes become `""` (cmd.exe's escape form inside quoted strings).
75
+ *
76
+ * This is narrow on purpose: it's only used when we're forced to assemble a shell string
77
+ * for `.cmd` / `.bat` wrappers on Windows (DEP0190 path). Callers still control what's
78
+ * in `args`, but this keeps a stray space, glob metachar, or paren from getting
79
+ * re-interpreted by the shell.
80
+ */
81
+ export function windowsShellQuote(arg) {
82
+ if (arg === '' || /["\s&|<>^()%!]/.test(arg)) {
83
+ return `"${arg.replaceAll('"', '""')}"`;
84
+ }
85
+ return arg;
86
+ }
87
+ /**
88
+ * Build the single `cmd.exe` command line used when a Windows shim forces shell mode
89
+ * (Node's DEP0190 rejects `shell: true` with a separate args array, so command + args
90
+ * must be one string). `commandToken` is the already-resolved command — a bare PATH
91
+ * name that `cmd.exe` re-resolves via PATHEXT, or a pre-quoted explicit path — and each
92
+ * arg is quoted via {@link windowsShellQuote} so shell metacharacters can't re-interpret.
93
+ */
94
+ export function buildWindowsShellLine(commandToken, args) {
95
+ return `${commandToken} ${args.map(windowsShellQuote).join(' ')}`;
96
+ }
97
+ //# sourceMappingURL=windows-shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windows-shell.js","sourceRoot":"","sources":["../src/windows-shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yFAAyF;IACzF,4FAA4F;IAC5F,yDAAyD;IACzD,2EAA2E;IAC3E,EAAE;IACF,gDAAgD;IAChD,wEAAwE;IACxE,4DAA4D;IAE5D,yEAAyE;IACzE,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAChG,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,GAAG,KAAK,EAAE,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IAC1C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB,EAAE,IAAc;IACxE,OAAO,GAAG,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACpE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/utils",
3
- "version": "0.1.40",
3
+ "version": "0.1.41-rc.2",
4
4
  "type": "module",
5
5
  "description": "Core utility functions shared across the vibe-agent-toolkit packages",
6
6
  "sideEffects": false,