prjct-cli 0.8.8 → 0.9.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/CHANGELOG.md +140 -0
- package/core/agentic/agent-router.js +482 -0
- package/core/agentic/command-executor.js +70 -15
- package/core/agentic/context-filter.js +545 -0
- package/core/agentic/prompt-builder.js +48 -38
- package/core/command-registry.js +104 -164
- package/core/domain/agent-generator.js +55 -44
- package/core/domain/architecture-generator.js +561 -0
- package/core/domain/task-stack.js +496 -0
- package/package.json +1 -1
- package/templates/commands/analyze.md +10 -53
- package/templates/commands/bug.md +11 -70
- package/templates/commands/build.md +7 -37
- package/templates/commands/cleanup.md +9 -32
- package/templates/commands/dash.md +241 -0
- package/templates/commands/design.md +5 -28
- package/templates/commands/done.md +6 -20
- package/templates/commands/feature.md +11 -83
- package/templates/commands/help.md +9 -38
- package/templates/commands/idea.md +7 -28
- package/templates/commands/init.md +10 -89
- package/templates/commands/next.md +6 -26
- package/templates/commands/now.md +6 -26
- package/templates/commands/pause.md +18 -0
- package/templates/commands/progress.md +5 -50
- package/templates/commands/recap.md +5 -54
- package/templates/commands/resume.md +97 -0
- package/templates/commands/ship.md +13 -68
- package/templates/commands/status.md +7 -32
- package/templates/commands/sync.md +7 -24
- package/templates/commands/work.md +44 -0
- package/templates/commands/workflow.md +3 -25
- package/templates/planning-methodology.md +195 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,146 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.1] - 2024-11-22
|
|
11
|
+
|
|
12
|
+
### 🎯 Context Optimization & Prompt Efficiency
|
|
13
|
+
|
|
14
|
+
Major performance improvements through context window optimization and prompt conciseness.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Mandatory Agent Assignment System**
|
|
19
|
+
- Every task now requires specialized agent assignment
|
|
20
|
+
- Automatic expertise detection from task descriptions
|
|
21
|
+
- Universal technology support (Ruby, Go, Python, etc.)
|
|
22
|
+
|
|
23
|
+
- **Context Filtering System**
|
|
24
|
+
- 70-90% context window reduction per task
|
|
25
|
+
- Technology-specific file filtering
|
|
26
|
+
- Smart pattern detection for any framework
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **Optimized Command Templates** (~70% reduction)
|
|
31
|
+
- Concise, efficient prompts for AI understanding
|
|
32
|
+
- Removed verbose explanations
|
|
33
|
+
- Direct flow instructions with → and | notation
|
|
34
|
+
|
|
35
|
+
- **Agent Generation Improvements**
|
|
36
|
+
- Dynamic, concise agent prompts
|
|
37
|
+
- Removed 200+ lines of hardcoded patterns
|
|
38
|
+
- Universal technology detection
|
|
39
|
+
|
|
40
|
+
### Performance
|
|
41
|
+
|
|
42
|
+
- Context window usage: **70-90% reduction**
|
|
43
|
+
- Template verbosity: **~70% average reduction**
|
|
44
|
+
- Agent specialization: True domain focus achieved
|
|
45
|
+
|
|
46
|
+
## [0.9.0] - 2024-11-22
|
|
47
|
+
|
|
48
|
+
### 🚀 Major Release: Simplified Commands + Pause/Resume + Intelligent Ideas
|
|
49
|
+
|
|
50
|
+
This release represents a **major simplification** of prjct-cli, reducing commands by 48% while adding powerful new capabilities including pause/resume for task interruptions and AI-powered idea development.
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- **Task Stack System** - Natural workflow with interruptions
|
|
55
|
+
- ✅ `/p:pause [reason]` - Pause active task to handle interruptions
|
|
56
|
+
- ✅ `/p:resume [task_id]` - Resume paused tasks with preserved context
|
|
57
|
+
- ✅ Multiple concurrent paused tasks supported
|
|
58
|
+
- ✅ Automatic duration tracking (excludes paused time)
|
|
59
|
+
- ✅ Migration from legacy `now.md` to new `stack.jsonl` format
|
|
60
|
+
- 📊 Impact: Handle urgent tasks without losing context
|
|
61
|
+
|
|
62
|
+
- **Intelligent Idea Development** - Transform ideas into complete architectures
|
|
63
|
+
- ✅ `/p:idea` enhanced to develop full technical specifications
|
|
64
|
+
- ✅ Simple ideas → Quick capture (< 20 words)
|
|
65
|
+
- ✅ Complex ideas → Complete architecture generation
|
|
66
|
+
- ✅ Interactive discovery process with AI
|
|
67
|
+
- ✅ Generates: Tech stack, API specs, database schema, roadmap
|
|
68
|
+
- ✅ Saves to `planning/architectures/{id}/` for reference
|
|
69
|
+
- 📊 Impact: Go from idea to implementation-ready specs in one command
|
|
70
|
+
|
|
71
|
+
- **Unified Commands** - Fewer commands, more power
|
|
72
|
+
- ✅ `/p:work [task]` - Replaces `/p:now` + `/p:build`
|
|
73
|
+
- No params → Show current task
|
|
74
|
+
- With task → Start new task
|
|
75
|
+
- ✅ `/p:dash [view]` - Replaces 4 dashboard commands
|
|
76
|
+
- Default → Full dashboard
|
|
77
|
+
- `week/month` → Progress views
|
|
78
|
+
- `roadmap` → Planning view
|
|
79
|
+
- `compact` → Minimal status
|
|
80
|
+
- ✅ `/p:help [topic]` - Enhanced to absorb 3 commands
|
|
81
|
+
- Absorbs `/p:ask`, `/p:suggest`, `/p:stuck`
|
|
82
|
+
- Context-aware suggestions
|
|
83
|
+
- Intent to action translation
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
|
|
87
|
+
- **Command Count** - Reduced from 23 → 13 (48% reduction)
|
|
88
|
+
- Core workflow remains 13 commands but simplified
|
|
89
|
+
- Removed redundant overlapping commands
|
|
90
|
+
- Better organization and clearer purpose
|
|
91
|
+
|
|
92
|
+
- **Architecture Generator** - New system for idea development
|
|
93
|
+
- `core/domain/architecture-generator.js` - Full architecture generation
|
|
94
|
+
- `core/domain/task-stack.js` - Pause/resume task management
|
|
95
|
+
- `templates/planning-methodology.md` - Comprehensive planning guide
|
|
96
|
+
|
|
97
|
+
### Removed
|
|
98
|
+
|
|
99
|
+
- **Deprecated Commands** - Completely removed (not just marked deprecated)
|
|
100
|
+
- ❌ `/p:now` → Use `/p:work`
|
|
101
|
+
- ❌ `/p:build` → Use `/p:work "task"`
|
|
102
|
+
- ❌ `/p:status` → Use `/p:dash`
|
|
103
|
+
- ❌ `/p:roadmap` → Use `/p:dash roadmap`
|
|
104
|
+
- ❌ `/p:recap` → Use `/p:dash`
|
|
105
|
+
- ❌ `/p:progress` → Use `/p:dash week`
|
|
106
|
+
- ❌ `/p:ask` → Use `/p:help`
|
|
107
|
+
- ❌ `/p:suggest` → Use `/p:help`
|
|
108
|
+
- ❌ `/p:stuck` → Use `/p:help stuck:`
|
|
109
|
+
- ❌ `/p:workflow` → Automatic in `/p:ship`
|
|
110
|
+
- ❌ `/p:task` → Use `/p:feature` for breakdown
|
|
111
|
+
|
|
112
|
+
### Migration Guide
|
|
113
|
+
|
|
114
|
+
**For existing users:**
|
|
115
|
+
1. First run will automatically migrate `now.md` to new stack system
|
|
116
|
+
2. Old commands will show error with suggestion to use new command
|
|
117
|
+
3. All data preserved during migration
|
|
118
|
+
|
|
119
|
+
**Command mapping:**
|
|
120
|
+
```bash
|
|
121
|
+
# Old → New
|
|
122
|
+
/p:now → /p:work
|
|
123
|
+
/p:build "task" → /p:work "task"
|
|
124
|
+
/p:status → /p:dash
|
|
125
|
+
/p:roadmap → /p:dash roadmap
|
|
126
|
+
/p:ask "question" → /p:help ask: "question"
|
|
127
|
+
/p:suggest → /p:help
|
|
128
|
+
/p:stuck "issue" → /p:help stuck: "issue"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**New workflow:**
|
|
132
|
+
```bash
|
|
133
|
+
/p:idea "build CRM" # Develop complete architecture
|
|
134
|
+
/p:work "implement auth" # Start task
|
|
135
|
+
/p:pause # Urgent interruption
|
|
136
|
+
/p:work "fix bug" # Handle urgent task
|
|
137
|
+
/p:done # Complete bug
|
|
138
|
+
/p:resume # Back to auth
|
|
139
|
+
/p:ship "auth feature" # Ship when done
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Technical Details
|
|
143
|
+
|
|
144
|
+
- New files: 10 templates, 3 domain modules
|
|
145
|
+
- Modified: Command registry, core commands
|
|
146
|
+
- Lines of code: +2000 (new features), -3000 (removed redundancy)
|
|
147
|
+
- Breaking changes: Yes (old commands removed)
|
|
148
|
+
- Data migration: Automatic
|
|
149
|
+
|
|
10
150
|
## [0.8.8] - 2025-10-06
|
|
11
151
|
|
|
12
152
|
### Added
|
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mandatory Agent Router
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: Ensures EVERY task is executed by a specialized agent
|
|
5
|
+
* No task can run without an assigned expert agent
|
|
6
|
+
*
|
|
7
|
+
* @version 1.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs').promises;
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const AgentGenerator = require('../domain/agent-generator');
|
|
13
|
+
|
|
14
|
+
class MandatoryAgentRouter {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.agentGenerator = new AgentGenerator();
|
|
17
|
+
this.agentCache = new Map();
|
|
18
|
+
this.usageLog = [];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Main entry point - ALL tasks MUST go through here
|
|
23
|
+
* @throws {Error} If no agent can be assigned
|
|
24
|
+
*/
|
|
25
|
+
async executeTask(task, context, projectPath) {
|
|
26
|
+
// STEP 1: Analyze task to determine required expertise
|
|
27
|
+
const taskAnalysis = this.analyzeTask(task);
|
|
28
|
+
|
|
29
|
+
// STEP 2: Select or generate specialized agent (MANDATORY)
|
|
30
|
+
const agent = await this.assignAgent(taskAnalysis, context);
|
|
31
|
+
|
|
32
|
+
// STEP 3: Validate agent assignment
|
|
33
|
+
if (!agent || !agent.name) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`CRITICAL: No agent assigned for task "${task.description}".
|
|
36
|
+
System requires ALL tasks to use specialized agents.`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// STEP 4: Filter context for this specific agent
|
|
41
|
+
const filteredContext = await this.filterContextForAgent(
|
|
42
|
+
agent,
|
|
43
|
+
context,
|
|
44
|
+
taskAnalysis
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// STEP 5: Log agent usage for tracking
|
|
48
|
+
this.logAgentUsage(task, agent, filteredContext);
|
|
49
|
+
|
|
50
|
+
// STEP 6: Return agent with filtered context
|
|
51
|
+
return {
|
|
52
|
+
agent,
|
|
53
|
+
context: filteredContext,
|
|
54
|
+
taskAnalysis,
|
|
55
|
+
routing: {
|
|
56
|
+
reason: taskAnalysis.reason,
|
|
57
|
+
confidence: taskAnalysis.confidence,
|
|
58
|
+
alternativeAgents: taskAnalysis.alternatives
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Analyze task to determine what type of expertise is needed
|
|
65
|
+
*/
|
|
66
|
+
analyzeTask(task) {
|
|
67
|
+
const description = task.description?.toLowerCase() || '';
|
|
68
|
+
const type = task.type?.toLowerCase() || '';
|
|
69
|
+
|
|
70
|
+
// Keywords for different domains
|
|
71
|
+
const patterns = {
|
|
72
|
+
frontend: [
|
|
73
|
+
'component', 'ui', 'react', 'vue', 'angular', 'style',
|
|
74
|
+
'css', 'layout', 'responsive', 'user interface', 'frontend'
|
|
75
|
+
],
|
|
76
|
+
backend: [
|
|
77
|
+
'api', 'server', 'endpoint', 'route', 'middleware',
|
|
78
|
+
'auth', 'authentication', 'jwt', 'session', 'backend'
|
|
79
|
+
],
|
|
80
|
+
database: [
|
|
81
|
+
'database', 'query', 'migration', 'schema', 'model',
|
|
82
|
+
'sql', 'postgres', 'mysql', 'mongo', 'index'
|
|
83
|
+
],
|
|
84
|
+
devops: [
|
|
85
|
+
'deploy', 'docker', 'kubernetes', 'ci/cd', 'pipeline',
|
|
86
|
+
'build', 'ship', 'release', 'production'
|
|
87
|
+
],
|
|
88
|
+
qa: [
|
|
89
|
+
'test', 'bug', 'error', 'fix', 'debug', 'issue',
|
|
90
|
+
'quality', 'coverage', 'unit test', 'integration'
|
|
91
|
+
],
|
|
92
|
+
architecture: [
|
|
93
|
+
'design', 'architecture', 'pattern', 'structure',
|
|
94
|
+
'refactor', 'organize', 'plan', 'feature'
|
|
95
|
+
]
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Detect primary domain
|
|
99
|
+
let detectedDomain = 'generalist';
|
|
100
|
+
let confidence = 0;
|
|
101
|
+
let matchedKeywords = [];
|
|
102
|
+
|
|
103
|
+
for (const [domain, keywords] of Object.entries(patterns)) {
|
|
104
|
+
const matches = keywords.filter(keyword =>
|
|
105
|
+
description.includes(keyword) || type.includes(keyword)
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
if (matches.length > confidence) {
|
|
109
|
+
confidence = matches.length;
|
|
110
|
+
detectedDomain = domain;
|
|
111
|
+
matchedKeywords = matches;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Detect technology stack
|
|
116
|
+
const techStack = this.detectTechnology(task, description);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
domain: detectedDomain,
|
|
120
|
+
confidence: confidence > 0 ? (confidence / 3) : 0.3, // confidence score
|
|
121
|
+
matchedKeywords,
|
|
122
|
+
techStack,
|
|
123
|
+
reason: `Detected ${detectedDomain} task based on: ${matchedKeywords.join(', ')}`,
|
|
124
|
+
alternatives: this.getSimilarDomains(detectedDomain)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Detect specific technologies mentioned or implied
|
|
130
|
+
*/
|
|
131
|
+
detectTechnology(task, description) {
|
|
132
|
+
const technologies = {
|
|
133
|
+
languages: [],
|
|
134
|
+
frameworks: [],
|
|
135
|
+
databases: [],
|
|
136
|
+
tools: []
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Language detection
|
|
140
|
+
const languages = [
|
|
141
|
+
'javascript', 'typescript', 'python', 'ruby', 'go',
|
|
142
|
+
'rust', 'java', 'csharp', 'php', 'elixir', 'swift'
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
const frameworks = [
|
|
146
|
+
'react', 'vue', 'angular', 'express', 'django', 'rails',
|
|
147
|
+
'spring', 'laravel', 'phoenix', 'gin', 'fastapi', 'nextjs'
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
const databases = [
|
|
151
|
+
'postgres', 'mysql', 'mongodb', 'redis', 'elasticsearch',
|
|
152
|
+
'dynamodb', 'firebase', 'supabase', 'sqlite'
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
// Check for each technology
|
|
156
|
+
languages.forEach(lang => {
|
|
157
|
+
if (description.includes(lang)) {
|
|
158
|
+
technologies.languages.push(lang);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
frameworks.forEach(fw => {
|
|
163
|
+
if (description.includes(fw)) {
|
|
164
|
+
technologies.frameworks.push(fw);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
databases.forEach(db => {
|
|
169
|
+
if (description.includes(db)) {
|
|
170
|
+
technologies.databases.push(db);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
return technologies;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Assign the best agent for the task
|
|
179
|
+
* Creates a new one if needed
|
|
180
|
+
*/
|
|
181
|
+
async assignAgent(taskAnalysis, context) {
|
|
182
|
+
const { domain, techStack } = taskAnalysis;
|
|
183
|
+
|
|
184
|
+
// Check cache first
|
|
185
|
+
const cacheKey = `${domain}-${techStack.languages.join('-')}`;
|
|
186
|
+
if (this.agentCache.has(cacheKey)) {
|
|
187
|
+
return this.agentCache.get(cacheKey);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Generate specialized agent based on detection
|
|
191
|
+
const agent = await this.generateSpecializedAgent(domain, techStack, context);
|
|
192
|
+
|
|
193
|
+
// Cache for reuse
|
|
194
|
+
this.agentCache.set(cacheKey, agent);
|
|
195
|
+
|
|
196
|
+
return agent;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Generate a specialized agent for the detected domain and tech
|
|
201
|
+
*/
|
|
202
|
+
async generateSpecializedAgent(domain, techStack, context) {
|
|
203
|
+
// Map domain to agent type
|
|
204
|
+
const agentTypes = {
|
|
205
|
+
frontend: 'frontend-specialist',
|
|
206
|
+
backend: 'backend-specialist',
|
|
207
|
+
database: 'database-specialist',
|
|
208
|
+
devops: 'devops-specialist',
|
|
209
|
+
qa: 'qa-specialist',
|
|
210
|
+
architecture: 'architect',
|
|
211
|
+
generalist: 'full-stack'
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const agentType = agentTypes[domain] || 'full-stack';
|
|
215
|
+
|
|
216
|
+
// Generate with detected technologies
|
|
217
|
+
const config = {
|
|
218
|
+
domain,
|
|
219
|
+
techStack,
|
|
220
|
+
projectContext: context.projectSummary || '',
|
|
221
|
+
bestPractices: await this.getBestPractices(domain, techStack)
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
return this.agentGenerator.generateDynamicAgent(agentType, config);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Get best practices for the domain and tech stack
|
|
229
|
+
*/
|
|
230
|
+
async getBestPractices(domain, techStack) {
|
|
231
|
+
const practices = [];
|
|
232
|
+
|
|
233
|
+
// Domain-specific best practices
|
|
234
|
+
const domainPractices = {
|
|
235
|
+
frontend: [
|
|
236
|
+
'Component composition over inheritance',
|
|
237
|
+
'State management patterns',
|
|
238
|
+
'Responsive design principles',
|
|
239
|
+
'Accessibility standards',
|
|
240
|
+
'Performance optimization (lazy loading, memoization)'
|
|
241
|
+
],
|
|
242
|
+
backend: [
|
|
243
|
+
'RESTful API design principles',
|
|
244
|
+
'Authentication and authorization patterns',
|
|
245
|
+
'Error handling and logging',
|
|
246
|
+
'Rate limiting and caching',
|
|
247
|
+
'Database connection pooling'
|
|
248
|
+
],
|
|
249
|
+
database: [
|
|
250
|
+
'Normalization principles',
|
|
251
|
+
'Index optimization',
|
|
252
|
+
'Query performance tuning',
|
|
253
|
+
'Transaction management',
|
|
254
|
+
'Backup and recovery strategies'
|
|
255
|
+
],
|
|
256
|
+
devops: [
|
|
257
|
+
'CI/CD pipeline best practices',
|
|
258
|
+
'Container orchestration',
|
|
259
|
+
'Infrastructure as Code',
|
|
260
|
+
'Monitoring and alerting',
|
|
261
|
+
'Security scanning'
|
|
262
|
+
],
|
|
263
|
+
qa: [
|
|
264
|
+
'Test pyramid (unit, integration, e2e)',
|
|
265
|
+
'Test coverage standards',
|
|
266
|
+
'Mocking and stubbing',
|
|
267
|
+
'Performance testing',
|
|
268
|
+
'Security testing'
|
|
269
|
+
]
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
practices.push(...(domainPractices[domain] || []));
|
|
273
|
+
|
|
274
|
+
// Technology-specific practices
|
|
275
|
+
if (techStack.languages.includes('javascript') || techStack.languages.includes('typescript')) {
|
|
276
|
+
practices.push('ES6+ features', 'Async/await patterns', 'Module system');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (techStack.frameworks.includes('react')) {
|
|
280
|
+
practices.push('Hooks patterns', 'Context API', 'Component lifecycle');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (techStack.languages.includes('ruby')) {
|
|
284
|
+
practices.push('Ruby idioms', 'Metaprogramming carefully', 'Convention over configuration');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (techStack.languages.includes('go')) {
|
|
288
|
+
practices.push('Goroutines and channels', 'Error handling patterns', 'Interface design');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return practices;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Filter context to only what's relevant for this agent
|
|
296
|
+
*/
|
|
297
|
+
async filterContextForAgent(agent, fullContext, taskAnalysis) {
|
|
298
|
+
const { domain } = taskAnalysis;
|
|
299
|
+
|
|
300
|
+
// Define what each agent type should see
|
|
301
|
+
const contextPatterns = {
|
|
302
|
+
frontend: {
|
|
303
|
+
include: ['components', 'views', 'styles', 'pages', 'layouts'],
|
|
304
|
+
exclude: ['node_modules', 'dist', 'build', 'migrations'],
|
|
305
|
+
extensions: ['.jsx', '.tsx', '.vue', '.css', '.scss', '.styled.js']
|
|
306
|
+
},
|
|
307
|
+
backend: {
|
|
308
|
+
include: ['routes', 'controllers', 'services', 'middleware', 'api'],
|
|
309
|
+
exclude: ['node_modules', 'dist', 'public', 'styles'],
|
|
310
|
+
extensions: ['.js', '.ts', '.py', '.rb', '.go', '.java']
|
|
311
|
+
},
|
|
312
|
+
database: {
|
|
313
|
+
include: ['models', 'migrations', 'schemas', 'seeds', 'queries'],
|
|
314
|
+
exclude: ['node_modules', 'public', 'styles', 'components'],
|
|
315
|
+
extensions: ['.sql', '.js', '.ts', '.rb', '.py']
|
|
316
|
+
},
|
|
317
|
+
devops: {
|
|
318
|
+
include: ['.github', '.gitlab', 'docker', 'k8s', 'terraform'],
|
|
319
|
+
exclude: ['node_modules', 'src', 'public'],
|
|
320
|
+
extensions: ['.yml', '.yaml', '.dockerfile', '.sh', '.tf']
|
|
321
|
+
},
|
|
322
|
+
qa: {
|
|
323
|
+
include: ['tests', 'spec', '__tests__', 'test'],
|
|
324
|
+
exclude: ['node_modules', 'dist', 'build'],
|
|
325
|
+
extensions: ['.test.js', '.spec.js', '.test.ts', '.spec.ts']
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const pattern = contextPatterns[domain] || {
|
|
330
|
+
include: [],
|
|
331
|
+
exclude: ['node_modules', 'dist', 'build'],
|
|
332
|
+
extensions: []
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// Filter the context based on patterns
|
|
336
|
+
const filtered = {
|
|
337
|
+
...fullContext,
|
|
338
|
+
files: this.filterFiles(fullContext.files || [], pattern),
|
|
339
|
+
relevantOnly: true,
|
|
340
|
+
filterApplied: domain
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
return filtered;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Filter files based on patterns
|
|
348
|
+
*/
|
|
349
|
+
filterFiles(files, pattern) {
|
|
350
|
+
return files.filter(file => {
|
|
351
|
+
// Check if file should be excluded
|
|
352
|
+
for (const exclude of pattern.exclude) {
|
|
353
|
+
if (file.includes(exclude)) return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check if file matches include patterns
|
|
357
|
+
if (pattern.include.length > 0) {
|
|
358
|
+
let matches = false;
|
|
359
|
+
for (const include of pattern.include) {
|
|
360
|
+
if (file.includes(include)) {
|
|
361
|
+
matches = true;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (!matches) return false;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Check extensions if specified
|
|
369
|
+
if (pattern.extensions.length > 0) {
|
|
370
|
+
let hasValidExtension = false;
|
|
371
|
+
for (const ext of pattern.extensions) {
|
|
372
|
+
if (file.endsWith(ext)) {
|
|
373
|
+
hasValidExtension = true;
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (!hasValidExtension) return false;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return true;
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Log agent usage for metrics and optimization
|
|
386
|
+
*/
|
|
387
|
+
logAgentUsage(task, agent, context) {
|
|
388
|
+
const usage = {
|
|
389
|
+
timestamp: new Date().toISOString(),
|
|
390
|
+
task: task.description,
|
|
391
|
+
agent: agent.name,
|
|
392
|
+
domain: agent.domain || 'unknown',
|
|
393
|
+
contextSize: context.files?.length || 0,
|
|
394
|
+
contextReduction: this.calculateContextReduction(context),
|
|
395
|
+
confidence: agent.confidence || 1.0
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
this.usageLog.push(usage);
|
|
399
|
+
|
|
400
|
+
// Also append to a log file for persistence
|
|
401
|
+
this.appendToLogFile(usage);
|
|
402
|
+
|
|
403
|
+
return usage;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Calculate how much context was reduced
|
|
408
|
+
*/
|
|
409
|
+
calculateContextReduction(filteredContext) {
|
|
410
|
+
// This would compare against full context
|
|
411
|
+
// For now, estimate based on filtering
|
|
412
|
+
if (filteredContext.relevantOnly) {
|
|
413
|
+
return '70-90%'; // Typical reduction when filtering
|
|
414
|
+
}
|
|
415
|
+
return '0%';
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Append usage to log file
|
|
420
|
+
*/
|
|
421
|
+
async appendToLogFile(usage) {
|
|
422
|
+
try {
|
|
423
|
+
const logPath = path.join(
|
|
424
|
+
process.env.HOME,
|
|
425
|
+
'.prjct-cli',
|
|
426
|
+
'agent-usage.jsonl'
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
const logEntry = JSON.stringify(usage) + '\n';
|
|
430
|
+
await fs.appendFile(logPath, logEntry);
|
|
431
|
+
} catch (error) {
|
|
432
|
+
// Log errors silently, don't break execution
|
|
433
|
+
console.error('Failed to log agent usage:', error.message);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Get similar domains for fallback
|
|
439
|
+
*/
|
|
440
|
+
getSimilarDomains(domain) {
|
|
441
|
+
const similarities = {
|
|
442
|
+
frontend: ['fullstack', 'ui/ux'],
|
|
443
|
+
backend: ['fullstack', 'api', 'services'],
|
|
444
|
+
database: ['backend', 'data'],
|
|
445
|
+
devops: ['infrastructure', 'platform'],
|
|
446
|
+
qa: ['testing', 'quality'],
|
|
447
|
+
architecture: ['design', 'planning']
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
return similarities[domain] || ['generalist'];
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Get usage statistics
|
|
455
|
+
*/
|
|
456
|
+
getUsageStats() {
|
|
457
|
+
const stats = {
|
|
458
|
+
totalTasks: this.usageLog.length,
|
|
459
|
+
byAgent: {},
|
|
460
|
+
avgContextReduction: '0%',
|
|
461
|
+
mostUsedAgent: null
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// Calculate stats from usage log
|
|
465
|
+
this.usageLog.forEach(log => {
|
|
466
|
+
stats.byAgent[log.agent] = (stats.byAgent[log.agent] || 0) + 1;
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// Find most used agent
|
|
470
|
+
let maxUsage = 0;
|
|
471
|
+
for (const [agent, count] of Object.entries(stats.byAgent)) {
|
|
472
|
+
if (count > maxUsage) {
|
|
473
|
+
maxUsage = count;
|
|
474
|
+
stats.mostUsedAgent = agent;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return stats;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
module.exports = MandatoryAgentRouter;
|