ultra-dex 2.2.0 → 3.1.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 +84 -122
- package/assets/agents/0-orchestration/orchestrator.md +2 -2
- package/assets/agents/00-AGENT_INDEX.md +1 -1
- package/assets/docs/LAUNCH-POSTS.md +1 -1
- package/assets/docs/QUICK-REFERENCE.md +12 -7
- package/assets/docs/ROADMAP.md +5 -5
- package/assets/docs/VISION-V2.md +1 -1
- package/assets/docs/WORKFLOW-DIAGRAMS.md +1 -1
- package/assets/hooks/pre-commit +98 -0
- package/assets/saas-plan/04-Imp-Template.md +1 -1
- package/assets/templates/README.md +1 -1
- package/bin/ultra-dex.js +93 -2096
- package/lib/commands/advanced.js +471 -0
- package/lib/commands/agent-builder.js +226 -0
- package/lib/commands/agents.js +101 -47
- package/lib/commands/auto-implement.js +68 -0
- package/lib/commands/build.js +73 -187
- package/lib/commands/ci-monitor.js +84 -0
- package/lib/commands/config.js +207 -0
- package/lib/commands/dashboard.js +770 -0
- package/lib/commands/diff.js +233 -0
- package/lib/commands/doctor.js +397 -0
- package/lib/commands/export.js +408 -0
- package/lib/commands/fix.js +96 -0
- package/lib/commands/generate.js +96 -72
- package/lib/commands/hooks.js +251 -76
- package/lib/commands/init.js +56 -6
- package/lib/commands/memory.js +80 -0
- package/lib/commands/plan.js +82 -0
- package/lib/commands/review.js +34 -5
- package/lib/commands/run.js +233 -0
- package/lib/commands/serve.js +188 -40
- package/lib/commands/state.js +354 -0
- package/lib/commands/swarm.js +284 -0
- package/lib/commands/sync.js +94 -0
- package/lib/commands/team.js +275 -0
- package/lib/commands/upgrade.js +190 -0
- package/lib/commands/validate.js +34 -0
- package/lib/commands/verify.js +81 -0
- package/lib/commands/watch.js +79 -0
- package/lib/mcp/graph.js +92 -0
- package/lib/mcp/memory.js +95 -0
- package/lib/mcp/resources.js +152 -0
- package/lib/mcp/server.js +34 -0
- package/lib/mcp/tools.js +481 -0
- package/lib/mcp/websocket.js +117 -0
- package/lib/providers/index.js +49 -4
- package/lib/providers/ollama.js +136 -0
- package/lib/providers/router.js +63 -0
- package/lib/quality/scanner.js +128 -0
- package/lib/swarm/coordinator.js +97 -0
- package/lib/swarm/index.js +598 -0
- package/lib/swarm/protocol.js +677 -0
- package/lib/swarm/tiers.js +485 -0
- package/lib/templates/context.js +2 -2
- package/lib/templates/custom-agent.md +10 -0
- package/lib/utils/fallback.js +4 -2
- package/lib/utils/files.js +7 -34
- package/lib/utils/graph.js +108 -0
- package/lib/utils/sync.js +216 -0
- package/package.json +22 -13
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultra-Dex Agent Tier System v3.0
|
|
3
|
+
* Defines the hierarchical structure of agents and their dependencies.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// TIER DEFINITIONS
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tier structure for all 16 agents.
|
|
12
|
+
* Lower tier numbers indicate higher-level strategic roles.
|
|
13
|
+
*/
|
|
14
|
+
export const TIERS = {
|
|
15
|
+
META: {
|
|
16
|
+
id: 0,
|
|
17
|
+
name: 'Meta Orchestration',
|
|
18
|
+
description: 'Coordinates all other agents',
|
|
19
|
+
agents: ['orchestrator']
|
|
20
|
+
},
|
|
21
|
+
LEADERSHIP: {
|
|
22
|
+
id: 1,
|
|
23
|
+
name: 'Leadership',
|
|
24
|
+
description: 'Strategic planning and technology decisions',
|
|
25
|
+
agents: ['cto', 'planner', 'research']
|
|
26
|
+
},
|
|
27
|
+
DEVELOPMENT: {
|
|
28
|
+
id: 2,
|
|
29
|
+
name: 'Development',
|
|
30
|
+
description: 'Core implementation of features',
|
|
31
|
+
agents: ['backend', 'frontend', 'database']
|
|
32
|
+
},
|
|
33
|
+
SECURITY: {
|
|
34
|
+
id: 3,
|
|
35
|
+
name: 'Security',
|
|
36
|
+
description: 'Authentication, authorization, and security audits',
|
|
37
|
+
agents: ['auth', 'security']
|
|
38
|
+
},
|
|
39
|
+
DEVOPS: {
|
|
40
|
+
id: 4,
|
|
41
|
+
name: 'DevOps',
|
|
42
|
+
description: 'Deployment and infrastructure management',
|
|
43
|
+
agents: ['devops']
|
|
44
|
+
},
|
|
45
|
+
QUALITY: {
|
|
46
|
+
id: 5,
|
|
47
|
+
name: 'Quality',
|
|
48
|
+
description: 'Testing, debugging, and code review',
|
|
49
|
+
agents: ['testing', 'reviewer', 'debugger', 'documentation']
|
|
50
|
+
},
|
|
51
|
+
SPECIALIST: {
|
|
52
|
+
id: 6,
|
|
53
|
+
name: 'Specialist',
|
|
54
|
+
description: 'Advanced optimization and code improvement',
|
|
55
|
+
agents: ['performance', 'refactoring']
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// AGENT REGISTRY
|
|
61
|
+
// ============================================================================
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Complete agent registry with metadata.
|
|
65
|
+
*/
|
|
66
|
+
export const AGENTS = {
|
|
67
|
+
// Tier 0: Meta
|
|
68
|
+
orchestrator: {
|
|
69
|
+
name: 'Orchestrator',
|
|
70
|
+
tier: 0,
|
|
71
|
+
tierName: 'Meta Orchestration',
|
|
72
|
+
role: 'Coordinate all agents for complete features',
|
|
73
|
+
invocation: '@orchestrator',
|
|
74
|
+
file: '0-orchestration/orchestrator.md',
|
|
75
|
+
capabilities: ['task_decomposition', 'agent_selection', 'pipeline_execution', 'result_synthesis'],
|
|
76
|
+
canInvoke: ['all']
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// Tier 1: Leadership
|
|
80
|
+
cto: {
|
|
81
|
+
name: 'CTO',
|
|
82
|
+
tier: 1,
|
|
83
|
+
tierName: 'Leadership',
|
|
84
|
+
role: 'Architecture & tech stack decisions',
|
|
85
|
+
invocation: '@cto',
|
|
86
|
+
file: '1-leadership/cto.md',
|
|
87
|
+
capabilities: ['architecture_design', 'tech_selection', 'system_design'],
|
|
88
|
+
canInvoke: ['research']
|
|
89
|
+
},
|
|
90
|
+
planner: {
|
|
91
|
+
name: 'Planner',
|
|
92
|
+
tier: 1,
|
|
93
|
+
tierName: 'Leadership',
|
|
94
|
+
role: 'Task breakdown & sprint planning',
|
|
95
|
+
invocation: '@planner',
|
|
96
|
+
file: '1-leadership/planner.md',
|
|
97
|
+
capabilities: ['task_breakdown', 'estimation', 'prioritization'],
|
|
98
|
+
canInvoke: []
|
|
99
|
+
},
|
|
100
|
+
research: {
|
|
101
|
+
name: 'Research',
|
|
102
|
+
tier: 1,
|
|
103
|
+
tierName: 'Leadership',
|
|
104
|
+
role: 'Technology evaluation & comparison',
|
|
105
|
+
invocation: '@research',
|
|
106
|
+
file: '1-leadership/research.md',
|
|
107
|
+
capabilities: ['technology_evaluation', 'comparison', 'recommendations'],
|
|
108
|
+
canInvoke: []
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// Tier 2: Development
|
|
112
|
+
backend: {
|
|
113
|
+
name: 'Backend',
|
|
114
|
+
tier: 2,
|
|
115
|
+
tierName: 'Development',
|
|
116
|
+
role: 'API & server implementation',
|
|
117
|
+
invocation: '@backend',
|
|
118
|
+
file: '2-development/backend.md',
|
|
119
|
+
capabilities: ['api_development', 'business_logic', 'integrations'],
|
|
120
|
+
canInvoke: ['database']
|
|
121
|
+
},
|
|
122
|
+
frontend: {
|
|
123
|
+
name: 'Frontend',
|
|
124
|
+
tier: 2,
|
|
125
|
+
tierName: 'Development',
|
|
126
|
+
role: 'UI & component implementation',
|
|
127
|
+
invocation: '@frontend',
|
|
128
|
+
file: '2-development/frontend.md',
|
|
129
|
+
capabilities: ['ui_development', 'components', 'state_management'],
|
|
130
|
+
canInvoke: []
|
|
131
|
+
},
|
|
132
|
+
database: {
|
|
133
|
+
name: 'Database',
|
|
134
|
+
tier: 2,
|
|
135
|
+
tierName: 'Development',
|
|
136
|
+
role: 'Schema design & query optimization',
|
|
137
|
+
invocation: '@database',
|
|
138
|
+
file: '2-development/database.md',
|
|
139
|
+
capabilities: ['schema_design', 'migrations', 'query_optimization'],
|
|
140
|
+
canInvoke: []
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Tier 3: Security
|
|
144
|
+
auth: {
|
|
145
|
+
name: 'Auth',
|
|
146
|
+
tier: 3,
|
|
147
|
+
tierName: 'Security',
|
|
148
|
+
role: 'Authentication & authorization',
|
|
149
|
+
invocation: '@auth',
|
|
150
|
+
file: '3-security/auth.md',
|
|
151
|
+
capabilities: ['authentication', 'authorization', 'session_management'],
|
|
152
|
+
canInvoke: ['backend', 'database']
|
|
153
|
+
},
|
|
154
|
+
security: {
|
|
155
|
+
name: 'Security',
|
|
156
|
+
tier: 3,
|
|
157
|
+
tierName: 'Security',
|
|
158
|
+
role: 'Security audits & vulnerability fixes',
|
|
159
|
+
invocation: '@security',
|
|
160
|
+
file: '3-security/security.md',
|
|
161
|
+
capabilities: ['security_audit', 'vulnerability_detection', 'hardening'],
|
|
162
|
+
canInvoke: []
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// Tier 4: DevOps
|
|
166
|
+
devops: {
|
|
167
|
+
name: 'DevOps',
|
|
168
|
+
tier: 4,
|
|
169
|
+
tierName: 'DevOps',
|
|
170
|
+
role: 'Deployment & infrastructure',
|
|
171
|
+
invocation: '@devops',
|
|
172
|
+
file: '4-devops/devops.md',
|
|
173
|
+
capabilities: ['deployment', 'ci_cd', 'infrastructure', 'monitoring'],
|
|
174
|
+
canInvoke: []
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// Tier 5: Quality
|
|
178
|
+
testing: {
|
|
179
|
+
name: 'Testing',
|
|
180
|
+
tier: 5,
|
|
181
|
+
tierName: 'Quality',
|
|
182
|
+
role: 'QA & test automation',
|
|
183
|
+
invocation: '@testing',
|
|
184
|
+
file: '5-quality/testing.md',
|
|
185
|
+
capabilities: ['unit_testing', 'integration_testing', 'e2e_testing'],
|
|
186
|
+
canInvoke: []
|
|
187
|
+
},
|
|
188
|
+
reviewer: {
|
|
189
|
+
name: 'Reviewer',
|
|
190
|
+
tier: 5,
|
|
191
|
+
tierName: 'Quality',
|
|
192
|
+
role: 'Code review & quality checks',
|
|
193
|
+
invocation: '@reviewer',
|
|
194
|
+
file: '5-quality/reviewer.md',
|
|
195
|
+
capabilities: ['code_review', 'best_practices', 'quality_gates'],
|
|
196
|
+
canInvoke: []
|
|
197
|
+
},
|
|
198
|
+
debugger: {
|
|
199
|
+
name: 'Debugger',
|
|
200
|
+
tier: 5,
|
|
201
|
+
tierName: 'Quality',
|
|
202
|
+
role: 'Bug investigation & fixes',
|
|
203
|
+
invocation: '@debugger',
|
|
204
|
+
file: '5-quality/debugger.md',
|
|
205
|
+
capabilities: ['debugging', 'root_cause_analysis', 'bug_fixing'],
|
|
206
|
+
canInvoke: ['backend', 'frontend', 'database']
|
|
207
|
+
},
|
|
208
|
+
documentation: {
|
|
209
|
+
name: 'Documentation',
|
|
210
|
+
tier: 5,
|
|
211
|
+
tierName: 'Quality',
|
|
212
|
+
role: 'Technical writing & docs maintenance',
|
|
213
|
+
invocation: '@documentation',
|
|
214
|
+
file: '5-quality/documentation.md',
|
|
215
|
+
capabilities: ['technical_writing', 'api_docs', 'user_guides'],
|
|
216
|
+
canInvoke: []
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
// Tier 6: Specialist
|
|
220
|
+
performance: {
|
|
221
|
+
name: 'Performance',
|
|
222
|
+
tier: 6,
|
|
223
|
+
tierName: 'Specialist',
|
|
224
|
+
role: 'Performance optimization',
|
|
225
|
+
invocation: '@performance',
|
|
226
|
+
file: '6-specialist/performance.md',
|
|
227
|
+
capabilities: ['profiling', 'optimization', 'caching', 'load_testing'],
|
|
228
|
+
canInvoke: ['backend', 'frontend', 'database']
|
|
229
|
+
},
|
|
230
|
+
refactoring: {
|
|
231
|
+
name: 'Refactoring',
|
|
232
|
+
tier: 6,
|
|
233
|
+
tierName: 'Specialist',
|
|
234
|
+
role: 'Code quality & design patterns',
|
|
235
|
+
invocation: '@refactoring',
|
|
236
|
+
file: '6-specialist/refactoring.md',
|
|
237
|
+
capabilities: ['code_cleanup', 'design_patterns', 'architecture_improvement'],
|
|
238
|
+
canInvoke: ['backend', 'frontend']
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// TIER DEPENDENCY GRAPH
|
|
244
|
+
// ============================================================================
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Defines standard execution flow between tiers.
|
|
248
|
+
* This represents the typical order of operations for a full feature.
|
|
249
|
+
*/
|
|
250
|
+
export const TIER_FLOW = {
|
|
251
|
+
standard: [
|
|
252
|
+
{ tier: 1, phase: 'Planning', required: true },
|
|
253
|
+
{ tier: 2, phase: 'Implementation', required: true },
|
|
254
|
+
{ tier: 3, phase: 'Security', required: false },
|
|
255
|
+
{ tier: 5, phase: 'Quality', required: true },
|
|
256
|
+
{ tier: 4, phase: 'Deployment', required: false },
|
|
257
|
+
{ tier: 6, phase: 'Optimization', required: false }
|
|
258
|
+
],
|
|
259
|
+
hotfix: [
|
|
260
|
+
{ tier: 5, phase: 'Debug', agents: ['debugger'], required: true },
|
|
261
|
+
{ tier: 5, phase: 'Test', agents: ['testing'], required: true },
|
|
262
|
+
{ tier: 4, phase: 'Deploy', agents: ['devops'], required: true }
|
|
263
|
+
],
|
|
264
|
+
optimization: [
|
|
265
|
+
{ tier: 6, phase: 'Optimize', required: true },
|
|
266
|
+
{ tier: 5, phase: 'Test', agents: ['testing'], required: true },
|
|
267
|
+
{ tier: 5, phase: 'Review', agents: ['reviewer'], required: true }
|
|
268
|
+
]
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Agent dependency graph - which agents depend on outputs from others.
|
|
273
|
+
*/
|
|
274
|
+
export const AGENT_DEPENDENCIES = {
|
|
275
|
+
// Leadership tier has no dependencies (entry points)
|
|
276
|
+
planner: [],
|
|
277
|
+
cto: ['planner'],
|
|
278
|
+
research: ['planner'],
|
|
279
|
+
|
|
280
|
+
// Development depends on leadership decisions
|
|
281
|
+
database: ['cto'],
|
|
282
|
+
backend: ['cto', 'database'],
|
|
283
|
+
frontend: ['cto', 'backend'],
|
|
284
|
+
|
|
285
|
+
// Security depends on implementation
|
|
286
|
+
auth: ['backend', 'database'],
|
|
287
|
+
security: ['backend', 'frontend', 'auth'],
|
|
288
|
+
|
|
289
|
+
// Quality depends on implementation
|
|
290
|
+
testing: ['backend', 'frontend'],
|
|
291
|
+
reviewer: ['backend', 'frontend', 'testing'],
|
|
292
|
+
debugger: [], // Can be invoked anytime
|
|
293
|
+
documentation: ['backend', 'frontend'],
|
|
294
|
+
|
|
295
|
+
// DevOps depends on quality approval
|
|
296
|
+
devops: ['testing', 'reviewer'],
|
|
297
|
+
|
|
298
|
+
// Specialist can run after implementation
|
|
299
|
+
performance: ['backend', 'frontend'],
|
|
300
|
+
refactoring: ['backend', 'frontend']
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// ============================================================================
|
|
304
|
+
// UTILITY FUNCTIONS
|
|
305
|
+
// ============================================================================
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Get agent by name.
|
|
309
|
+
*/
|
|
310
|
+
export function getAgent(name) {
|
|
311
|
+
const normalized = name.toLowerCase().replace('@', '');
|
|
312
|
+
return AGENTS[normalized] || null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Get all agents in a tier.
|
|
317
|
+
*/
|
|
318
|
+
export function getAgentsByTier(tierId) {
|
|
319
|
+
return Object.values(AGENTS).filter(agent => agent.tier === tierId);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Get tier by ID.
|
|
324
|
+
*/
|
|
325
|
+
export function getTier(tierId) {
|
|
326
|
+
return Object.values(TIERS).find(tier => tier.id === tierId) || null;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Get tier by agent name.
|
|
331
|
+
*/
|
|
332
|
+
export function getTierForAgent(agentName) {
|
|
333
|
+
const agent = getAgent(agentName);
|
|
334
|
+
return agent ? getTier(agent.tier) : null;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Get dependencies for an agent.
|
|
339
|
+
*/
|
|
340
|
+
export function getAgentDependencies(agentName) {
|
|
341
|
+
const normalized = agentName.toLowerCase().replace('@', '');
|
|
342
|
+
return AGENT_DEPENDENCIES[normalized] || [];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Check if agent A can invoke agent B.
|
|
347
|
+
*/
|
|
348
|
+
export function canInvoke(agentA, agentB) {
|
|
349
|
+
const a = getAgent(agentA);
|
|
350
|
+
if (!a) return false;
|
|
351
|
+
if (a.canInvoke.includes('all')) return true;
|
|
352
|
+
return a.canInvoke.includes(agentB.toLowerCase().replace('@', ''));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Get execution order for a set of agents based on dependencies.
|
|
357
|
+
*/
|
|
358
|
+
export function getExecutionOrder(agentNames) {
|
|
359
|
+
const normalized = agentNames.map(n => n.toLowerCase().replace('@', ''));
|
|
360
|
+
const visited = new Set();
|
|
361
|
+
const order = [];
|
|
362
|
+
|
|
363
|
+
function visit(agent) {
|
|
364
|
+
if (visited.has(agent)) return;
|
|
365
|
+
visited.add(agent);
|
|
366
|
+
|
|
367
|
+
const deps = AGENT_DEPENDENCIES[agent] || [];
|
|
368
|
+
for (const dep of deps) {
|
|
369
|
+
if (normalized.includes(dep)) {
|
|
370
|
+
visit(dep);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
order.push(agent);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
for (const agent of normalized) {
|
|
377
|
+
visit(agent);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return order;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Identify parallel execution opportunities.
|
|
385
|
+
*/
|
|
386
|
+
export function findParallelGroups(agentNames) {
|
|
387
|
+
const order = getExecutionOrder(agentNames);
|
|
388
|
+
const groups = [];
|
|
389
|
+
const scheduled = new Set();
|
|
390
|
+
|
|
391
|
+
while (scheduled.size < order.length) {
|
|
392
|
+
const group = [];
|
|
393
|
+
|
|
394
|
+
for (const agent of order) {
|
|
395
|
+
if (scheduled.has(agent)) continue;
|
|
396
|
+
|
|
397
|
+
const deps = AGENT_DEPENDENCIES[agent] || [];
|
|
398
|
+
const depsInList = deps.filter(d => order.includes(d));
|
|
399
|
+
const depsMet = depsInList.every(d => scheduled.has(d));
|
|
400
|
+
|
|
401
|
+
if (depsMet) {
|
|
402
|
+
group.push(agent);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (group.length === 0) break; // Prevent infinite loop
|
|
407
|
+
|
|
408
|
+
for (const agent of group) {
|
|
409
|
+
scheduled.add(agent);
|
|
410
|
+
}
|
|
411
|
+
groups.push(group);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return groups;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Generate a tier summary for display.
|
|
419
|
+
*/
|
|
420
|
+
export function getTierSummary() {
|
|
421
|
+
return Object.values(TIERS).map(tier => ({
|
|
422
|
+
id: tier.id,
|
|
423
|
+
name: tier.name,
|
|
424
|
+
description: tier.description,
|
|
425
|
+
agentCount: tier.agents.length,
|
|
426
|
+
agents: tier.agents.map(a => AGENTS[a]?.name || a)
|
|
427
|
+
}));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Validate a pipeline for dependency violations.
|
|
432
|
+
*/
|
|
433
|
+
export function validatePipeline(pipeline) {
|
|
434
|
+
const errors = [];
|
|
435
|
+
const completed = new Set();
|
|
436
|
+
|
|
437
|
+
for (let i = 0; i < pipeline.length; i++) {
|
|
438
|
+
const step = pipeline[i];
|
|
439
|
+
const agent = step.agent?.toLowerCase().replace('@', '');
|
|
440
|
+
const deps = AGENT_DEPENDENCIES[agent] || [];
|
|
441
|
+
|
|
442
|
+
for (const dep of deps) {
|
|
443
|
+
// Check if dependency is in pipeline and comes before
|
|
444
|
+
const depIndex = pipeline.findIndex(s =>
|
|
445
|
+
s.agent?.toLowerCase().replace('@', '') === dep
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
if (depIndex > i) {
|
|
449
|
+
errors.push({
|
|
450
|
+
step: i + 1,
|
|
451
|
+
agent,
|
|
452
|
+
error: `Depends on ${dep} which is scheduled after (step ${depIndex + 1})`
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
completed.add(agent);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return {
|
|
461
|
+
valid: errors.length === 0,
|
|
462
|
+
errors
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// ============================================================================
|
|
467
|
+
// EXPORTS
|
|
468
|
+
// ============================================================================
|
|
469
|
+
|
|
470
|
+
export default {
|
|
471
|
+
TIERS,
|
|
472
|
+
AGENTS,
|
|
473
|
+
TIER_FLOW,
|
|
474
|
+
AGENT_DEPENDENCIES,
|
|
475
|
+
getAgent,
|
|
476
|
+
getAgentsByTier,
|
|
477
|
+
getTier,
|
|
478
|
+
getTierForAgent,
|
|
479
|
+
getAgentDependencies,
|
|
480
|
+
canInvoke,
|
|
481
|
+
getExecutionOrder,
|
|
482
|
+
findParallelGroups,
|
|
483
|
+
getTierSummary,
|
|
484
|
+
validatePipeline
|
|
485
|
+
};
|
package/lib/templates/context.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { githubBlobUrl,
|
|
1
|
+
import { githubBlobUrl, githubWebUrl } from '../config/urls.js';
|
|
2
2
|
|
|
3
3
|
export const CONTEXT_TEMPLATE = `# {{PROJECT_NAME}} - Context
|
|
4
4
|
|
|
@@ -21,6 +21,6 @@ export const CONTEXT_TEMPLATE = `# {{PROJECT_NAME}} - Context
|
|
|
21
21
|
Setting up the implementation plan.
|
|
22
22
|
|
|
23
23
|
## Resources
|
|
24
|
-
- [Ultra-Dex Template](${
|
|
24
|
+
- [Ultra-Dex Template](${githubWebUrl()})
|
|
25
25
|
- [TaskFlow Example](${githubBlobUrl('@%20Ultra%20DeX/Saas%20plan/Examples/TaskFlow-Complete.md')})
|
|
26
26
|
`;
|
package/lib/utils/fallback.js
CHANGED
|
@@ -26,11 +26,13 @@ export async function copyWithFallback(primaryPath, fallbackPath, destinationPat
|
|
|
26
26
|
|
|
27
27
|
export async function listWithFallback(primaryPath, fallbackPath) {
|
|
28
28
|
try {
|
|
29
|
-
|
|
29
|
+
const files = await fs.readdir(primaryPath);
|
|
30
|
+
return { files, sourcePath: primaryPath };
|
|
30
31
|
} catch (primaryError) {
|
|
31
32
|
if (!fallbackPath) {
|
|
32
33
|
throw primaryError;
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
const files = await fs.readdir(fallbackPath);
|
|
36
|
+
return { files, sourcePath: fallbackPath };
|
|
35
37
|
}
|
|
36
38
|
}
|
package/lib/utils/files.js
CHANGED
|
@@ -21,47 +21,20 @@ export async function pathExists(targetPath, type = 'file') {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export async function copyWithFallback({ primary, fallback, destination, onPrimaryMissing }) {
|
|
25
|
-
try {
|
|
26
|
-
await fs.copyFile(primary, destination);
|
|
27
|
-
return 'primary';
|
|
28
|
-
} catch (primaryError) {
|
|
29
|
-
if (onPrimaryMissing) {
|
|
30
|
-
onPrimaryMissing(primaryError);
|
|
31
|
-
}
|
|
32
|
-
if (!fallback) {
|
|
33
|
-
throw primaryError;
|
|
34
|
-
}
|
|
35
|
-
await fs.copyFile(fallback, destination);
|
|
36
|
-
return 'fallback';
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export async function readWithFallback({ primary, fallback, encoding = 'utf-8' }) {
|
|
41
|
-
try {
|
|
42
|
-
return await fs.readFile(primary, encoding);
|
|
43
|
-
} catch (primaryError) {
|
|
44
|
-
if (!fallback) {
|
|
45
|
-
throw primaryError;
|
|
46
|
-
}
|
|
47
|
-
return await fs.readFile(fallback, encoding);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
24
|
export function resolveAssetPath(basePath, relativePath) {
|
|
52
25
|
return path.join(basePath, relativePath);
|
|
53
26
|
}
|
|
54
27
|
|
|
55
|
-
export async function copyDirectory(
|
|
56
|
-
await fs.mkdir(
|
|
57
|
-
const entries = await fs.readdir(
|
|
28
|
+
export async function copyDirectory(sourceDir, targetDir) {
|
|
29
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
30
|
+
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
58
31
|
for (const entry of entries) {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
32
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
33
|
+
const targetPath = path.join(targetDir, entry.name);
|
|
61
34
|
if (entry.isDirectory()) {
|
|
62
|
-
await copyDirectory(
|
|
35
|
+
await copyDirectory(sourcePath, targetPath);
|
|
63
36
|
} else if (entry.isFile()) {
|
|
64
|
-
await fs.copyFile(
|
|
37
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
65
38
|
}
|
|
66
39
|
}
|
|
67
40
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Utility (CPG Implementation)
|
|
3
|
+
* Manages the Code Property Graph (CPG) for architectural memory
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { glob } from 'glob';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build a simple Code Property Graph (CPG)
|
|
12
|
+
* Maps files, functions, and dependencies
|
|
13
|
+
*/
|
|
14
|
+
export async function buildGraph() {
|
|
15
|
+
const files = await glob('**/*.{js,ts,jsx,tsx}', {
|
|
16
|
+
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**'],
|
|
17
|
+
nodir: true
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const graph = {
|
|
21
|
+
nodes: [],
|
|
22
|
+
edges: [],
|
|
23
|
+
lastUpdated: new Date().toISOString()
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
for (const file of files) {
|
|
27
|
+
try {
|
|
28
|
+
const content = await fs.readFile(file, 'utf8');
|
|
29
|
+
const fileNode = {
|
|
30
|
+
id: file,
|
|
31
|
+
type: 'file',
|
|
32
|
+
path: file,
|
|
33
|
+
exports: [],
|
|
34
|
+
imports: []
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Naive parsing using Regex (Phase 2.1)
|
|
38
|
+
// In Phase 2.2+ this would use tree-sitter
|
|
39
|
+
|
|
40
|
+
// Extract imports
|
|
41
|
+
const importRegex = /import\s+.*?\s+from\s+['"](.+?)['"]/g;
|
|
42
|
+
let match;
|
|
43
|
+
while ((match = importRegex.exec(content)) !== null) {
|
|
44
|
+
fileNode.imports.push(match[1]);
|
|
45
|
+
graph.edges.push({
|
|
46
|
+
source: file,
|
|
47
|
+
target: match[1],
|
|
48
|
+
type: 'depends_on'
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Extract function declarations
|
|
53
|
+
const funcRegex = /(?:export\s+)?(?:async\s+)?function\s+([a-zA-Z0-9_]+)/g;
|
|
54
|
+
while ((match = funcRegex.exec(content)) !== null) {
|
|
55
|
+
const funcName = match[1];
|
|
56
|
+
const funcId = `${file}:${funcName}`;
|
|
57
|
+
graph.nodes.push({
|
|
58
|
+
id: funcId,
|
|
59
|
+
type: 'function',
|
|
60
|
+
name: funcName,
|
|
61
|
+
parent: file
|
|
62
|
+
});
|
|
63
|
+
graph.edges.push({
|
|
64
|
+
source: funcId,
|
|
65
|
+
target: file,
|
|
66
|
+
type: 'contained_in'
|
|
67
|
+
});
|
|
68
|
+
fileNode.exports.push(funcName);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
graph.nodes.push(fileNode);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
// Skip files that can't be read
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return graph;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Find the impact of changing a file
|
|
82
|
+
* @param {Object} graph - The CPG
|
|
83
|
+
* @param {string} filePath - The file being changed
|
|
84
|
+
*/
|
|
85
|
+
export function getImpactAnalysis(graph, filePath) {
|
|
86
|
+
const impactedBy = graph.edges
|
|
87
|
+
.filter(edge => edge.target === filePath || filePath.endsWith(edge.target))
|
|
88
|
+
.map(edge => edge.source);
|
|
89
|
+
|
|
90
|
+
return [...new Set(impactedBy)];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Find structural truth (exact subgraph)
|
|
95
|
+
* @param {Object} graph - The CPG
|
|
96
|
+
* @param {string} query - Symbol name
|
|
97
|
+
*/
|
|
98
|
+
export function queryGraph(graph, query) {
|
|
99
|
+
return graph.nodes.filter(node =>
|
|
100
|
+
node.id.includes(query) || (node.name && node.name === query)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
buildGraph,
|
|
106
|
+
getImpactAnalysis,
|
|
107
|
+
queryGraph
|
|
108
|
+
};
|