@wundr.io/cli 1.0.1 → 1.0.2-dev.20260530174250.ef0ec927

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 (69) hide show
  1. package/bin/wundr.js +13 -5
  2. package/package.json +30 -9
  3. package/src/ai/ai-service.ts +6 -4
  4. package/src/ai/claude-client.ts +6 -2
  5. package/src/ai/conversation-manager.ts +12 -5
  6. package/src/cli.ts +42 -13
  7. package/src/commands/ai.ts +340 -64
  8. package/src/commands/alignment.ts +1212 -0
  9. package/src/commands/analyze-optimized.ts +371 -33
  10. package/src/commands/analyze.ts +8 -6
  11. package/src/commands/batch.ts +166 -26
  12. package/src/commands/chat.ts +20 -10
  13. package/src/commands/claude-init.ts +31 -27
  14. package/src/commands/claude-setup.ts +761 -81
  15. package/src/commands/computer-setup.ts +524 -12
  16. package/src/commands/create-command.ts +3 -3
  17. package/src/commands/create.ts +9 -6
  18. package/src/commands/dashboard.ts +11 -6
  19. package/src/commands/govern.ts +11 -6
  20. package/src/commands/governance.ts +1005 -0
  21. package/src/commands/guardian.ts +887 -0
  22. package/src/commands/init.ts +104 -11
  23. package/src/commands/orchestrator.ts +789 -0
  24. package/src/commands/performance-optimizer.ts +15 -10
  25. package/src/commands/plugins.ts +8 -5
  26. package/src/commands/project-update.ts +1156 -0
  27. package/src/commands/rag.ts +1011 -0
  28. package/src/commands/session.ts +631 -0
  29. package/src/commands/setup.ts +42 -344
  30. package/src/commands/test-init.ts +3 -2
  31. package/src/commands/test.ts +3 -2
  32. package/src/commands/watch.ts +21 -11
  33. package/src/commands/worktree.ts +1057 -0
  34. package/src/context/context-manager.ts +5 -2
  35. package/src/context/session-manager.ts +18 -7
  36. package/src/framework/command-interface.ts +520 -0
  37. package/src/framework/command-registry.ts +942 -0
  38. package/src/framework/completion-exporter.ts +383 -0
  39. package/src/framework/debug-logger.ts +519 -0
  40. package/src/framework/error-handler.ts +867 -0
  41. package/src/framework/help-generator.ts +540 -0
  42. package/src/framework/index.ts +169 -0
  43. package/src/framework/interactive-repl.ts +703 -0
  44. package/src/framework/output-formatter.ts +834 -0
  45. package/src/framework/progress-manager.ts +539 -0
  46. package/src/index.ts +3 -2
  47. package/src/interactive/interactive-mode.ts +14 -7
  48. package/src/lib/conflict-resolution.ts +818 -0
  49. package/src/lib/merge-strategy.ts +550 -0
  50. package/src/lib/safety-mechanisms.ts +451 -0
  51. package/src/lib/state-detection.ts +1030 -0
  52. package/src/nlp/command-mapper.ts +8 -3
  53. package/src/nlp/command-parser.ts +5 -2
  54. package/src/nlp/intent-parser.ts +23 -9
  55. package/src/plugins/plugin-manager.ts +50 -24
  56. package/src/tests/computer-setup-integration.test.ts +46 -15
  57. package/src/types/index.ts +1 -1
  58. package/src/types/modules.d.ts +425 -1
  59. package/src/utils/backup-rollback-manager.ts +19 -14
  60. package/src/utils/claude-config-installer.ts +119 -28
  61. package/src/utils/config-manager.ts +9 -6
  62. package/src/utils/error-handler.ts +3 -1
  63. package/src/utils/logger.ts +35 -12
  64. package/templates/batch/ci-cd.yaml +7 -7
  65. package/test-suites/api/health.spec.ts +20 -23
  66. package/test-suites/helpers/test-config.ts +14 -13
  67. package/test-suites/ui/accessibility.spec.ts +27 -22
  68. package/test-suites/ui/smoke.spec.ts +26 -21
  69. package/src/commands/computer-setup-commands.ts +0 -869
@@ -3,11 +3,14 @@
3
3
  * Integrates new-starter functionality into the unified wundr CLI
4
4
  */
5
5
 
6
- import { Command } from 'commander';
6
+ import { ComputerSetupManager } from '@wundr.io/computer-setup';
7
7
  import chalk from 'chalk';
8
- import ora from 'ora';
8
+ import { Command } from 'commander';
9
+ import * as fs from 'fs/promises';
9
10
  import inquirer from 'inquirer';
10
- import { ComputerSetupManager } from '@wundr.io/computer-setup';
11
+ import * as os from 'os';
12
+ import ora from 'ora';
13
+ import * as path from 'path';
11
14
  // import { getLogger } from '@wundr/core';
12
15
  const logger = { info: console.log, error: console.error, warn: console.warn };
13
16
 
@@ -35,8 +38,28 @@ export function createComputerSetupCommand(): Command {
35
38
  .option('--parallel', 'Install tools in parallel where possible')
36
39
  .option('--verbose', 'Show detailed output')
37
40
  .option('--report', 'Generate a detailed setup report')
38
- .action(async options => {
39
- await runComputerSetup(options);
41
+ .option(
42
+ '-y, --yes',
43
+ 'Skip confirmation prompts (assume yes) — implied on non-TTY/CI runs'
44
+ )
45
+ .option(
46
+ '--non-interactive',
47
+ 'Run fully unattended with no prompts (for headless / MDM provisioning)'
48
+ )
49
+ .option(
50
+ '--no-remote-access',
51
+ 'Skip remote-access provisioning (Tailscale, SSH, power management, desktop sharing)'
52
+ )
53
+ .action(async (options, command) => {
54
+ // `--dry-run`, `--verbose` and `--interactive` are declared as GLOBAL
55
+ // options on the root program, so they land in the parent's opts, not the
56
+ // sub-command's. optsWithGlobals() merges both so flags like --dry-run
57
+ // actually take effect here.
58
+ const merged =
59
+ typeof command?.optsWithGlobals === 'function'
60
+ ? { ...command.optsWithGlobals(), ...options }
61
+ : options;
62
+ await runComputerSetup(merged);
40
63
  });
41
64
 
42
65
  // Subcommands
@@ -72,7 +95,7 @@ export function createComputerSetupCommand(): Command {
72
95
  return command;
73
96
  }
74
97
 
75
- async function runComputerSetup(options: any): Promise<void> {
98
+ export async function runComputerSetup(options: any): Promise<void> {
76
99
  const spinner = ora('Initializing computer setup...').start();
77
100
 
78
101
  try {
@@ -81,6 +104,17 @@ async function runComputerSetup(options: any): Promise<void> {
81
104
 
82
105
  spinner.stop();
83
106
 
107
+ // A run is non-interactive when there is no console, in CI, or when the
108
+ // caller asked for it (--yes / --non-interactive / a non-interactive mode).
109
+ // In that case we never prompt — for a profile OR for confirmation — and
110
+ // fall back to the default profile.
111
+ const nonInteractive =
112
+ Boolean(options.yes) ||
113
+ Boolean(options.nonInteractive) ||
114
+ options.mode !== 'interactive' ||
115
+ !process.stdin.isTTY ||
116
+ Boolean(process.env.CI);
117
+
84
118
  // Get or create profile
85
119
  let profile;
86
120
  if (options.profile) {
@@ -92,12 +126,20 @@ async function runComputerSetup(options: any): Promise<void> {
92
126
  );
93
127
  profile = await manager.getDefaultProfile();
94
128
  }
95
- } else if (options.mode === 'interactive' || options.interactive) {
129
+ } else if (!nonInteractive) {
96
130
  profile = await createInteractiveProfile();
97
131
  } else {
98
132
  profile = await manager.getDefaultProfile();
99
133
  }
100
134
 
135
+ // commander sets options.remoteAccess === false for --no-remote-access.
136
+ if (profile && options.remoteAccess === false) {
137
+ profile.remoteAccess = {
138
+ ...(profile.remoteAccess ?? {}),
139
+ enabled: false,
140
+ };
141
+ }
142
+
101
143
  // Detect platform
102
144
  const platform = {
103
145
  os: process.platform as 'darwin' | 'linux' | 'win32',
@@ -122,8 +164,9 @@ async function runComputerSetup(options: any): Promise<void> {
122
164
  );
123
165
  }
124
166
 
125
- // Confirm before proceeding
126
- if (options.mode === 'interactive' && !options.dryRun) {
167
+ // Confirm before proceeding (only in a real interactive session — the
168
+ // `nonInteractive` flag computed above already accounts for TTY/CI/--yes).
169
+ if (!options.dryRun && !nonInteractive) {
127
170
  const { proceed } = await inquirer.prompt([
128
171
  {
129
172
  type: 'confirm',
@@ -199,7 +242,24 @@ async function runComputerSetup(options: any): Promise<void> {
199
242
  }
200
243
 
201
244
  if (result.report) {
202
- console.log(chalk.cyan(`\n📄 Setup report generated successfully`));
245
+ console.log(chalk.cyan('\n📄 Setup report generated successfully'));
246
+ }
247
+
248
+ // Set up Fleet Mode if enabled
249
+ if (profile.preferences?.aiTools?.fleetMode) {
250
+ try {
251
+ await setupFleetMode(profile as DeveloperProfile);
252
+ } catch (fleetError) {
253
+ console.error(
254
+ chalk.red('\n⚠️ Fleet Mode setup encountered issues:'),
255
+ fleetError
256
+ );
257
+ console.log(
258
+ chalk.yellow(
259
+ 'You can retry with: wundr computer-setup --profile <your-profile>'
260
+ )
261
+ );
262
+ }
203
263
  }
204
264
 
205
265
  // Display next steps
@@ -308,9 +368,16 @@ async function createInteractiveProfile(): Promise<any> {
308
368
  type: 'confirm',
309
369
  name: 'aiTools',
310
370
  message:
311
- 'Do you want to set up AI development tools (Claude Code, Claude Flow)?',
371
+ 'Do you want to set up AI development tools (Claude Code, Ruflo)?',
312
372
  default: true,
313
373
  },
374
+ {
375
+ type: 'confirm',
376
+ name: 'fleetMode',
377
+ message: 'Enable Fleet-Scale Autonomous Engineering mode?',
378
+ default: false,
379
+ when: (answers: any) => answers.aiTools,
380
+ },
314
381
  {
315
382
  type: 'confirm',
316
383
  name: 'slack',
@@ -338,10 +405,11 @@ async function createInteractiveProfile(): Promise<any> {
338
405
  },
339
406
  aiTools: {
340
407
  claudeCode: answers.aiTools,
341
- claudeFlow: answers.aiTools,
408
+ ruflo: answers.aiTools,
342
409
  mcpTools: answers.aiTools ? ['all'] : [],
343
410
  swarmAgents: answers.aiTools ? ['default'] : [],
344
411
  memoryAllocation: '2GB',
412
+ fleetMode: answers.fleetMode || false,
345
413
  },
346
414
  },
347
415
  tools: {
@@ -425,6 +493,450 @@ function buildLanguageConfig(languages: string[]): any {
425
493
  return config;
426
494
  }
427
495
 
496
+ /**
497
+ * Developer profile interface with fleet mode support
498
+ */
499
+ interface DeveloperProfile {
500
+ name: string;
501
+ email: string;
502
+ role: string;
503
+ team?: string;
504
+ preferences: {
505
+ shell: string;
506
+ editor: string;
507
+ theme: string;
508
+ gitConfig: {
509
+ userName: string;
510
+ userEmail: string;
511
+ signCommits: boolean;
512
+ defaultBranch: string;
513
+ aliases: Record<string, string>;
514
+ };
515
+ aiTools: {
516
+ claudeCode: boolean;
517
+ ruflo: boolean;
518
+ mcpTools: string[];
519
+ swarmAgents: string[];
520
+ memoryAllocation: string;
521
+ fleetMode: boolean;
522
+ };
523
+ };
524
+ tools: Record<string, unknown>;
525
+ }
526
+
527
+ /**
528
+ * Sets up Fleet-Scale Autonomous Engineering mode
529
+ * Installs Orchestrator Daemon scripts, Memory Bank templates, and IPRE governance defaults
530
+ */
531
+ async function setupFleetMode(profile: DeveloperProfile): Promise<void> {
532
+ const wundrDir = path.join(os.homedir(), '.wundr');
533
+ const orchestratorDaemonDir = path.join(wundrDir, 'orchestrator-daemon');
534
+ const governanceDir = path.join(wundrDir, 'governance');
535
+ const templatesDir = path.join(wundrDir, 'templates');
536
+
537
+ console.log(
538
+ chalk.cyan('\n🚀 Setting up Fleet-Scale Autonomous Engineering mode...\n')
539
+ );
540
+
541
+ // Create directory structure
542
+ await fs.mkdir(orchestratorDaemonDir, { recursive: true });
543
+ await fs.mkdir(governanceDir, { recursive: true });
544
+ await fs.mkdir(path.join(templatesDir, 'memory-bank'), { recursive: true });
545
+ await fs.mkdir(path.join(templatesDir, 'sub-agents'), { recursive: true });
546
+
547
+ // 1. Install Orchestrator Daemon configuration
548
+ const orchestratorConfig = {
549
+ version: '1.0.0',
550
+ identity: {
551
+ name: profile.name,
552
+ email: profile.email,
553
+ role: 'Orchestrator-Supervisor',
554
+ },
555
+ resourceLimits: {
556
+ maxSessions: 10,
557
+ tokenBudget: {
558
+ subscription: 0.8, // 80% for Orchestrator & Session Managers
559
+ api: 0.2, // 20% for sub-agent swarms
560
+ },
561
+ },
562
+ systemLimits: {
563
+ fileDescriptors: 65000,
564
+ diskSpaceBufferGB: 10,
565
+ maxWorktreesPerMachine: 200,
566
+ },
567
+ measurableObjectives: {
568
+ responseTime: '<30s to Slack mentions',
569
+ rateLimit: "Zero 'Rate Limit Exceeded' per week",
570
+ routingAccuracy: '100% correct task routing',
571
+ },
572
+ hardConstraints: [
573
+ 'Never exhaust API quota',
574
+ 'Always maintain audit trail',
575
+ 'Escalate blocked requests within 5 minutes',
576
+ ],
577
+ };
578
+
579
+ await fs.writeFile(
580
+ path.join(orchestratorDaemonDir, 'config.yaml'),
581
+ generateYamlContent(orchestratorConfig),
582
+ 'utf-8'
583
+ );
584
+ console.log(chalk.green(' ✓ Orchestrator Daemon configuration installed'));
585
+
586
+ // 2. Copy Orchestrator Charter template
587
+ const orchestratorCharter = `---
588
+ name: orchestrator-supervisor
589
+ role: Tier1-Orchestrator
590
+ identity:
591
+ name: '${profile.name}'
592
+ email: '${profile.email}'
593
+ slackHandle: '@orchestrator-supervisor'
594
+
595
+ responsibilities:
596
+ - triage_requests
597
+ - manage_session_lifecycle
598
+ - allocate_token_budget
599
+ - human_communication
600
+ - fleet_status_reporting
601
+
602
+ resourceLimits:
603
+ maxSessions: 10
604
+ tokenBudget:
605
+ subscription: 80%
606
+ api: 20%
607
+
608
+ measurableObjectives:
609
+ responseTime: '<30s to Slack mentions'
610
+ rateLimit: "Zero 'Rate Limit Exceeded' per week"
611
+ routingAccuracy: '100% correct task routing'
612
+
613
+ hardConstraints:
614
+ - 'Never exhaust API quota'
615
+ - 'Always maintain audit trail'
616
+ - 'Escalate blocked requests within 5 minutes'
617
+ ---
618
+ `;
619
+
620
+ await fs.writeFile(
621
+ path.join(orchestratorDaemonDir, 'orchestrator-charter.md'),
622
+ orchestratorCharter,
623
+ 'utf-8'
624
+ );
625
+ console.log(chalk.green(' ✓ Orchestrator Charter template deployed'));
626
+
627
+ // 3. Set up token budgeting configuration
628
+ const tokenBudgetConfig = {
629
+ version: '1.0.0',
630
+ subscription: {
631
+ type: 'claude-code-max-20x',
632
+ promptsPerFiveHours: 800,
633
+ warningThreshold: 0.8,
634
+ criticalThreshold: 0.95,
635
+ },
636
+ api: {
637
+ monthlyBudget: 500,
638
+ haikuRatePerMillion: 0.25,
639
+ sonnetRatePerMillion: 3.0,
640
+ },
641
+ modelAllocation: {
642
+ tier1: {
643
+ model: 'claude-3-5-sonnet',
644
+ source: 'subscription',
645
+ priority: 'critical',
646
+ },
647
+ tier2: {
648
+ model: 'claude-3-5-sonnet',
649
+ source: 'subscription',
650
+ priority: 'high',
651
+ },
652
+ tier3: {
653
+ model: 'claude-3-5-haiku',
654
+ source: 'api',
655
+ priority: 'normal',
656
+ },
657
+ },
658
+ throttlingPolicy: {
659
+ onWarning: ['pause_non_critical_sessions', 'queue_new_requests'],
660
+ onCritical: ['pause_all_except_critical', 'notify_orchestrator_human'],
661
+ },
662
+ };
663
+
664
+ await fs.writeFile(
665
+ path.join(orchestratorDaemonDir, 'token-budget.yaml'),
666
+ generateYamlContent(tokenBudgetConfig),
667
+ 'utf-8'
668
+ );
669
+ console.log(chalk.green(' ✓ Token budgeting configuration set up'));
670
+
671
+ // 4. Deploy Memory Bank templates
672
+ const sessionTemplate = `# Active Context - Session {{SESSION_ID}}
673
+
674
+ ## Current Focus
675
+ <!-- Updated by session manager -->
676
+
677
+ ## Working Memory
678
+ - Last action:
679
+ - Next planned step:
680
+ - Blockers:
681
+
682
+ ## Context Window State
683
+ - Tokens used: X / 200,000
684
+ - Compression needed: Yes/No
685
+
686
+ ## Handoff Notes
687
+ <!-- For session resumption -->
688
+ `;
689
+
690
+ const progressTemplate = `# Progress Tracker - Session {{SESSION_ID}}
691
+
692
+ ## Milestones
693
+ | Status | Milestone | Target Date | Notes |
694
+ |--------|-----------|-------------|-------|
695
+
696
+ ## Completed Tasks
697
+ <!-- Archive of completed work -->
698
+
699
+ ## Blockers
700
+ <!-- Current impediments -->
701
+ `;
702
+
703
+ const subAgentDelegationTemplate = `# Sub-Agent Delegation Tracker
704
+
705
+ ## Active Sub-Agents
706
+ | ID | Type | Task | Status | Worktree | Started |
707
+ |----|------|------|--------|----------|---------|
708
+
709
+ ## Completed Tasks
710
+ <!-- Archive of completed sub-agent work -->
711
+
712
+ ## Resource Usage
713
+ - Active worktrees: X / 20
714
+ - API calls (session): X
715
+ `;
716
+
717
+ const ipreAlignmentTemplate = `# IPRE Alignment State
718
+
719
+ ## Active Policies
720
+ <!-- Hard constraints for this session -->
721
+
722
+ ## Reward Weights
723
+ \`\`\`yaml
724
+ customer_value: 0.35
725
+ code_quality: 0.30
726
+ timeline: 0.20
727
+ technical_debt: 0.15
728
+ \`\`\`
729
+
730
+ ## Alignment Score
731
+ - Current: 85/100
732
+ - Last evaluation: {{TIMESTAMP}}
733
+ - Trend: Improving
734
+
735
+ ## Escalation History
736
+ <!-- Guardian review log -->
737
+ `;
738
+
739
+ await fs.writeFile(
740
+ path.join(templatesDir, 'memory-bank', 'activeContext.md'),
741
+ sessionTemplate,
742
+ 'utf-8'
743
+ );
744
+ await fs.writeFile(
745
+ path.join(templatesDir, 'memory-bank', 'progress.md'),
746
+ progressTemplate,
747
+ 'utf-8'
748
+ );
749
+ await fs.writeFile(
750
+ path.join(templatesDir, 'memory-bank', 'subAgentDelegation.md'),
751
+ subAgentDelegationTemplate,
752
+ 'utf-8'
753
+ );
754
+ await fs.writeFile(
755
+ path.join(templatesDir, 'memory-bank', 'ipre-alignment.md'),
756
+ ipreAlignmentTemplate,
757
+ 'utf-8'
758
+ );
759
+ console.log(chalk.green(' ✓ Memory Bank templates deployed'));
760
+
761
+ // 5. Initialize IPRE governance defaults
762
+ const ipreDefaults = {
763
+ version: '1.0.0',
764
+ intent: {
765
+ mission: 'Deliver high-quality software that solves customer problems',
766
+ values: [
767
+ 'customer_first',
768
+ 'technical_excellence',
769
+ 'sustainable_velocity',
770
+ ],
771
+ },
772
+ policies: {
773
+ security: [
774
+ 'No secrets in code',
775
+ 'No SQL injection vulnerabilities',
776
+ 'No XSS attack vectors',
777
+ ],
778
+ compliance: [
779
+ 'All changes require PR review',
780
+ 'No force pushes to main/master',
781
+ 'Test coverage minimum 80%',
782
+ ],
783
+ operational: [
784
+ 'No deployments on Fridays after 2pm',
785
+ 'Rollback plan required for production changes',
786
+ ],
787
+ },
788
+ rewards: {
789
+ customer_value: 0.35,
790
+ code_quality: 0.25,
791
+ delivery_speed: 0.2,
792
+ technical_debt_reduction: 0.15,
793
+ documentation: 0.05,
794
+ },
795
+ evaluators: [
796
+ {
797
+ type: 'policy_compliance',
798
+ frequency: 'per_commit',
799
+ action: 'block_on_violation',
800
+ },
801
+ {
802
+ type: 'reward_alignment',
803
+ frequency: 'hourly',
804
+ threshold: 0.7,
805
+ action: 'escalate_to_guardian',
806
+ },
807
+ {
808
+ type: 'drift_detection',
809
+ frequency: 'daily',
810
+ patterns: ['reward_hacking', 'escalation_suppression'],
811
+ action: 'alert_architect',
812
+ },
813
+ ],
814
+ };
815
+
816
+ await fs.writeFile(
817
+ path.join(governanceDir, 'ipre-defaults.yaml'),
818
+ generateYamlContent(ipreDefaults),
819
+ 'utf-8'
820
+ );
821
+ console.log(chalk.green(' ✓ IPRE governance defaults initialized'));
822
+
823
+ // 6. Configure system resource limits guidance
824
+ const resourceGuidance = `# System Resource Configuration for Fleet Mode
825
+
826
+ ## File Descriptor Limits
827
+ For optimal fleet operation with up to 200 worktrees, configure:
828
+
829
+ ### macOS / Linux
830
+ \`\`\`bash
831
+ # Add to ~/.zshrc or ~/.bashrc
832
+ ulimit -n 65000
833
+ \`\`\`
834
+
835
+ ### Persistent Configuration (macOS)
836
+ \`\`\`bash
837
+ # Create /Library/LaunchDaemons/limit.maxfiles.plist with:
838
+ # soft limit: 65000
839
+ # hard limit: 200000
840
+ \`\`\`
841
+
842
+ ### Persistent Configuration (Linux)
843
+ \`\`\`bash
844
+ # Add to /etc/security/limits.conf
845
+ * soft nofile 65000
846
+ * hard nofile 200000
847
+ \`\`\`
848
+
849
+ ## Disk Space Requirements
850
+ - Minimum: 500GB SSD
851
+ - Recommended: 4TB+ SSD (for 200 worktrees at ~2GB each)
852
+ - Buffer: Keep 10GB free at all times
853
+
854
+ ## Git Worktree Best Practices
855
+ - Session Managers sync with remote (fetch/pull)
856
+ - Sub-Agents rarely git fetch (reduces index lock contention)
857
+ - Use fractional worktree pattern:
858
+ - Read-only agents: Share Session Manager's worktree
859
+ - Write-access agents: Get dedicated worktrees
860
+
861
+ ## Monitoring Commands
862
+ \`\`\`bash
863
+ # Check current file descriptor limit
864
+ ulimit -n
865
+
866
+ # Check open files
867
+ lsof | wc -l
868
+
869
+ # Check disk space
870
+ df -h
871
+
872
+ # List active worktrees
873
+ git worktree list
874
+ \`\`\`
875
+ `;
876
+
877
+ await fs.writeFile(
878
+ path.join(wundrDir, 'RESOURCE_LIMITS.md'),
879
+ resourceGuidance,
880
+ 'utf-8'
881
+ );
882
+ console.log(chalk.green(' ✓ System resource limits guidance configured'));
883
+
884
+ console.log(
885
+ chalk.cyan('\n✅ Fleet-Scale Autonomous Engineering mode setup complete!\n')
886
+ );
887
+ console.log(chalk.white('Files created:'));
888
+ console.log(chalk.gray(' ~/.wundr/orchestrator-daemon/config.yaml'));
889
+ console.log(
890
+ chalk.gray(' ~/.wundr/orchestrator-daemon/orchestrator-charter.md')
891
+ );
892
+ console.log(chalk.gray(' ~/.wundr/orchestrator-daemon/token-budget.yaml'));
893
+ console.log(chalk.gray(' ~/.wundr/templates/memory-bank/'));
894
+ console.log(chalk.gray(' ~/.wundr/governance/ipre-defaults.yaml'));
895
+ console.log(chalk.gray(' ~/.wundr/RESOURCE_LIMITS.md'));
896
+ console.log(
897
+ chalk.yellow(
898
+ '\n⚠️ Review ~/.wundr/RESOURCE_LIMITS.md for system configuration recommendations.'
899
+ )
900
+ );
901
+ }
902
+
903
+ /**
904
+ * Simple YAML generator for configuration objects
905
+ */
906
+ function generateYamlContent(obj: Record<string, unknown>, indent = 0): string {
907
+ let yaml = '';
908
+ const spaces = ' '.repeat(indent);
909
+
910
+ for (const [key, value] of Object.entries(obj)) {
911
+ if (value === null || value === undefined) {
912
+ yaml += `${spaces}${key}: null\n`;
913
+ } else if (typeof value === 'object' && !Array.isArray(value)) {
914
+ yaml += `${spaces}${key}:\n`;
915
+ yaml += generateYamlContent(value as Record<string, unknown>, indent + 1);
916
+ } else if (Array.isArray(value)) {
917
+ yaml += `${spaces}${key}:\n`;
918
+ for (const item of value) {
919
+ if (typeof item === 'object') {
920
+ yaml += `${spaces} -\n`;
921
+ const itemYaml = generateYamlContent(
922
+ item as Record<string, unknown>,
923
+ indent + 2
924
+ );
925
+ yaml += itemYaml;
926
+ } else {
927
+ yaml += `${spaces} - '${item}'\n`;
928
+ }
929
+ }
930
+ } else if (typeof value === 'string') {
931
+ yaml += `${spaces}${key}: '${value}'\n`;
932
+ } else {
933
+ yaml += `${spaces}${key}: ${value}\n`;
934
+ }
935
+ }
936
+
937
+ return yaml;
938
+ }
939
+
428
940
  async function manageProfiles(): Promise<void> {
429
941
  const manager = new ComputerSetupManager();
430
942
  await manager.initialize();
@@ -3,10 +3,10 @@
3
3
  * Scaffolds new wundr-compliant projects
4
4
  */
5
5
 
6
- import { Command } from 'commander';
7
- import chalk from 'chalk';
8
- import { projectTemplates } from '@wundr/project-templates';
9
6
  import { getLogger } from '@wundr/core';
7
+ import { projectTemplates } from '@wundr/project-templates';
8
+ import chalk from 'chalk';
9
+ import { Command } from 'commander';
10
10
 
11
11
  const logger = getLogger('cli:create');
12
12
 
@@ -1,12 +1,15 @@
1
- import { Command } from 'commander';
2
- import inquirer from 'inquirer';
3
- import fs from 'fs-extra';
4
1
  import path from 'path';
2
+
5
3
  import chalk from 'chalk';
6
- import { ConfigManager } from '../utils/config-manager';
7
- import { PluginManager } from '../plugins/plugin-manager';
8
- import { logger } from '../utils/logger';
4
+ import fs from 'fs-extra';
5
+ import inquirer from 'inquirer';
6
+
9
7
  import { errorHandler } from '../utils/error-handler';
8
+ import { logger } from '../utils/logger';
9
+
10
+ import type { PluginManager } from '../plugins/plugin-manager';
11
+ import type { ConfigManager } from '../utils/config-manager';
12
+ import type { Command } from 'commander';
10
13
  // import { projectTemplates } from '@wundr/project-templates';
11
14
  // TODO: Fix this import - project-templates package needs to be created
12
15
  const projectTemplates = {
@@ -1,12 +1,15 @@
1
- import { Command } from 'commander';
2
1
  import { spawn } from 'child_process';
3
- import fs from 'fs-extra';
4
2
  import path from 'path';
3
+
5
4
  import chalk from 'chalk';
6
- import { ConfigManager } from '../utils/config-manager';
7
- import { PluginManager } from '../plugins/plugin-manager';
8
- import { logger } from '../utils/logger';
5
+ import fs from 'fs-extra';
6
+
9
7
  import { errorHandler } from '../utils/error-handler';
8
+ import { logger } from '../utils/logger';
9
+
10
+ import type { PluginManager } from '../plugins/plugin-manager';
11
+ import type { ConfigManager } from '../utils/config-manager';
12
+ import type { Command } from 'commander';
10
13
 
11
14
  /**
12
15
  * Dashboard commands for web interface and visualization
@@ -489,7 +492,9 @@ export class DashboardCommands {
489
492
  */
490
493
  private async isDashboardRunning(): Promise<boolean> {
491
494
  const processInfo = await this.loadDashboardProcess();
492
- if (!processInfo) return false;
495
+ if (!processInfo) {
496
+ return false;
497
+ }
493
498
 
494
499
  try {
495
500
  process.kill(processInfo.pid, 0);