mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
fix: address remaining orchestration review comments
This commit is contained in:
@@ -106,11 +106,31 @@ function parseWorkerTask(content) {
|
||||
};
|
||||
}
|
||||
|
||||
function parseFirstSection(content, headings) {
|
||||
for (const heading of headings) {
|
||||
const section = parseSection(content, heading);
|
||||
if (section) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function parseWorkerHandoff(content) {
|
||||
return {
|
||||
summary: parseBullets(parseSection(content, 'Summary')),
|
||||
validation: parseBullets(parseSection(content, 'Validation')),
|
||||
remainingRisks: parseBullets(parseSection(content, 'Remaining Risks'))
|
||||
summary: parseBullets(parseFirstSection(content, ['Summary'])),
|
||||
validation: parseBullets(parseFirstSection(content, [
|
||||
'Validation',
|
||||
'Tests / Verification',
|
||||
'Tests',
|
||||
'Verification'
|
||||
])),
|
||||
remainingRisks: parseBullets(parseFirstSection(content, [
|
||||
'Remaining Risks',
|
||||
'Follow-ups',
|
||||
'Follow Ups'
|
||||
]))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -250,18 +270,48 @@ function buildSessionSnapshot({ sessionName, coordinationDir, panes }) {
|
||||
};
|
||||
}
|
||||
|
||||
function readPlanConfig(absoluteTarget) {
|
||||
let config;
|
||||
|
||||
try {
|
||||
config = JSON.parse(fs.readFileSync(absoluteTarget, 'utf8'));
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid orchestration plan JSON: ${absoluteTarget}`);
|
||||
}
|
||||
|
||||
if (!config || Array.isArray(config) || typeof config !== 'object') {
|
||||
throw new Error(`Invalid orchestration plan: expected a JSON object (${absoluteTarget})`);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
function readPlanString(config, key, absoluteTarget) {
|
||||
const value = config[key];
|
||||
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeof value !== 'string' || value.trim().length === 0) {
|
||||
throw new Error(`Invalid orchestration plan: ${key} must be a non-empty string (${absoluteTarget})`);
|
||||
}
|
||||
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
function resolveSnapshotTarget(targetPath, cwd = process.cwd()) {
|
||||
const absoluteTarget = path.resolve(cwd, targetPath);
|
||||
|
||||
if (fs.existsSync(absoluteTarget) && fs.statSync(absoluteTarget).isFile()) {
|
||||
const config = JSON.parse(fs.readFileSync(absoluteTarget, 'utf8'));
|
||||
const repoRoot = path.resolve(config.repoRoot || cwd);
|
||||
const config = readPlanConfig(absoluteTarget);
|
||||
const repoRoot = path.resolve(readPlanString(config, 'repoRoot', absoluteTarget) || cwd);
|
||||
const sessionName = normalizeSessionName(
|
||||
config.sessionName || path.basename(repoRoot),
|
||||
readPlanString(config, 'sessionName', absoluteTarget) || path.basename(repoRoot),
|
||||
'session'
|
||||
);
|
||||
const coordinationRoot = path.resolve(
|
||||
config.coordinationRoot || path.join(repoRoot, '.orchestration')
|
||||
readPlanString(config, 'coordinationRoot', absoluteTarget) || path.join(repoRoot, '.orchestration')
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -34,6 +34,18 @@ function formatCommand(program, args) {
|
||||
return [program, ...args.map(shellQuote)].join(' ');
|
||||
}
|
||||
|
||||
function buildTemplateVariables(values) {
|
||||
return Object.entries(values).reduce((accumulator, [key, value]) => {
|
||||
const stringValue = String(value);
|
||||
const quotedValue = shellQuote(stringValue);
|
||||
|
||||
accumulator[key] = quotedValue;
|
||||
accumulator[`${key}_raw`] = stringValue;
|
||||
accumulator[`${key}_sh`] = quotedValue;
|
||||
return accumulator;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function normalizeSeedPaths(seedPaths, repoRoot) {
|
||||
const resolvedRepoRoot = path.resolve(repoRoot);
|
||||
const entries = Array.isArray(seedPaths) ? seedPaths : [];
|
||||
@@ -126,6 +138,13 @@ function buildWorkerArtifacts(workerPlan) {
|
||||
'## Completion',
|
||||
'Do not spawn subagents or external agents for this task.',
|
||||
'Report results in your final response.',
|
||||
'Respond with these exact sections so orchestration parsing can succeed:',
|
||||
'## Summary',
|
||||
'- ...',
|
||||
'## Validation',
|
||||
'- ...',
|
||||
'## Remaining Risks',
|
||||
'- ...',
|
||||
`The worker launcher captures your response in \`${workerPlan.handoffFilePath}\` automatically.`,
|
||||
`The worker launcher updates \`${workerPlan.statusFilePath}\` automatically.`
|
||||
].join('\n')
|
||||
@@ -138,13 +157,10 @@ function buildWorkerArtifacts(workerPlan) {
|
||||
'## Summary',
|
||||
'- Pending',
|
||||
'',
|
||||
'## Files Changed',
|
||||
'## Validation',
|
||||
'- Pending',
|
||||
'',
|
||||
'## Tests / Verification',
|
||||
'- Pending',
|
||||
'',
|
||||
'## Follow-ups',
|
||||
'## Remaining Risks',
|
||||
'- Pending'
|
||||
].join('\n')
|
||||
},
|
||||
@@ -180,6 +196,7 @@ function buildOrchestrationPlan(config = {}) {
|
||||
throw new Error('buildOrchestrationPlan requires at least one worker');
|
||||
}
|
||||
|
||||
const seenWorkerSlugs = new Map();
|
||||
const workerPlans = workers.map((worker, index) => {
|
||||
if (!worker || typeof worker.task !== 'string' || worker.task.trim().length === 0) {
|
||||
throw new Error(`Worker ${index + 1} is missing a task`);
|
||||
@@ -187,6 +204,13 @@ function buildOrchestrationPlan(config = {}) {
|
||||
|
||||
const workerName = worker.name || `worker-${index + 1}`;
|
||||
const workerSlug = slugify(workerName, `worker-${index + 1}`);
|
||||
if (seenWorkerSlugs.has(workerSlug)) {
|
||||
const firstWorkerName = seenWorkerSlugs.get(workerSlug);
|
||||
throw new Error(
|
||||
`Worker names must map to unique slugs: ${workerSlug} (${firstWorkerName}, ${workerName})`
|
||||
);
|
||||
}
|
||||
seenWorkerSlugs.set(workerSlug, workerName);
|
||||
const branchName = `orchestrator-${sessionName}-${workerSlug}`;
|
||||
const worktreePath = path.join(worktreeRoot, `${repoName}-${sessionName}-${workerSlug}`);
|
||||
const workerCoordinationDir = path.join(coordinationDir, workerSlug);
|
||||
@@ -196,7 +220,7 @@ function buildOrchestrationPlan(config = {}) {
|
||||
const launcherCommand = worker.launcherCommand || defaultLauncher;
|
||||
const workerSeedPaths = normalizeSeedPaths(worker.seedPaths, repoRoot);
|
||||
const seedPaths = normalizeSeedPaths([...globalSeedPaths, ...workerSeedPaths], repoRoot);
|
||||
const templateVariables = {
|
||||
const templateVariables = buildTemplateVariables({
|
||||
branch_name: branchName,
|
||||
handoff_file: handoffFilePath,
|
||||
repo_root: repoRoot,
|
||||
@@ -206,7 +230,7 @@ function buildOrchestrationPlan(config = {}) {
|
||||
worker_name: workerName,
|
||||
worker_slug: workerSlug,
|
||||
worktree_path: worktreePath
|
||||
};
|
||||
});
|
||||
|
||||
if (!launcherCommand) {
|
||||
throw new Error(`Worker ${workerName} is missing a launcherCommand`);
|
||||
|
||||
@@ -51,11 +51,11 @@ Rules:
|
||||
- Report progress and final results in stdout only.
|
||||
- Do not write handoff or status files yourself; the launcher manages those artifacts.
|
||||
- If you change code or docs, keep the scope narrow and defensible.
|
||||
- In your final response, include exactly these sections:
|
||||
- In your final response, include these exact sections:
|
||||
1. Summary
|
||||
2. Files Changed
|
||||
3. Validation
|
||||
4. Remaining Risks
|
||||
2. Validation
|
||||
3. Remaining Risks
|
||||
- You may include Files Changed if useful, but keep the three sections above exact.
|
||||
|
||||
Task file: $task_file
|
||||
|
||||
|
||||
@@ -17,8 +17,11 @@ function usage() {
|
||||
' node scripts/orchestrate-worktrees.js <plan.json> [--write-only]',
|
||||
'',
|
||||
'Placeholders supported in launcherCommand:',
|
||||
' {worker_name} {worker_slug} {session_name} {repo_root}',
|
||||
' {worktree_path} {branch_name} {task_file} {handoff_file} {status_file}',
|
||||
' Shell-safe defaults: {worker_name} {worker_slug} {session_name} {repo_root}',
|
||||
' Shell-safe defaults: {worktree_path} {branch_name} {task_file} {handoff_file} {status_file}',
|
||||
' Raw variants: {worker_name_raw} {worker_slug_raw} {session_name_raw} {repo_root_raw}',
|
||||
' Raw variants: {worktree_path_raw} {branch_name_raw} {task_file_raw} {handoff_file_raw} {status_file_raw}',
|
||||
' Explicit shell-safe aliases also exist with the _sh suffix.',
|
||||
'',
|
||||
'Without flags the script prints a dry-run plan only.'
|
||||
].join('\n'));
|
||||
|
||||
Reference in New Issue
Block a user