fix(loop): make Docker sandbox opt-in and preserve progress file

- Add --sandbox flag to loop command (default: use plain claude -p)
- Append to progress.txt instead of overwriting between runs
- Display execution mode (Docker sandbox vs Claude CLI) in output
This commit is contained in:
Ralph Khreish
2026-01-14 11:06:09 +01:00
parent 3cc6174b47
commit e762e4f646
7 changed files with 52 additions and 19 deletions

View File

@@ -188,7 +188,8 @@ export class LoopDomain {
partial.progressFile ??
path.join(this.projectRoot, '.taskmaster', 'progress.txt'),
sleepSeconds: partial.sleepSeconds ?? 5,
tag: partial.tag
tag: partial.tag,
sandbox: partial.sandbox ?? false
};
}
}

View File

@@ -3,7 +3,7 @@
*/
import { spawnSync } from 'node:child_process';
import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises';
import { appendFile, mkdir, readFile } from 'node:fs/promises';
import path from 'node:path';
import { PRESETS, isPreset as checkIsPreset } from '../presets/index.js';
import type {
@@ -80,7 +80,11 @@ export class LoopService {
console.log(`━━━ Iteration ${i} of ${config.iterations} ━━━`);
const prompt = await this.buildPrompt(config, i);
const iteration = this.executeIteration(prompt, i);
const iteration = this.executeIteration(
prompt,
i,
config.sandbox ?? false
);
iterations.push(iteration);
// Check for early exit conditions
@@ -135,9 +139,11 @@ export class LoopService {
private async initProgressFile(config: LoopConfig): Promise<void> {
await mkdir(path.dirname(config.progressFile), { recursive: true });
const tagLine = config.tag ? `# Tag: ${config.tag}\n` : '';
await writeFile(
// Append to existing progress file instead of overwriting
await appendFile(
config.progressFile,
`# Task Master Loop Progress
`
# Task Master Loop Progress
# Started: ${new Date().toISOString()}
# Preset: ${config.prompt}
# Max Iterations: ${config.iterations}
@@ -217,20 +223,23 @@ Loop iteration ${iteration} of ${config.iterations}${tagInfo}`;
private executeIteration(
prompt: string,
iterationNum: number
iterationNum: number,
sandbox: boolean
): LoopIteration {
const startTime = Date.now();
const result = spawnSync(
'docker',
['sandbox', 'run', 'claude', '-p', prompt],
{
cwd: this.projectRoot,
encoding: 'utf-8',
maxBuffer: 50 * 1024 * 1024, // 50MB buffer
stdio: ['inherit', 'pipe', 'pipe']
}
);
// Use docker sandbox or plain claude based on config
const command = sandbox ? 'docker' : 'claude';
const args = sandbox
? ['sandbox', 'run', 'claude', '-p', prompt]
: ['-p', prompt, '--allowedTools', 'Edit,Write,Bash,Read,Glob,Grep'];
const result = spawnSync(command, args, {
cwd: this.projectRoot,
encoding: 'utf-8',
maxBuffer: 50 * 1024 * 1024, // 50MB buffer
stdio: ['inherit', 'pipe', 'pipe']
});
const output = (result.stdout || '') + (result.stderr || '');

View File

@@ -26,6 +26,8 @@ export interface LoopConfig {
sleepSeconds: number;
/** Tag context to operate on (optional) */
tag?: string;
/** Run Claude in Docker sandbox mode (default: false) */
sandbox?: boolean;
}
/**