@polymorphism-tech/morph-spec 4.2.0 → 4.3.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.
Files changed (132) hide show
  1. package/bin/morph-spec.js +283 -8
  2. package/bin/validate.js +4 -4
  3. package/docs/{v3.0 → next-generation}/AGENTS.md +1 -1
  4. package/docs/next-generation/CONTEXT-OPTIMIZATION.md +267 -0
  5. package/docs/next-generation/EXECUTION-FLOW.md +274 -0
  6. package/docs/next-generation/META-PROMPTS.md +235 -0
  7. package/docs/next-generation/MIGRATION-GUIDE.md +253 -0
  8. package/docs/next-generation/THREAD-MANAGEMENT.md +240 -0
  9. package/package.json +5 -5
  10. package/src/commands/agents/agents-fuse.js +96 -0
  11. package/src/commands/agents/micro-agent.js +112 -0
  12. package/src/commands/agents/spawn-team.js +69 -4
  13. package/src/commands/agents/squad-template.js +146 -0
  14. package/src/commands/analytics/analytics.js +176 -0
  15. package/src/commands/context/context-prime.js +63 -0
  16. package/src/commands/context/core-four.js +54 -0
  17. package/src/commands/mcp/mcp.js +102 -0
  18. package/src/commands/project/detect-agents.js +1 -1
  19. package/src/commands/project/doctor.js +573 -356
  20. package/src/commands/project/init.js +1 -1
  21. package/src/commands/project/update.js +1 -1
  22. package/src/commands/state/advance-phase.js +433 -416
  23. package/src/commands/templates/template-render.js +80 -1
  24. package/src/commands/threads/thread-template.js +103 -0
  25. package/src/commands/threads/threads.js +261 -0
  26. package/src/commands/trust/trust.js +205 -0
  27. package/src/{orchestrator.js → core/orchestrator.js} +8 -8
  28. package/src/core/state/state-manager.js +18 -2
  29. package/src/core/workflows/workflow-detector.js +100 -2
  30. package/src/lib/agents/micro-agent-factory.js +161 -0
  31. package/src/lib/analytics/analytics-engine.js +345 -0
  32. package/src/lib/checkpoints/checkpoint-hooks.js +293 -258
  33. package/src/lib/context/context-bundler.js +240 -0
  34. package/src/lib/context/context-optimizer.js +212 -0
  35. package/src/lib/context/context-tracker.js +273 -0
  36. package/src/lib/context/core-four-tracker.js +201 -0
  37. package/src/lib/context/mcp-optimizer.js +200 -0
  38. package/src/lib/execution/fusion-executor.js +304 -0
  39. package/src/lib/execution/parallel-executor.js +270 -0
  40. package/src/lib/generators/context-generator.js +3 -3
  41. package/src/lib/generators/recap-generator.js +2 -2
  42. package/src/lib/hooks/hook-executor.js +169 -0
  43. package/src/lib/hooks/stop-hook-executor.js +286 -0
  44. package/src/lib/hops/hop-composer.js +221 -0
  45. package/src/lib/threads/thread-coordinator.js +238 -0
  46. package/src/lib/threads/thread-manager.js +317 -0
  47. package/src/lib/tracking/artifact-trail.js +202 -0
  48. package/src/lib/trust/trust-manager.js +269 -0
  49. package/src/lib/validators/design-system/design-system-validator.js +2 -2
  50. package/src/lib/validators/validation-runner.js +6 -6
  51. package/stacks/blazor-azure/.morph/config/agents.json +72 -3
  52. package/stacks/nextjs-supabase/.morph/config/agents.json +3 -3
  53. package/CLAUDE.md +0 -993
  54. package/docs/llm-interaction-config.md +0 -735
  55. package/docs/v3.0/EXECUTION-FLOW.md +0 -1304
  56. package/src/commands/utils/migrate-state.js +0 -158
  57. package/src/commands/utils/upgrade.js +0 -346
  58. package/src/lib/validators/architecture-validator.js +0 -60
  59. package/src/lib/validators/content-validator.js +0 -164
  60. package/src/lib/validators/package-validator.js +0 -61
  61. package/src/lib/validators/ui-contrast-validator.js +0 -44
  62. package/stacks/blazor-azure/.claude/commands/morph-apply.md +0 -221
  63. package/stacks/blazor-azure/.claude/commands/morph-archive.md +0 -79
  64. package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
  65. package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
  66. package/stacks/blazor-azure/.claude/commands/morph-preflight.md +0 -227
  67. package/stacks/blazor-azure/.claude/commands/morph-proposal.md +0 -122
  68. package/stacks/blazor-azure/.claude/commands/morph-status.md +0 -86
  69. package/stacks/blazor-azure/.claude/commands/morph-troubleshoot.md +0 -122
  70. package/stacks/blazor-azure/.claude/skills/level-0-meta/README.md +0 -7
  71. package/stacks/blazor-azure/.claude/skills/level-0-meta/code-review.md +0 -226
  72. package/stacks/blazor-azure/.claude/skills/level-0-meta/morph-checklist.md +0 -117
  73. package/stacks/blazor-azure/.claude/skills/level-0-meta/simulation-checklist.md +0 -77
  74. package/stacks/blazor-azure/.claude/skills/level-1-workflows/README.md +0 -7
  75. package/stacks/blazor-azure/.claude/skills/level-1-workflows/morph-replicate.md +0 -213
  76. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-clarify.md +0 -131
  77. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-design.md +0 -213
  78. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-setup.md +0 -106
  79. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-tasks.md +0 -164
  80. package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-uiux.md +0 -169
  81. package/stacks/blazor-azure/.claude/skills/level-2-domains/README.md +0 -14
  82. package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -192
  83. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -197
  84. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -189
  85. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -320
  86. package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -156
  87. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +0 -59
  88. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -77
  89. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -58
  90. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -126
  91. package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -45
  92. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -210
  93. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -154
  94. package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -191
  95. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -142
  96. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -699
  97. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -126
  98. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -131
  99. package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -119
  100. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -130
  101. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -142
  102. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -108
  103. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +0 -64
  104. package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/resend-email.md +0 -119
  105. package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -235
  106. package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -126
  107. package/stacks/blazor-azure/.claude/skills/level-3-technologies/README.md +0 -7
  108. package/stacks/blazor-azure/.claude/skills/level-4-patterns/README.md +0 -7
  109. package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
  110. package/stacks/blazor-azure/.morph/features/.gitkeep +0 -25
  111. package/stacks/blazor-azure/.morph/schemas/agent.schema.json +0 -296
  112. package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
  113. package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
  114. package/stacks/blazor-azure/.morph/test-infra/example.bicep +0 -59
  115. package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +0 -221
  116. package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +0 -79
  117. package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +0 -529
  118. package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +0 -209
  119. package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +0 -227
  120. package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +0 -122
  121. package/stacks/nextjs-supabase/.claude/commands/morph-status.md +0 -86
  122. package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +0 -122
  123. package/stacks/nextjs-supabase/.claude/settings.local.json +0 -6
  124. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +0 -244
  125. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +0 -335
  126. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +0 -189
  127. package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +0 -50
  128. /package/docs/{v3.0 → next-generation}/ANALYSIS.md +0 -0
  129. /package/docs/{v3.0 → next-generation}/ARCHITECTURE.md +0 -0
  130. /package/docs/{v3.0 → next-generation}/FEATURES.md +0 -0
  131. /package/docs/{v3.0 → next-generation}/README.md +0 -0
  132. /package/docs/{v3.0 → next-generation}/ROADMAP.md +0 -0
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Micro Agent CLI command
3
+ *
4
+ * Usage:
5
+ * morph-spec micro-agent create <name> --base-agent=<agent> --mission="..." [--standards=file1,file2]
6
+ * morph-spec micro-agent list
7
+ * morph-spec micro-agent show <name>
8
+ */
9
+
10
+ import chalk from 'chalk';
11
+ import {
12
+ createMicroAgent, saveMicroAgent, listMicroAgents, getMicroAgent
13
+ } from '../../lib/agents/micro-agent-factory.js';
14
+
15
+ export async function microAgentCreateCommand(name, options) {
16
+ try {
17
+ if (!options.baseAgent) {
18
+ console.error(chalk.red('--base-agent is required'));
19
+ process.exit(1);
20
+ }
21
+ if (!options.mission) {
22
+ console.error(chalk.red('--mission is required'));
23
+ process.exit(1);
24
+ }
25
+
26
+ const standards = options.standards ? options.standards.split(',').map(s => s.trim()) : [];
27
+
28
+ const agent = createMicroAgent({
29
+ name,
30
+ baseAgent: options.baseAgent,
31
+ standards,
32
+ mission: options.mission,
33
+ tools: options.tools ? options.tools.split(',').map(t => t.trim()) : null
34
+ });
35
+
36
+ const filePath = saveMicroAgent(agent);
37
+
38
+ console.log(chalk.green(`\n ✓ Micro-agent created: ${name}`));
39
+ console.log(` Base agent: ${options.baseAgent}`);
40
+ console.log(` Standards: ${standards.length > 0 ? standards.join(', ') : '(none)'}`);
41
+ console.log(` Context estimate: ${agent.contextEstimate.total.toLocaleString()} tokens`);
42
+ console.log(` Saved to: ${chalk.gray(filePath)}`);
43
+ console.log('');
44
+ } catch (err) {
45
+ console.error(chalk.red(`Error: ${err.message}`));
46
+ process.exit(1);
47
+ }
48
+ }
49
+
50
+ export async function microAgentListCommand(options) {
51
+ try {
52
+ const agents = listMicroAgents();
53
+
54
+ if (agents.length === 0) {
55
+ console.log(chalk.gray('\n No micro-agents found. Create one with: morph-spec micro-agent create\n'));
56
+ return;
57
+ }
58
+
59
+ console.log(chalk.cyan(`\n Micro-Agents (${agents.length})\n`));
60
+ console.log(' ' + 'Name'.padEnd(20) + ' ' + 'Base'.padEnd(20) + ' ' + 'Standards'.padEnd(12) + ' ' + 'Context');
61
+ console.log(' ' + '─'.repeat(70));
62
+
63
+ for (const agent of agents) {
64
+ console.log(
65
+ ' ' +
66
+ agent.id.padEnd(20) + ' ' +
67
+ (agent.baseAgent || '—').padEnd(20) + ' ' +
68
+ String(agent.standards).padEnd(12) + ' ' +
69
+ `${(agent.contextEstimate / 1000).toFixed(1)}K tokens`
70
+ );
71
+ }
72
+ console.log('');
73
+ } catch (err) {
74
+ console.error(chalk.red(`Error: ${err.message}`));
75
+ process.exit(1);
76
+ }
77
+ }
78
+
79
+ export async function microAgentShowCommand(name, options) {
80
+ try {
81
+ const agent = getMicroAgent(name);
82
+ if (!agent) {
83
+ console.error(chalk.red(`Micro-agent not found: ${name}`));
84
+ process.exit(1);
85
+ }
86
+
87
+ console.log(chalk.cyan(`\n Micro-Agent: ${name}\n`));
88
+ console.log(` Base agent: ${agent.baseAgent}`);
89
+ console.log(` Domain: ${agent.domain}`);
90
+ console.log(` Created: ${agent.createdAt}`);
91
+ console.log(`\n Mission:\n ${agent.mission}`);
92
+
93
+ if (agent.standards?.length > 0) {
94
+ console.log('\n Standards:');
95
+ agent.standards.forEach(s => console.log(` - ${s}`));
96
+ }
97
+
98
+ console.log('\n Context estimate:');
99
+ console.log(` Standards: ${agent.contextEstimate?.standards?.toLocaleString() || 0} tokens`);
100
+ console.log(` Overhead: ${agent.contextEstimate?.overhead?.toLocaleString() || 0} tokens`);
101
+ console.log(` Total: ${agent.contextEstimate?.total?.toLocaleString() || 0} tokens`);
102
+
103
+ if (options.showPrompt) {
104
+ console.log(chalk.cyan('\n Generated Prompt:'));
105
+ console.log(agent.prompt);
106
+ }
107
+ console.log('');
108
+ } catch (err) {
109
+ console.error(chalk.red(`Error: ${err.message}`));
110
+ process.exit(1);
111
+ }
112
+ }
@@ -1,7 +1,10 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
+ import { join } from 'path';
3
4
  import { getFeature } from '../../core/state/state-manager.js';
4
5
  import { orchestrateTeam } from '../../lib/orchestration/team-orchestrator.js';
6
+ import { spawnParallel } from '../../lib/execution/parallel-executor.js';
7
+ import { renderHOP } from '../../lib/hops/hop-composer.js';
5
8
 
6
9
  /**
7
10
  * Spawn Team Command - Generate agent team configurations
@@ -15,6 +18,35 @@ const program = new Command();
15
18
  /**
16
19
  * Spawn team action function
17
20
  */
21
+ /**
22
+ * Spawn team in parallel mode
23
+ * --parallel backend,frontend,infra
24
+ */
25
+ export async function spawnTeamParallelCommand(featureName, squads, options = {}) {
26
+ const squadList = squads.split(',').map(s => s.trim());
27
+ const maxConcurrent = parseInt(options.maxConcurrent || '3', 10);
28
+
29
+ console.log(chalk.cyan(`\n Spawning ${squadList.length} parallel squads for: ${featureName}\n`));
30
+
31
+ const threadConfigs = squadList.map(squad => ({
32
+ agent: squad,
33
+ mission: `Implement ${squad} domain for ${featureName}`,
34
+ meta: { squad }
35
+ }));
36
+
37
+ try {
38
+ const threads = await spawnParallel({ feature: featureName, threadConfigs, maxConcurrent });
39
+ console.log(chalk.green(` ✓ ${threads.length} threads spawned in parallel`));
40
+ for (const t of threads) {
41
+ console.log(` ${chalk.gray(t.id.substring(0, 8))} — ${t.agent} (${t.status})`);
42
+ }
43
+ console.log(`\n Monitor with: morph-spec threads wait-all ${featureName}\n`);
44
+ } catch (err) {
45
+ console.error(chalk.red(` Error: ${err.message}`));
46
+ process.exit(1);
47
+ }
48
+ }
49
+
18
50
  export async function spawnTeamCommand(featureName, options = {}) {
19
51
  try {
20
52
  // Get feature state
@@ -94,12 +126,44 @@ export async function spawnTeamCommand(featureName, options = {}) {
94
126
  });
95
127
  }
96
128
 
97
- // Show Task tool usage
129
+ // Show Task tool usage (with HOP rendering)
98
130
  console.log(chalk.bold('\n📝 Task Tool Usage:'));
99
131
  console.log(chalk.gray('\nUse the following pattern to spawn the team:\n'));
100
132
 
101
- console.log(chalk.cyan('```typescript'));
102
- console.log(chalk.white(`{
133
+ // Try to render backend squad HOP if applicable
134
+ let hopPrompt = null;
135
+ const hasBackend = teamConfig.teammates.some(t => t.id.includes('dotnet') || t.id.includes('api') || t.id.includes('ef'));
136
+ if (hasBackend && options.useHop !== false) {
137
+ try {
138
+ const frameworkRoot = join(process.cwd(), 'framework');
139
+ const domainLeaders = teamConfig.teammates
140
+ .filter(t => t.tier === 2)
141
+ .map(t => `- ${t.id}: ${t.role}`)
142
+ .join('\n');
143
+ hopPrompt = renderHOP('hop-backend-squad', {
144
+ AGENT_ID: teamConfig.teamHierarchy.teamLead,
145
+ MISSION: `Implement ${featureName}`,
146
+ SPEC_SUMMARY: `Feature: ${featureName}. See spec.md for full details.`,
147
+ ADDITIONAL_LEADERS: domainLeaders,
148
+ TASKS: teamConfig.teammates.filter(t => t.tier === 3).map((t, i) => `- T${String(i+1).padStart(3,'0')}: ${t.role}`).join('\n'),
149
+ DELIVERABLES: 'See spec.md deliverables section',
150
+ CONSTRAINTS: 'Follow all architecture and security standards',
151
+ FEATURE_NAME: featureName
152
+ }, { frameworkRoot });
153
+ } catch {
154
+ hopPrompt = null;
155
+ }
156
+ }
157
+
158
+ if (hopPrompt) {
159
+ console.log(chalk.cyan('HOP-rendered prompt (backend squad):'));
160
+ console.log(chalk.gray('─'.repeat(60)));
161
+ console.log(chalk.white(hopPrompt.substring(0, 800) + (hopPrompt.length > 800 ? '\n...[truncated]' : '')));
162
+ console.log(chalk.gray('─'.repeat(60)));
163
+ console.log(chalk.dim('\nFull HOP: morph-spec hop render hop-backend-squad output.md \'{...}\''));
164
+ } else {
165
+ console.log(chalk.cyan('```typescript'));
166
+ console.log(chalk.white(`{
103
167
  subagent_type: "general-purpose",
104
168
  description: "Implement ${featureName}",
105
169
  prompt: \`You are the Team Lead (${teamConfig.teamHierarchy.teamLead})...
@@ -123,7 +187,8 @@ Standards to follow: [coding.md, architecture.md]
123
187
  Deliverables: [list specific outputs]
124
188
  \`
125
189
  }`));
126
- console.log(chalk.cyan('```\n'));
190
+ console.log(chalk.cyan('```\n'));
191
+ }
127
192
 
128
193
  // Show individual teammates
129
194
  console.log(chalk.bold('Individual Teammates:'));
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Squad Template CLI command
3
+ *
4
+ * Usage:
5
+ * morph-spec squad-template list
6
+ * morph-spec squad-template use <template-id> --feature=<feature>
7
+ * morph-spec squad-template show <template-id>
8
+ */
9
+
10
+ import chalk from 'chalk';
11
+ import { readFileSync, existsSync, readdirSync } from 'fs';
12
+ import { join } from 'path';
13
+
14
+ const SQUAD_TEMPLATES_DIR = join(process.cwd(), 'framework/squad-templates');
15
+
16
+ function loadTemplate(id) {
17
+ const filePath = join(SQUAD_TEMPLATES_DIR, `${id}.json`);
18
+ if (!existsSync(filePath)) return null;
19
+ try {
20
+ return JSON.parse(readFileSync(filePath, 'utf8'));
21
+ } catch {
22
+ return null;
23
+ }
24
+ }
25
+
26
+ function listAllTemplates() {
27
+ if (!existsSync(SQUAD_TEMPLATES_DIR)) return [];
28
+ return readdirSync(SQUAD_TEMPLATES_DIR)
29
+ .filter(f => f.endsWith('.json'))
30
+ .map(f => {
31
+ try {
32
+ return JSON.parse(readFileSync(join(SQUAD_TEMPLATES_DIR, f), 'utf8'));
33
+ } catch {
34
+ return null;
35
+ }
36
+ })
37
+ .filter(Boolean);
38
+ }
39
+
40
+ export async function squadTemplateListCommand(options) {
41
+ try {
42
+ const templates = listAllTemplates();
43
+
44
+ if (templates.length === 0) {
45
+ console.log(chalk.gray('\n No squad templates found.\n'));
46
+ return;
47
+ }
48
+
49
+ console.log(chalk.cyan(`\n Squad Templates (${templates.length})\n`));
50
+
51
+ for (const t of templates) {
52
+ console.log(` ${chalk.bold(t.id)} — ${t.name}`);
53
+ console.log(` ${chalk.gray(t.description)}`);
54
+ console.log(` Agents: ${t.agents.map(a => a.id).join(', ')}`);
55
+ console.log(` Parallel: ${t.parallel ? chalk.green('yes') : chalk.gray('no')} | Coordination: ${t.coordination}`);
56
+ console.log(` Gain: ${chalk.cyan(t.estimatedParallelGain)}`);
57
+ console.log('');
58
+ }
59
+ } catch (err) {
60
+ console.error(chalk.red(`Error: ${err.message}`));
61
+ process.exit(1);
62
+ }
63
+ }
64
+
65
+ export async function squadTemplateUseCommand(templateId, options) {
66
+ try {
67
+ if (!options.feature) {
68
+ console.error(chalk.red('--feature is required'));
69
+ process.exit(1);
70
+ }
71
+
72
+ const template = loadTemplate(templateId);
73
+ if (!template) {
74
+ console.error(chalk.red(`Template not found: ${templateId}`));
75
+ console.error(chalk.gray('Run `morph-spec squad-template list` to see available templates'));
76
+ process.exit(1);
77
+ }
78
+
79
+ console.log(chalk.cyan(`\n Configuring Squad Template: ${templateId}\n`));
80
+ console.log(` Feature: ${options.feature}`);
81
+ console.log(` Template: ${template.name}`);
82
+ console.log(` Agents: ${template.agents.length}`);
83
+ console.log(` Parallel: ${template.parallel ? 'yes' : 'no'}`);
84
+
85
+ // Show spawn-team configuration
86
+ console.log(chalk.yellow('\n To spawn this squad, use the Task tool with these configs:\n'));
87
+
88
+ for (const agent of template.agents) {
89
+ console.log(` Agent: ${chalk.bold(agent.id)} (${agent.role})`);
90
+ console.log(` Standards: ${agent.standards?.join(', ') || '(none)'}`);
91
+ const deliverable = template.deliverables?.[agent.id];
92
+ if (deliverable) {
93
+ console.log(` Deliverable: ${deliverable}`);
94
+ }
95
+ console.log('');
96
+ }
97
+
98
+ console.log(chalk.gray(' See: morph-spec spawn-team --template=' + templateId + ' --feature=' + options.feature));
99
+ console.log('');
100
+ } catch (err) {
101
+ console.error(chalk.red(`Error: ${err.message}`));
102
+ process.exit(1);
103
+ }
104
+ }
105
+
106
+ export async function squadTemplateShowCommand(templateId, options) {
107
+ try {
108
+ const template = loadTemplate(templateId);
109
+ if (!template) {
110
+ console.error(chalk.red(`Template not found: ${templateId}`));
111
+ process.exit(1);
112
+ }
113
+
114
+ if (options.json) {
115
+ console.log(JSON.stringify(template, null, 2));
116
+ return;
117
+ }
118
+
119
+ console.log(chalk.cyan(`\n Squad Template: ${template.id}\n`));
120
+ console.log(` Name: ${template.name}`);
121
+ console.log(` Description: ${template.description}`);
122
+ console.log(` Parallel: ${template.parallel ? chalk.green('yes') : chalk.gray('no')}`);
123
+ console.log(` Coordinator: ${template.coordination}`);
124
+ console.log(` Wait all: ${template.waitForAll ? 'yes' : 'no'}`);
125
+ console.log(` Gain: ${template.estimatedParallelGain}`);
126
+
127
+ console.log('\n Agents:');
128
+ for (const agent of template.agents) {
129
+ console.log(` ${chalk.bold(agent.id)} — ${agent.role} (${agent.domain})`);
130
+ if (agent.standards?.length > 0) {
131
+ console.log(` Standards: ${agent.standards.join(', ')}`);
132
+ }
133
+ }
134
+
135
+ if (template.deliverables) {
136
+ console.log('\n Deliverables:');
137
+ for (const [agent, deliverable] of Object.entries(template.deliverables)) {
138
+ console.log(` ${agent}: ${deliverable}`);
139
+ }
140
+ }
141
+ console.log('');
142
+ } catch (err) {
143
+ console.error(chalk.red(`Error: ${err.message}`));
144
+ process.exit(1);
145
+ }
146
+ }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Analytics CLI command — Metrics dashboards
3
+ *
4
+ * Usage:
5
+ * morph-spec analytics feature <name>
6
+ * morph-spec analytics context <name>
7
+ * morph-spec analytics project [--period=30d]
8
+ */
9
+
10
+ import chalk from 'chalk';
11
+ import {
12
+ getFeatureAnalytics, getProjectAnalytics,
13
+ generateAsciiChart, generateTimelineChart,
14
+ recordEvent
15
+ } from '../../lib/analytics/analytics-engine.js';
16
+ import { readFileSync, existsSync } from 'fs';
17
+ import { join } from 'path';
18
+
19
+ // ============================================================================
20
+ // Feature Analytics Dashboard
21
+ // ============================================================================
22
+
23
+ export async function analyticsFeatureCommand(featureName, options) {
24
+ try {
25
+ const analytics = getFeatureAnalytics(featureName);
26
+
27
+ console.log(chalk.cyan(`\n Feature Analytics — ${featureName}\n`));
28
+ console.log(' ' + '─'.repeat(50));
29
+
30
+ console.log(`\n Threads:`);
31
+ for (const [status, count] of Object.entries(analytics.threads)) {
32
+ console.log(` ${status.padEnd(12)} ${count}`);
33
+ }
34
+
35
+ console.log(`\n Performance:`);
36
+ console.log(` Checkpoint pass rate: ${analytics.checkpointPassRate}%`);
37
+ console.log(` Total duration: ${formatDuration(analytics.totalDuration)}`);
38
+ console.log(` Total tool calls: ${analytics.totalToolCalls}`);
39
+ console.log(` Total tokens used: ${analytics.totalTokensUsed.toLocaleString()}`);
40
+ console.log(` Context optimizations: ${analytics.optimizationEvents}`);
41
+
42
+ if (Object.keys(analytics.threads).length > 0) {
43
+ console.log('\n' + generateAsciiChart(analytics.threads, { title: 'Threads by Status' }));
44
+ }
45
+
46
+ console.log('');
47
+ } catch (err) {
48
+ console.error(chalk.red(`Error: ${err.message}`));
49
+ process.exit(1);
50
+ }
51
+ }
52
+
53
+ // ============================================================================
54
+ // Context Analytics Dashboard
55
+ // ============================================================================
56
+
57
+ export async function analyticsContextCommand(featureName, options) {
58
+ try {
59
+ // Load context events from JSONL
60
+ const contextLogPath = join(process.cwd(), '.morph/analytics/context-log.jsonl');
61
+
62
+ if (!existsSync(contextLogPath)) {
63
+ console.log(chalk.gray(` No context analytics found for: ${featureName}`));
64
+ console.log(chalk.gray(' Run a session with context tracking to populate analytics.\n'));
65
+ return;
66
+ }
67
+
68
+ const lines = readFileSync(contextLogPath, 'utf8').trim().split('\n').filter(Boolean);
69
+ const events = lines.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
70
+ const featureEvents = events.filter(e => e.feature === featureName);
71
+
72
+ const tokenSamples = featureEvents.filter(e => e.type === 'token_usage');
73
+ const criticalMoments = featureEvents.filter(e => e.type === 'context_critical');
74
+ const optimizations = featureEvents.filter(e => e.type === 'context_optimized');
75
+
76
+ console.log(chalk.cyan(`\n Context Analytics — ${featureName}\n`));
77
+ console.log(' ' + '─'.repeat(50));
78
+
79
+ if (tokenSamples.length === 0) {
80
+ console.log(chalk.gray(' No token usage data available.\n'));
81
+ return;
82
+ }
83
+
84
+ const avgTokens = Math.round(tokenSamples.reduce((s, e) => s + (e.data?.tokensUsed || 0), 0) / tokenSamples.length);
85
+ const peakTokens = Math.max(...tokenSamples.map(e => e.data?.tokensUsed || 0));
86
+ const avgUtilization = Math.round(tokenSamples.reduce((s, e) => s + (e.data?.utilization || 0), 0) / tokenSamples.length * 100);
87
+
88
+ console.log(`\n Token Usage:`);
89
+ console.log(` Average tokens: ${avgTokens.toLocaleString()}`);
90
+ console.log(` Peak tokens: ${peakTokens.toLocaleString()}`);
91
+ console.log(` Avg utilization: ${avgUtilization}%`);
92
+ console.log(` Critical moments: ${criticalMoments.length}`);
93
+ console.log(` Optimizations applied: ${optimizations.length}`);
94
+
95
+ // Optimization opportunities
96
+ if (criticalMoments.length > 0) {
97
+ console.log(chalk.yellow('\n ⚠ Optimization Opportunities:'));
98
+ const recs = criticalMoments.flatMap(e => e.data?.recommendations || []);
99
+ const uniqueStrategies = [...new Set(recs.map(r => r.strategy))];
100
+ for (const strategy of uniqueStrategies) {
101
+ const rec = recs.find(r => r.strategy === strategy);
102
+ console.log(` • ${strategy}: ${rec?.description || ''}`);
103
+ console.log(` Savings: ${rec?.estimatedSavings || 'unknown'}`);
104
+ }
105
+ }
106
+
107
+ console.log('');
108
+ } catch (err) {
109
+ console.error(chalk.red(`Error: ${err.message}`));
110
+ process.exit(1);
111
+ }
112
+ }
113
+
114
+ // ============================================================================
115
+ // Project-Wide Dashboard
116
+ // ============================================================================
117
+
118
+ export async function analyticsProjectCommand(options) {
119
+ try {
120
+ const analytics = getProjectAnalytics();
121
+
122
+ console.log(chalk.cyan(`\n Project Analytics Dashboard — ${analytics.period}\n`));
123
+ console.log(' ' + '═'.repeat(55));
124
+
125
+ console.log(`\n 📊 Overview`);
126
+ console.log(` Features tracked: ${analytics.features}`);
127
+ console.log(` Total threads: ${analytics.threads.total}`);
128
+ console.log(` Completed: ${analytics.threads.completed}`);
129
+ console.log(` Failed: ${analytics.threads.failed}`);
130
+
131
+ console.log(`\n ✓ Checkpoints`);
132
+ console.log(` Total run: ${analytics.checkpoints.total}`);
133
+ console.log(` Passed: ${analytics.checkpoints.passed}`);
134
+ console.log(` Pass rate: ${analytics.checkpoints.passRate}%`);
135
+
136
+ if (analytics.checkpoints.total > 0) {
137
+ const bar = buildBar(analytics.checkpoints.passRate, 30);
138
+ console.log(` ${bar}`);
139
+ }
140
+
141
+ console.log(`\n ⫸ Parallelization`);
142
+ console.log(` Avg concurrency: ${analytics.parallelization.avgConcurrency}x`);
143
+ console.log(` Parallel threads: ${analytics.parallelization.parallelThreads}`);
144
+
145
+ console.log(`\n ⚡ Trust & Auto-Approval`);
146
+ console.log(` Auto-approvals: ${analytics.trust.autoApprovals}`);
147
+ console.log(` Trust level changes: ${analytics.trust.trustChanges}`);
148
+
149
+ console.log(`\n 🧠 Context`);
150
+ console.log(` Avg tokens/session: ${analytics.context.avgTokensPerSession.toLocaleString()}`);
151
+ console.log(` Optimizations: ${analytics.context.optimizations}`);
152
+
153
+ console.log('\n ' + '─'.repeat(55));
154
+ console.log('');
155
+ } catch (err) {
156
+ console.error(chalk.red(`Error: ${err.message}`));
157
+ process.exit(1);
158
+ }
159
+ }
160
+
161
+ // ============================================================================
162
+ // Helpers
163
+ // ============================================================================
164
+
165
+ function formatDuration(seconds) {
166
+ if (!seconds) return '—';
167
+ if (seconds < 60) return `${seconds}s`;
168
+ if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
169
+ return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
170
+ }
171
+
172
+ function buildBar(pct, width) {
173
+ const filled = Math.round(pct / 100 * width);
174
+ const color = pct >= 90 ? chalk.green : pct >= 70 ? chalk.yellow : chalk.red;
175
+ return color('[' + '█'.repeat(filled) + '░'.repeat(width - filled) + `] ${pct}%`);
176
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Context Prime CLI command — Load minimal context priming files
3
+ *
4
+ * Usage:
5
+ * morph-spec prime feature (outputs feature-prime.md to stdout)
6
+ * morph-spec prime bug
7
+ * morph-spec prime refactor
8
+ * morph-spec prime design
9
+ * morph-spec prime infra
10
+ */
11
+
12
+ import chalk from 'chalk';
13
+ import { readFileSync, existsSync } from 'fs';
14
+ import { join } from 'path';
15
+
16
+ const PRIME_FILES = {
17
+ feature: '.morph/context/feature-prime.md',
18
+ bug: '.morph/context/bug-prime.md',
19
+ refactor: '.morph/context/refactor-prime.md',
20
+ design: '.morph/context/design-prime.md',
21
+ infra: '.morph/context/infra-prime.md'
22
+ };
23
+
24
+ const PRIME_TYPES = Object.keys(PRIME_FILES);
25
+
26
+ export async function contextPrimeCommand(type, options) {
27
+ if (!type) {
28
+ console.log(chalk.cyan('\n Available prime types:\n'));
29
+ for (const [key, path] of Object.entries(PRIME_FILES)) {
30
+ const exists = existsSync(join(process.cwd(), path));
31
+ const status = exists ? chalk.green('✓') : chalk.red('✗');
32
+ console.log(` ${status} ${key.padEnd(10)} → ${path}`);
33
+ }
34
+ console.log('');
35
+ console.log(chalk.gray(' Usage: morph-spec prime <type>'));
36
+ console.log(chalk.gray(' Example: morph-spec prime feature\n'));
37
+ return;
38
+ }
39
+
40
+ if (!PRIME_TYPES.includes(type)) {
41
+ console.error(chalk.red(`Unknown prime type: ${type}`));
42
+ console.error(chalk.gray(`Valid types: ${PRIME_TYPES.join(', ')}`));
43
+ process.exit(1);
44
+ }
45
+
46
+ const filePath = join(process.cwd(), PRIME_FILES[type]);
47
+
48
+ if (!existsSync(filePath)) {
49
+ console.error(chalk.red(`Prime file not found: ${filePath}`));
50
+ console.error(chalk.gray('Run `morph-spec init` to initialize MORPH-SPEC files.'));
51
+ process.exit(1);
52
+ }
53
+
54
+ const content = readFileSync(filePath, 'utf8');
55
+
56
+ if (options.json) {
57
+ console.log(JSON.stringify({ type, path: filePath, content }));
58
+ return;
59
+ }
60
+
61
+ // Output to stdout — designed to be read into context
62
+ console.log(content);
63
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Core Four CLI command — Context/Model/Prompt/Tools dashboard
3
+ *
4
+ * Usage:
5
+ * morph-spec core-four <feature>
6
+ * morph-spec core-four <feature> --json
7
+ */
8
+
9
+ import chalk from 'chalk';
10
+ import { getCoreFour, formatCoreFour, initCoreFour } from '../../lib/context/core-four-tracker.js';
11
+ import { loadState } from '../../core/state/state-manager.js';
12
+
13
+ export async function coreFourCommand(featureName, options) {
14
+ try {
15
+ // Initialize with defaults if not already set
16
+ initCoreFour({
17
+ model: 'claude-sonnet-4-6',
18
+ contextWindow: 200000,
19
+ feature: featureName
20
+ });
21
+
22
+ // Try to populate context breakdown from feature state
23
+ try {
24
+ const state = loadState(false);
25
+ if (state?.features?.[featureName]) {
26
+ const feature = state.features[featureName];
27
+ // Attempt to estimate context breakdown from known files
28
+ const breakdown = {
29
+ 'CLAUDE.md': 23000,
30
+ standards: feature.activeAgents ? feature.activeAgents.length * 500 : 0,
31
+ spec: feature.outputs?.includes('spec') ? 8000 : 0,
32
+ conversation: 5000,
33
+ other: 2000
34
+ };
35
+ const { updateContextBreakdown } = await import('../../lib/context/core-four-tracker.js');
36
+ updateContextBreakdown(breakdown);
37
+ }
38
+ } catch {
39
+ // Best-effort
40
+ }
41
+
42
+ if (options.json) {
43
+ const data = getCoreFour();
44
+ console.log(JSON.stringify(data, null, 2));
45
+ return;
46
+ }
47
+
48
+ console.log('\n' + formatCoreFour());
49
+ console.log('');
50
+ } catch (err) {
51
+ console.error(chalk.red(`Error: ${err.message}`));
52
+ process.exit(1);
53
+ }
54
+ }