prjct-cli 0.10.10 β†’ 0.10.12

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/core/commands.js CHANGED
@@ -22,6 +22,7 @@ const commandExecutor = require('./agentic/command-executor')
22
22
  const contextBuilder = require('./agentic/context-builder')
23
23
  const toolRegistry = require('./agentic/tool-registry')
24
24
  const memorySystem = require('./agentic/memory-system')
25
+ const AgentRouter = require('./agentic/agent-router')
25
26
  const pathManager = require('./infrastructure/path-manager')
26
27
  const configManager = require('./infrastructure/config-manager')
27
28
  const authorDetector = require('./infrastructure/author-detector')
@@ -46,6 +47,7 @@ class PrjctCommands {
46
47
  this.updateChecker = new UpdateChecker()
47
48
  this.updateNotificationShown = false
48
49
  this.commandExecutor = commandExecutor
50
+ this.agentRouter = new AgentRouter()
49
51
  }
50
52
 
51
53
  /**
@@ -138,17 +140,24 @@ class PrjctCommands {
138
140
  const context = await contextBuilder.build(projectPath, { task })
139
141
 
140
142
  if (task) {
141
- // Set task
142
- const nowContent = `# NOW\n\n**${task}**\n\nStarted: ${new Date().toLocaleString()}\n`
143
+ // MANDATORY: Assign agent before setting task
144
+ const agentResult = await this._assignAgentForTask(task, projectPath, context)
145
+ const agent = agentResult.agent?.name || 'generalist'
146
+ const confidence = agentResult.routing?.confidence || 0.5
147
+
148
+ // Set task WITH agent
149
+ const nowContent = `# NOW\n\n**${task}**\n\nStarted: ${new Date().toLocaleString()}\nAgent: ${agent} (${Math.round(confidence * 100)}% confidence)\n`
143
150
  await toolRegistry.get('Write')(context.paths.now, nowContent)
144
151
 
145
- out.done(`${task} (started)`)
152
+ out.done(`${task} [${agent}]`)
146
153
 
147
154
  await this.logToMemory(projectPath, 'task_started', {
148
155
  task,
156
+ agent,
157
+ confidence,
149
158
  timestamp: dateHelper.getTimestamp(),
150
159
  })
151
- return { success: true, task }
160
+ return { success: true, task, agent }
152
161
  } else {
153
162
  // Show current task
154
163
  const nowContent = await toolRegistry.get('Read')(context.paths.now)
@@ -158,10 +167,12 @@ class PrjctCommands {
158
167
  return { success: true, message: 'No active task' }
159
168
  }
160
169
 
161
- // Extract task name for minimal output
170
+ // Extract task name and agent for minimal output
162
171
  const taskMatch = nowContent.match(/\*\*(.+?)\*\*/)
172
+ const agentMatch = nowContent.match(/Agent: ([^\s(]+)/)
163
173
  const currentTask = taskMatch ? taskMatch[1] : 'unknown'
164
- out.done(`working on: ${currentTask}`)
174
+ const currentAgent = agentMatch ? agentMatch[1] : ''
175
+ out.done(`working on: ${currentTask}${currentAgent ? ` [${currentAgent}]` : ''}`)
165
176
  return { success: true, content: nowContent }
166
177
  }
167
178
  } catch (error) {
@@ -427,26 +438,42 @@ class PrjctCommands {
427
438
  // Task breakdown
428
439
  const tasks = this._breakdownFeatureTasks(description)
429
440
 
430
- // Write to next.md
441
+ // MANDATORY: Assign agent to each task
442
+ const tasksWithAgents = []
443
+ for (const taskDesc of tasks) {
444
+ const agentResult = await this._assignAgentForTask(taskDesc, projectPath, context)
445
+ const agent = agentResult.agent?.name || 'generalist'
446
+ tasksWithAgents.push({ task: taskDesc, agent })
447
+ }
448
+
449
+ // Write to next.md with agents
431
450
  const nextContent =
432
451
  (await toolRegistry.get('Read')(context.paths.next)) || '# NEXT\n\n## Priority Queue\n\n'
433
452
  const taskSection =
434
453
  `\n## Feature: ${description}\n\n` +
435
- tasks.map((t, i) => `${i + 1}. [ ] ${t}`).join('\n') +
454
+ tasksWithAgents.map((t, i) => `${i + 1}. [${t.agent}] [ ] ${t.task}`).join('\n') +
436
455
  `\n\nEstimated: ${tasks.length * 2}h\n`
437
456
 
438
457
  await toolRegistry.get('Write')(context.paths.next, nextContent + taskSection)
439
458
 
440
- // Log to memory
459
+ // Log to memory with agent assignments
441
460
  await this.logToMemory(projectPath, 'feature_planned', {
442
461
  feature: description,
443
- tasks: tasks.length,
462
+ tasks: tasksWithAgents.length,
463
+ assignments: tasksWithAgents.map(t => ({ task: t.task, agent: t.agent })),
444
464
  timestamp: dateHelper.getTimestamp(),
445
465
  })
446
466
 
447
- out.done(`${tasks.length} tasks created`)
467
+ // Show summary with agent distribution
468
+ const agentCounts = tasksWithAgents.reduce((acc, t) => {
469
+ acc[t.agent] = (acc[t.agent] || 0) + 1
470
+ return acc
471
+ }, {})
472
+ const agentSummary = Object.entries(agentCounts).map(([a, c]) => `${a}:${c}`).join(' ')
473
+
474
+ out.done(`${tasks.length} tasks [${agentSummary}]`)
448
475
 
449
- return { success: true, feature: description, tasks }
476
+ return { success: true, feature: description, tasks: tasksWithAgents }
450
477
  } catch (error) {
451
478
  out.fail(error.message)
452
479
  return { success: false, error: error.message }
@@ -459,36 +486,13 @@ class PrjctCommands {
459
486
  * @private
460
487
  */
461
488
  _breakdownFeatureTasks(description) {
462
- // Simplified breakdown - Claude would analyze and create appropriate tasks
463
- const lowerDesc = description.toLowerCase()
464
-
465
- if (lowerDesc.includes('test')) {
466
- return [
467
- 'Setup testing framework configuration',
468
- 'Write tests for core utilities',
469
- 'Write tests for components/modules',
470
- 'Add CI/CD test runner',
471
- 'Update docs with testing guide',
472
- ]
473
- }
474
-
475
- if (lowerDesc.includes('auth') || lowerDesc.includes('login')) {
476
- return [
477
- 'Design authentication flow',
478
- 'Implement backend authentication API',
479
- 'Implement frontend login/signup UI',
480
- 'Add session management',
481
- 'Test authentication flow',
482
- ]
483
- }
484
-
485
- // Default breakdown
489
+ // AGENTIC: Claude analyzes and creates tasks via templates/analysis/task-breakdown.md
490
+ // This returns a placeholder - real breakdown happens in template execution
486
491
  return [
487
- `Research and design ${description}`,
492
+ `Analyze and plan: ${description}`,
488
493
  'Implement core functionality',
489
- 'Add tests and validation',
490
- 'Update documentation',
491
- 'Review and refine',
494
+ 'Test and validate',
495
+ 'Document changes',
492
496
  ]
493
497
  }
494
498
 
@@ -511,10 +515,14 @@ class PrjctCommands {
511
515
  const context = await contextBuilder.build(projectPath, { description })
512
516
  const severity = this._detectBugSeverity(description)
513
517
 
514
- // Add to next.md with priority
518
+ // MANDATORY: Assign agent to bug
519
+ const agentResult = await this._assignAgentForTask(`fix bug: ${description}`, projectPath, context)
520
+ const agent = agentResult.agent?.name || 'generalist'
521
+
522
+ // Add to next.md with priority and agent
515
523
  const nextContent =
516
524
  (await toolRegistry.get('Read')(context.paths.next)) || '# NEXT\n\n## Priority Queue\n\n'
517
- const bugEntry = `\n## πŸ› BUG [${severity.toUpperCase()}]: ${description}\n\nReported: ${new Date().toLocaleString()}\nPriority: ${severity === 'critical' ? '⚠️ URGENT' : severity === 'high' ? 'πŸ”΄ High' : '🟑 Normal'}\n`
525
+ const bugEntry = `\n## πŸ› BUG [${severity.toUpperCase()}] [${agent}]: ${description}\n\nReported: ${new Date().toLocaleString()}\nPriority: ${severity === 'critical' ? '⚠️ URGENT' : severity === 'high' ? 'πŸ”΄ High' : '🟑 Normal'}\nAssigned: ${agent}\n`
518
526
 
519
527
  // Insert at top if critical/high, at bottom otherwise
520
528
  const updatedContent =
@@ -524,16 +532,17 @@ class PrjctCommands {
524
532
 
525
533
  await toolRegistry.get('Write')(context.paths.next, updatedContent)
526
534
 
527
- // Log to memory
535
+ // Log to memory with agent
528
536
  await this.logToMemory(projectPath, 'bug_reported', {
529
537
  bug: description,
530
538
  severity,
539
+ agent,
531
540
  timestamp: dateHelper.getTimestamp(),
532
541
  })
533
542
 
534
- out.done(`bug [${severity}] tracked`)
543
+ out.done(`bug [${severity}] β†’ ${agent}`)
535
544
 
536
- return { success: true, bug: description, severity }
545
+ return { success: true, bug: description, severity, agent }
537
546
  } catch (error) {
538
547
  out.fail(error.message)
539
548
  return { success: false, error: error.message }
@@ -546,20 +555,8 @@ class PrjctCommands {
546
555
  * @private
547
556
  */
548
557
  _detectBugSeverity(description) {
549
- const lowerDesc = description.toLowerCase()
550
-
551
- if (
552
- lowerDesc.includes('crash') ||
553
- lowerDesc.includes('broken') ||
554
- lowerDesc.includes('not working')
555
- ) {
556
- return 'critical'
557
- }
558
-
559
- if (lowerDesc.includes('error') || lowerDesc.includes('fail') || lowerDesc.includes('bug')) {
560
- return 'high'
561
- }
562
-
558
+ // AGENTIC: Claude assesses severity via templates/analysis/bug-severity.md
559
+ // Returns default - real assessment happens in template execution
563
560
  return 'medium'
564
561
  }
565
562
 
@@ -971,68 +968,8 @@ class PrjctCommands {
971
968
  * @private
972
969
  */
973
970
  _generateArchitectureDesign(target, projectPath) {
974
- const projectName = path.basename(projectPath)
975
- return `# Architecture Design: ${target}
976
-
977
- **Project**: ${projectName}
978
- **Created**: ${new Date().toLocaleString()}
979
- **Type**: System Architecture
980
-
981
- ## Overview
982
-
983
- High-level architecture design for ${target}.
984
-
985
- ## Components
986
-
987
- ### Core Components
988
- 1. **Component A**
989
- - Responsibility: [Define responsibility]
990
- - Dependencies: [List dependencies]
991
- - Interfaces: [Define interfaces]
992
-
993
- 2. **Component B**
994
- - Responsibility: [Define responsibility]
995
- - Dependencies: [List dependencies]
996
- - Interfaces: [Define interfaces]
997
-
998
- ## Data Flow
999
-
1000
- \`\`\`
1001
- [User] β†’ [Frontend] β†’ [API Gateway] β†’ [Backend Services] β†’ [Database]
1002
- ↓
1003
- [Cache Layer]
1004
- \`\`\`
1005
-
1006
- ## Technology Stack
1007
-
1008
- - **Frontend**: [Framework/Library]
1009
- - **Backend**: [Framework/Runtime]
1010
- - **Database**: [Type/System]
1011
- - **Deployment**: [Platform/Method]
1012
-
1013
- ## Design Decisions
1014
-
1015
- ### Decision 1: [Title]
1016
- - **Context**: [Why this decision is needed]
1017
- - **Options**: [Alternatives considered]
1018
- - **Choice**: [What was chosen]
1019
- - **Rationale**: [Why this choice]
1020
-
1021
- ## Implementation Plan
1022
-
1023
- 1. [ ] Setup project structure
1024
- 2. [ ] Implement core components
1025
- 3. [ ] Add integration layer
1026
- 4. [ ] Testing and validation
1027
- 5. [ ] Documentation
1028
-
1029
- ## Notes
1030
-
1031
- [Additional notes, constraints, assumptions]
1032
-
1033
- ---
1034
- *This is a living document. Update as design evolves.*
1035
- `
971
+ // AGENTIC: Claude generates via templates/design/architecture.md
972
+ return `# Architecture Design: ${target}\n\n*Use templates/design/architecture.md for full design*\n`
1036
973
  }
1037
974
 
1038
975
  /**
@@ -1040,79 +977,8 @@ High-level architecture design for ${target}.
1040
977
  * @private
1041
978
  */
1042
979
  _generateApiDesign(target) {
1043
- return `# API Design: ${target}
1044
-
1045
- **Created**: ${new Date().toLocaleString()}
1046
- **Type**: API Specification
1047
-
1048
- ## Endpoints
1049
-
1050
- ### GET /api/${target.toLowerCase()}
1051
- **Description**: Retrieve ${target}
1052
-
1053
- **Request**:
1054
- \`\`\`
1055
- GET /api/${target.toLowerCase()}?limit=10&offset=0
1056
- \`\`\`
1057
-
1058
- **Response** (200 OK):
1059
- \`\`\`json
1060
- {
1061
- "data": [],
1062
- "meta": {
1063
- "total": 0,
1064
- "limit": 10,
1065
- "offset": 0
1066
- }
1067
- }
1068
- \`\`\`
1069
-
1070
- ### POST /api/${target.toLowerCase()}
1071
- **Description**: Create new ${target}
1072
-
1073
- **Request**:
1074
- \`\`\`json
1075
- {
1076
- "name": "string",
1077
- "description": "string"
1078
- }
1079
- \`\`\`
1080
-
1081
- **Response** (201 Created):
1082
- \`\`\`json
1083
- {
1084
- "id": "string",
1085
- "name": "string",
1086
- "description": "string",
1087
- "createdAt": "ISO8601"
1088
- }
1089
- \`\`\`
1090
-
1091
- ## Error Handling
1092
-
1093
- \`\`\`json
1094
- {
1095
- "error": {
1096
- "code": "ERROR_CODE",
1097
- "message": "Human-readable message",
1098
- "details": {}
1099
- }
1100
- }
1101
- \`\`\`
1102
-
1103
- ## Authentication
1104
-
1105
- - **Method**: Bearer Token
1106
- - **Header**: \`Authorization: Bearer <token>\`
1107
-
1108
- ## Rate Limiting
1109
-
1110
- - **Limit**: 100 requests/minute
1111
- - **Headers**: \`X-RateLimit-Limit\`, \`X-RateLimit-Remaining\`
1112
-
1113
- ---
1114
- *Update this specification as API evolves.*
1115
- `
980
+ // AGENTIC: Claude generates via templates/design/api.md
981
+ return `# API Design: ${target}\n\n*Use templates/design/api.md for full design*\n`
1116
982
  }
1117
983
 
1118
984
  /**
@@ -1120,79 +986,8 @@ GET /api/${target.toLowerCase()}?limit=10&offset=0
1120
986
  * @private
1121
987
  */
1122
988
  _generateComponentDesign(target) {
1123
- return `# Component Design: ${target}
1124
-
1125
- **Created**: ${new Date().toLocaleString()}
1126
- **Type**: Component Specification
1127
-
1128
- ## Overview
1129
-
1130
- Component for ${target} functionality.
1131
-
1132
- ## Props/Interface
1133
-
1134
- \`\`\`typescript
1135
- interface ${target}Props {
1136
- // Define props
1137
- id?: string
1138
- className?: string
1139
- onAction?: (data: any) => void
1140
- }
1141
- \`\`\`
1142
-
1143
- ## State
1144
-
1145
- \`\`\`typescript
1146
- interface ${target}State {
1147
- // Define internal state
1148
- loading: boolean
1149
- data: any[]
1150
- error: Error | null
1151
- }
1152
- \`\`\`
1153
-
1154
- ## Component Structure
1155
-
1156
- \`\`\`
1157
- ${target}/
1158
- β”œβ”€β”€ index.ts # Barrel export
1159
- β”œβ”€β”€ ${target}.tsx # Main component
1160
- β”œβ”€β”€ ${target}.test.tsx # Tests
1161
- β”œβ”€β”€ ${target}.styles.ts # Styles
1162
- └── types.ts # Type definitions
1163
- \`\`\`
1164
-
1165
- ## Usage Example
1166
-
1167
- \`\`\`tsx
1168
- import { ${target} } from '@/components/${target}'
1169
-
1170
- function App() {
1171
- return (
1172
- <${target}
1173
- id="example"
1174
- onAction={(data) => console.log(data)}
1175
- />
1176
- )
1177
- }
1178
- \`\`\`
1179
-
1180
- ## Dependencies
1181
-
1182
- - React
1183
- - [Other libraries]
1184
-
1185
- ## Implementation Notes
1186
-
1187
- 1. [ ] Setup component structure
1188
- 2. [ ] Implement core logic
1189
- 3. [ ] Add styling
1190
- 4. [ ] Write tests
1191
- 5. [ ] Document usage
1192
-
1193
- ---
1194
- *Component design is iterative. Update as needed.*
1195
- `
989
+ // AGENTIC: Claude generates via templates/design/component.md
990
+ return `# Component Design: ${target}\n\n*Use templates/design/component.md for full design*\n`
1196
991
  }
1197
992
 
1198
993
  /**
@@ -1200,68 +995,8 @@ function App() {
1200
995
  * @private
1201
996
  */
1202
997
  _generateDatabaseDesign(target) {
1203
- return `# Database Design: ${target}
1204
-
1205
- **Created**: ${new Date().toLocaleString()}
1206
- **Type**: Database Schema
1207
-
1208
- ## Schema
1209
-
1210
- ### Table: ${target.toLowerCase()}
1211
-
1212
- \`\`\`sql
1213
- CREATE TABLE ${target.toLowerCase()} (
1214
- id SERIAL PRIMARY KEY,
1215
- name VARCHAR(255) NOT NULL,
1216
- description TEXT,
1217
- status VARCHAR(50) DEFAULT 'active',
1218
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1219
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
1220
- );
1221
- \`\`\`
1222
-
1223
- ## Indexes
1224
-
1225
- \`\`\`sql
1226
- CREATE INDEX idx_${target.toLowerCase()}_status ON ${target.toLowerCase()}(status);
1227
- CREATE INDEX idx_${target.toLowerCase()}_created_at ON ${target.toLowerCase()}(created_at);
1228
- \`\`\`
1229
-
1230
- ## Relationships
1231
-
1232
- - **Related Tables**: [List related tables]
1233
- - **Foreign Keys**: [Define foreign keys]
1234
-
1235
- ## Queries
1236
-
1237
- ### Common Queries
1238
-
1239
- \`\`\`sql
1240
- -- Get active records
1241
- SELECT * FROM ${target.toLowerCase()} WHERE status = 'active';
1242
-
1243
- -- Get recent records
1244
- SELECT * FROM ${target.toLowerCase()}
1245
- ORDER BY created_at DESC
1246
- LIMIT 10;
1247
- \`\`\`
1248
-
1249
- ## Migrations
1250
-
1251
- 1. [ ] Create initial schema
1252
- 2. [ ] Add indexes
1253
- 3. [ ] Setup relationships
1254
- 4. [ ] Add constraints
1255
-
1256
- ## Notes
1257
-
1258
- - Consider partitioning for large datasets
1259
- - Add audit logging if needed
1260
- - Implement soft deletes
1261
-
1262
- ---
1263
- *Database design should evolve with requirements.*
1264
- `
998
+ // AGENTIC: Claude generates via templates/design/database.md
999
+ return `# Database Design: ${target}\n\n*Use templates/design/database.md for full design*\n`
1265
1000
  }
1266
1001
 
1267
1002
  /**
@@ -1269,63 +1004,8 @@ LIMIT 10;
1269
1004
  * @private
1270
1005
  */
1271
1006
  _generateFlowDesign(target) {
1272
- return `# Flow Design: ${target}
1273
-
1274
- **Created**: ${new Date().toLocaleString()}
1275
- **Type**: Process Flow
1276
-
1277
- ## Flow Overview
1278
-
1279
- Process flow for ${target}.
1280
-
1281
- ## Steps
1282
-
1283
- \`\`\`
1284
- 1. [User Action/Trigger]
1285
- ↓
1286
- 2. [Validation]
1287
- ↓
1288
- 3. [Processing]
1289
- ↓
1290
- 4. [Side Effects]
1291
- ↓
1292
- 5. [Response/Completion]
1293
- \`\`\`
1294
-
1295
- ## Detailed Flow
1296
-
1297
- ### Step 1: Initial Action
1298
- - **Input**: [What triggers this]
1299
- - **Validation**: [What gets checked]
1300
- - **Output**: [What proceeds]
1301
-
1302
- ### Step 2: Processing
1303
- - **Actions**: [What happens]
1304
- - **Dependencies**: [What's needed]
1305
- - **Side Effects**: [What changes]
1306
-
1307
- ### Step 3: Completion
1308
- - **Success**: [What happens on success]
1309
- - **Failure**: [What happens on failure]
1310
- - **Notifications**: [Who gets notified]
1311
-
1312
- ## Error Handling
1313
-
1314
- - **Error Type 1**: [Recovery strategy]
1315
- - **Error Type 2**: [Recovery strategy]
1316
-
1317
- ## Rollback Strategy
1318
-
1319
- [How to undo if needed]
1320
-
1321
- ## Monitoring
1322
-
1323
- - **Metrics**: [What to track]
1324
- - **Alerts**: [When to alert]
1325
-
1326
- ---
1327
- *Document edge cases and special scenarios.*
1328
- `
1007
+ // AGENTIC: Claude generates via templates/design/flow.md
1008
+ return `# Flow Design: ${target}\n\n*Use templates/design/flow.md for full design*\n`
1329
1009
  }
1330
1010
 
1331
1011
  /**
@@ -1661,30 +1341,13 @@ Status: ⏸️ Planned
1661
1341
  * @private
1662
1342
  */
1663
1343
  _calculateHealth(stats) {
1664
- let score = 50 // Base score
1665
-
1666
- // Active task is good
1667
- if (stats.activeTask) score += 20
1668
-
1669
- // Having tasks but not too many
1670
- if (stats.tasksInQueue > 0 && stats.tasksInQueue < 15) score += 15
1671
- if (stats.tasksInQueue >= 15) score -= 5 // Too many tasks
1672
-
1673
- // Shipped features is great
1674
- score += Math.min(20, stats.featuresShipped * 5)
1675
-
1676
- // Ideas are good but not critical
1677
- score += Math.min(10, stats.ideasCaptured * 2)
1678
-
1679
- score = Math.max(0, Math.min(100, score))
1680
-
1681
- let message = ''
1682
- if (score >= 80) message = '🟒 Excellent - Great momentum!'
1683
- else if (score >= 60) message = '🟑 Good - Keep shipping!'
1684
- else if (score >= 40) message = '🟠 Fair - Need more activity'
1685
- else message = 'πŸ”΄ Low - Time to get started!'
1686
-
1687
- return { score, message }
1344
+ // AGENTIC: Claude evaluates health via templates/analysis/health.md
1345
+ // Simple calculation - real assessment happens in template execution
1346
+ const hasActivity = stats.activeTask || stats.featuresShipped > 0
1347
+ return {
1348
+ score: hasActivity ? 70 : 50,
1349
+ message: hasActivity ? '🟒 Active' : '🟑 Ready to start',
1350
+ }
1688
1351
  }
1689
1352
 
1690
1353
  /**
@@ -1747,9 +1410,11 @@ Status: ⏸️ Planned
1747
1410
  console.log(` Estimated: ${estimate}h`)
1748
1411
  console.log(` Type: ${complexity.type}\n`)
1749
1412
 
1750
- // Auto-assign agent (simplified)
1751
- const agent = this._autoAssignAgent(task)
1752
- console.log(`πŸ€– Agent: ${agent}\n`)
1413
+ // MANDATORY: Assign agent using router
1414
+ const agentResult = await this._assignAgentForTask(task, projectPath, context)
1415
+ const agent = agentResult.agent?.name || 'generalist'
1416
+ const confidence = agentResult.routing?.confidence || 0.5
1417
+ console.log(`πŸ€– Agent: ${agent} (${Math.round(confidence * 100)}% confidence)\n`)
1753
1418
 
1754
1419
  // Set as current task with metadata
1755
1420
  const nowContentNew = `# NOW
@@ -1759,7 +1424,7 @@ Status: ⏸️ Planned
1759
1424
  Started: ${new Date().toLocaleString()}
1760
1425
  Estimated: ${estimate}h
1761
1426
  Complexity: ${complexity.level}
1762
- Agent: ${agent}
1427
+ Agent: ${agent} (${Math.round(confidence * 100)}% confidence)
1763
1428
  `
1764
1429
  await toolRegistry.get('Write')(context.paths.now, nowContentNew)
1765
1430
 
@@ -1774,6 +1439,7 @@ Agent: ${agent}
1774
1439
  complexity: complexity.level,
1775
1440
  estimate,
1776
1441
  agent,
1442
+ confidence,
1777
1443
  timestamp: dateHelper.getTimestamp(),
1778
1444
  })
1779
1445
 
@@ -1789,72 +1455,64 @@ Agent: ${agent}
1789
1455
  * @private
1790
1456
  */
1791
1457
  _detectComplexity(task) {
1792
- const lowerTask = task.toLowerCase()
1793
-
1794
- // Type detection
1795
- let type = 'general'
1796
- if (lowerTask.includes('fix') || lowerTask.includes('bug')) type = 'bugfix'
1797
- else if (lowerTask.includes('test')) type = 'testing'
1798
- else if (lowerTask.includes('refactor')) type = 'refactoring'
1799
- else if (lowerTask.includes('implement') || lowerTask.includes('add')) type = 'feature'
1800
- else if (lowerTask.includes('design')) type = 'design'
1801
-
1802
- // Complexity indicators
1803
- const complexityIndicators = {
1804
- high: ['architecture', 'redesign', 'migration', 'integration', 'authentication', 'database'],
1805
- medium: ['api', 'component', 'service', 'endpoint', 'feature'],
1806
- low: ['fix', 'update', 'modify', 'adjust', 'tweak'],
1807
- }
1458
+ // AGENTIC: Claude analyzes complexity via templates/analysis/complexity.md
1459
+ // Returns default - real analysis happens in template execution
1460
+ return { level: 'medium', hours: 4, type: 'feature' }
1461
+ }
1808
1462
 
1809
- let level = 'medium'
1810
- let hours = 4
1463
+ /**
1464
+ * Assign agent for a task
1465
+ * AGENTIC: Claude decides via templates/agent-assignment.md
1466
+ * JS only orchestrates: load agents β†’ build context β†’ delegate to Claude
1467
+ * @private
1468
+ */
1469
+ async _assignAgentForTask(taskDescription, projectPath, context) {
1470
+ try {
1471
+ const projectId = await configManager.getProjectId(projectPath)
1811
1472
 
1812
- for (const [levelKey, indicators] of Object.entries(complexityIndicators)) {
1813
- if (indicators.some((indicator) => lowerTask.includes(indicator))) {
1814
- level = levelKey
1815
- break
1473
+ // ORCHESTRATION ONLY: Load available agents
1474
+ const agentsPath = pathManager.getPath(projectId, 'agents')
1475
+ const agentFiles = await fileHelper.listFiles(agentsPath, '.md')
1476
+ const agents = agentFiles.map(f => f.replace('.md', ''))
1477
+
1478
+ // ORCHESTRATION ONLY: Build context for Claude
1479
+ const assignmentContext = {
1480
+ task: taskDescription,
1481
+ agents: agents.join(', ') || 'generalist',
1482
+ projectPath,
1483
+ // Claude will use this context + template to decide
1816
1484
  }
1817
- }
1818
-
1819
- // Estimate hours
1820
- if (level === 'high') hours = 8
1821
- else if (level === 'medium') hours = 4
1822
- else hours = 2
1823
1485
 
1824
- return { level, hours, type }
1486
+ // AGENTIC: Claude decides agent via template
1487
+ // The template templates/agent-assignment.md guides Claude's decision
1488
+ // For now, return structure that prompt-builder will use with template
1489
+ return {
1490
+ agent: { name: agents[0] || 'generalist', domain: 'auto' },
1491
+ routing: {
1492
+ confidence: 0.8,
1493
+ reason: 'Claude assigns via templates/agent-assignment.md',
1494
+ availableAgents: agents
1495
+ },
1496
+ _agenticNote: 'Use templates/agent-assignment.md for actual assignment'
1497
+ }
1498
+ } catch (error) {
1499
+ // Fallback - still return structure
1500
+ return {
1501
+ agent: { name: 'generalist', domain: 'general' },
1502
+ routing: { confidence: 0.5, reason: 'Fallback - no agents found' }
1503
+ }
1504
+ }
1825
1505
  }
1826
1506
 
1827
1507
  /**
1828
- * Auto-assign agent based on task
1508
+ * Auto-assign agent based on task (sync wrapper for backward compat)
1509
+ * DEPRECATED: Use _assignAgentForTask instead
1829
1510
  * @private
1830
1511
  */
1831
1512
  _autoAssignAgent(task) {
1832
- const lowerTask = task.toLowerCase()
1833
-
1834
- if (
1835
- lowerTask.includes('ui') ||
1836
- lowerTask.includes('component') ||
1837
- lowerTask.includes('frontend')
1838
- ) {
1839
- return 'frontend-specialist'
1840
- }
1841
- if (
1842
- lowerTask.includes('api') ||
1843
- lowerTask.includes('backend') ||
1844
- lowerTask.includes('database')
1845
- ) {
1846
- return 'backend-specialist'
1847
- }
1848
- if (lowerTask.includes('test')) {
1849
- return 'qa-specialist'
1850
- }
1851
- if (lowerTask.includes('design') || lowerTask.includes('architecture')) {
1852
- return 'architect'
1853
- }
1854
- if (lowerTask.includes('deploy') || lowerTask.includes('docker')) {
1855
- return 'devops-specialist'
1856
- }
1857
-
1513
+ // For backward compatibility, return generalist synchronously
1514
+ // New code should use _assignAgentForTask() which is async
1515
+ console.warn('DEPRECATED: Use _assignAgentForTask() for proper agent routing')
1858
1516
  return 'generalist'
1859
1517
  }
1860
1518