@codeledger/harness 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,443 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { execFileSync } from 'node:child_process';
3
+ import { join } from 'node:path';
4
+ import { LedgerStore } from '@codeledger/core';
5
+ import { buildBundleViaEngine } from '@codeledger/core-engine';
6
+ import { runPreflight, validatePreflight, getHeadCommit, execCommand, RunRecorder, } from '@codeledger/instrument';
7
+ import { GenericAdapter } from './adapters/generic.js';
8
+ import { GuidedAdapter } from './adapters/guided.js';
9
+ import { injectIntoPrompt, renderBundleMarkdown } from './injection.js';
10
+ import { createWorktree, cleanupAllWorktrees } from './worktree.js';
11
+ // ─── Signal-safe worktree cleanup ──────────────────────────────────────────
12
+ // When a SIGINT/SIGTERM arrives mid-run we need synchronous cleanup because
13
+ // Node won't await async work in signal handlers. The worktree cleanup
14
+ // closure only does execFileSync internally so a sync wrapper is safe here.
15
+ let activeCleanup = null;
16
+ function signalCleanupHandler(signal) {
17
+ if (activeCleanup) {
18
+ try {
19
+ activeCleanup();
20
+ }
21
+ catch {
22
+ // Best effort — process is exiting anyway
23
+ }
24
+ activeCleanup = null;
25
+ }
26
+ // Re-raise so the default handler fires (correct exit code for callers)
27
+ process.kill(process.pid, signal);
28
+ }
29
+ let signalHandlersInstalled = false;
30
+ function installSignalHandlers() {
31
+ if (signalHandlersInstalled)
32
+ return;
33
+ signalHandlersInstalled = true;
34
+ process.once('SIGINT', signalCleanupHandler);
35
+ process.once('SIGTERM', signalCleanupHandler);
36
+ }
37
+ function removeSignalHandlers() {
38
+ if (!signalHandlersInstalled)
39
+ return;
40
+ signalHandlersInstalled = false;
41
+ process.removeListener('SIGINT', signalCleanupHandler);
42
+ process.removeListener('SIGTERM', signalCleanupHandler);
43
+ }
44
+ export async function runScenario(opts) {
45
+ const { cwd, force = false } = opts;
46
+ // Load config
47
+ const configPath = join(cwd, '.codeledger', 'config.json');
48
+ if (!existsSync(configPath)) {
49
+ throw new Error('No .codeledger/config.json found. Run "codeledger init" first.');
50
+ }
51
+ let config;
52
+ try {
53
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
54
+ }
55
+ catch {
56
+ throw new Error(`Failed to parse config at ${configPath}. Ensure it contains valid JSON.`);
57
+ }
58
+ // Preflight
59
+ const indexPath = join(cwd, config.workspace.cache_dir, 'repo-index.json');
60
+ const preflight = runPreflight(cwd, configPath, indexPath);
61
+ const validation = validatePreflight(preflight, 'run', force);
62
+ for (const err of validation.errors) {
63
+ console.error(`❌ ${err}`);
64
+ }
65
+ for (const warn of validation.warnings) {
66
+ console.warn(`⚠️ ${warn}`);
67
+ }
68
+ if (!validation.ok) {
69
+ throw new Error('Preflight checks failed.');
70
+ }
71
+ // Load scenario — validate scenario file exists and has safe ID
72
+ if (!existsSync(opts.scenarioPath)) {
73
+ throw new Error(`Scenario file not found: ${opts.scenarioPath}`);
74
+ }
75
+ let scenario;
76
+ try {
77
+ scenario = JSON.parse(readFileSync(opts.scenarioPath, 'utf-8'));
78
+ }
79
+ catch {
80
+ throw new Error(`Failed to parse scenario at ${opts.scenarioPath}. Ensure it contains valid JSON.`);
81
+ }
82
+ validateScenarioId(scenario.id);
83
+ // Load repo index
84
+ let repoIndex;
85
+ try {
86
+ repoIndex = JSON.parse(readFileSync(indexPath, 'utf-8'));
87
+ }
88
+ catch {
89
+ throw new Error(`Failed to parse repo index at ${indexPath}. Run "codeledger scan" to regenerate.`);
90
+ }
91
+ // Init ledger
92
+ const dbPath = join(cwd, config.workspace.db_path);
93
+ const ledger = new LedgerStore(dbPath);
94
+ ledger.init();
95
+ const headCommit = getHeadCommit(cwd);
96
+ const useWorktree = opts.useWorktree ?? true;
97
+ const worktreeRoot = opts.worktreeRoot ?? join(cwd, config.workspace.worktree_root);
98
+ // Clean up any orphaned worktrees from previous crashed runs
99
+ const orphansRemoved = cleanupAllWorktrees(cwd, worktreeRoot);
100
+ if (orphansRemoved > 0) {
101
+ console.log(`🧹 Cleaned up ${orphansRemoved} orphaned worktree${orphansRemoved > 1 ? 's' : ''} from a previous run`);
102
+ }
103
+ const results = [];
104
+ try {
105
+ for (const mode of scenario.modes) {
106
+ console.log(`\n🔄 Running mode: ${mode.name}`);
107
+ const modeAgentCmd = selectAgentCmdForMode(mode.name, opts);
108
+ const recorder = new RunRecorder(ledger);
109
+ recorder.startRun({
110
+ scenario_id: scenario.id,
111
+ mode: mode.name,
112
+ injection_mode: mode.context_injection === 'on'
113
+ ? (opts.injectionOverride ?? mode.injection_mode ?? config.injection.default_mode)
114
+ : null,
115
+ repeat_num: 1,
116
+ agent: modeAgentCmd ?? (opts.guided ? 'guided' : null),
117
+ git_ref: headCommit,
118
+ started_at: new Date().toISOString(),
119
+ });
120
+ let worktreePath = cwd;
121
+ let cleanup = null;
122
+ // Create worktree sandbox if enabled
123
+ if (useWorktree && preflight.worktree_supported) {
124
+ try {
125
+ const wt = createWorktree({
126
+ repoRoot: cwd,
127
+ worktreeRoot,
128
+ commit: headCommit,
129
+ prefix: mode.name,
130
+ dependencyMode: config.harness.worktree_dependency_mode,
131
+ installCmd: config.harness.worktree_install_cmd,
132
+ });
133
+ worktreePath = wt.path;
134
+ cleanup = wt.cleanup;
135
+ // Register synchronous signal handler so Ctrl+C still cleans up
136
+ installSignalHandlers();
137
+ activeCleanup = () => {
138
+ try {
139
+ execFileSync('git', ['worktree', 'remove', '--force', wt.path], {
140
+ cwd,
141
+ stdio: ['pipe', 'pipe', 'pipe'],
142
+ });
143
+ }
144
+ catch {
145
+ // Best effort
146
+ }
147
+ };
148
+ console.log(` 📁 Worktree: ${worktreePath}`);
149
+ }
150
+ catch (err) {
151
+ console.warn(` ⚠️ Failed to create worktree, running in-place: ${err}`);
152
+ }
153
+ }
154
+ try {
155
+ // Generate bundle if with_codeledger
156
+ let bundle = null;
157
+ let bundleMarkdown = null;
158
+ if (mode.context_injection === 'on') {
159
+ const budget = mode.budget ?? config.selector.default_budget;
160
+ bundle = await buildBundleViaEngine({
161
+ taskText: scenario.task.prompt,
162
+ repoIndex,
163
+ selectorConfig: config.selector,
164
+ budget,
165
+ indexPath: indexPath,
166
+ });
167
+ bundleMarkdown = renderBundleMarkdown(bundle);
168
+ recorder.recordEvent('bundle_generated', {
169
+ bundle_id: bundle.bundle_id,
170
+ files: bundle.files.length,
171
+ tokens: bundle.total_tokens,
172
+ });
173
+ console.log(` 📦 Bundle: ${bundle.files.length} files, ~${bundle.total_tokens} tokens`);
174
+ }
175
+ // Select adapter
176
+ const adapter = opts.guided
177
+ ? new GuidedAdapter()
178
+ : new GenericAdapter();
179
+ // Run agent
180
+ recorder.recordEvent('agent_prompt', {
181
+ task: scenario.task.prompt,
182
+ mode: mode.name,
183
+ injection: mode.context_injection,
184
+ });
185
+ // Pick per-mode agent command if provided, otherwise fall back to agentCmd
186
+ const effectiveAgentCmd = mode.name === 'with_codeledger'
187
+ ? (opts.agentCmdWith ?? opts.agentCmd)
188
+ : (opts.agentCmdWithout ?? opts.agentCmd);
189
+ if (effectiveAgentCmd) {
190
+ const source = mode.name === 'with_codeledger' && opts.agentCmdWith
191
+ ? '--agentCmdWith'
192
+ : mode.name === 'without_codeledger' && opts.agentCmdWithout
193
+ ? '--agentCmdWithout'
194
+ : '--agentCmd';
195
+ console.log(` 🔧 Agent command (${source}): ${effectiveAgentCmd}`);
196
+ }
197
+ const agentResult = await adapter.run({
198
+ scenario,
199
+ mode,
200
+ worktree_path: worktreePath,
201
+ bundle: bundle ?? undefined,
202
+ bundle_markdown: bundleMarkdown ?? undefined,
203
+ agent_cmd: modeAgentCmd,
204
+ guided_timeout_sec: opts.guidedTimeoutSec ?? config.harness.guided_timeout_sec,
205
+ });
206
+ console.log(` 🤖 Agent completed (exit: ${agentResult.exit_code}, ${agentResult.duration_ms}ms)`);
207
+ // Run acceptance commands
208
+ const acceptanceResults = [];
209
+ let acceptanceDurationMs = 0;
210
+ const usedCmdNames = new Set();
211
+ for (const cmd of scenario.task.acceptance.commands) {
212
+ let cmdName = inferCommandName(cmd);
213
+ if (usedCmdNames.has(cmdName)) {
214
+ let suffix = 2;
215
+ while (usedCmdNames.has(`${cmdName}_${suffix}`))
216
+ suffix++;
217
+ cmdName = `${cmdName}_${suffix}`;
218
+ }
219
+ usedCmdNames.add(cmdName);
220
+ console.log(` 🧪 Running: ${cmd}`);
221
+ const execResult = execCommand(cmd, { cwd: worktreePath, timeout: 120_000 });
222
+ const passed = execResult.exit_code === 0;
223
+ acceptanceDurationMs += execResult.duration_ms;
224
+ acceptanceResults.push({
225
+ name: cmdName,
226
+ pass: passed,
227
+ failures: passed ? 0 : 1,
228
+ });
229
+ recorder.recordEvent('cmd_exec', {
230
+ command: cmd,
231
+ exit_code: execResult.exit_code,
232
+ duration_ms: execResult.duration_ms,
233
+ });
234
+ console.log(` ${passed ? '✅' : '❌'} ${cmdName}: ${passed ? 'passed' : 'failed'}`);
235
+ }
236
+ const accepted = acceptanceResults.every((r) => r.pass);
237
+ const totalDurationMs = agentResult.duration_ms + acceptanceDurationMs;
238
+ const promptTokenEstimate = estimatePromptTokenUsage(scenario.task.prompt, bundleMarkdown, mode.context_injection, opts.injectionOverride ?? mode.injection_mode ?? config.injection.default_mode);
239
+ // Collect real metrics from the worktree
240
+ const wtMetrics = collectWorktreeMetrics(worktreePath, agentResult.stdout_path ?? null);
241
+ // Build metrics
242
+ const metrics = {
243
+ duration_sec: Math.round(totalDurationMs / 1000),
244
+ duration_ms_total: totalDurationMs,
245
+ agent_duration_ms: agentResult.duration_ms,
246
+ acceptance_duration_ms: acceptanceDurationMs,
247
+ attempt_number: 1,
248
+ accepted,
249
+ commands: Object.fromEntries(acceptanceResults.map((r) => [r.name, r])),
250
+ files_read_count: wtMetrics.filesRead,
251
+ files_changed_count: wtMetrics.filesChanged,
252
+ iterations: wtMetrics.iterations,
253
+ reverts: wtMetrics.reverts,
254
+ token_estimate: promptTokenEstimate,
255
+ };
256
+ // Build injection proof
257
+ let injectionProof = null;
258
+ if (bundle && mode.context_injection === 'on') {
259
+ injectionProof = {
260
+ mode: opts.injectionOverride ?? mode.injection_mode ?? config.injection.default_mode,
261
+ bundle_id: bundle.bundle_id,
262
+ bundle_tokens: bundle.total_tokens,
263
+ selected_files: bundle.files.length,
264
+ top_files: bundle.files.slice(0, 5).map((f) => f.path),
265
+ };
266
+ }
267
+ const reportRun = {
268
+ mode: mode.name,
269
+ injection: injectionProof,
270
+ repeat: 1,
271
+ metrics,
272
+ ...(bundle
273
+ ? {
274
+ bundle: {
275
+ bundle_id: bundle.bundle_id,
276
+ token_budget: bundle.budget.tokens ?? null,
277
+ max_files: bundle.budget.max_files ?? null,
278
+ selected_files: bundle.files.length,
279
+ },
280
+ }
281
+ : {}),
282
+ };
283
+ results.push(reportRun);
284
+ recorder.finishRun('completed', metrics);
285
+ }
286
+ catch (err) {
287
+ recorder.finishRun('failed', { error: String(err) });
288
+ throw err;
289
+ }
290
+ finally {
291
+ activeCleanup = null;
292
+ if (cleanup && !opts.keepWorktree) {
293
+ await cleanup();
294
+ }
295
+ }
296
+ }
297
+ }
298
+ finally {
299
+ removeSignalHandlers();
300
+ }
301
+ ledger.close();
302
+ return results;
303
+ }
304
+ const SAFE_SCENARIO_ID = /^[a-zA-Z0-9_-]+$/;
305
+ function validateScenarioId(id) {
306
+ if (!SAFE_SCENARIO_ID.test(id)) {
307
+ throw new Error(`Invalid scenario ID: "${id}". IDs must contain only alphanumeric, underscore, and hyphen characters.`);
308
+ }
309
+ }
310
+ export function selectAgentCmdForMode(modeName, opts) {
311
+ if (modeName === 'without_codeledger') {
312
+ return opts.agentCmdWithout ?? opts.agentCmd;
313
+ }
314
+ if (modeName === 'with_codeledger') {
315
+ return opts.agentCmdWith ?? opts.agentCmd;
316
+ }
317
+ return opts.agentCmd;
318
+ }
319
+ function estimatePromptTokenUsage(taskText, bundleMarkdown, contextInjection, injectionMode) {
320
+ if (contextInjection === 'off') {
321
+ return estimateTextTokens(taskText);
322
+ }
323
+ if (!bundleMarkdown) {
324
+ return estimateTextTokens(taskText);
325
+ }
326
+ if (injectionMode === 'prompt_prepend') {
327
+ return estimateTextTokens(injectIntoPrompt(taskText, bundleMarkdown));
328
+ }
329
+ // file_drop and guided include prompt + separate bundle exposure.
330
+ return estimateTextTokens(taskText) + estimateTextTokens(bundleMarkdown);
331
+ }
332
+ function estimateTextTokens(text) {
333
+ return Math.ceil(text.length / 4);
334
+ }
335
+ function inferCommandName(cmd) {
336
+ if (cmd.includes('test'))
337
+ return 'tests';
338
+ if (cmd.includes('lint'))
339
+ return 'lint';
340
+ if (cmd.includes('build'))
341
+ return 'build';
342
+ return cmd;
343
+ }
344
+ /**
345
+ * Collect real metrics from the worktree after the agent has run.
346
+ *
347
+ * - filesChanged: count of files modified/added/deleted vs HEAD (git diff)
348
+ * - filesRead: heuristic count from agent stdout (lines matching common
349
+ * file-read patterns), falls back to 0 when no log is available.
350
+ * - iterations: heuristic count of retry/re-attempt cycles detected in the
351
+ * agent stdout log. Defaults to 1 (the initial attempt always counts).
352
+ * - reverts: count of revert-like git operations (reset, checkout, revert)
353
+ * detected in the agent stdout log or git reflog.
354
+ */
355
+ function collectWorktreeMetrics(worktreePath, stdoutLogPath) {
356
+ // --- files changed via git diff ---
357
+ let filesChanged = 0;
358
+ try {
359
+ const diffOutput = execFileSync('git', ['diff', '--name-only', 'HEAD'], { cwd: worktreePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
360
+ // Also count untracked files the agent may have created
361
+ const untrackedOutput = execFileSync('git', ['ls-files', '--others', '--exclude-standard'], { cwd: worktreePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
362
+ filesChanged =
363
+ (diffOutput ? diffOutput.split('\n').length : 0) +
364
+ (untrackedOutput ? untrackedOutput.split('\n').length : 0);
365
+ }
366
+ catch {
367
+ // Not inside a git worktree or git unavailable — leave at 0
368
+ }
369
+ // --- Parse agent stdout log for file reads, iterations, and reverts ---
370
+ let filesRead = 0;
371
+ let iterations = 1; // The initial attempt always counts
372
+ let logReverts = 0;
373
+ if (stdoutLogPath && existsSync(stdoutLogPath)) {
374
+ try {
375
+ const log = readFileSync(stdoutLogPath, 'utf-8');
376
+ // Count unique file-path-like tokens the agent mentioned reading
377
+ const fileRefs = new Set();
378
+ for (const match of log.matchAll(/(?:reading|read|open(?:ed)?|cat)\s+["']?([^\s"']+\.\w{1,6})["']?/gi)) {
379
+ fileRefs.add(match[1]);
380
+ }
381
+ filesRead = fileRefs.size;
382
+ // Detect iteration/retry patterns in agent output
383
+ // Common patterns: "retry", "retrying", "attempt N", "re-running",
384
+ // "trying again", "iteration N", loop indicators
385
+ const retryPatterns = [
386
+ /\bretry(?:ing)?\b/gi,
387
+ /\bre-?running\b/gi,
388
+ /\btrying again\b/gi,
389
+ /\battempt\s+(\d+)/gi,
390
+ /\biteration\s+(\d+)/gi,
391
+ /\bfailed[,.]?\s*(?:re-?)?trying\b/gi,
392
+ /\broll(?:ing)?\s*back\b/gi,
393
+ ];
394
+ for (const pattern of retryPatterns) {
395
+ for (const match of log.matchAll(pattern)) {
396
+ // If a numbered attempt/iteration, use it directly if higher
397
+ const num = match[1] ? parseInt(match[1], 10) : 0;
398
+ if (num > iterations) {
399
+ iterations = num;
400
+ }
401
+ else {
402
+ // Each retry match beyond the initial attempt adds 1
403
+ iterations++;
404
+ }
405
+ }
406
+ }
407
+ // Detect revert-like operations in agent output
408
+ const revertPatterns = [
409
+ /\bgit\s+revert\b/gi,
410
+ /\bgit\s+reset\b/gi,
411
+ /\bgit\s+checkout\s+--\s/gi,
412
+ /\bgit\s+restore\b/gi,
413
+ /\breverting\b/gi,
414
+ /\bundoing\b/gi,
415
+ ];
416
+ for (const pattern of revertPatterns) {
417
+ const matches = log.match(pattern);
418
+ logReverts += matches ? matches.length : 0;
419
+ }
420
+ }
421
+ catch {
422
+ // Non-fatal
423
+ }
424
+ }
425
+ // --- Detect reverts via git reflog in worktree ---
426
+ let gitReverts = 0;
427
+ try {
428
+ const reflogOutput = execFileSync('git', ['reflog', '--format=%gs'], { cwd: worktreePath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
429
+ if (reflogOutput) {
430
+ for (const line of reflogOutput.split('\n')) {
431
+ if (/\b(?:reset|revert|checkout)\b/i.test(line)) {
432
+ gitReverts++;
433
+ }
434
+ }
435
+ }
436
+ }
437
+ catch {
438
+ // Not inside a git worktree or git unavailable
439
+ }
440
+ const reverts = logReverts + gitReverts;
441
+ return { filesChanged, filesRead, iterations, reverts };
442
+ }
443
+ //# sourceMappingURL=scenario-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-runner.js","sourceRoot":"","sources":["../src/scenario-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=scenario-runner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-runner.test.d.ts","sourceRoot":"","sources":["../src/scenario-runner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { selectAgentCmdForMode } from './scenario-runner.js';
3
+ describe('selectAgentCmdForMode', () => {
4
+ it('prefers mode-specific agent command for without_codeledger', () => {
5
+ const cmd = selectAgentCmdForMode('without_codeledger', {
6
+ agentCmd: 'agent default',
7
+ agentCmdWithout: 'agent without',
8
+ agentCmdWith: 'agent with',
9
+ });
10
+ expect(cmd).toBe('agent without');
11
+ });
12
+ it('prefers mode-specific agent command for with_codeledger', () => {
13
+ const cmd = selectAgentCmdForMode('with_codeledger', {
14
+ agentCmd: 'agent default',
15
+ agentCmdWithout: 'agent without',
16
+ agentCmdWith: 'agent with',
17
+ });
18
+ expect(cmd).toBe('agent with');
19
+ });
20
+ it('falls back to default agent command when override is missing', () => {
21
+ const cmd = selectAgentCmdForMode('with_codeledger', {
22
+ agentCmd: 'agent default',
23
+ agentCmdWithout: 'agent without',
24
+ });
25
+ expect(cmd).toBe('agent default');
26
+ });
27
+ });
28
+ //# sourceMappingURL=scenario-runner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-runner.test.js","sourceRoot":"","sources":["../src/scenario-runner.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,GAAG,GAAG,qBAAqB,CAAC,oBAAoB,EAAE;YACtD,QAAQ,EAAE,eAAe;YACzB,eAAe,EAAE,eAAe;YAChC,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,qBAAqB,CAAC,iBAAiB,EAAE;YACnD,QAAQ,EAAE,eAAe;YACzB,eAAe,EAAE,eAAe;YAChC,YAAY,EAAE,YAAY;SAC3B,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,GAAG,GAAG,qBAAqB,CAAC,iBAAiB,EAAE;YACnD,QAAQ,EAAE,eAAe;YACzB,eAAe,EAAE,eAAe;SACjC,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { WorktreeHandle, WorktreeDependencyMode } from '@codeledger/types';
2
+ export interface WorktreeSpec {
3
+ repoRoot: string;
4
+ worktreeRoot: string;
5
+ commit: string;
6
+ prefix?: string;
7
+ dependencyMode?: WorktreeDependencyMode;
8
+ /** Custom install command that replaces the default pnpm/npm fallback chain. */
9
+ installCmd?: string;
10
+ }
11
+ export declare function createWorktree(spec: WorktreeSpec): WorktreeHandle;
12
+ /**
13
+ * Remove all orphaned codeledger sandbox worktrees.
14
+ *
15
+ * 1. Runs `git worktree prune` to clean stale bookkeeping entries.
16
+ * 2. Lists remaining worktrees via `git worktree list --porcelain`.
17
+ * 3. Removes any whose path contains `codeledger-sandbox-`.
18
+ * 4. Deletes leftover sandbox directories under `worktreeRoot` that git
19
+ * no longer tracks (e.g. from a hard kill where the entry was never
20
+ * registered or was already pruned but the directory survived).
21
+ *
22
+ * Returns the number of worktrees removed.
23
+ */
24
+ export declare function cleanupAllWorktrees(repoRoot: string, worktreeRoot?: string): number;
25
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../src/worktree.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAKhF,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CA0CjE;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CA4EnF"}