@vibe-agent-toolkit/utils 0.2.0-rc.1 → 0.2.0-rc.3
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/README.md +6 -3
- package/dist/compare-code-units.d.ts +28 -0
- package/dist/compare-code-units.d.ts.map +1 -0
- package/dist/compare-code-units.js +33 -0
- package/dist/compare-code-units.js.map +1 -0
- package/dist/crawl-timing.d.ts +680 -0
- package/dist/crawl-timing.d.ts.map +1 -0
- package/dist/crawl-timing.js +809 -0
- package/dist/crawl-timing.js.map +1 -0
- package/dist/file-crawler.d.ts +22 -0
- package/dist/file-crawler.d.ts.map +1 -1
- package/dist/file-crawler.js +31 -7
- package/dist/file-crawler.js.map +1 -1
- package/dist/fs-utils.d.ts +17 -0
- package/dist/fs-utils.d.ts.map +1 -1
- package/dist/fs-utils.js +69 -0
- package/dist/fs-utils.js.map +1 -1
- package/dist/fs.d.ts +3 -1
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +5 -1
- package/dist/fs.js.map +1 -1
- package/dist/git-run.d.ts +167 -0
- package/dist/git-run.d.ts.map +1 -0
- package/dist/git-run.js +154 -0
- package/dist/git-run.js.map +1 -0
- package/dist/git-snapshot.d.ts +181 -0
- package/dist/git-snapshot.d.ts.map +1 -0
- package/dist/git-snapshot.js +232 -0
- package/dist/git-snapshot.js.map +1 -0
- package/dist/git-tracker.d.ts +94 -1
- package/dist/git-tracker.d.ts.map +1 -1
- package/dist/git-tracker.js +135 -3
- package/dist/git-tracker.js.map +1 -1
- package/dist/git-utils.d.ts +38 -0
- package/dist/git-utils.d.ts.map +1 -1
- package/dist/git-utils.js +103 -80
- package/dist/git-utils.js.map +1 -1
- package/dist/git.d.ts +2 -1
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +2 -1
- package/dist/git.js.map +1 -1
- package/dist/gitignore-checker.d.ts.map +1 -1
- package/dist/gitignore-checker.js +6 -3
- package/dist/gitignore-checker.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -1
- package/dist/index.js.map +1 -1
- package/dist/link-auth/expand-macro.d.ts.map +1 -1
- package/dist/link-auth/expand-macro.js +7 -1
- package/dist/link-auth/expand-macro.js.map +1 -1
- package/dist/link-auth/resolve-token.d.ts.map +1 -1
- package/dist/link-auth/resolve-token.js +15 -1
- package/dist/link-auth/resolve-token.js.map +1 -1
- package/dist/path-core.d.ts +1 -1
- package/dist/path-core.js +1 -1
- package/dist/project-utils.d.ts.map +1 -1
- package/dist/project-utils.js +6 -3
- package/dist/project-utils.js.map +1 -1
- package/dist/safe-exec.d.ts +38 -10
- package/dist/safe-exec.d.ts.map +1 -1
- package/dist/safe-exec.js +88 -19
- package/dist/safe-exec.js.map +1 -1
- package/dist/skill-test/index.d.ts +1 -1
- package/dist/skill-test/index.d.ts.map +1 -1
- package/dist/skill-test/index.js +1 -1
- package/dist/skill-test/index.js.map +1 -1
- package/dist/skill-test/spawn-claude.d.ts +28 -0
- package/dist/skill-test/spawn-claude.d.ts.map +1 -1
- package/dist/skill-test/spawn-claude.js +51 -2
- package/dist/skill-test/spawn-claude.js.map +1 -1
- package/dist/skill-test/transcript.d.ts +41 -2
- package/dist/skill-test/transcript.d.ts.map +1 -1
- package/dist/skill-test/transcript.js +47 -3
- package/dist/skill-test/transcript.js.map +1 -1
- package/dist/test-helpers.d.ts +185 -13
- package/dist/test-helpers.d.ts.map +1 -1
- package/dist/test-helpers.js +274 -27
- package/dist/test-helpers.js.map +1 -1
- package/dist/text-content.d.ts +197 -0
- package/dist/text-content.d.ts.map +1 -0
- package/dist/text-content.js +348 -0
- package/dist/text-content.js.map +1 -0
- package/dist/text-file.d.ts +45 -0
- package/dist/text-file.d.ts.map +1 -0
- package/dist/text-file.js +53 -0
- package/dist/text-file.js.map +1 -0
- package/dist/text.d.ts +16 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +16 -0
- package/dist/text.js.map +1 -0
- package/dist/timing-dump.d.ts +119 -0
- package/dist/timing-dump.d.ts.map +1 -0
- package/dist/timing-dump.js +164 -0
- package/dist/timing-dump.js.map +1 -0
- package/eslint/README.md +105 -3
- package/eslint/index.cjs +41 -0
- package/eslint/index.d.cts +7 -4
- package/eslint/rules/no-bare-symlink-in-tests.cjs +200 -0
- package/eslint/rules/no-raw-text-decode.cjs +296 -0
- package/eslint/rules/no-self-package-import.cjs +157 -0
- package/package.json +9 -2
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 { runGit } from './git-run.js';
|
|
3
4
|
import { buildWindowsShellLine, resolveShellCommandToken, shouldUseShell, } from './windows-shell.js';
|
|
4
5
|
/**
|
|
5
6
|
* Error thrown when command execution fails
|
|
@@ -16,6 +17,38 @@ export class CommandExecutionError extends Error {
|
|
|
16
17
|
this.stderr = stderr;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Refuse `git` here, and say where it belongs.
|
|
22
|
+
*
|
|
23
|
+
* "Safe" in this module's name has always meant *shell-injection*-safe: PATH
|
|
24
|
+
* resolved once, no shell interpreter. It says nothing about the environment,
|
|
25
|
+
* and `git` is the one command for which the environment silently decides which
|
|
26
|
+
* repository the answer describes — `GIT_DIR` and `GIT_INDEX_FILE`, exported
|
|
27
|
+
* into every child of a `git` hook, override the `cwd` passed here. The failure
|
|
28
|
+
* is a well-formed answer about the wrong repository at exit 0, so no caller
|
|
29
|
+
* discovers it by testing.
|
|
30
|
+
*
|
|
31
|
+
* A refusal rather than a silent scrub, because the two meanings are not
|
|
32
|
+
* interchangeable: only the caller knows whether it means the path it passed or
|
|
33
|
+
* the repository it stands in, and guessing on their behalf would be wrong half
|
|
34
|
+
* the time in a way nothing reports. {@link runGit} makes them say.
|
|
35
|
+
*
|
|
36
|
+
* @param command - The command about to be spawned
|
|
37
|
+
* @throws {Error} When the command is git
|
|
38
|
+
*/
|
|
39
|
+
function isGitCommand(command) {
|
|
40
|
+
const name = command.toLowerCase().replace(/\.(exe|cmd)$/, '');
|
|
41
|
+
return name === 'git' || name.endsWith('/git') || name.endsWith(String.raw `\git`);
|
|
42
|
+
}
|
|
43
|
+
function refuseGit(command) {
|
|
44
|
+
if (!isGitCommand(command))
|
|
45
|
+
return;
|
|
46
|
+
throw new Error('Use runGit() from @vibe-agent-toolkit/utils to run git, not safeExecSync/safeExecResult.\n' +
|
|
47
|
+
" runGit(args, { cwd }) — about a path you were handed (scrubs the inherited\n" +
|
|
48
|
+
' GIT_DIR/GIT_INDEX_FILE that would override cwd)\n' +
|
|
49
|
+
' runGit(args, { ambient: true }) — about the repository this process stands in\n' +
|
|
50
|
+
'Inside a git hook the difference decides which repository you read — or write.');
|
|
51
|
+
}
|
|
19
52
|
/**
|
|
20
53
|
* Resolve command, build spawn options, and execute via spawnSync.
|
|
21
54
|
*
|
|
@@ -31,6 +64,8 @@ export class CommandExecutionError extends Error {
|
|
|
31
64
|
* value. Passing the raw command here used to break silently on `C:\Program Files\…`.
|
|
32
65
|
*/
|
|
33
66
|
function resolveAndSpawn(command, args, options) {
|
|
67
|
+
if (options.allowGit !== true)
|
|
68
|
+
refuseGit(command);
|
|
34
69
|
const commandPath = which.sync(command);
|
|
35
70
|
const useShell = shouldUseShell(commandPath);
|
|
36
71
|
const spawnOptions = {
|
|
@@ -56,7 +91,11 @@ function resolveAndSpawn(command, args, options) {
|
|
|
56
91
|
* - Resolves PATH once using pure Node.js (which package)
|
|
57
92
|
* - Executes with absolute path and shell: false
|
|
58
93
|
* - No shell interpreter = no command injection risk
|
|
59
|
-
* - Supports custom env vars
|
|
94
|
+
* - Supports custom env vars
|
|
95
|
+
*
|
|
96
|
+
* ⛔ **Not for `git`** — it throws. "Safe" here means shell-injection-safe and
|
|
97
|
+
* says nothing about `GIT_DIR`/`GIT_INDEX_FILE`, which silently decide which
|
|
98
|
+
* repository a git command answers about. Use `runGit()`.
|
|
60
99
|
*
|
|
61
100
|
* @param command - Command name (e.g., 'git', 'gitleaks', 'node')
|
|
62
101
|
* @param args - Array of arguments
|
|
@@ -69,14 +108,11 @@ function resolveAndSpawn(command, args, options) {
|
|
|
69
108
|
* safeExecSync('gitleaks', ['--version'], { stdio: 'ignore' });
|
|
70
109
|
*
|
|
71
110
|
* @example
|
|
72
|
-
* // Git with custom env
|
|
73
|
-
* safeExecSync('git', ['add', '--all'], {
|
|
74
|
-
* env: { ...process.env, GIT_INDEX_FILE: tempFile }
|
|
75
|
-
* });
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
111
|
* // Get output as string
|
|
79
112
|
* const version = safeExecSync('node', ['--version'], { encoding: 'utf8' });
|
|
113
|
+
*
|
|
114
|
+
* @throws {Error} When `command` is git — use `runGit()` instead, which owns the
|
|
115
|
+
* inherited-environment problem this helper cannot see
|
|
80
116
|
*/
|
|
81
117
|
export function safeExecSync(command, args = [], options = {}) {
|
|
82
118
|
const result = resolveAndSpawn(command, args, options);
|
|
@@ -102,14 +138,22 @@ export function safeExecSync(command, args = [], options = {}) {
|
|
|
102
138
|
* @returns Detailed execution result
|
|
103
139
|
*
|
|
104
140
|
* @example
|
|
105
|
-
* const result = safeExecResult('
|
|
141
|
+
* const result = safeExecResult('gh', ['pr', 'list']);
|
|
106
142
|
* if (result.success) {
|
|
107
143
|
* console.log(result.stdout.toString());
|
|
108
144
|
* } else {
|
|
109
145
|
* console.error(`Failed: ${result.stderr.toString()}`);
|
|
110
146
|
* }
|
|
147
|
+
*
|
|
148
|
+
* @throws {Error} When `command` is git — use `runGit()` instead
|
|
111
149
|
*/
|
|
112
150
|
export function safeExecResult(command, args = [], options = {}) {
|
|
151
|
+
// Deliberately OUTSIDE the try: this is a programming error to fix at the call
|
|
152
|
+
// site, not a command that failed. Folded into the result it would read as
|
|
153
|
+
// "git is unavailable" and callers that treat a failure as information — most
|
|
154
|
+
// of them — would carry on silently.
|
|
155
|
+
if (options.allowGit !== true)
|
|
156
|
+
refuseGit(command);
|
|
113
157
|
try {
|
|
114
158
|
const result = resolveAndSpawn(command, args, options);
|
|
115
159
|
const status = result.status ?? -1;
|
|
@@ -148,6 +192,8 @@ export function safeExecResult(command, args = [], options = {}) {
|
|
|
148
192
|
* }
|
|
149
193
|
*/
|
|
150
194
|
export function isToolAvailable(toolName) {
|
|
195
|
+
if (isGitCommand(toolName))
|
|
196
|
+
return probeVersion(toolName, '--version') !== null;
|
|
151
197
|
try {
|
|
152
198
|
safeExecSync(toolName, ['--version'], { stdio: 'ignore' });
|
|
153
199
|
return true;
|
|
@@ -156,6 +202,36 @@ export function isToolAvailable(toolName) {
|
|
|
156
202
|
return false;
|
|
157
203
|
}
|
|
158
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Ask a binary its version, routing `git` around {@link refuseGit}.
|
|
207
|
+
*
|
|
208
|
+
* A version probe names the *executable*, never a repository, so the refusal
|
|
209
|
+
* would be a false negative here — and a silent one, because both callers below
|
|
210
|
+
* report "not installed" for a null. `vat doctor` did exactly that: correct
|
|
211
|
+
* `git`, reported missing. {@link runGit} is the sanctioned path regardless.
|
|
212
|
+
*
|
|
213
|
+
* @param toolName - Binary to ask
|
|
214
|
+
* @param versionArg - Argument that makes it print its version
|
|
215
|
+
* @returns Trimmed version string, or null when the tool is genuinely absent
|
|
216
|
+
*/
|
|
217
|
+
function probeVersion(toolName, versionArg) {
|
|
218
|
+
if (isGitCommand(toolName)) {
|
|
219
|
+
// The scrub is a no-op for a command that reads nothing; keeping the safe
|
|
220
|
+
// default means no call site here has to reason about it.
|
|
221
|
+
const result = runGit([versionArg]);
|
|
222
|
+
return result.ok ? result.stdout : null;
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
const version = safeExecSync(toolName, [versionArg], {
|
|
226
|
+
encoding: 'utf8',
|
|
227
|
+
stdio: 'pipe',
|
|
228
|
+
});
|
|
229
|
+
return version.trim();
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
159
235
|
/**
|
|
160
236
|
* Get tool version if available
|
|
161
237
|
*
|
|
@@ -172,16 +248,7 @@ export function isToolAvailable(toolName) {
|
|
|
172
248
|
* console.log(gitVersion); // "git version 2.39.2"
|
|
173
249
|
*/
|
|
174
250
|
export function getToolVersion(toolName, versionArg = '--version') {
|
|
175
|
-
|
|
176
|
-
const version = safeExecSync(toolName, [versionArg], {
|
|
177
|
-
encoding: 'utf8',
|
|
178
|
-
stdio: 'pipe',
|
|
179
|
-
});
|
|
180
|
-
return version.trim();
|
|
181
|
-
}
|
|
182
|
-
catch {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
251
|
+
return probeVersion(toolName, versionArg);
|
|
185
252
|
}
|
|
186
253
|
/**
|
|
187
254
|
* Shell syntax character sets for hyper-efficient single-pass detection
|
|
@@ -301,9 +368,11 @@ export function hasShellSyntax(commandString) {
|
|
|
301
368
|
* @example
|
|
302
369
|
* ```typescript
|
|
303
370
|
* // ✅ Simple commands (these work)
|
|
304
|
-
* safeExecFromString('git status');
|
|
305
371
|
* safeExecFromString('pnpm test --watch');
|
|
306
372
|
* safeExecFromString('gh pr view 123');
|
|
373
|
+
*
|
|
374
|
+
* // ❌ git is refused here too — the string form is not a back door around
|
|
375
|
+
* // the chokepoint. Use runGit(['status'], { cwd }).
|
|
307
376
|
* ```
|
|
308
377
|
*
|
|
309
378
|
* @example
|
package/dist/safe-exec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-exec.js","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,cAAc,GACf,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"safe-exec.js","sourceRoot":"","sources":["../src/safe-exec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, protectedEnvNames, type DeclaredEnvInput, type DeclaredEnvResult, type ForwardEnvOptions, } from './env-scrub.js';
|
|
1
|
+
export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, isProtectedName, 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
3
|
export { assembleClaudeArgs, killAllActiveClaudeChildren, spawnHeadlessClaude, type ClaudeSpawnArgs, type SpawnHeadlessOptions, type SpawnResult, } from './spawn-claude.js';
|
|
4
4
|
export { detectInvocationFromTranscript, parseStreamJsonTranscript, type ParsedTranscript, } from './transcript.js';
|
|
@@ -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,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
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skill-test/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,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"}
|
package/dist/skill-test/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, protectedEnvNames, } from './env-scrub.js';
|
|
1
|
+
export { applyDeclaredEnv, buildForwardedEnv, formatForwardedEnvLine, isProtectedName, protectedEnvNames, } from './env-scrub.js';
|
|
2
2
|
export { AuthPreflightError, probeAuthStatus, resolveAuth, } from './auth-resolver.js';
|
|
3
3
|
export { assembleClaudeArgs, killAllActiveClaudeChildren, spawnHeadlessClaude, } from './spawn-claude.js';
|
|
4
4
|
export { detectInvocationFromTranscript, parseStreamJsonTranscript, } from './transcript.js';
|
|
@@ -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,2BAA2B,EAC3B,mBAAmB,GAIpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,GAE1B,MAAM,iBAAiB,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,eAAe,EACf,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"}
|
|
@@ -11,6 +11,34 @@ export interface ClaudeSpawnArgs {
|
|
|
11
11
|
* `--prompt-file` flag — the prompt is fed to the child's stdin by
|
|
12
12
|
* {@link spawnHeadlessClaude} instead. `--setting-sources ""` suppresses
|
|
13
13
|
* user/project settings; built-in skills remain (§5).
|
|
14
|
+
*
|
|
15
|
+
* `--no-session-persistence` is load-bearing for the harness's integrity model,
|
|
16
|
+
* not a tidiness flag. Claude Code otherwise writes every headless session to
|
|
17
|
+
* `$CLAUDE_CONFIG_DIR/projects/<cwd-slug>/<uuid>.jsonl` — plaintext, mode 0600,
|
|
18
|
+
* retained indefinitely — and `CLAUDE_CONFIG_DIR` and `HOME` are both forwarded
|
|
19
|
+
* to the child (they have to be: that is where auth lives). That file falsifies
|
|
20
|
+
* three of the harness's stated guarantees at once:
|
|
21
|
+
*
|
|
22
|
+
* - the per-run grading NONCE, which {@link SpawnHeadlessOptions.prompt} keeps
|
|
23
|
+
* off disk precisely so untrusted skill code cannot read it back and forge a
|
|
24
|
+
* passing grading.json — the grader's own session file contains it verbatim;
|
|
25
|
+
* - the eval ANSWER KEY (`expected_output`), which `eval-suite-isolation.ts`
|
|
26
|
+
* exists solely to keep off the executor's filesystem;
|
|
27
|
+
* - the `--baseline` control, which could read the treatment arm's entire
|
|
28
|
+
* session by listing `projects/` for its slug.
|
|
29
|
+
*
|
|
30
|
+
* And it leaks ACROSS runs: a transcript from one run is still readable weeks
|
|
31
|
+
* later by the next run's executor, so no per-run randomness helps.
|
|
32
|
+
*
|
|
33
|
+
* VERIFIED on macOS with claude 2.x, both directions: without the flag one
|
|
34
|
+
* `.jsonl` lands under the config dir per spawn; with it, zero, and the session
|
|
35
|
+
* still authenticates. It is `--print`-only, which is exactly this spawn's shape.
|
|
36
|
+
*
|
|
37
|
+
* 🪤 An ephemeral per-spawn `CLAUDE_CONFIG_DIR` — the obvious alternative — does
|
|
38
|
+
* NOT work: on macOS the subscription credential is a Keychain item whose service
|
|
39
|
+
* name is derived from the config-dir PATH, so a fresh dir reports "Not logged
|
|
40
|
+
* in" even with the real `.claude.json` copied in (verified). Materializing the
|
|
41
|
+
* token into a dir the executor can read would be strictly worse than the leak.
|
|
14
42
|
*/
|
|
15
43
|
export declare function assembleClaudeArgs(opts: ClaudeSpawnArgs): string[];
|
|
16
44
|
export interface SpawnResult {
|
|
@@ -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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,EAAE,CAoBlE;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,CA8G1F"}
|
|
@@ -7,6 +7,34 @@ import { spawnHardened } from '../spawn-hardened.js';
|
|
|
7
7
|
* `--prompt-file` flag — the prompt is fed to the child's stdin by
|
|
8
8
|
* {@link spawnHeadlessClaude} instead. `--setting-sources ""` suppresses
|
|
9
9
|
* user/project settings; built-in skills remain (§5).
|
|
10
|
+
*
|
|
11
|
+
* `--no-session-persistence` is load-bearing for the harness's integrity model,
|
|
12
|
+
* not a tidiness flag. Claude Code otherwise writes every headless session to
|
|
13
|
+
* `$CLAUDE_CONFIG_DIR/projects/<cwd-slug>/<uuid>.jsonl` — plaintext, mode 0600,
|
|
14
|
+
* retained indefinitely — and `CLAUDE_CONFIG_DIR` and `HOME` are both forwarded
|
|
15
|
+
* to the child (they have to be: that is where auth lives). That file falsifies
|
|
16
|
+
* three of the harness's stated guarantees at once:
|
|
17
|
+
*
|
|
18
|
+
* - the per-run grading NONCE, which {@link SpawnHeadlessOptions.prompt} keeps
|
|
19
|
+
* off disk precisely so untrusted skill code cannot read it back and forge a
|
|
20
|
+
* passing grading.json — the grader's own session file contains it verbatim;
|
|
21
|
+
* - the eval ANSWER KEY (`expected_output`), which `eval-suite-isolation.ts`
|
|
22
|
+
* exists solely to keep off the executor's filesystem;
|
|
23
|
+
* - the `--baseline` control, which could read the treatment arm's entire
|
|
24
|
+
* session by listing `projects/` for its slug.
|
|
25
|
+
*
|
|
26
|
+
* And it leaks ACROSS runs: a transcript from one run is still readable weeks
|
|
27
|
+
* later by the next run's executor, so no per-run randomness helps.
|
|
28
|
+
*
|
|
29
|
+
* VERIFIED on macOS with claude 2.x, both directions: without the flag one
|
|
30
|
+
* `.jsonl` lands under the config dir per spawn; with it, zero, and the session
|
|
31
|
+
* still authenticates. It is `--print`-only, which is exactly this spawn's shape.
|
|
32
|
+
*
|
|
33
|
+
* 🪤 An ephemeral per-spawn `CLAUDE_CONFIG_DIR` — the obvious alternative — does
|
|
34
|
+
* NOT work: on macOS the subscription credential is a Keychain item whose service
|
|
35
|
+
* name is derived from the config-dir PATH, so a fresh dir reports "Not logged
|
|
36
|
+
* in" even with the real `.claude.json` copied in (verified). Materializing the
|
|
37
|
+
* token into a dir the executor can read would be strictly worse than the leak.
|
|
10
38
|
*/
|
|
11
39
|
export function assembleClaudeArgs(opts) {
|
|
12
40
|
const args = [
|
|
@@ -17,6 +45,7 @@ export function assembleClaudeArgs(opts) {
|
|
|
17
45
|
'--output-format', 'stream-json',
|
|
18
46
|
'--verbose',
|
|
19
47
|
'--setting-sources', '',
|
|
48
|
+
'--no-session-persistence',
|
|
20
49
|
'--permission-mode', 'bypassPermissions',
|
|
21
50
|
'--add-dir', opts.sandboxDir,
|
|
22
51
|
];
|
|
@@ -119,6 +148,24 @@ export async function spawnHeadlessClaude(opts) {
|
|
|
119
148
|
// Register immediately after spawn so the child is reapable by
|
|
120
149
|
// killAllActiveClaudeChildren() for the entire time it can be in flight.
|
|
121
150
|
activeClaudeChildren.add(child);
|
|
151
|
+
// Decode BOTH output streams as UTF-8 at the stream, not per chunk.
|
|
152
|
+
//
|
|
153
|
+
// A pipe hands the reader whatever bytes have arrived (typically capped at
|
|
154
|
+
// 64 KiB) with no regard for character boundaries, so `chunk.toString()` on
|
|
155
|
+
// each Buffer independently mangles any multi-byte character that straddles a
|
|
156
|
+
// boundary into replacement characters on both sides of the split. That
|
|
157
|
+
// corruption lands INSIDE a stream-json line, and it costs the harness
|
|
158
|
+
// evidence two ways: the line can stop parsing, silently deleting the tool
|
|
159
|
+
// call in it (see ParsedTranscript.malformedLineCount), or — worse, because
|
|
160
|
+
// nothing reports it — the line still parses with a mangled VALUE, so a
|
|
161
|
+
// contamination needle no longer matches the path the arm actually reached.
|
|
162
|
+
//
|
|
163
|
+
// `setEncoding` runs the stream's own StringDecoder, which holds a partial
|
|
164
|
+
// sequence back until the rest arrives AND flushes whatever is left at EOF, so
|
|
165
|
+
// a genuinely truncated tail still surfaces (as U+FFFD) rather than vanishing.
|
|
166
|
+
// Set before any listener is attached, so no chunk is ever seen undecoded.
|
|
167
|
+
child.stdout.setEncoding('utf8');
|
|
168
|
+
child.stderr.setEncoding('utf8');
|
|
122
169
|
let timedOut = false;
|
|
123
170
|
let stalled = false;
|
|
124
171
|
// Feed the prompt to the child via stdin (claude 2.x has no --prompt-file).
|
|
@@ -170,8 +217,10 @@ export async function spawnHeadlessClaude(opts) {
|
|
|
170
217
|
// child's real exit status).
|
|
171
218
|
child.stdin.on('error', () => { });
|
|
172
219
|
promptStream.pipe(child.stdin);
|
|
173
|
-
|
|
174
|
-
|
|
220
|
+
// `d` is already a string: setEncoding('utf8') above put the stream's
|
|
221
|
+
// StringDecoder in front of these listeners. Never call `.toString()` here.
|
|
222
|
+
child.stdout.on('data', (d) => { opts.onStdout?.(d); });
|
|
223
|
+
child.stderr.on('data', (d) => { opts.onStderr?.(d); });
|
|
175
224
|
// Reap on 'error' too: clearAllTimers() unregisters the child, so if 'error'
|
|
176
225
|
// ever fires while the process is actually alive we would otherwise drop it
|
|
177
226
|
// from the reap set without killing it (the exact orphan this file guards
|
|
@@ -1 +1 @@
|
|
|
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
|
|
1
|
+
{"version":3,"file":"spawn-claude.js","sourceRoot":"","sources":["../../src/skill-test/spawn-claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* The stream-json schema is informally documented and may shift between
|
|
7
7
|
* Claude Code releases. This parser is intentionally tolerant of unknown
|
|
8
|
-
* event kinds —
|
|
8
|
+
* event kinds — an event whose `type` we do not recognise is simply not
|
|
9
|
+
* consumed. Tolerance stops at unknown SHAPES: a line that is not JSON at all is
|
|
10
|
+
* counted into {@link ParsedTranscript.malformedLineCount}, because that is data
|
|
11
|
+
* loss, not forward compatibility.
|
|
9
12
|
*
|
|
10
13
|
* Shape notes (empirically verified):
|
|
11
14
|
* - `tool_use` content blocks carry `input.command` for Bash calls.
|
|
@@ -23,11 +26,40 @@ export interface ParsedTranscript {
|
|
|
23
26
|
inputSummary: string;
|
|
24
27
|
}>;
|
|
25
28
|
errors: string[];
|
|
26
|
-
|
|
29
|
+
/**
|
|
30
|
+
* How many non-empty lines failed `JSON.parse` and were therefore NOT consumed.
|
|
31
|
+
*
|
|
32
|
+
* This is the only thing that distinguishes "parsed fine, nothing found" from
|
|
33
|
+
* "we lost the evidence". A corrupted line drops its whole event — the tool call
|
|
34
|
+
* in it, and any contamination it proves — while every other line, including the
|
|
35
|
+
* terminal `result`, still parses. Every downstream "did this transcript decode?"
|
|
36
|
+
* test is an any-of over the populated fields, so the surviving `result` line on
|
|
37
|
+
* its own certifies the transcript as decoded and the loss goes unremarked.
|
|
38
|
+
*
|
|
39
|
+
* Non-zero means the scan that consumed this transcript ran on less than the
|
|
40
|
+
* whole transcript and its verdict must be reported as DEGRADED, never clean.
|
|
41
|
+
* Zero is a positive statement, not an absence: every line was accounted for.
|
|
42
|
+
*/
|
|
43
|
+
malformedLineCount: number;
|
|
27
44
|
toolUses: Array<{
|
|
28
45
|
id: string | null;
|
|
29
46
|
name: string;
|
|
30
47
|
command?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The FULL, unsummarized tool input.
|
|
50
|
+
*
|
|
51
|
+
* `inputSummary` beside it is truncated to 200 characters by
|
|
52
|
+
* {@link summarizeValue}, which is fine for an observation record a human
|
|
53
|
+
* skims and useless for anything that has to REASON about what the call did
|
|
54
|
+
* — a path 200 characters into a `Read` input simply is not there. The
|
|
55
|
+
* baseline-integrity detector walks tool inputs to decide whether the
|
|
56
|
+
* skill-absent arm reached the skill, so it needs the whole value; the
|
|
57
|
+
* summary stays for the consumers that only ever display it.
|
|
58
|
+
*
|
|
59
|
+
* `unknown` because the shape is per-tool and informally documented — every
|
|
60
|
+
* consumer narrows it itself rather than trusting a type we invented.
|
|
61
|
+
*/
|
|
62
|
+
input: unknown;
|
|
31
63
|
inputSummary: string;
|
|
32
64
|
parentToolUseId: string | null;
|
|
33
65
|
}>;
|
|
@@ -35,6 +67,13 @@ export interface ParsedTranscript {
|
|
|
35
67
|
toolUseId: string | null;
|
|
36
68
|
isError: boolean;
|
|
37
69
|
contentSummary: string;
|
|
70
|
+
/**
|
|
71
|
+
* The FULL tool result, flattened to text. Same reason as `input` above:
|
|
72
|
+
* `contentSummary` is truncated to 200 characters, so scanning a tool RESULT
|
|
73
|
+
* for evidence (a file's contents echoed back, a grep hit line) cannot be
|
|
74
|
+
* done through it. Never truncated — the caller bounds what it keeps.
|
|
75
|
+
*/
|
|
76
|
+
content: string;
|
|
38
77
|
}>;
|
|
39
78
|
result?: {
|
|
40
79
|
subtype?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;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;;;;;;;;;;;;;OAaG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB;;;;;;;;;;;;;WAaG;QACH,KAAK,EAAE,OAAO,CAAC;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC,CAAC;IACH,WAAW,EAAE,KAAK,CAAC;QACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB;;;;;WAKG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,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;AA+JD,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,GAAG,gBAAgB,CA+B9E;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,gBAAgB,EACxB,iBAAiB,EAAE,SAAS,MAAM,EAAE,GACnC,OAAO,CAOT"}
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* The stream-json schema is informally documented and may shift between
|
|
7
7
|
* Claude Code releases. This parser is intentionally tolerant of unknown
|
|
8
|
-
* event kinds —
|
|
8
|
+
* event kinds — an event whose `type` we do not recognise is simply not
|
|
9
|
+
* consumed. Tolerance stops at unknown SHAPES: a line that is not JSON at all is
|
|
10
|
+
* counted into {@link ParsedTranscript.malformedLineCount}, because that is data
|
|
11
|
+
* loss, not forward compatibility.
|
|
9
12
|
*
|
|
10
13
|
* Shape notes (empirically verified):
|
|
11
14
|
* - `tool_use` content blocks carry `input.command` for Bash calls.
|
|
@@ -25,6 +28,42 @@ function summarizeValue(value) {
|
|
|
25
28
|
return '<unserializable>';
|
|
26
29
|
}
|
|
27
30
|
}
|
|
31
|
+
function stringifyValue(value) {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.stringify(value) ?? '';
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return '<unserializable>';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Flatten a `tool_result` `content` field to plain text, WITHOUT truncating.
|
|
41
|
+
*
|
|
42
|
+
* Three shapes occur in practice: a bare string (most Bash results), an array of
|
|
43
|
+
* content blocks (`{type:'text',text}` and friends), and — for a tool that
|
|
44
|
+
* returns structured data — an arbitrary object. The array case is the one that
|
|
45
|
+
* matters: `JSON.stringify` of it would bury the text behind escaped quotes, and
|
|
46
|
+
* a consumer scanning for a verbatim sentence would never find it.
|
|
47
|
+
*/
|
|
48
|
+
function contentToText(value) {
|
|
49
|
+
if (typeof value === 'string')
|
|
50
|
+
return value;
|
|
51
|
+
if (Array.isArray(value))
|
|
52
|
+
return value.map((block) => contentBlockToText(block)).join('\n');
|
|
53
|
+
if (value === undefined || value === null)
|
|
54
|
+
return '';
|
|
55
|
+
return stringifyValue(value);
|
|
56
|
+
}
|
|
57
|
+
function contentBlockToText(block) {
|
|
58
|
+
if (typeof block === 'string')
|
|
59
|
+
return block;
|
|
60
|
+
if (block !== null && typeof block === 'object') {
|
|
61
|
+
const { text } = block;
|
|
62
|
+
if (typeof text === 'string')
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
return stringifyValue(block);
|
|
66
|
+
}
|
|
28
67
|
function extractCommand(input) {
|
|
29
68
|
if (input !== null && typeof input === 'object' && typeof input.command === 'string') {
|
|
30
69
|
return input.command;
|
|
@@ -44,6 +83,7 @@ function consumeAssistantBlocks(blocks, parentToolUseId, out) {
|
|
|
44
83
|
id: typeof block.id === 'string' ? block.id : null,
|
|
45
84
|
name: block.name,
|
|
46
85
|
...(command === undefined ? {} : { command }),
|
|
86
|
+
input: block.input,
|
|
47
87
|
inputSummary,
|
|
48
88
|
parentToolUseId,
|
|
49
89
|
});
|
|
@@ -57,6 +97,7 @@ function consumeUserBlocks(blocks, out) {
|
|
|
57
97
|
toolUseId: typeof block.tool_use_id === 'string' ? block.tool_use_id : null,
|
|
58
98
|
isError: block.is_error === true,
|
|
59
99
|
contentSummary: summarizeValue(block.content),
|
|
100
|
+
content: contentToText(block.content),
|
|
60
101
|
});
|
|
61
102
|
}
|
|
62
103
|
}
|
|
@@ -114,22 +155,25 @@ export function parseStreamJsonTranscript(streamText) {
|
|
|
114
155
|
text: '',
|
|
115
156
|
toolUseEvents: [],
|
|
116
157
|
errors: [],
|
|
117
|
-
raw: [],
|
|
118
158
|
toolUses: [],
|
|
119
159
|
toolResults: [],
|
|
120
160
|
rateLimited: false,
|
|
161
|
+
malformedLineCount: 0,
|
|
121
162
|
};
|
|
122
163
|
const lines = streamText.split('\n');
|
|
123
164
|
for (const line of lines) {
|
|
124
165
|
const trimmed = line.trim();
|
|
125
166
|
if (trimmed.length === 0)
|
|
126
167
|
continue;
|
|
127
|
-
out.raw.push(trimmed);
|
|
128
168
|
let parsed;
|
|
129
169
|
try {
|
|
130
170
|
parsed = JSON.parse(trimmed);
|
|
131
171
|
}
|
|
132
172
|
catch {
|
|
173
|
+
// Counted, not thrown on, and never pushed into `errors`: `errors` reports
|
|
174
|
+
// what the AGENT hit, this reports what the PARSER lost. Conflating them
|
|
175
|
+
// would make a harness defect look like a run failure and vice versa.
|
|
176
|
+
out.malformedLineCount += 1;
|
|
133
177
|
continue;
|
|
134
178
|
}
|
|
135
179
|
applyEvent(parsed, out);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/skill-test/transcript.ts"],"names":[],"mappings":"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"}
|