mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-13 02:41:50 +08:00
feat(discovery): enhance discovery progress reading with new schema support
This commit is contained in:
@@ -172,19 +172,17 @@ TodoWrite({
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Phase 2: Unified Explore + Plan (issue-plan-agent)
|
### Phase 2: Unified Explore + Plan (issue-plan-agent) - PARALLEL
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
Bash(`mkdir -p .workflow/issues/solutions`);
|
Bash(`mkdir -p .workflow/issues/solutions`);
|
||||||
const pendingSelections = []; // Collect multi-solution issues for user selection
|
const pendingSelections = []; // Collect multi-solution issues for user selection
|
||||||
|
|
||||||
for (const [batchIndex, batch] of batches.entries()) {
|
// Build prompts for all batches
|
||||||
updateTodo(`Plan batch ${batchIndex + 1}`, 'in_progress');
|
const agentTasks = batches.map((batch, batchIndex) => {
|
||||||
|
|
||||||
// Build issue list with metadata for agent context
|
|
||||||
const issueList = batch.map(i => `- ${i.id}: ${i.title}${i.tags.length ? ` [${i.tags.join(', ')}]` : ''}`).join('\n');
|
const issueList = batch.map(i => `- ${i.id}: ${i.title}${i.tags.length ? ` [${i.tags.join(', ')}]` : ''}`).join('\n');
|
||||||
|
const batchIds = batch.map(i => i.id);
|
||||||
|
|
||||||
// Build minimal prompt - agent handles exploration, planning, and binding
|
|
||||||
const issuePrompt = `
|
const issuePrompt = `
|
||||||
## Plan Issues
|
## Plan Issues
|
||||||
|
|
||||||
@@ -223,32 +221,43 @@ ${issueList}
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Launch issue-plan-agent - agent writes solutions directly
|
return { batchIndex, batchIds, issuePrompt, batch };
|
||||||
const batchIds = batch.map(i => i.id);
|
});
|
||||||
const result = Task(
|
|
||||||
subagent_type="issue-plan-agent",
|
|
||||||
run_in_background=false,
|
|
||||||
description=`Explore & plan ${batch.length} issues: ${batchIds.join(', ')}`,
|
|
||||||
prompt=issuePrompt
|
|
||||||
);
|
|
||||||
|
|
||||||
// Parse summary from agent
|
// Launch agents in parallel (max 10 concurrent)
|
||||||
const summary = JSON.parse(result);
|
const MAX_PARALLEL = 10;
|
||||||
|
for (let i = 0; i < agentTasks.length; i += MAX_PARALLEL) {
|
||||||
|
const chunk = agentTasks.slice(i, i + MAX_PARALLEL);
|
||||||
|
const taskIds = [];
|
||||||
|
|
||||||
// Display auto-bound solutions
|
// Launch chunk in parallel
|
||||||
for (const item of summary.bound || []) {
|
for (const { batchIndex, batchIds, issuePrompt, batch } of chunk) {
|
||||||
console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`);
|
updateTodo(`Plan batch ${batchIndex + 1}`, 'in_progress');
|
||||||
|
const taskId = Task(
|
||||||
|
subagent_type="issue-plan-agent",
|
||||||
|
run_in_background=true,
|
||||||
|
description=`Explore & plan ${batch.length} issues: ${batchIds.join(', ')}`,
|
||||||
|
prompt=issuePrompt
|
||||||
|
);
|
||||||
|
taskIds.push({ taskId, batchIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect pending selections for Phase 3
|
console.log(`Launched ${taskIds.length} agents (batch ${i/MAX_PARALLEL + 1}/${Math.ceil(agentTasks.length/MAX_PARALLEL)})...`);
|
||||||
pendingSelections.push(...(summary.pending_selection || []));
|
|
||||||
|
|
||||||
// Show conflicts
|
// Collect results from this chunk
|
||||||
if (summary.conflicts?.length > 0) {
|
for (const { taskId, batchIndex } of taskIds) {
|
||||||
console.log(`⚠ Conflicts: ${summary.conflicts.map(c => c.file).join(', ')}`);
|
const result = TaskOutput(task_id=taskId, block=true);
|
||||||
|
const summary = JSON.parse(result);
|
||||||
|
|
||||||
|
for (const item of summary.bound || []) {
|
||||||
|
console.log(`✓ ${item.issue_id}: ${item.solution_id} (${item.task_count} tasks)`);
|
||||||
|
}
|
||||||
|
pendingSelections.push(...(summary.pending_selection || []));
|
||||||
|
if (summary.conflicts?.length > 0) {
|
||||||
|
console.log(`⚠ Conflicts: ${summary.conflicts.map(c => c.file).join(', ')}`);
|
||||||
|
}
|
||||||
|
updateTodo(`Plan batch ${batchIndex + 1}`, 'completed');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTodo(`Plan batch ${batchIndex + 1}`, 'completed');
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -116,13 +116,51 @@ function readDiscoveryState(discoveriesDir: string, discoveryId: string): any |
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readDiscoveryProgress(discoveriesDir: string, discoveryId: string): any | null {
|
function readDiscoveryProgress(discoveriesDir: string, discoveryId: string): any | null {
|
||||||
const progressPath = join(discoveriesDir, discoveryId, 'discovery-progress.json');
|
// Try merged state first (new schema)
|
||||||
if (!existsSync(progressPath)) return null;
|
const statePath = join(discoveriesDir, discoveryId, 'discovery-state.json');
|
||||||
try {
|
if (existsSync(statePath)) {
|
||||||
return JSON.parse(readFileSync(progressPath, 'utf8'));
|
try {
|
||||||
} catch {
|
const state = JSON.parse(readFileSync(statePath, 'utf8'));
|
||||||
return null;
|
// New merged schema: perspectives array + results object
|
||||||
|
if (state.perspectives && Array.isArray(state.perspectives)) {
|
||||||
|
const completed = state.perspectives.filter((p: any) => p.status === 'completed').length;
|
||||||
|
const total = state.perspectives.length;
|
||||||
|
return {
|
||||||
|
discovery_id: discoveryId,
|
||||||
|
phase: state.phase,
|
||||||
|
last_update: state.updated_at || state.created_at,
|
||||||
|
progress: {
|
||||||
|
perspective_analysis: {
|
||||||
|
total,
|
||||||
|
completed,
|
||||||
|
in_progress: state.perspectives.filter((p: any) => p.status === 'in_progress').length,
|
||||||
|
percent_complete: total > 0 ? Math.round((completed / total) * 100) : 0
|
||||||
|
},
|
||||||
|
external_research: state.external_research || { enabled: false, completed: false },
|
||||||
|
aggregation: { completed: state.phase === 'aggregation' || state.phase === 'complete' },
|
||||||
|
issue_generation: { completed: state.phase === 'complete', issues_count: state.results?.issues_generated || 0 }
|
||||||
|
},
|
||||||
|
agent_status: state.perspectives
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Old schema: metadata.perspectives (backward compat)
|
||||||
|
if (state.metadata?.perspectives) {
|
||||||
|
return {
|
||||||
|
discovery_id: discoveryId,
|
||||||
|
phase: state.phase,
|
||||||
|
progress: { perspective_analysis: { total: state.metadata.perspectives.length, completed: state.perspectives_completed?.length || 0 } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Fall through
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Fallback: try legacy progress file
|
||||||
|
const progressPath = join(discoveriesDir, discoveryId, 'discovery-progress.json');
|
||||||
|
if (existsSync(progressPath)) {
|
||||||
|
try { return JSON.parse(readFileSync(progressPath, 'utf8')); } catch { return null; }
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readPerspectiveFindings(discoveriesDir: string, discoveryId: string): any[] {
|
function readPerspectiveFindings(discoveriesDir: string, discoveryId: string): any[] {
|
||||||
|
|||||||
Reference in New Issue
Block a user