prjct-cli 0.35.0 → 0.35.2

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.
@@ -24,6 +24,7 @@ import type {
24
24
  ThinkBlock,
25
25
  Memory,
26
26
  PlanInfo,
27
+ OrchestratorContext,
27
28
  } from '../types'
28
29
 
29
30
  // Re-export types for convenience
@@ -287,7 +288,8 @@ class PromptBuilder {
287
288
  learnedPatterns: LearnedPatterns | null = null,
288
289
  thinkBlock: ThinkBlock | null = null,
289
290
  relevantMemories: Memory[] | null = null,
290
- planInfo: PlanInfo | null = null
291
+ planInfo: PlanInfo | null = null,
292
+ orchestratorContext: OrchestratorContext | null = null
291
293
  ): string {
292
294
  const parts: string[] = []
293
295
 
@@ -326,6 +328,70 @@ class PromptBuilder {
326
328
  // This ensures Claude sees ALL instructions including critical rules at the top
327
329
  parts.push(template.content)
328
330
 
331
+ // ORCHESTRATOR CONTEXT: Inject loaded agents, skills, and subtasks
332
+ if (orchestratorContext) {
333
+ parts.push('\n## ORCHESTRATOR CONTEXT\n')
334
+ parts.push(`**Primary Domain**: ${orchestratorContext.primaryDomain}\n`)
335
+ parts.push(`**Domains**: ${orchestratorContext.detectedDomains.join(', ')}\n`)
336
+ parts.push(`**Ecosystem**: ${orchestratorContext.project.ecosystem}\n\n`)
337
+
338
+ // Inject loaded agent content (truncated for context efficiency)
339
+ if (orchestratorContext.agents.length > 0) {
340
+ parts.push('### LOADED AGENTS (Project-Specific Specialists)\n\n')
341
+ for (const agent of orchestratorContext.agents) {
342
+ parts.push(`#### Agent: ${agent.name} (${agent.domain})\n`)
343
+ if (agent.skills.length > 0) {
344
+ parts.push(`Skills: ${agent.skills.join(', ')}\n`)
345
+ }
346
+ // Include first 1500 chars of agent content
347
+ const truncatedContent = agent.content.length > 1500
348
+ ? agent.content.substring(0, 1500) + '\n... (truncated, read full file for more)'
349
+ : agent.content
350
+ parts.push(`\`\`\`markdown\n${truncatedContent}\n\`\`\`\n\n`)
351
+ }
352
+ }
353
+
354
+ // Inject loaded skill content (truncated)
355
+ if (orchestratorContext.skills.length > 0) {
356
+ parts.push('### LOADED SKILLS (From Agent Frontmatter)\n\n')
357
+ for (const skill of orchestratorContext.skills) {
358
+ parts.push(`#### Skill: ${skill.name}\n`)
359
+ // Include first 1000 chars of skill content
360
+ const truncatedContent = skill.content.length > 1000
361
+ ? skill.content.substring(0, 1000) + '\n... (truncated)'
362
+ : skill.content
363
+ parts.push(`\`\`\`markdown\n${truncatedContent}\n\`\`\`\n\n`)
364
+ }
365
+ }
366
+
367
+ // Inject subtasks if fragmented
368
+ if (orchestratorContext.requiresFragmentation && orchestratorContext.subtasks) {
369
+ parts.push('### SUBTASKS (Execute in Order)\n\n')
370
+ parts.push('**IMPORTANT**: Focus on the CURRENT subtask. Use `p. done` when complete to advance.\n\n')
371
+ parts.push('| # | Domain | Description | Status |\n')
372
+ parts.push('|---|--------|-------------|--------|\n')
373
+
374
+ for (const subtask of orchestratorContext.subtasks) {
375
+ const statusIcon = subtask.status === 'in_progress' ? '▶️ **CURRENT**'
376
+ : subtask.status === 'completed' ? '✅ Done'
377
+ : subtask.status === 'failed' ? '❌ Failed'
378
+ : '⏳ Pending'
379
+ parts.push(`| ${subtask.order} | ${subtask.domain} | ${subtask.description} | ${statusIcon} |\n`)
380
+ }
381
+
382
+ // Find and highlight current subtask
383
+ const currentSubtask = orchestratorContext.subtasks.find(s => s.status === 'in_progress')
384
+ if (currentSubtask) {
385
+ parts.push(`\n**FOCUS ON SUBTASK #${currentSubtask.order}**: ${currentSubtask.description}\n`)
386
+ parts.push(`Agent: ${currentSubtask.agent} | Domain: ${currentSubtask.domain}\n`)
387
+ if (currentSubtask.dependsOn.length > 0) {
388
+ parts.push(`Dependencies: ${currentSubtask.dependsOn.join(', ')}\n`)
389
+ }
390
+ }
391
+ parts.push('\n')
392
+ }
393
+ }
394
+
329
395
  // Current state (only if exists and relevant)
330
396
  const relevantState = this.filterRelevantState(state)
331
397
  if (relevantState) {
@@ -19,6 +19,7 @@ import {
19
19
  } from './base'
20
20
  import { stateStorage, queueStorage } from '../storage'
21
21
  import { templateExecutor } from '../agentic/template-executor'
22
+ import commandExecutor from '../agentic/command-executor'
22
23
 
23
24
  export class WorkflowCommands extends PrjctCommandsBase {
24
25
  /**
@@ -36,12 +37,13 @@ export class WorkflowCommands extends PrjctCommandsBase {
36
37
  }
37
38
 
38
39
  if (task) {
39
- // AGENTIC: Build execution context for Claude to decide
40
- const execContext = await templateExecutor.buildContext('task', task, projectPath)
41
- const agenticInfo = templateExecutor.buildAgenticPrompt(execContext)
40
+ // AGENTIC: Use CommandExecutor for full orchestration support
41
+ const result = await commandExecutor.execute('task', { task }, projectPath)
42
42
 
43
- // Get available agents for context
44
- const availableAgents = await templateExecutor.getAvailableAgents(projectPath)
43
+ if (!result.success) {
44
+ out.fail(result.error || 'Failed to execute task')
45
+ return { success: false, error: result.error }
46
+ }
45
47
 
46
48
  // Write-through: JSON → MD → Event
47
49
  await stateStorage.startTask(projectId, {
@@ -50,18 +52,31 @@ export class WorkflowCommands extends PrjctCommandsBase {
50
52
  sessionId: generateUUID()
51
53
  })
52
54
 
53
- // AGENTIC: Log that Claude will decide via templates
55
+ // Log orchestrator results if available
56
+ if (result.orchestratorContext) {
57
+ const oc = result.orchestratorContext
58
+ const agentsList = oc.agents.map((a: { name: string }) => a.name).join(', ') || 'none'
59
+ const domainsList = oc.detectedDomains.join(', ')
60
+ console.log(`🎯 Orchestrator: ${domainsList} → [${agentsList}]`)
61
+
62
+ if (oc.requiresFragmentation && oc.subtasks) {
63
+ console.log(` → ${oc.subtasks.length} subtasks created`)
64
+ }
65
+ }
66
+
67
+ // Get available agents for backward compatibility
68
+ const availableAgents = await templateExecutor.getAvailableAgents(projectPath)
54
69
  const agentsList = availableAgents.length > 0
55
70
  ? availableAgents.join(', ')
56
71
  : 'none (run p. sync)'
57
72
 
58
- console.log(`🤖 Agentic mode: Claude will read templates and decide`)
59
73
  out.done(`${task} [specialists: ${agentsList}]`)
60
74
 
61
75
  await this.logToMemory(projectPath, 'task_started', {
62
76
  task,
63
77
  agenticMode: true,
64
78
  availableAgents,
79
+ orchestratorContext: result.orchestratorContext,
65
80
  timestamp: dateHelper.getTimestamp(),
66
81
  })
67
82
 
@@ -70,8 +85,8 @@ export class WorkflowCommands extends PrjctCommandsBase {
70
85
  task,
71
86
  agenticMode: true,
72
87
  availableAgents,
73
- execContext,
74
- agenticPrompt: agenticInfo.prompt,
88
+ // Include full CommandExecutor result (orchestratorContext, prompt, etc.)
89
+ ...result,
75
90
  }
76
91
  } else {
77
92
  // Read from storage (JSON is source of truth)
@@ -443,6 +443,7 @@ export interface ExecutionResult {
443
443
  compressionMetrics?: unknown
444
444
  learnedPatterns?: unknown
445
445
  relevantMemories?: unknown
446
+ orchestratorContext?: OrchestratorContext | null
446
447
  formatResponse?: (data: unknown) => string
447
448
  formatThinkBlock?: (verbose: boolean) => string
448
449
  parallel?: {
@@ -571,3 +572,64 @@ export interface LearnedPatterns {
571
572
  preferred_agent?: string | null
572
573
  [key: string]: string | null | undefined
573
574
  }
575
+
576
+ // =============================================================================
577
+ // Orchestrator Types
578
+ // =============================================================================
579
+
580
+ /**
581
+ * A loaded agent with its content
582
+ */
583
+ export interface LoadedAgent {
584
+ name: string
585
+ domain: string
586
+ content: string
587
+ skills: string[]
588
+ filePath: string
589
+ }
590
+
591
+ /**
592
+ * A loaded skill with its content
593
+ */
594
+ export interface LoadedSkill {
595
+ name: string
596
+ content: string
597
+ filePath: string
598
+ }
599
+
600
+ /**
601
+ * Subtask for task fragmentation
602
+ */
603
+ export interface OrchestratorSubtask {
604
+ id: string
605
+ description: string
606
+ domain: string
607
+ agent: string
608
+ status: 'pending' | 'in_progress' | 'completed' | 'failed'
609
+ dependsOn: string[]
610
+ order: number
611
+ }
612
+
613
+ /**
614
+ * Full orchestrator context returned after execution
615
+ */
616
+ export interface OrchestratorContext {
617
+ /** Domains detected for this task */
618
+ detectedDomains: string[]
619
+ /** Primary domain (most important) */
620
+ primaryDomain: string
621
+ /** Loaded agents with their content */
622
+ agents: LoadedAgent[]
623
+ /** Loaded skills from agent frontmatter */
624
+ skills: LoadedSkill[]
625
+ /** Whether task requires fragmentation (3+ domains) */
626
+ requiresFragmentation: boolean
627
+ /** Subtasks if fragmented, null otherwise */
628
+ subtasks: OrchestratorSubtask[] | null
629
+ /** Project info */
630
+ project: {
631
+ id: string
632
+ ecosystem: string
633
+ conventions: string[]
634
+ }
635
+ }
@@ -158,6 +158,11 @@ export type {
158
158
  ReasoningStep,
159
159
  ReasoningResult,
160
160
  ChainOfThoughtResult,
161
+ // Orchestrator types
162
+ OrchestratorContext,
163
+ LoadedAgent,
164
+ LoadedSkill,
165
+ OrchestratorSubtask,
161
166
  } from './agentic'
162
167
 
163
168
  // =============================================================================