musubi-sdd 5.1.0 → 5.6.1
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.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
|
@@ -15,33 +15,33 @@ const EventEmitter = require('events');
|
|
|
15
15
|
const DEFAULT_CONFIG = {
|
|
16
16
|
// Enable proactive optimization
|
|
17
17
|
enabled: true,
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
// Evaluation frequency (every N successful tasks)
|
|
20
20
|
evaluateEvery: 3,
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
// Minimum improvement threshold to trigger re-routing (percentage)
|
|
23
23
|
minImprovementThreshold: 0.15,
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
// Maximum time to spend on optimization (ms)
|
|
26
26
|
optimizationTimeout: 5000,
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
// Consider parallel execution opportunities
|
|
29
29
|
considerParallelization: true,
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
// Consider task merging opportunities
|
|
32
32
|
considerMerging: true,
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
// Consider task reordering for better dependency resolution
|
|
35
35
|
considerReordering: true,
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
// Consider skipping optional tasks when ahead of schedule
|
|
38
38
|
considerSkipping: false,
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
// Learning from past executions
|
|
41
41
|
learningEnabled: true,
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
// Maximum optimization history to keep
|
|
44
|
-
maxHistorySize: 100
|
|
44
|
+
maxHistorySize: 100,
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -79,7 +79,7 @@ class PathMetrics {
|
|
|
79
79
|
compareWith(other) {
|
|
80
80
|
const thisScore = this.getScore();
|
|
81
81
|
const otherScore = other.getScore();
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
if (otherScore === 0) return 0;
|
|
84
84
|
return (otherScore - thisScore) / otherScore;
|
|
85
85
|
}
|
|
@@ -120,16 +120,16 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
120
120
|
*/
|
|
121
121
|
constructor(llmProvider, options = {}) {
|
|
122
122
|
super();
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
this.llm = llmProvider;
|
|
125
125
|
this.config = { ...DEFAULT_CONFIG, ...options.config };
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
// State
|
|
128
128
|
this.successCount = 0;
|
|
129
129
|
this.optimizationHistory = [];
|
|
130
130
|
this.learningData = new Map(); // Task patterns -> performance data
|
|
131
131
|
this.currentMetrics = null;
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
// Analyzers
|
|
134
134
|
this.parallelizationAnalyzer = new ParallelizationAnalyzer();
|
|
135
135
|
this.mergingAnalyzer = new MergingAnalyzer();
|
|
@@ -145,19 +145,19 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
145
145
|
*/
|
|
146
146
|
async onTaskSuccess(task, context, result) {
|
|
147
147
|
if (!this.config.enabled) return null;
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
this.successCount++;
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
// Record performance data for learning
|
|
152
152
|
if (this.config.learningEnabled) {
|
|
153
153
|
this.recordPerformance(task, result);
|
|
154
154
|
}
|
|
155
|
-
|
|
155
|
+
|
|
156
156
|
// Check if we should evaluate
|
|
157
157
|
if (this.successCount % this.config.evaluateEvery !== 0) {
|
|
158
158
|
return null;
|
|
159
159
|
}
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
// Perform proactive optimization
|
|
162
162
|
return this.optimize(context);
|
|
163
163
|
}
|
|
@@ -169,65 +169,65 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
169
169
|
*/
|
|
170
170
|
async optimize(context) {
|
|
171
171
|
const startTime = Date.now();
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
// Calculate current path metrics
|
|
174
174
|
this.currentMetrics = this.calculatePathMetrics(context);
|
|
175
|
-
|
|
175
|
+
|
|
176
176
|
// Find optimization opportunities
|
|
177
177
|
const opportunities = await this.findOpportunities(context);
|
|
178
|
-
|
|
178
|
+
|
|
179
179
|
if (opportunities.length === 0) {
|
|
180
180
|
return {
|
|
181
181
|
optimized: false,
|
|
182
182
|
reason: 'No optimization opportunities found',
|
|
183
|
-
currentMetrics: this.currentMetrics
|
|
183
|
+
currentMetrics: this.currentMetrics,
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
// Rank opportunities
|
|
188
188
|
const ranked = this.rankOpportunities(opportunities);
|
|
189
189
|
const best = ranked[0];
|
|
190
|
-
|
|
190
|
+
|
|
191
191
|
// Check if improvement meets threshold
|
|
192
192
|
if (best.estimatedImprovement < this.config.minImprovementThreshold) {
|
|
193
193
|
return {
|
|
194
194
|
optimized: false,
|
|
195
195
|
reason: `Best improvement (${(best.estimatedImprovement * 100).toFixed(1)}%) below threshold`,
|
|
196
196
|
opportunities: ranked.slice(0, 3),
|
|
197
|
-
currentMetrics: this.currentMetrics
|
|
197
|
+
currentMetrics: this.currentMetrics,
|
|
198
198
|
};
|
|
199
199
|
}
|
|
200
|
-
|
|
200
|
+
|
|
201
201
|
// Validate the optimization
|
|
202
202
|
const validation = await this.validateOptimization(best, context);
|
|
203
|
-
|
|
203
|
+
|
|
204
204
|
if (!validation.valid) {
|
|
205
205
|
return {
|
|
206
206
|
optimized: false,
|
|
207
207
|
reason: validation.reason,
|
|
208
208
|
opportunities: ranked.slice(0, 3),
|
|
209
|
-
currentMetrics: this.currentMetrics
|
|
209
|
+
currentMetrics: this.currentMetrics,
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
// Record optimization
|
|
214
214
|
this.recordOptimization(best, context);
|
|
215
|
-
|
|
215
|
+
|
|
216
216
|
// Emit optimization event
|
|
217
217
|
this.emit('optimization', {
|
|
218
218
|
type: best.type,
|
|
219
219
|
improvement: best.estimatedImprovement,
|
|
220
220
|
affectedTasks: best.affectedTasks,
|
|
221
|
-
newPath: best.newPath
|
|
221
|
+
newPath: best.newPath,
|
|
222
222
|
});
|
|
223
|
-
|
|
223
|
+
|
|
224
224
|
return {
|
|
225
225
|
optimized: true,
|
|
226
226
|
optimization: best,
|
|
227
227
|
newPath: best.newPath,
|
|
228
228
|
estimatedImprovement: best.estimatedImprovement,
|
|
229
229
|
newMetrics: this.calculatePathMetrics({ ...context, pending: best.newPath }),
|
|
230
|
-
duration: Date.now() - startTime
|
|
230
|
+
duration: Date.now() - startTime,
|
|
231
231
|
};
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -238,31 +238,29 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
238
238
|
*/
|
|
239
239
|
calculatePathMetrics(context) {
|
|
240
240
|
const pending = context.pending || [];
|
|
241
|
-
|
|
241
|
+
|
|
242
242
|
// Estimate total time
|
|
243
243
|
let estimatedTime = 0;
|
|
244
244
|
pending.forEach(task => {
|
|
245
245
|
const historical = this.getHistoricalDuration(task);
|
|
246
246
|
estimatedTime += historical || task.estimatedDuration || 30000;
|
|
247
247
|
});
|
|
248
|
-
|
|
248
|
+
|
|
249
249
|
// Calculate parallelization factor
|
|
250
250
|
const parallelizable = this.countParallelizable(pending);
|
|
251
|
-
const parallelizationFactor = pending.length > 0
|
|
252
|
-
|
|
253
|
-
: 1.0;
|
|
254
|
-
|
|
251
|
+
const parallelizationFactor = pending.length > 0 ? parallelizable / pending.length : 1.0;
|
|
252
|
+
|
|
255
253
|
// Calculate risk score
|
|
256
254
|
const riskScore = this.calculateRiskScore(pending, context);
|
|
257
|
-
|
|
255
|
+
|
|
258
256
|
// Calculate dependency complexity
|
|
259
257
|
const dependencyComplexity = this.calculateDependencyComplexity(pending);
|
|
260
|
-
|
|
258
|
+
|
|
261
259
|
return new PathMetrics({
|
|
262
260
|
estimatedTime,
|
|
263
261
|
parallelizationFactor,
|
|
264
262
|
riskScore,
|
|
265
|
-
dependencyComplexity
|
|
263
|
+
dependencyComplexity,
|
|
266
264
|
});
|
|
267
265
|
}
|
|
268
266
|
|
|
@@ -274,33 +272,33 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
274
272
|
async findOpportunities(context) {
|
|
275
273
|
const opportunities = [];
|
|
276
274
|
const pending = context.pending || [];
|
|
277
|
-
|
|
275
|
+
|
|
278
276
|
if (pending.length < 2) return opportunities;
|
|
279
|
-
|
|
277
|
+
|
|
280
278
|
// Check parallelization opportunities
|
|
281
279
|
if (this.config.considerParallelization) {
|
|
282
280
|
const parallelOps = this.parallelizationAnalyzer.analyze(pending, context);
|
|
283
281
|
opportunities.push(...parallelOps);
|
|
284
282
|
}
|
|
285
|
-
|
|
283
|
+
|
|
286
284
|
// Check merging opportunities
|
|
287
285
|
if (this.config.considerMerging) {
|
|
288
286
|
const mergeOps = this.mergingAnalyzer.analyze(pending, context);
|
|
289
287
|
opportunities.push(...mergeOps);
|
|
290
288
|
}
|
|
291
|
-
|
|
289
|
+
|
|
292
290
|
// Check reordering opportunities
|
|
293
291
|
if (this.config.considerReordering) {
|
|
294
292
|
const reorderOps = this.reorderingAnalyzer.analyze(pending, context);
|
|
295
293
|
opportunities.push(...reorderOps);
|
|
296
294
|
}
|
|
297
|
-
|
|
295
|
+
|
|
298
296
|
// Use LLM for additional insights if available
|
|
299
297
|
if (this.llm && pending.length >= 3) {
|
|
300
298
|
const llmOps = await this.getLLMOptimizations(pending, context);
|
|
301
299
|
opportunities.push(...llmOps);
|
|
302
300
|
}
|
|
303
|
-
|
|
301
|
+
|
|
304
302
|
return opportunities;
|
|
305
303
|
}
|
|
306
304
|
|
|
@@ -313,14 +311,14 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
313
311
|
async getLLMOptimizations(pending, context) {
|
|
314
312
|
try {
|
|
315
313
|
const prompt = this.buildOptimizationPrompt(pending, context);
|
|
316
|
-
|
|
314
|
+
|
|
317
315
|
const response = await Promise.race([
|
|
318
316
|
this.llm.completeJSON(prompt, this.getOptimizationSchema()),
|
|
319
|
-
new Promise((_, reject) =>
|
|
317
|
+
new Promise((_, reject) =>
|
|
320
318
|
setTimeout(() => reject(new Error('Timeout')), this.config.optimizationTimeout)
|
|
321
|
-
)
|
|
319
|
+
),
|
|
322
320
|
]);
|
|
323
|
-
|
|
321
|
+
|
|
324
322
|
return this.processLLMResponse(response, pending);
|
|
325
323
|
} catch (error) {
|
|
326
324
|
// LLM optimization is optional, don't fail on error
|
|
@@ -337,16 +335,16 @@ class ProactivePathOptimizer extends EventEmitter {
|
|
|
337
335
|
buildOptimizationPrompt(pending, context) {
|
|
338
336
|
const completedSummary = (context.completed || []).map(t => ({
|
|
339
337
|
name: t.name || t.skill,
|
|
340
|
-
duration: t.duration
|
|
338
|
+
duration: t.duration,
|
|
341
339
|
}));
|
|
342
|
-
|
|
340
|
+
|
|
343
341
|
const pendingSummary = pending.map(t => ({
|
|
344
342
|
id: t.id,
|
|
345
343
|
name: t.name || t.skill,
|
|
346
344
|
dependencies: t.dependencies || [],
|
|
347
|
-
estimatedDuration: t.estimatedDuration
|
|
345
|
+
estimatedDuration: t.estimatedDuration,
|
|
348
346
|
}));
|
|
349
|
-
|
|
347
|
+
|
|
350
348
|
return `Analyze this execution plan and suggest optimizations:
|
|
351
349
|
|
|
352
350
|
COMPLETED TASKS:
|
|
@@ -377,16 +375,19 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
377
375
|
items: {
|
|
378
376
|
type: 'object',
|
|
379
377
|
properties: {
|
|
380
|
-
type: {
|
|
378
|
+
type: {
|
|
379
|
+
type: 'string',
|
|
380
|
+
enum: ['parallelize', 'merge', 'reorder', 'skip', 'substitute'],
|
|
381
|
+
},
|
|
381
382
|
description: { type: 'string' },
|
|
382
383
|
affectedTaskIds: { type: 'array', items: { type: 'string' } },
|
|
383
384
|
estimatedImprovement: { type: 'number' },
|
|
384
385
|
newOrder: { type: 'array', items: { type: 'string' } },
|
|
385
|
-
reasoning: { type: 'string' }
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
386
|
+
reasoning: { type: 'string' },
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
},
|
|
390
391
|
};
|
|
391
392
|
}
|
|
392
393
|
|
|
@@ -398,18 +399,16 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
398
399
|
*/
|
|
399
400
|
processLLMResponse(response, pending) {
|
|
400
401
|
if (!response || !response.optimizations) return [];
|
|
401
|
-
|
|
402
|
+
|
|
402
403
|
return response.optimizations.map(opt => {
|
|
403
404
|
const affectedTasks = (opt.affectedTaskIds || [])
|
|
404
405
|
.map(id => pending.find(t => t.id === id))
|
|
405
406
|
.filter(Boolean);
|
|
406
|
-
|
|
407
|
+
|
|
407
408
|
let newPath = null;
|
|
408
409
|
if (opt.newOrder) {
|
|
409
|
-
newPath = opt.newOrder
|
|
410
|
-
|
|
411
|
-
.filter(Boolean);
|
|
412
|
-
|
|
410
|
+
newPath = opt.newOrder.map(id => pending.find(t => t.id === id)).filter(Boolean);
|
|
411
|
+
|
|
413
412
|
// Add any tasks not in newOrder at the end
|
|
414
413
|
const inOrder = new Set(opt.newOrder);
|
|
415
414
|
pending.forEach(t => {
|
|
@@ -418,7 +417,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
418
417
|
}
|
|
419
418
|
});
|
|
420
419
|
}
|
|
421
|
-
|
|
420
|
+
|
|
422
421
|
return new OptimizationOpportunity({
|
|
423
422
|
type: opt.type,
|
|
424
423
|
description: opt.description,
|
|
@@ -426,7 +425,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
426
425
|
estimatedImprovement: opt.estimatedImprovement || 0.1,
|
|
427
426
|
confidence: 0.6, // LLM suggestions get moderate confidence
|
|
428
427
|
newPath,
|
|
429
|
-
reasoning: opt.reasoning
|
|
428
|
+
reasoning: opt.reasoning,
|
|
430
429
|
});
|
|
431
430
|
});
|
|
432
431
|
}
|
|
@@ -437,9 +436,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
437
436
|
* @returns {OptimizationOpportunity[]} Ranked opportunities
|
|
438
437
|
*/
|
|
439
438
|
rankOpportunities(opportunities) {
|
|
440
|
-
return [...opportunities].sort((a, b) =>
|
|
441
|
-
b.getWeightedScore() - a.getWeightedScore()
|
|
442
|
-
);
|
|
439
|
+
return [...opportunities].sort((a, b) => b.getWeightedScore() - a.getWeightedScore());
|
|
443
440
|
}
|
|
444
441
|
|
|
445
442
|
/**
|
|
@@ -448,7 +445,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
448
445
|
* @param {Object} context - Execution context
|
|
449
446
|
* @returns {Promise<{valid: boolean, reason?: string}>} Validation result
|
|
450
447
|
*/
|
|
451
|
-
async validateOptimization(optimization,
|
|
448
|
+
async validateOptimization(optimization, _context) {
|
|
452
449
|
// Check dependency constraints
|
|
453
450
|
if (optimization.newPath) {
|
|
454
451
|
const valid = this.validateDependencies(optimization.newPath);
|
|
@@ -456,17 +453,15 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
456
453
|
return { valid: false, reason: 'New path violates dependency constraints' };
|
|
457
454
|
}
|
|
458
455
|
}
|
|
459
|
-
|
|
456
|
+
|
|
460
457
|
// Check resource constraints
|
|
461
458
|
if (optimization.type === 'parallelize') {
|
|
462
|
-
const canParallelize = this.checkResourceCapacity(
|
|
463
|
-
optimization.affectedTasks.length
|
|
464
|
-
);
|
|
459
|
+
const canParallelize = this.checkResourceCapacity(optimization.affectedTasks.length);
|
|
465
460
|
if (!canParallelize) {
|
|
466
461
|
return { valid: false, reason: 'Insufficient resources for parallelization' };
|
|
467
462
|
}
|
|
468
463
|
}
|
|
469
|
-
|
|
464
|
+
|
|
470
465
|
return { valid: true };
|
|
471
466
|
}
|
|
472
467
|
|
|
@@ -477,7 +472,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
477
472
|
*/
|
|
478
473
|
validateDependencies(path) {
|
|
479
474
|
const completed = new Set();
|
|
480
|
-
|
|
475
|
+
|
|
481
476
|
for (const task of path) {
|
|
482
477
|
const deps = task.dependencies || [];
|
|
483
478
|
for (const dep of deps) {
|
|
@@ -492,7 +487,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
492
487
|
}
|
|
493
488
|
completed.add(task.id);
|
|
494
489
|
}
|
|
495
|
-
|
|
490
|
+
|
|
496
491
|
return true;
|
|
497
492
|
}
|
|
498
493
|
|
|
@@ -513,20 +508,20 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
513
508
|
*/
|
|
514
509
|
recordPerformance(task, result) {
|
|
515
510
|
const key = task.skill || task.name;
|
|
516
|
-
|
|
511
|
+
|
|
517
512
|
if (!this.learningData.has(key)) {
|
|
518
513
|
this.learningData.set(key, {
|
|
519
514
|
durations: [],
|
|
520
515
|
successRate: 0,
|
|
521
|
-
totalCount: 0
|
|
516
|
+
totalCount: 0,
|
|
522
517
|
});
|
|
523
518
|
}
|
|
524
|
-
|
|
519
|
+
|
|
525
520
|
const data = this.learningData.get(key);
|
|
526
521
|
data.durations.push(result.duration || 0);
|
|
527
522
|
data.totalCount++;
|
|
528
523
|
data.successRate = (data.successRate * (data.totalCount - 1) + 1) / data.totalCount;
|
|
529
|
-
|
|
524
|
+
|
|
530
525
|
// Keep only last 50 durations
|
|
531
526
|
if (data.durations.length > 50) {
|
|
532
527
|
data.durations.shift();
|
|
@@ -541,9 +536,9 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
541
536
|
getHistoricalDuration(task) {
|
|
542
537
|
const key = task.skill || task.name;
|
|
543
538
|
const data = this.learningData.get(key);
|
|
544
|
-
|
|
539
|
+
|
|
545
540
|
if (!data || data.durations.length === 0) return null;
|
|
546
|
-
|
|
541
|
+
|
|
547
542
|
return data.durations.reduce((a, b) => a + b, 0) / data.durations.length;
|
|
548
543
|
}
|
|
549
544
|
|
|
@@ -555,7 +550,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
555
550
|
countParallelizable(tasks) {
|
|
556
551
|
let count = 0;
|
|
557
552
|
const completed = new Set();
|
|
558
|
-
|
|
553
|
+
|
|
559
554
|
for (const task of tasks) {
|
|
560
555
|
const deps = task.dependencies || [];
|
|
561
556
|
if (deps.length === 0 || deps.every(d => completed.has(d))) {
|
|
@@ -563,7 +558,7 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
563
558
|
}
|
|
564
559
|
completed.add(task.id);
|
|
565
560
|
}
|
|
566
|
-
|
|
561
|
+
|
|
567
562
|
return count;
|
|
568
563
|
}
|
|
569
564
|
|
|
@@ -573,24 +568,24 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
573
568
|
* @param {Object} context - Execution context
|
|
574
569
|
* @returns {number} Risk score (0-1)
|
|
575
570
|
*/
|
|
576
|
-
calculateRiskScore(pending,
|
|
571
|
+
calculateRiskScore(pending, _context) {
|
|
577
572
|
if (pending.length === 0) return 0;
|
|
578
|
-
|
|
573
|
+
|
|
579
574
|
let riskSum = 0;
|
|
580
|
-
|
|
575
|
+
|
|
581
576
|
for (const task of pending) {
|
|
582
577
|
const key = task.skill || task.name;
|
|
583
578
|
const data = this.learningData.get(key);
|
|
584
|
-
|
|
579
|
+
|
|
585
580
|
if (data) {
|
|
586
581
|
// Use failure rate as risk indicator
|
|
587
|
-
riskSum +=
|
|
582
|
+
riskSum += 1 - data.successRate;
|
|
588
583
|
} else {
|
|
589
584
|
// Unknown tasks get moderate risk
|
|
590
585
|
riskSum += 0.3;
|
|
591
586
|
}
|
|
592
587
|
}
|
|
593
|
-
|
|
588
|
+
|
|
594
589
|
return riskSum / pending.length;
|
|
595
590
|
}
|
|
596
591
|
|
|
@@ -601,20 +596,20 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
601
596
|
*/
|
|
602
597
|
calculateDependencyComplexity(tasks) {
|
|
603
598
|
if (tasks.length === 0) return 0;
|
|
604
|
-
|
|
599
|
+
|
|
605
600
|
let totalDeps = 0;
|
|
606
601
|
let maxDeps = 0;
|
|
607
|
-
|
|
602
|
+
|
|
608
603
|
for (const task of tasks) {
|
|
609
604
|
const deps = (task.dependencies || []).length;
|
|
610
605
|
totalDeps += deps;
|
|
611
606
|
maxDeps = Math.max(maxDeps, deps);
|
|
612
607
|
}
|
|
613
|
-
|
|
608
|
+
|
|
614
609
|
// Normalize: average deps / max possible deps
|
|
615
610
|
const avgDeps = totalDeps / tasks.length;
|
|
616
611
|
const normalized = Math.min(avgDeps / 5, 1); // Assume 5+ deps is max complexity
|
|
617
|
-
|
|
612
|
+
|
|
618
613
|
return normalized;
|
|
619
614
|
}
|
|
620
615
|
|
|
@@ -631,10 +626,10 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
631
626
|
tasksAffected: optimization.affectedTasks.length,
|
|
632
627
|
contextSnapshot: {
|
|
633
628
|
completedCount: context.completed?.length || 0,
|
|
634
|
-
pendingCount: context.pending?.length || 0
|
|
635
|
-
}
|
|
629
|
+
pendingCount: context.pending?.length || 0,
|
|
630
|
+
},
|
|
636
631
|
});
|
|
637
|
-
|
|
632
|
+
|
|
638
633
|
// Limit history size
|
|
639
634
|
while (this.optimizationHistory.length > this.config.maxHistorySize) {
|
|
640
635
|
this.optimizationHistory.shift();
|
|
@@ -647,28 +642,28 @@ Return optimization suggestions with estimated improvement percentages.`;
|
|
|
647
642
|
*/
|
|
648
643
|
getStatistics() {
|
|
649
644
|
const history = this.optimizationHistory;
|
|
650
|
-
|
|
645
|
+
|
|
651
646
|
if (history.length === 0) {
|
|
652
647
|
return {
|
|
653
648
|
totalOptimizations: 0,
|
|
654
649
|
averageImprovement: 0,
|
|
655
|
-
byType: {}
|
|
650
|
+
byType: {},
|
|
656
651
|
};
|
|
657
652
|
}
|
|
658
|
-
|
|
653
|
+
|
|
659
654
|
const byType = {};
|
|
660
655
|
let totalImprovement = 0;
|
|
661
|
-
|
|
656
|
+
|
|
662
657
|
for (const opt of history) {
|
|
663
658
|
byType[opt.type] = (byType[opt.type] || 0) + 1;
|
|
664
659
|
totalImprovement += opt.improvement;
|
|
665
660
|
}
|
|
666
|
-
|
|
661
|
+
|
|
667
662
|
return {
|
|
668
663
|
totalOptimizations: history.length,
|
|
669
664
|
averageImprovement: totalImprovement / history.length,
|
|
670
665
|
byType,
|
|
671
|
-
learningDataSize: this.learningData.size
|
|
666
|
+
learningDataSize: this.learningData.size,
|
|
672
667
|
};
|
|
673
668
|
}
|
|
674
669
|
|
|
@@ -700,33 +695,31 @@ class ParallelizationAnalyzer {
|
|
|
700
695
|
* @param {Object} context - Context
|
|
701
696
|
* @returns {OptimizationOpportunity[]} Opportunities
|
|
702
697
|
*/
|
|
703
|
-
analyze(tasks,
|
|
698
|
+
analyze(tasks, _context) {
|
|
704
699
|
const opportunities = [];
|
|
705
700
|
const groups = this.findParallelGroups(tasks);
|
|
706
|
-
|
|
701
|
+
|
|
707
702
|
for (const group of groups) {
|
|
708
703
|
if (group.length >= 2) {
|
|
709
|
-
const sequentialTime = group.reduce((sum, t) =>
|
|
710
|
-
|
|
711
|
-
);
|
|
712
|
-
const parallelTime = Math.max(...group.map(t =>
|
|
713
|
-
t.estimatedDuration || 30000
|
|
714
|
-
));
|
|
704
|
+
const sequentialTime = group.reduce((sum, t) => sum + (t.estimatedDuration || 30000), 0);
|
|
705
|
+
const parallelTime = Math.max(...group.map(t => t.estimatedDuration || 30000));
|
|
715
706
|
const improvement = (sequentialTime - parallelTime) / sequentialTime;
|
|
716
|
-
|
|
707
|
+
|
|
717
708
|
if (improvement > 0.1) {
|
|
718
|
-
opportunities.push(
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
709
|
+
opportunities.push(
|
|
710
|
+
new OptimizationOpportunity({
|
|
711
|
+
type: 'parallelize',
|
|
712
|
+
description: `Run ${group.length} tasks in parallel`,
|
|
713
|
+
affectedTasks: group,
|
|
714
|
+
estimatedImprovement: improvement,
|
|
715
|
+
confidence: 0.8,
|
|
716
|
+
reasoning: 'Tasks have no interdependencies',
|
|
717
|
+
})
|
|
718
|
+
);
|
|
726
719
|
}
|
|
727
720
|
}
|
|
728
721
|
}
|
|
729
|
-
|
|
722
|
+
|
|
730
723
|
return opportunities;
|
|
731
724
|
}
|
|
732
725
|
|
|
@@ -739,40 +732,42 @@ class ParallelizationAnalyzer {
|
|
|
739
732
|
const groups = [];
|
|
740
733
|
const used = new Set();
|
|
741
734
|
const completed = new Set();
|
|
742
|
-
|
|
735
|
+
|
|
743
736
|
for (let i = 0; i < tasks.length; i++) {
|
|
744
737
|
if (used.has(i)) continue;
|
|
745
|
-
|
|
738
|
+
|
|
746
739
|
const task = tasks[i];
|
|
747
740
|
const deps = task.dependencies || [];
|
|
748
|
-
|
|
741
|
+
|
|
749
742
|
// Check if dependencies are satisfied
|
|
750
743
|
if (!deps.every(d => completed.has(d))) continue;
|
|
751
|
-
|
|
744
|
+
|
|
752
745
|
// Find other tasks that can run in parallel
|
|
753
746
|
const group = [task];
|
|
754
747
|
used.add(i);
|
|
755
|
-
|
|
748
|
+
|
|
756
749
|
for (let j = i + 1; j < tasks.length; j++) {
|
|
757
750
|
if (used.has(j)) continue;
|
|
758
|
-
|
|
751
|
+
|
|
759
752
|
const other = tasks[j];
|
|
760
753
|
const otherDeps = other.dependencies || [];
|
|
761
|
-
|
|
754
|
+
|
|
762
755
|
// Can run in parallel if:
|
|
763
756
|
// 1. Its dependencies are satisfied
|
|
764
757
|
// 2. It doesn't depend on any task in the current group
|
|
765
|
-
if (
|
|
766
|
-
|
|
758
|
+
if (
|
|
759
|
+
otherDeps.every(d => completed.has(d)) &&
|
|
760
|
+
!otherDeps.some(d => group.some(g => g.id === d))
|
|
761
|
+
) {
|
|
767
762
|
group.push(other);
|
|
768
763
|
used.add(j);
|
|
769
764
|
}
|
|
770
765
|
}
|
|
771
|
-
|
|
766
|
+
|
|
772
767
|
groups.push(group);
|
|
773
768
|
group.forEach(t => completed.add(t.id));
|
|
774
769
|
}
|
|
775
|
-
|
|
770
|
+
|
|
776
771
|
return groups;
|
|
777
772
|
}
|
|
778
773
|
}
|
|
@@ -788,32 +783,32 @@ class MergingAnalyzer {
|
|
|
788
783
|
* @param {Object} context - Context
|
|
789
784
|
* @returns {OptimizationOpportunity[]} Opportunities
|
|
790
785
|
*/
|
|
791
|
-
analyze(tasks,
|
|
786
|
+
analyze(tasks, _context) {
|
|
792
787
|
const opportunities = [];
|
|
793
788
|
const groups = this.findMergeableGroups(tasks);
|
|
794
|
-
|
|
789
|
+
|
|
795
790
|
for (const group of groups) {
|
|
796
791
|
if (group.length >= 2) {
|
|
797
792
|
const overhead = 5000; // Assumed overhead per task
|
|
798
793
|
const savingsTime = overhead * (group.length - 1);
|
|
799
|
-
const totalTime = group.reduce((sum, t) =>
|
|
800
|
-
sum + (t.estimatedDuration || 30000), 0
|
|
801
|
-
);
|
|
794
|
+
const totalTime = group.reduce((sum, t) => sum + (t.estimatedDuration || 30000), 0);
|
|
802
795
|
const improvement = savingsTime / totalTime;
|
|
803
|
-
|
|
796
|
+
|
|
804
797
|
if (improvement > 0.05) {
|
|
805
|
-
opportunities.push(
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
798
|
+
opportunities.push(
|
|
799
|
+
new OptimizationOpportunity({
|
|
800
|
+
type: 'merge',
|
|
801
|
+
description: `Merge ${group.length} similar ${group[0].skill || group[0].name} tasks`,
|
|
802
|
+
affectedTasks: group,
|
|
803
|
+
estimatedImprovement: improvement,
|
|
804
|
+
confidence: 0.7,
|
|
805
|
+
reasoning: 'Tasks operate on similar targets',
|
|
806
|
+
})
|
|
807
|
+
);
|
|
813
808
|
}
|
|
814
809
|
}
|
|
815
810
|
}
|
|
816
|
-
|
|
811
|
+
|
|
817
812
|
return opportunities;
|
|
818
813
|
}
|
|
819
814
|
|
|
@@ -824,7 +819,7 @@ class MergingAnalyzer {
|
|
|
824
819
|
*/
|
|
825
820
|
findMergeableGroups(tasks) {
|
|
826
821
|
const bySkill = new Map();
|
|
827
|
-
|
|
822
|
+
|
|
828
823
|
for (const task of tasks) {
|
|
829
824
|
const skill = task.skill || task.name;
|
|
830
825
|
if (!bySkill.has(skill)) {
|
|
@@ -832,7 +827,7 @@ class MergingAnalyzer {
|
|
|
832
827
|
}
|
|
833
828
|
bySkill.get(skill).push(task);
|
|
834
829
|
}
|
|
835
|
-
|
|
830
|
+
|
|
836
831
|
// Return groups with 2+ tasks of the same skill
|
|
837
832
|
return Array.from(bySkill.values()).filter(g => g.length >= 2);
|
|
838
833
|
}
|
|
@@ -849,28 +844,30 @@ class ReorderingAnalyzer {
|
|
|
849
844
|
* @param {Object} context - Context
|
|
850
845
|
* @returns {OptimizationOpportunity[]} Opportunities
|
|
851
846
|
*/
|
|
852
|
-
analyze(tasks,
|
|
847
|
+
analyze(tasks, _context) {
|
|
853
848
|
const opportunities = [];
|
|
854
|
-
|
|
849
|
+
|
|
855
850
|
// Check for dependency-based improvements
|
|
856
851
|
const optimalOrder = this.topologicalSort(tasks);
|
|
857
|
-
|
|
852
|
+
|
|
858
853
|
if (!this.arraysEqual(tasks, optimalOrder)) {
|
|
859
854
|
const improvement = this.estimateReorderImprovement(tasks, optimalOrder);
|
|
860
|
-
|
|
855
|
+
|
|
861
856
|
if (improvement > 0.05) {
|
|
862
|
-
opportunities.push(
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
857
|
+
opportunities.push(
|
|
858
|
+
new OptimizationOpportunity({
|
|
859
|
+
type: 'reorder',
|
|
860
|
+
description: 'Optimize task order for better dependency resolution',
|
|
861
|
+
affectedTasks: tasks,
|
|
862
|
+
estimatedImprovement: improvement,
|
|
863
|
+
confidence: 0.9,
|
|
864
|
+
newPath: optimalOrder,
|
|
865
|
+
reasoning: 'Current order causes unnecessary waiting',
|
|
866
|
+
})
|
|
867
|
+
);
|
|
871
868
|
}
|
|
872
869
|
}
|
|
873
|
-
|
|
870
|
+
|
|
874
871
|
return opportunities;
|
|
875
872
|
}
|
|
876
873
|
|
|
@@ -883,28 +880,28 @@ class ReorderingAnalyzer {
|
|
|
883
880
|
const taskMap = new Map(tasks.map(t => [t.id, t]));
|
|
884
881
|
const inDegree = new Map();
|
|
885
882
|
const result = [];
|
|
886
|
-
|
|
883
|
+
|
|
887
884
|
// Initialize in-degrees
|
|
888
885
|
for (const task of tasks) {
|
|
889
886
|
inDegree.set(task.id, 0);
|
|
890
887
|
}
|
|
891
|
-
|
|
888
|
+
|
|
892
889
|
// Calculate in-degrees
|
|
893
890
|
for (const task of tasks) {
|
|
894
|
-
for (const dep of
|
|
891
|
+
for (const dep of task.dependencies || []) {
|
|
895
892
|
if (taskMap.has(dep)) {
|
|
896
893
|
inDegree.set(task.id, inDegree.get(task.id) + 1);
|
|
897
894
|
}
|
|
898
895
|
}
|
|
899
896
|
}
|
|
900
|
-
|
|
897
|
+
|
|
901
898
|
// Queue tasks with no dependencies
|
|
902
899
|
const queue = tasks.filter(t => inDegree.get(t.id) === 0);
|
|
903
|
-
|
|
900
|
+
|
|
904
901
|
while (queue.length > 0) {
|
|
905
902
|
const task = queue.shift();
|
|
906
903
|
result.push(task);
|
|
907
|
-
|
|
904
|
+
|
|
908
905
|
// Reduce in-degree for dependent tasks
|
|
909
906
|
for (const other of tasks) {
|
|
910
907
|
if ((other.dependencies || []).includes(task.id)) {
|
|
@@ -916,14 +913,14 @@ class ReorderingAnalyzer {
|
|
|
916
913
|
}
|
|
917
914
|
}
|
|
918
915
|
}
|
|
919
|
-
|
|
916
|
+
|
|
920
917
|
// Add remaining tasks (circular dependencies)
|
|
921
918
|
for (const task of tasks) {
|
|
922
919
|
if (!result.includes(task)) {
|
|
923
920
|
result.push(task);
|
|
924
921
|
}
|
|
925
922
|
}
|
|
926
|
-
|
|
923
|
+
|
|
927
924
|
return result;
|
|
928
925
|
}
|
|
929
926
|
|
|
@@ -955,7 +952,7 @@ class ReorderingAnalyzer {
|
|
|
955
952
|
outOfPlace++;
|
|
956
953
|
}
|
|
957
954
|
}
|
|
958
|
-
|
|
955
|
+
|
|
959
956
|
// More out of place = more potential improvement
|
|
960
957
|
return (outOfPlace / current.length) * 0.3;
|
|
961
958
|
}
|
|
@@ -968,5 +965,5 @@ module.exports = {
|
|
|
968
965
|
ParallelizationAnalyzer,
|
|
969
966
|
MergingAnalyzer,
|
|
970
967
|
ReorderingAnalyzer,
|
|
971
|
-
DEFAULT_CONFIG
|
|
968
|
+
DEFAULT_CONFIG,
|
|
972
969
|
};
|