@wundr.io/cli 1.0.1 → 1.0.2-dev.20260530180455.e1307186
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/bin/wundr.js +13 -5
- package/package.json +30 -9
- package/src/ai/ai-service.ts +6 -4
- package/src/ai/claude-client.ts +6 -2
- package/src/ai/conversation-manager.ts +12 -5
- package/src/cli.ts +42 -13
- package/src/commands/ai.ts +340 -64
- package/src/commands/alignment.ts +1212 -0
- package/src/commands/analyze-optimized.ts +371 -33
- package/src/commands/analyze.ts +8 -6
- package/src/commands/batch.ts +166 -26
- package/src/commands/chat.ts +20 -10
- package/src/commands/claude-init.ts +31 -27
- package/src/commands/claude-setup.ts +761 -81
- package/src/commands/computer-setup.ts +524 -12
- package/src/commands/create-command.ts +3 -3
- package/src/commands/create.ts +9 -6
- package/src/commands/dashboard.ts +11 -6
- package/src/commands/govern.ts +11 -6
- package/src/commands/governance.ts +1005 -0
- package/src/commands/guardian.ts +887 -0
- package/src/commands/init.ts +104 -11
- package/src/commands/orchestrator.ts +789 -0
- package/src/commands/performance-optimizer.ts +15 -10
- package/src/commands/plugins.ts +8 -5
- package/src/commands/project-update.ts +1156 -0
- package/src/commands/rag.ts +1011 -0
- package/src/commands/session.ts +631 -0
- package/src/commands/setup.ts +42 -344
- package/src/commands/test-init.ts +3 -2
- package/src/commands/test.ts +3 -2
- package/src/commands/watch.ts +21 -11
- package/src/commands/worktree.ts +1057 -0
- package/src/context/context-manager.ts +5 -2
- package/src/context/session-manager.ts +18 -7
- package/src/framework/command-interface.ts +520 -0
- package/src/framework/command-registry.ts +942 -0
- package/src/framework/completion-exporter.ts +383 -0
- package/src/framework/debug-logger.ts +519 -0
- package/src/framework/error-handler.ts +867 -0
- package/src/framework/help-generator.ts +540 -0
- package/src/framework/index.ts +169 -0
- package/src/framework/interactive-repl.ts +703 -0
- package/src/framework/output-formatter.ts +834 -0
- package/src/framework/progress-manager.ts +539 -0
- package/src/index.ts +3 -2
- package/src/interactive/interactive-mode.ts +14 -7
- package/src/lib/conflict-resolution.ts +818 -0
- package/src/lib/merge-strategy.ts +550 -0
- package/src/lib/safety-mechanisms.ts +451 -0
- package/src/lib/state-detection.ts +1030 -0
- package/src/nlp/command-mapper.ts +8 -3
- package/src/nlp/command-parser.ts +5 -2
- package/src/nlp/intent-parser.ts +23 -9
- package/src/plugins/plugin-manager.ts +50 -24
- package/src/tests/computer-setup-integration.test.ts +46 -15
- package/src/types/index.ts +1 -1
- package/src/types/modules.d.ts +425 -1
- package/src/utils/backup-rollback-manager.ts +19 -14
- package/src/utils/claude-config-installer.ts +119 -28
- package/src/utils/config-manager.ts +9 -6
- package/src/utils/error-handler.ts +3 -1
- package/src/utils/logger.ts +35 -12
- package/templates/batch/ci-cd.yaml +7 -7
- package/test-suites/api/health.spec.ts +20 -23
- package/test-suites/helpers/test-config.ts +14 -13
- package/test-suites/ui/accessibility.spec.ts +27 -22
- package/test-suites/ui/smoke.spec.ts +26 -21
- 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 {
|
|
6
|
+
import { ComputerSetupManager } from '@wundr.io/computer-setup';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
|
-
import
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import * as fs from 'fs/promises';
|
|
9
10
|
import inquirer from 'inquirer';
|
|
10
|
-
import
|
|
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
|
-
.
|
|
39
|
-
|
|
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 (
|
|
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
|
-
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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
|
|
package/src/commands/create.ts
CHANGED
|
@@ -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
|
|
7
|
-
import
|
|
8
|
-
|
|
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
|
|
7
|
-
|
|
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)
|
|
495
|
+
if (!processInfo) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
493
498
|
|
|
494
499
|
try {
|
|
495
500
|
process.kill(processInfo.pid, 0);
|