oh-my-claude-sisyphus 3.3.10 → 3.4.0
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.
- package/README.md +3 -3
- package/agents/explore-high.md +195 -0
- package/agents/qa-tester-high.md +141 -0
- package/agents/templates/README.md +110 -0
- package/agents/templates/base-agent.md +54 -0
- package/agents/templates/tier-instructions.md +94 -0
- package/commands/ecomode.md +60 -0
- package/commands/help.md +1 -1
- package/commands/mcp-setup.md +7 -6
- package/commands/ralplan.md +8 -1
- package/commands/ultrapilot.md +158 -0
- package/commands/ultrawork.md +1 -0
- package/dist/__tests__/delegation-enforcer-integration.test.d.ts +6 -0
- package/dist/__tests__/delegation-enforcer-integration.test.d.ts.map +1 -0
- package/dist/__tests__/delegation-enforcer-integration.test.js +136 -0
- package/dist/__tests__/delegation-enforcer-integration.test.js.map +1 -0
- package/dist/__tests__/delegation-enforcer.test.d.ts +5 -0
- package/dist/__tests__/delegation-enforcer.test.d.ts.map +1 -0
- package/dist/__tests__/delegation-enforcer.test.js +208 -0
- package/dist/__tests__/delegation-enforcer.test.js.map +1 -0
- package/dist/__tests__/hooks.test.js +2 -2
- package/dist/__tests__/hooks.test.js.map +1 -1
- package/dist/__tests__/installer.test.js +4 -6
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/__tests__/ralph-prd.test.js +1 -1
- package/dist/__tests__/ralph-prd.test.js.map +1 -1
- package/dist/__tests__/ralph-progress.test.js +1 -1
- package/dist/__tests__/ralph-progress.test.js.map +1 -1
- package/dist/__tests__/skills.test.js +31 -24
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/agents/analyst.d.ts.map +1 -1
- package/dist/agents/analyst.js +1 -0
- package/dist/agents/analyst.js.map +1 -1
- package/dist/agents/architect.d.ts.map +1 -1
- package/dist/agents/architect.js +1 -0
- package/dist/agents/architect.js.map +1 -1
- package/dist/agents/critic.d.ts.map +1 -1
- package/dist/agents/critic.js +1 -0
- package/dist/agents/critic.js.map +1 -1
- package/dist/agents/definitions.d.ts +5 -1
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +53 -155
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/designer.d.ts.map +1 -1
- package/dist/agents/designer.js +1 -0
- package/dist/agents/designer.js.map +1 -1
- package/dist/agents/executor.d.ts.map +1 -1
- package/dist/agents/executor.js +1 -0
- package/dist/agents/executor.js.map +1 -1
- package/dist/agents/explore.d.ts.map +1 -1
- package/dist/agents/explore.js +1 -0
- package/dist/agents/explore.js.map +1 -1
- package/dist/agents/planner.d.ts.map +1 -1
- package/dist/agents/planner.js +1 -0
- package/dist/agents/planner.js.map +1 -1
- package/dist/agents/qa-tester.d.ts.map +1 -1
- package/dist/agents/qa-tester.js +1 -0
- package/dist/agents/qa-tester.js.map +1 -1
- package/dist/agents/researcher.d.ts.map +1 -1
- package/dist/agents/researcher.js +1 -0
- package/dist/agents/researcher.js.map +1 -1
- package/dist/agents/scientist.d.ts.map +1 -1
- package/dist/agents/scientist.js +1 -0
- package/dist/agents/scientist.js.map +1 -1
- package/dist/agents/types.d.ts +2 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/types.js.map +1 -1
- package/dist/agents/vision.d.ts.map +1 -1
- package/dist/agents/vision.js +1 -0
- package/dist/agents/vision.js.map +1 -1
- package/dist/agents/writer.d.ts.map +1 -1
- package/dist/agents/writer.js +1 -0
- package/dist/agents/writer.js.map +1 -1
- package/dist/cli/index.js +0 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +1 -6
- package/dist/config/loader.js.map +1 -1
- package/dist/features/delegation-enforcer.d.ts +71 -0
- package/dist/features/delegation-enforcer.d.ts.map +1 -0
- package/dist/features/delegation-enforcer.js +128 -0
- package/dist/features/delegation-enforcer.js.map +1 -0
- package/dist/features/index.d.ts +3 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +18 -0
- package/dist/features/index.js.map +1 -1
- package/dist/features/state-manager/index.d.ts +100 -0
- package/dist/features/state-manager/index.d.ts.map +1 -0
- package/dist/features/state-manager/index.js +407 -0
- package/dist/features/state-manager/index.js.map +1 -0
- package/dist/features/state-manager/types.d.ts +147 -0
- package/dist/features/state-manager/types.d.ts.map +1 -0
- package/dist/features/state-manager/types.js +30 -0
- package/dist/features/state-manager/types.js.map +1 -0
- package/dist/features/task-decomposer/index.d.ts +33 -0
- package/dist/features/task-decomposer/index.d.ts.map +1 -0
- package/dist/features/task-decomposer/index.js +698 -0
- package/dist/features/task-decomposer/index.js.map +1 -0
- package/dist/features/task-decomposer/types.d.ts +133 -0
- package/dist/features/task-decomposer/types.d.ts.map +1 -0
- package/dist/features/task-decomposer/types.js +8 -0
- package/dist/features/task-decomposer/types.js.map +1 -0
- package/dist/features/verification/example.d.ts +49 -0
- package/dist/features/verification/example.d.ts.map +1 -0
- package/dist/features/verification/example.js +235 -0
- package/dist/features/verification/example.js.map +1 -0
- package/dist/features/verification/index.d.ts +97 -0
- package/dist/features/verification/index.d.ts.map +1 -0
- package/dist/features/verification/index.js +439 -0
- package/dist/features/verification/index.js.map +1 -0
- package/dist/features/verification/types.d.ts +142 -0
- package/dist/features/verification/types.d.ts.map +1 -0
- package/dist/features/verification/types.js +7 -0
- package/dist/features/verification/types.js.map +1 -0
- package/dist/hooks/agent-usage-reminder/constants.d.ts.map +1 -1
- package/dist/hooks/agent-usage-reminder/constants.js +0 -1
- package/dist/hooks/agent-usage-reminder/constants.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/cancel.test.js +4 -4
- package/dist/hooks/autopilot/__tests__/cancel.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/summary.test.js +1 -1
- package/dist/hooks/autopilot/__tests__/summary.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/transition.test.js +1 -2
- package/dist/hooks/autopilot/__tests__/transition.test.js.map +1 -1
- package/dist/hooks/autopilot/cancel.js +2 -2
- package/dist/hooks/autopilot/cancel.js.map +1 -1
- package/dist/hooks/autopilot/enforcement.d.ts +16 -2
- package/dist/hooks/autopilot/enforcement.d.ts.map +1 -1
- package/dist/hooks/autopilot/enforcement.js +78 -4
- package/dist/hooks/autopilot/enforcement.js.map +1 -1
- package/dist/hooks/autopilot/index.d.ts +3 -6
- package/dist/hooks/autopilot/index.d.ts.map +1 -1
- package/dist/hooks/autopilot/index.js +6 -12
- package/dist/hooks/autopilot/index.js.map +1 -1
- package/dist/hooks/autopilot/state.d.ts +36 -2
- package/dist/hooks/autopilot/state.d.ts.map +1 -1
- package/dist/hooks/autopilot/state.js +216 -2
- package/dist/hooks/autopilot/state.js.map +1 -1
- package/dist/hooks/autopilot/validation.d.ts +23 -2
- package/dist/hooks/autopilot/validation.d.ts.map +1 -1
- package/dist/hooks/autopilot/validation.js +158 -1
- package/dist/hooks/autopilot/validation.js.map +1 -1
- package/dist/hooks/bridge.js +3 -3
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/index.d.ts +5 -9
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +31 -21
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/promotion.js +1 -1
- package/dist/hooks/learner/promotion.js.map +1 -1
- package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
- package/dist/hooks/persistent-mode/index.js +2 -3
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/ralph/index.d.ts +11 -0
- package/dist/hooks/ralph/index.d.ts.map +1 -0
- package/dist/hooks/ralph/index.js +53 -0
- package/dist/hooks/ralph/index.js.map +1 -0
- package/dist/hooks/ralph/loop.d.ts +116 -0
- package/dist/hooks/ralph/loop.d.ts.map +1 -0
- package/dist/hooks/ralph/loop.js +322 -0
- package/dist/hooks/ralph/loop.js.map +1 -0
- package/dist/hooks/ralph/prd.d.ts +130 -0
- package/dist/hooks/ralph/prd.d.ts.map +1 -0
- package/dist/hooks/ralph/prd.js +310 -0
- package/dist/hooks/ralph/prd.js.map +1 -0
- package/dist/hooks/ralph/progress.d.ts +102 -0
- package/dist/hooks/ralph/progress.d.ts.map +1 -0
- package/dist/hooks/ralph/progress.js +408 -0
- package/dist/hooks/ralph/progress.js.map +1 -0
- package/dist/hooks/ralph/verifier.d.ts +72 -0
- package/dist/hooks/ralph/verifier.d.ts.map +1 -0
- package/dist/hooks/ralph/verifier.js +223 -0
- package/dist/hooks/ralph/verifier.js.map +1 -0
- package/dist/hooks/recovery/constants.d.ts +114 -0
- package/dist/hooks/recovery/constants.d.ts.map +1 -0
- package/dist/hooks/recovery/constants.js +227 -0
- package/dist/hooks/recovery/constants.js.map +1 -0
- package/dist/hooks/recovery/context-window.d.ts +24 -0
- package/dist/hooks/recovery/context-window.d.ts.map +1 -0
- package/dist/hooks/recovery/context-window.js +321 -0
- package/dist/hooks/recovery/context-window.js.map +1 -0
- package/dist/hooks/recovery/edit-error.d.ts +24 -0
- package/dist/hooks/recovery/edit-error.d.ts.map +1 -0
- package/dist/hooks/recovery/edit-error.js +56 -0
- package/dist/hooks/recovery/edit-error.js.map +1 -0
- package/dist/hooks/recovery/index.d.ts +102 -0
- package/dist/hooks/recovery/index.d.ts.map +1 -0
- package/dist/hooks/recovery/index.js +166 -0
- package/dist/hooks/recovery/index.js.map +1 -0
- package/dist/hooks/recovery/session-recovery.d.ts +24 -0
- package/dist/hooks/recovery/session-recovery.d.ts.map +1 -0
- package/dist/hooks/recovery/session-recovery.js +281 -0
- package/dist/hooks/recovery/session-recovery.js.map +1 -0
- package/dist/hooks/recovery/storage.d.ts +75 -0
- package/dist/hooks/recovery/storage.d.ts.map +1 -0
- package/dist/hooks/recovery/storage.js +382 -0
- package/dist/hooks/recovery/storage.js.map +1 -0
- package/dist/hooks/recovery/types.d.ts +196 -0
- package/dist/hooks/recovery/types.d.ts.map +1 -0
- package/dist/hooks/recovery/types.js +32 -0
- package/dist/hooks/recovery/types.js.map +1 -0
- package/dist/hooks/ultrapilot/index.d.ts +90 -0
- package/dist/hooks/ultrapilot/index.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/index.js +310 -0
- package/dist/hooks/ultrapilot/index.js.map +1 -0
- package/dist/hooks/ultrapilot/state.d.ts +72 -0
- package/dist/hooks/ultrapilot/state.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/state.js +258 -0
- package/dist/hooks/ultrapilot/state.js.map +1 -0
- package/dist/hooks/ultrapilot/types.d.ts +113 -0
- package/dist/hooks/ultrapilot/types.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/types.js +36 -0
- package/dist/hooks/ultrapilot/types.js.map +1 -0
- package/dist/hooks/ultraqa/index.d.ts +94 -0
- package/dist/hooks/ultraqa/index.d.ts.map +1 -0
- package/dist/hooks/ultraqa/index.js +216 -0
- package/dist/hooks/ultraqa/index.js.map +1 -0
- package/dist/hooks/ultrawork/index.d.ts +62 -0
- package/dist/hooks/ultrawork/index.d.ts.map +1 -0
- package/dist/hooks/ultrawork/index.js +208 -0
- package/dist/hooks/ultrawork/index.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +1 -1
- package/dist/installer/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/servers.d.ts +2 -18
- package/dist/mcp/servers.d.ts.map +1 -1
- package/dist/mcp/servers.js +4 -36
- package/dist/mcp/servers.js.map +1 -1
- package/dist/shared/types.d.ts +1 -3
- package/dist/shared/types.d.ts.map +1 -1
- package/docs/CLAUDE.md +170 -44
- package/docs/DELEGATION-ENFORCER.md +282 -0
- package/docs/FULL-README.md +1 -1
- package/docs/LOCAL_PLUGIN_INSTALL.md +1 -1
- package/docs/MIGRATION.md +298 -104
- package/package.json +2 -2
- package/scripts/test-mutual-exclusion.ts +1 -1
- package/skills/analyze/SKILL.md +0 -1
- package/skills/autopilot/SKILL.md +0 -1
- package/skills/cancel/SKILL.md +580 -0
- package/skills/cancel-autopilot/SKILL.md +0 -1
- package/skills/cancel-ecomode/SKILL.md +41 -0
- package/skills/cancel-ralph/SKILL.md +0 -1
- package/skills/cancel-ultraqa/SKILL.md +0 -1
- package/skills/cancel-ultrawork/SKILL.md +0 -1
- package/skills/deepinit/SKILL.md +0 -1
- package/skills/deepsearch/SKILL.md +0 -1
- package/skills/doctor/SKILL.md +0 -1
- package/skills/ecomode/SKILL.md +128 -0
- package/skills/frontend-ui-ux/SKILL.md +0 -1
- package/skills/git-master/SKILL.md +0 -1
- package/skills/help/SKILL.md +1 -2
- package/skills/hud/SKILL.md +0 -1
- package/skills/learner/SKILL.md +0 -1
- package/skills/mcp-setup/SKILL.md +8 -7
- package/skills/note/SKILL.md +0 -1
- package/skills/omc-default/SKILL.md +0 -1
- package/skills/omc-default-global/SKILL.md +0 -1
- package/skills/omc-setup/SKILL.md +176 -10
- package/skills/orchestrate/SKILL.md +0 -1
- package/skills/pipeline/SKILL.md +417 -0
- package/skills/plan/SKILL.md +138 -21
- package/skills/planner/SKILL.md +0 -1
- package/skills/ralph/SKILL.md +65 -1
- package/skills/ralph-init/SKILL.md +0 -1
- package/skills/ralplan/SKILL.md +0 -1
- package/skills/release/SKILL.md +0 -1
- package/skills/research/SKILL.md +0 -1
- package/skills/review/SKILL.md +0 -1
- package/skills/swarm/SKILL.md +349 -0
- package/skills/tdd/SKILL.md +0 -1
- package/skills/ultrapilot/SKILL.md +563 -0
- package/skills/ultraqa/SKILL.md +0 -1
- package/skills/ultrawork/SKILL.md +0 -1
- package/docs/MIGRATION-v3.md +0 -186
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Decomposition Engine
|
|
3
|
+
*
|
|
4
|
+
* Analyzes tasks and splits them into parallelizable components
|
|
5
|
+
* with non-overlapping file ownership.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Main entry point: decompose a task into parallelizable subtasks
|
|
9
|
+
*/
|
|
10
|
+
export async function decomposeTask(task, projectContext = { rootDir: process.cwd() }) {
|
|
11
|
+
// Step 1: Analyze the task
|
|
12
|
+
const analysis = analyzeTask(task, projectContext);
|
|
13
|
+
// Step 2: Identify parallelizable components
|
|
14
|
+
const components = identifyComponents(analysis, projectContext);
|
|
15
|
+
// Step 3: Identify shared files
|
|
16
|
+
const sharedFiles = identifySharedFiles(components, projectContext);
|
|
17
|
+
// Step 4: Generate subtasks with file ownership
|
|
18
|
+
const subtasks = generateSubtasks(components, analysis, projectContext);
|
|
19
|
+
// Step 5: Assign non-overlapping file ownership
|
|
20
|
+
assignFileOwnership(subtasks, sharedFiles, projectContext);
|
|
21
|
+
// Step 6: Determine execution order
|
|
22
|
+
const executionOrder = calculateExecutionOrder(subtasks);
|
|
23
|
+
// Step 7: Validate decomposition
|
|
24
|
+
const warnings = validateDecomposition(subtasks, sharedFiles);
|
|
25
|
+
return {
|
|
26
|
+
analysis,
|
|
27
|
+
components,
|
|
28
|
+
subtasks,
|
|
29
|
+
sharedFiles,
|
|
30
|
+
executionOrder,
|
|
31
|
+
strategy: explainStrategy(analysis, components),
|
|
32
|
+
warnings
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Analyze task to understand structure and requirements
|
|
37
|
+
*/
|
|
38
|
+
export function analyzeTask(task, context) {
|
|
39
|
+
const lower = task.toLowerCase();
|
|
40
|
+
// Detect task type
|
|
41
|
+
const type = detectTaskType(lower);
|
|
42
|
+
// Detect complexity signals
|
|
43
|
+
const complexity = estimateComplexity(lower, type);
|
|
44
|
+
// Extract areas and technologies
|
|
45
|
+
const areas = extractAreas(lower, type);
|
|
46
|
+
const technologies = extractTechnologies(lower, context);
|
|
47
|
+
const filePatterns = extractFilePatterns(lower, context);
|
|
48
|
+
// Detect dependencies
|
|
49
|
+
const dependencies = analyzeDependencies(areas, type);
|
|
50
|
+
// Determine if parallelizable
|
|
51
|
+
const isParallelizable = complexity > 0.3 && areas.length >= 2;
|
|
52
|
+
const estimatedComponents = isParallelizable
|
|
53
|
+
? Math.max(2, Math.min(areas.length, 6))
|
|
54
|
+
: 1;
|
|
55
|
+
return {
|
|
56
|
+
task,
|
|
57
|
+
type,
|
|
58
|
+
complexity,
|
|
59
|
+
isParallelizable,
|
|
60
|
+
estimatedComponents,
|
|
61
|
+
areas,
|
|
62
|
+
technologies,
|
|
63
|
+
filePatterns,
|
|
64
|
+
dependencies
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Identify parallelizable components from analysis
|
|
69
|
+
*/
|
|
70
|
+
export function identifyComponents(analysis, context) {
|
|
71
|
+
if (!analysis.isParallelizable) {
|
|
72
|
+
// Single component for non-parallelizable tasks
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
id: 'main',
|
|
76
|
+
name: 'Main Task',
|
|
77
|
+
role: 'module',
|
|
78
|
+
description: analysis.task,
|
|
79
|
+
canParallelize: false,
|
|
80
|
+
dependencies: [],
|
|
81
|
+
effort: analysis.complexity,
|
|
82
|
+
technologies: analysis.technologies
|
|
83
|
+
}
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
// Select appropriate strategy
|
|
87
|
+
const strategy = selectStrategy(analysis);
|
|
88
|
+
const result = strategy.decompose(analysis, context);
|
|
89
|
+
return result.components;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Generate subtasks from components
|
|
93
|
+
*/
|
|
94
|
+
export function generateSubtasks(components, analysis, context) {
|
|
95
|
+
return components.map((component) => {
|
|
96
|
+
const subtask = {
|
|
97
|
+
id: component.id,
|
|
98
|
+
name: component.name,
|
|
99
|
+
component,
|
|
100
|
+
prompt: generatePromptForComponent(component, analysis, context),
|
|
101
|
+
ownership: {
|
|
102
|
+
componentId: component.id,
|
|
103
|
+
patterns: [],
|
|
104
|
+
files: [],
|
|
105
|
+
potentialConflicts: []
|
|
106
|
+
},
|
|
107
|
+
blockedBy: component.dependencies,
|
|
108
|
+
agentType: selectAgentType(component),
|
|
109
|
+
modelTier: selectModelTier(component),
|
|
110
|
+
acceptanceCriteria: generateAcceptanceCriteria(component, analysis),
|
|
111
|
+
verification: generateVerificationSteps(component, analysis)
|
|
112
|
+
};
|
|
113
|
+
return subtask;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Assign non-overlapping file ownership to subtasks
|
|
118
|
+
*/
|
|
119
|
+
export function assignFileOwnership(subtasks, sharedFiles, context) {
|
|
120
|
+
const assignments = new Map();
|
|
121
|
+
for (const subtask of subtasks) {
|
|
122
|
+
const patterns = inferFilePatterns(subtask.component, context);
|
|
123
|
+
const files = inferSpecificFiles(subtask.component, context);
|
|
124
|
+
subtask.ownership.patterns = patterns;
|
|
125
|
+
subtask.ownership.files = files;
|
|
126
|
+
// Track assignments for conflict detection
|
|
127
|
+
for (const pattern of patterns) {
|
|
128
|
+
if (!assignments.has(pattern)) {
|
|
129
|
+
assignments.set(pattern, new Set());
|
|
130
|
+
}
|
|
131
|
+
assignments.get(pattern).add(subtask.id);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Detect conflicts
|
|
135
|
+
for (const subtask of subtasks) {
|
|
136
|
+
const conflicts = [];
|
|
137
|
+
for (const pattern of subtask.ownership.patterns) {
|
|
138
|
+
const owners = assignments.get(pattern);
|
|
139
|
+
if (owners && owners.size > 1) {
|
|
140
|
+
// Check if it's a shared file
|
|
141
|
+
const isShared = sharedFiles.some((sf) => sf.pattern === pattern);
|
|
142
|
+
if (!isShared) {
|
|
143
|
+
conflicts.push(pattern);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
subtask.ownership.potentialConflicts = conflicts;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Identify files that should be managed by coordinator
|
|
152
|
+
*/
|
|
153
|
+
export function identifySharedFiles(components, context) {
|
|
154
|
+
const sharedFiles = [];
|
|
155
|
+
// Common shared files
|
|
156
|
+
const commonShared = [
|
|
157
|
+
'package.json',
|
|
158
|
+
'tsconfig.json',
|
|
159
|
+
'package-lock.json',
|
|
160
|
+
'yarn.lock',
|
|
161
|
+
'pnpm-lock.yaml',
|
|
162
|
+
'README.md',
|
|
163
|
+
'.gitignore',
|
|
164
|
+
'.env',
|
|
165
|
+
'.env.example',
|
|
166
|
+
'docker-compose.yml',
|
|
167
|
+
'Dockerfile'
|
|
168
|
+
];
|
|
169
|
+
for (const file of commonShared) {
|
|
170
|
+
const sharedBy = components
|
|
171
|
+
.filter((c) => c.role !== 'coordinator')
|
|
172
|
+
.map((c) => c.id);
|
|
173
|
+
if (sharedBy.length > 0) {
|
|
174
|
+
sharedFiles.push({
|
|
175
|
+
pattern: file,
|
|
176
|
+
reason: 'Common configuration file',
|
|
177
|
+
sharedBy,
|
|
178
|
+
requiresCoordinator: true
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Detect framework-specific shared files
|
|
183
|
+
if (context.technologies?.includes('react') || context.technologies?.includes('next')) {
|
|
184
|
+
sharedFiles.push({
|
|
185
|
+
pattern: 'src/types/**',
|
|
186
|
+
reason: 'Shared TypeScript types',
|
|
187
|
+
sharedBy: components.map((c) => c.id),
|
|
188
|
+
requiresCoordinator: false
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return sharedFiles;
|
|
192
|
+
}
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Helper Functions
|
|
195
|
+
// ============================================================================
|
|
196
|
+
function detectTaskType(task) {
|
|
197
|
+
if (task.includes('fullstack') ||
|
|
198
|
+
task.includes('full stack') ||
|
|
199
|
+
(task.includes('frontend') && task.includes('backend'))) {
|
|
200
|
+
return 'fullstack-app';
|
|
201
|
+
}
|
|
202
|
+
if (task.includes('refactor') || task.includes('restructure')) {
|
|
203
|
+
return 'refactoring';
|
|
204
|
+
}
|
|
205
|
+
if (task.includes('fix') ||
|
|
206
|
+
task.includes('bug') ||
|
|
207
|
+
task.includes('error') ||
|
|
208
|
+
task.includes('issue')) {
|
|
209
|
+
return 'bug-fix';
|
|
210
|
+
}
|
|
211
|
+
if (task.includes('feature') ||
|
|
212
|
+
task.includes('add') ||
|
|
213
|
+
task.includes('implement')) {
|
|
214
|
+
return 'feature';
|
|
215
|
+
}
|
|
216
|
+
if (task.includes('test') || task.includes('testing')) {
|
|
217
|
+
return 'testing';
|
|
218
|
+
}
|
|
219
|
+
if (task.includes('document') || task.includes('docs')) {
|
|
220
|
+
return 'documentation';
|
|
221
|
+
}
|
|
222
|
+
if (task.includes('deploy') ||
|
|
223
|
+
task.includes('infra') ||
|
|
224
|
+
task.includes('ci/cd')) {
|
|
225
|
+
return 'infrastructure';
|
|
226
|
+
}
|
|
227
|
+
if (task.includes('migrate') || task.includes('migration')) {
|
|
228
|
+
return 'migration';
|
|
229
|
+
}
|
|
230
|
+
if (task.includes('optimize') || task.includes('performance')) {
|
|
231
|
+
return 'optimization';
|
|
232
|
+
}
|
|
233
|
+
return 'unknown';
|
|
234
|
+
}
|
|
235
|
+
function estimateComplexity(task, type) {
|
|
236
|
+
let score = 0.3; // Base complexity
|
|
237
|
+
// Task type complexity
|
|
238
|
+
const typeComplexity = {
|
|
239
|
+
'fullstack-app': 0.9,
|
|
240
|
+
refactoring: 0.7,
|
|
241
|
+
'bug-fix': 0.4,
|
|
242
|
+
feature: 0.6,
|
|
243
|
+
testing: 0.5,
|
|
244
|
+
documentation: 0.3,
|
|
245
|
+
infrastructure: 0.8,
|
|
246
|
+
migration: 0.8,
|
|
247
|
+
optimization: 0.7,
|
|
248
|
+
unknown: 0.5
|
|
249
|
+
};
|
|
250
|
+
score = typeComplexity[type];
|
|
251
|
+
// Length factor
|
|
252
|
+
if (task.length > 200)
|
|
253
|
+
score += 0.1;
|
|
254
|
+
if (task.length > 500)
|
|
255
|
+
score += 0.1;
|
|
256
|
+
// Complexity keywords
|
|
257
|
+
const complexKeywords = [
|
|
258
|
+
'multiple',
|
|
259
|
+
'complex',
|
|
260
|
+
'advanced',
|
|
261
|
+
'integrate',
|
|
262
|
+
'system',
|
|
263
|
+
'architecture',
|
|
264
|
+
'scalable',
|
|
265
|
+
'real-time',
|
|
266
|
+
'distributed'
|
|
267
|
+
];
|
|
268
|
+
for (const keyword of complexKeywords) {
|
|
269
|
+
if (task.includes(keyword)) {
|
|
270
|
+
score += 0.05;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return Math.min(1, score);
|
|
274
|
+
}
|
|
275
|
+
function extractAreas(task, type) {
|
|
276
|
+
const areas = [];
|
|
277
|
+
const areaKeywords = {
|
|
278
|
+
frontend: ['frontend', 'ui', 'react', 'vue', 'angular', 'component'],
|
|
279
|
+
backend: ['backend', 'server', 'api', 'endpoint', 'service'],
|
|
280
|
+
database: ['database', 'db', 'schema', 'migration', 'model'],
|
|
281
|
+
auth: ['auth', 'authentication', 'login', 'user'],
|
|
282
|
+
testing: ['test', 'testing', 'spec', 'unit test'],
|
|
283
|
+
docs: ['document', 'docs', 'readme', 'guide'],
|
|
284
|
+
config: ['config', 'setup', 'environment']
|
|
285
|
+
};
|
|
286
|
+
for (const [area, keywords] of Object.entries(areaKeywords)) {
|
|
287
|
+
if (keywords.some((kw) => task.includes(kw))) {
|
|
288
|
+
areas.push(area);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return areas.length > 0 ? areas : ['main'];
|
|
292
|
+
}
|
|
293
|
+
function extractTechnologies(task, context) {
|
|
294
|
+
const techs = [];
|
|
295
|
+
const techKeywords = [
|
|
296
|
+
'react',
|
|
297
|
+
'vue',
|
|
298
|
+
'angular',
|
|
299
|
+
'next',
|
|
300
|
+
'nuxt',
|
|
301
|
+
'express',
|
|
302
|
+
'fastify',
|
|
303
|
+
'nest',
|
|
304
|
+
'typescript',
|
|
305
|
+
'javascript',
|
|
306
|
+
'node',
|
|
307
|
+
'postgres',
|
|
308
|
+
'mysql',
|
|
309
|
+
'mongodb',
|
|
310
|
+
'redis',
|
|
311
|
+
'docker',
|
|
312
|
+
'kubernetes'
|
|
313
|
+
];
|
|
314
|
+
for (const tech of techKeywords) {
|
|
315
|
+
if (task.includes(tech)) {
|
|
316
|
+
techs.push(tech);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Add from context
|
|
320
|
+
if (context.technologies) {
|
|
321
|
+
techs.push(...context.technologies);
|
|
322
|
+
}
|
|
323
|
+
return Array.from(new Set(techs));
|
|
324
|
+
}
|
|
325
|
+
function extractFilePatterns(task, context) {
|
|
326
|
+
const patterns = [];
|
|
327
|
+
// Look for explicit paths
|
|
328
|
+
const pathRegex = /(?:^|\s)([\w\-/]+\.[\w]+)/g;
|
|
329
|
+
let match;
|
|
330
|
+
while ((match = pathRegex.exec(task)) !== null) {
|
|
331
|
+
patterns.push(match[1]);
|
|
332
|
+
}
|
|
333
|
+
// Common directory patterns
|
|
334
|
+
if (task.includes('src'))
|
|
335
|
+
patterns.push('src/**');
|
|
336
|
+
if (task.includes('test'))
|
|
337
|
+
patterns.push('**/*.test.ts');
|
|
338
|
+
if (task.includes('component'))
|
|
339
|
+
patterns.push('**/components/**');
|
|
340
|
+
return patterns;
|
|
341
|
+
}
|
|
342
|
+
function analyzeDependencies(areas, type) {
|
|
343
|
+
const deps = [];
|
|
344
|
+
// Common dependencies
|
|
345
|
+
if (areas.includes('frontend') && areas.includes('backend')) {
|
|
346
|
+
deps.push({ from: 'frontend', to: 'backend' });
|
|
347
|
+
}
|
|
348
|
+
if (areas.includes('backend') && areas.includes('database')) {
|
|
349
|
+
deps.push({ from: 'backend', to: 'database' });
|
|
350
|
+
}
|
|
351
|
+
if (areas.includes('testing')) {
|
|
352
|
+
// Testing depends on everything else
|
|
353
|
+
for (const area of areas) {
|
|
354
|
+
if (area !== 'testing') {
|
|
355
|
+
deps.push({ from: 'testing', to: area });
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return deps;
|
|
360
|
+
}
|
|
361
|
+
function selectStrategy(analysis) {
|
|
362
|
+
switch (analysis.type) {
|
|
363
|
+
case 'fullstack-app':
|
|
364
|
+
return fullstackStrategy;
|
|
365
|
+
case 'refactoring':
|
|
366
|
+
return refactoringStrategy;
|
|
367
|
+
case 'bug-fix':
|
|
368
|
+
return bugFixStrategy;
|
|
369
|
+
case 'feature':
|
|
370
|
+
return featureStrategy;
|
|
371
|
+
default:
|
|
372
|
+
return defaultStrategy;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// ============================================================================
|
|
376
|
+
// Decomposition Strategies
|
|
377
|
+
// ============================================================================
|
|
378
|
+
const fullstackStrategy = {
|
|
379
|
+
name: 'Fullstack App',
|
|
380
|
+
applicableTypes: ['fullstack-app'],
|
|
381
|
+
decompose: (analysis, context) => {
|
|
382
|
+
const components = [];
|
|
383
|
+
// Frontend component
|
|
384
|
+
if (analysis.areas.includes('frontend') || analysis.areas.includes('ui')) {
|
|
385
|
+
components.push({
|
|
386
|
+
id: 'frontend',
|
|
387
|
+
name: 'Frontend',
|
|
388
|
+
role: 'frontend',
|
|
389
|
+
description: 'Frontend UI and components',
|
|
390
|
+
canParallelize: true,
|
|
391
|
+
dependencies: ['backend'],
|
|
392
|
+
effort: 0.4,
|
|
393
|
+
technologies: analysis.technologies.filter((t) => ['react', 'vue', 'angular', 'next'].includes(t))
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// Backend component
|
|
397
|
+
if (analysis.areas.includes('backend') || analysis.areas.includes('api')) {
|
|
398
|
+
components.push({
|
|
399
|
+
id: 'backend',
|
|
400
|
+
name: 'Backend',
|
|
401
|
+
role: 'backend',
|
|
402
|
+
description: 'Backend API and business logic',
|
|
403
|
+
canParallelize: true,
|
|
404
|
+
dependencies: analysis.areas.includes('database') ? ['database'] : [],
|
|
405
|
+
effort: 0.4,
|
|
406
|
+
technologies: analysis.technologies.filter((t) => ['express', 'fastify', 'nest', 'node'].includes(t))
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
// Database component
|
|
410
|
+
if (analysis.areas.includes('database')) {
|
|
411
|
+
components.push({
|
|
412
|
+
id: 'database',
|
|
413
|
+
name: 'Database',
|
|
414
|
+
role: 'database',
|
|
415
|
+
description: 'Database schema and migrations',
|
|
416
|
+
canParallelize: true,
|
|
417
|
+
dependencies: [],
|
|
418
|
+
effort: 0.2,
|
|
419
|
+
technologies: analysis.technologies.filter((t) => ['postgres', 'mysql', 'mongodb'].includes(t))
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
// Shared/coordinator component
|
|
423
|
+
components.push({
|
|
424
|
+
id: 'shared',
|
|
425
|
+
name: 'Shared',
|
|
426
|
+
role: 'shared',
|
|
427
|
+
description: 'Shared types, utilities, and configuration',
|
|
428
|
+
canParallelize: true,
|
|
429
|
+
dependencies: [],
|
|
430
|
+
effort: 0.2,
|
|
431
|
+
technologies: []
|
|
432
|
+
});
|
|
433
|
+
return { components, sharedFiles: [] };
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
const refactoringStrategy = {
|
|
437
|
+
name: 'Refactoring',
|
|
438
|
+
applicableTypes: ['refactoring'],
|
|
439
|
+
decompose: (analysis, context) => {
|
|
440
|
+
const components = [];
|
|
441
|
+
// Group by module/directory
|
|
442
|
+
for (const area of analysis.areas) {
|
|
443
|
+
components.push({
|
|
444
|
+
id: area,
|
|
445
|
+
name: `Refactor ${area}`,
|
|
446
|
+
role: 'module',
|
|
447
|
+
description: `Refactor ${area} module`,
|
|
448
|
+
canParallelize: true,
|
|
449
|
+
dependencies: [],
|
|
450
|
+
effort: analysis.complexity / analysis.areas.length,
|
|
451
|
+
technologies: []
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return { components, sharedFiles: [] };
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
const bugFixStrategy = {
|
|
458
|
+
name: 'Bug Fix',
|
|
459
|
+
applicableTypes: ['bug-fix'],
|
|
460
|
+
decompose: (analysis, context) => {
|
|
461
|
+
// Bug fixes usually not parallelizable
|
|
462
|
+
const components = [
|
|
463
|
+
{
|
|
464
|
+
id: 'bugfix',
|
|
465
|
+
name: 'Fix Bug',
|
|
466
|
+
role: 'module',
|
|
467
|
+
description: analysis.task,
|
|
468
|
+
canParallelize: false,
|
|
469
|
+
dependencies: [],
|
|
470
|
+
effort: analysis.complexity,
|
|
471
|
+
technologies: []
|
|
472
|
+
}
|
|
473
|
+
];
|
|
474
|
+
return { components, sharedFiles: [] };
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
const featureStrategy = {
|
|
478
|
+
name: 'Feature',
|
|
479
|
+
applicableTypes: ['feature'],
|
|
480
|
+
decompose: (analysis, context) => {
|
|
481
|
+
const components = [];
|
|
482
|
+
// Break down by feature area
|
|
483
|
+
for (const area of analysis.areas) {
|
|
484
|
+
components.push({
|
|
485
|
+
id: area,
|
|
486
|
+
name: `Implement ${area}`,
|
|
487
|
+
role: area,
|
|
488
|
+
description: `Implement ${area} for the feature`,
|
|
489
|
+
canParallelize: true,
|
|
490
|
+
dependencies: [],
|
|
491
|
+
effort: analysis.complexity / analysis.areas.length,
|
|
492
|
+
technologies: []
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
return { components, sharedFiles: [] };
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
const defaultStrategy = {
|
|
499
|
+
name: 'Default',
|
|
500
|
+
applicableTypes: [],
|
|
501
|
+
decompose: (analysis, context) => {
|
|
502
|
+
const components = [
|
|
503
|
+
{
|
|
504
|
+
id: 'main',
|
|
505
|
+
name: 'Main Task',
|
|
506
|
+
role: 'module',
|
|
507
|
+
description: analysis.task,
|
|
508
|
+
canParallelize: false,
|
|
509
|
+
dependencies: [],
|
|
510
|
+
effort: analysis.complexity,
|
|
511
|
+
technologies: []
|
|
512
|
+
}
|
|
513
|
+
];
|
|
514
|
+
return { components, sharedFiles: [] };
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
// ============================================================================
|
|
518
|
+
// Subtask Generation Helpers
|
|
519
|
+
// ============================================================================
|
|
520
|
+
function generatePromptForComponent(component, analysis, context) {
|
|
521
|
+
let prompt = `${component.description}\n\n`;
|
|
522
|
+
prompt += `CONTEXT:\n`;
|
|
523
|
+
prompt += `- Task Type: ${analysis.type}\n`;
|
|
524
|
+
prompt += `- Component Role: ${component.role}\n`;
|
|
525
|
+
if (component.technologies.length > 0) {
|
|
526
|
+
prompt += `- Technologies: ${component.technologies.join(', ')}\n`;
|
|
527
|
+
}
|
|
528
|
+
prompt += `\nYour responsibilities:\n`;
|
|
529
|
+
prompt += `1. ${component.description}\n`;
|
|
530
|
+
prompt += `2. Ensure code quality and follow best practices\n`;
|
|
531
|
+
prompt += `3. Write tests for your changes\n`;
|
|
532
|
+
prompt += `4. Update documentation as needed\n`;
|
|
533
|
+
if (component.dependencies.length > 0) {
|
|
534
|
+
prompt += `\nDependencies: This component depends on ${component.dependencies.join(', ')} completing first.\n`;
|
|
535
|
+
}
|
|
536
|
+
return prompt;
|
|
537
|
+
}
|
|
538
|
+
function selectAgentType(component) {
|
|
539
|
+
const roleToAgent = {
|
|
540
|
+
frontend: 'oh-my-claudecode:designer',
|
|
541
|
+
backend: 'oh-my-claudecode:executor',
|
|
542
|
+
database: 'oh-my-claudecode:executor',
|
|
543
|
+
api: 'oh-my-claudecode:executor',
|
|
544
|
+
ui: 'oh-my-claudecode:designer',
|
|
545
|
+
shared: 'oh-my-claudecode:executor',
|
|
546
|
+
coordinator: 'oh-my-claudecode:architect',
|
|
547
|
+
testing: 'oh-my-claudecode:qa-tester',
|
|
548
|
+
docs: 'oh-my-claudecode:writer',
|
|
549
|
+
config: 'oh-my-claudecode:executor',
|
|
550
|
+
module: 'oh-my-claudecode:executor'
|
|
551
|
+
};
|
|
552
|
+
return roleToAgent[component.role] || 'oh-my-claudecode:executor';
|
|
553
|
+
}
|
|
554
|
+
function selectModelTier(component) {
|
|
555
|
+
if (component.effort < 0.3)
|
|
556
|
+
return 'low';
|
|
557
|
+
if (component.effort < 0.7)
|
|
558
|
+
return 'medium';
|
|
559
|
+
return 'high';
|
|
560
|
+
}
|
|
561
|
+
function generateAcceptanceCriteria(component, analysis) {
|
|
562
|
+
const criteria = [];
|
|
563
|
+
criteria.push(`${component.name} implementation is complete`);
|
|
564
|
+
criteria.push('Code compiles without errors');
|
|
565
|
+
criteria.push('Tests pass');
|
|
566
|
+
if (component.role === 'frontend' || component.role === 'ui') {
|
|
567
|
+
criteria.push('UI components render correctly');
|
|
568
|
+
criteria.push('Responsive design works on all screen sizes');
|
|
569
|
+
}
|
|
570
|
+
if (component.role === 'backend' || component.role === 'api') {
|
|
571
|
+
criteria.push('API endpoints return expected responses');
|
|
572
|
+
criteria.push('Error handling is implemented');
|
|
573
|
+
}
|
|
574
|
+
if (component.role === 'database') {
|
|
575
|
+
criteria.push('Database schema is correct');
|
|
576
|
+
criteria.push('Migrations run successfully');
|
|
577
|
+
}
|
|
578
|
+
return criteria;
|
|
579
|
+
}
|
|
580
|
+
function generateVerificationSteps(component, analysis) {
|
|
581
|
+
const steps = [];
|
|
582
|
+
steps.push('Run TypeScript compiler: tsc --noEmit');
|
|
583
|
+
steps.push('Run linter: eslint');
|
|
584
|
+
steps.push('Run tests: npm test');
|
|
585
|
+
if (component.role === 'frontend' || component.role === 'ui') {
|
|
586
|
+
steps.push('Visual inspection of UI components');
|
|
587
|
+
}
|
|
588
|
+
if (component.role === 'backend' || component.role === 'api') {
|
|
589
|
+
steps.push('Test API endpoints with curl or Postman');
|
|
590
|
+
}
|
|
591
|
+
return steps;
|
|
592
|
+
}
|
|
593
|
+
function inferFilePatterns(component, context) {
|
|
594
|
+
const patterns = [];
|
|
595
|
+
switch (component.role) {
|
|
596
|
+
case 'frontend':
|
|
597
|
+
case 'ui':
|
|
598
|
+
patterns.push('src/components/**', 'src/pages/**', 'src/styles/**');
|
|
599
|
+
break;
|
|
600
|
+
case 'backend':
|
|
601
|
+
case 'api':
|
|
602
|
+
patterns.push('src/api/**', 'src/routes/**', 'src/controllers/**');
|
|
603
|
+
break;
|
|
604
|
+
case 'database':
|
|
605
|
+
patterns.push('src/db/**', 'src/models/**', 'migrations/**');
|
|
606
|
+
break;
|
|
607
|
+
case 'shared':
|
|
608
|
+
patterns.push('src/types/**', 'src/utils/**', 'src/lib/**');
|
|
609
|
+
break;
|
|
610
|
+
case 'testing':
|
|
611
|
+
patterns.push('**/*.test.ts', '**/*.spec.ts', 'tests/**');
|
|
612
|
+
break;
|
|
613
|
+
case 'docs':
|
|
614
|
+
patterns.push('docs/**', '*.md');
|
|
615
|
+
break;
|
|
616
|
+
default:
|
|
617
|
+
patterns.push(`src/${component.id}/**`);
|
|
618
|
+
}
|
|
619
|
+
return patterns;
|
|
620
|
+
}
|
|
621
|
+
function inferSpecificFiles(component, context) {
|
|
622
|
+
const files = [];
|
|
623
|
+
// Component-specific files can be added here
|
|
624
|
+
return files;
|
|
625
|
+
}
|
|
626
|
+
function calculateExecutionOrder(subtasks) {
|
|
627
|
+
const order = [];
|
|
628
|
+
const completed = new Set();
|
|
629
|
+
const remaining = new Set(subtasks.map((st) => st.id));
|
|
630
|
+
while (remaining.size > 0) {
|
|
631
|
+
const batch = [];
|
|
632
|
+
for (const subtask of subtasks) {
|
|
633
|
+
if (remaining.has(subtask.id)) {
|
|
634
|
+
// Check if all dependencies are completed
|
|
635
|
+
const canRun = subtask.blockedBy.every((dep) => completed.has(dep));
|
|
636
|
+
if (canRun) {
|
|
637
|
+
batch.push(subtask.id);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
if (batch.length === 0) {
|
|
642
|
+
// Circular dependency or error
|
|
643
|
+
order.push(Array.from(remaining));
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
order.push(batch);
|
|
647
|
+
for (const id of batch) {
|
|
648
|
+
remaining.delete(id);
|
|
649
|
+
completed.add(id);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return order;
|
|
653
|
+
}
|
|
654
|
+
function validateDecomposition(subtasks, sharedFiles) {
|
|
655
|
+
const warnings = [];
|
|
656
|
+
// Check for ownership overlaps
|
|
657
|
+
const patternOwners = new Map();
|
|
658
|
+
for (const subtask of subtasks) {
|
|
659
|
+
for (const pattern of subtask.ownership.patterns) {
|
|
660
|
+
if (!patternOwners.has(pattern)) {
|
|
661
|
+
patternOwners.set(pattern, []);
|
|
662
|
+
}
|
|
663
|
+
patternOwners.get(pattern).push(subtask.id);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
for (const [pattern, owners] of Array.from(patternOwners.entries())) {
|
|
667
|
+
if (owners.length > 1) {
|
|
668
|
+
const isShared = sharedFiles.some((sf) => sf.pattern === pattern);
|
|
669
|
+
if (!isShared) {
|
|
670
|
+
warnings.push(`Pattern "${pattern}" is owned by multiple subtasks: ${owners.join(', ')}`);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
// Check for subtasks with no file ownership
|
|
675
|
+
for (const subtask of subtasks) {
|
|
676
|
+
if (subtask.ownership.patterns.length === 0 &&
|
|
677
|
+
subtask.ownership.files.length === 0) {
|
|
678
|
+
warnings.push(`Subtask "${subtask.id}" has no file ownership assigned`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return warnings;
|
|
682
|
+
}
|
|
683
|
+
function explainStrategy(analysis, components) {
|
|
684
|
+
let explanation = `Task Type: ${analysis.type}\n`;
|
|
685
|
+
explanation += `Parallelizable: ${analysis.isParallelizable ? 'Yes' : 'No'}\n`;
|
|
686
|
+
explanation += `Components: ${components.length}\n\n`;
|
|
687
|
+
if (analysis.isParallelizable) {
|
|
688
|
+
explanation += `This task has been decomposed into ${components.length} parallel components:\n`;
|
|
689
|
+
for (const component of components) {
|
|
690
|
+
explanation += `- ${component.name} (${component.role})\n`;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
explanation += `This task is not suitable for parallelization and will be executed as a single component.\n`;
|
|
695
|
+
}
|
|
696
|
+
return explanation;
|
|
697
|
+
}
|
|
698
|
+
//# sourceMappingURL=index.js.map
|