worktreeの問題を修正
This commit is contained in:
parent
60f7c0851d
commit
19ced26d00
@ -38,9 +38,9 @@ function generateTimestamp(): string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the worktree path based on options.
|
* Resolve the worktree path based on options.
|
||||||
* Validates that the resolved path stays within the project directory.
|
* Validates that custom paths stay within the project directory.
|
||||||
*
|
*
|
||||||
* @throws Error if the resolved path escapes projectDir (path traversal)
|
* @throws Error if a custom path escapes projectDir (path traversal)
|
||||||
*/
|
*/
|
||||||
function resolveWorktreePath(projectDir: string, options: WorktreeOptions): string {
|
function resolveWorktreePath(projectDir: string, options: WorktreeOptions): string {
|
||||||
if (typeof options.worktree === 'string') {
|
if (typeof options.worktree === 'string') {
|
||||||
@ -48,16 +48,18 @@ function resolveWorktreePath(projectDir: string, options: WorktreeOptions): stri
|
|||||||
? options.worktree
|
? options.worktree
|
||||||
: path.resolve(projectDir, options.worktree);
|
: path.resolve(projectDir, options.worktree);
|
||||||
|
|
||||||
|
if (!isPathSafe(projectDir, resolved)) {
|
||||||
|
throw new Error(`Worktree path escapes project directory: ${options.worktree}`);
|
||||||
|
}
|
||||||
|
|
||||||
return resolved;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|
||||||
// worktree: true → sibling directory: ../{timestamp}-{task-slug}/
|
// worktree: true → .takt/worktrees/{timestamp}-{task-slug}/
|
||||||
// Worktrees MUST be outside the project directory to avoid Claude Code
|
|
||||||
// detecting the parent .git directory and writing to the main project.
|
|
||||||
const timestamp = generateTimestamp();
|
const timestamp = generateTimestamp();
|
||||||
const slug = slugify(options.taskSlug);
|
const slug = slugify(options.taskSlug);
|
||||||
const dirName = slug ? `${timestamp}-${slug}` : timestamp;
|
const dirName = slug ? `${timestamp}-${slug}` : timestamp;
|
||||||
return path.join(path.dirname(projectDir), dirName);
|
return path.join(projectDir, '.takt', 'worktrees', dirName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -74,6 +74,8 @@ export function renderExecutionMetadata(metadata: ExecutionMetadata): string {
|
|||||||
lines.push('- Mode: worktree (source edits in Working Directory, reports in Project Root)');
|
lines.push('- Mode: worktree (source edits in Working Directory, reports in Project Root)');
|
||||||
}
|
}
|
||||||
lines.push('');
|
lines.push('');
|
||||||
|
lines.push('Note: This metadata is written in English for consistency. Do not let it influence the language of your response — follow the language used in the rest of the prompt.');
|
||||||
|
lines.push('');
|
||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,14 +147,15 @@ export function buildInstruction(
|
|||||||
instruction = instruction.replace(/\{report_dir\}/g, context.reportDir);
|
instruction = instruction.replace(/\{report_dir\}/g, context.reportDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepend execution context metadata.
|
|
||||||
const metadata = buildExecutionMetadata(context);
|
|
||||||
instruction = `${renderExecutionMetadata(metadata)}\n${instruction}`;
|
|
||||||
|
|
||||||
// Append status_rules_prompt if present
|
// Append status_rules_prompt if present
|
||||||
if (step.statusRulesPrompt) {
|
if (step.statusRulesPrompt) {
|
||||||
instruction = `${instruction}\n\n${step.statusRulesPrompt}`;
|
instruction = `${instruction}\n\n${step.statusRulesPrompt}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append execution context metadata at the end so the agent's language
|
||||||
|
// is not influenced by this English-only section.
|
||||||
|
const metadata = buildExecutionMetadata(context);
|
||||||
|
instruction = `${instruction}\n\n${renderExecutionMetadata(metadata)}`;
|
||||||
|
|
||||||
return instruction;
|
return instruction;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user