@wundr.io/cli 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/bin/wundr.js +8 -4
  2. package/package.json +23 -23
  3. package/src/ai/ai-service.ts +16 -17
  4. package/src/ai/claude-client.ts +16 -16
  5. package/src/ai/conversation-manager.ts +29 -29
  6. package/src/cli.ts +4 -4
  7. package/src/commands/ai.ts +246 -78
  8. package/src/commands/alignment.ts +74 -74
  9. package/src/commands/analyze-optimized.ts +111 -78
  10. package/src/commands/analyze.ts +14 -14
  11. package/src/commands/batch.ts +179 -42
  12. package/src/commands/chat.ts +37 -30
  13. package/src/commands/claude-init.ts +41 -45
  14. package/src/commands/claude-setup.ts +204 -119
  15. package/src/commands/computer-setup.ts +85 -43
  16. package/src/commands/create-command.ts +4 -4
  17. package/src/commands/create.ts +27 -27
  18. package/src/commands/dashboard.ts +24 -24
  19. package/src/commands/govern.ts +25 -25
  20. package/src/commands/governance.ts +34 -34
  21. package/src/commands/guardian.ts +56 -56
  22. package/src/commands/init.ts +25 -22
  23. package/src/commands/orchestrator.ts +68 -41
  24. package/src/commands/performance-optimizer.ts +34 -35
  25. package/src/commands/plugins.ts +27 -27
  26. package/src/commands/project-update.ts +175 -72
  27. package/src/commands/rag.ts +185 -78
  28. package/src/commands/session.ts +35 -35
  29. package/src/commands/setup.ts +40 -344
  30. package/src/commands/test-init.ts +3 -3
  31. package/src/commands/test.ts +4 -4
  32. package/src/commands/watch.ts +28 -29
  33. package/src/commands/worktree.ts +49 -49
  34. package/src/context/context-manager.ts +10 -10
  35. package/src/context/session-manager.ts +41 -41
  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 +4 -4
  47. package/src/interactive/interactive-mode.ts +16 -16
  48. package/src/lib/conflict-resolution.ts +799 -9
  49. package/src/lib/merge-strategy.ts +529 -7
  50. package/src/lib/safety-mechanisms.ts +422 -18
  51. package/src/lib/state-detection.ts +1015 -13
  52. package/src/nlp/command-mapper.ts +29 -29
  53. package/src/nlp/command-parser.ts +17 -17
  54. package/src/nlp/intent-classifier.ts +7 -7
  55. package/src/nlp/intent-parser.ts +54 -52
  56. package/src/plugins/plugin-manager.ts +61 -39
  57. package/src/tests/computer-setup-integration.test.ts +46 -15
  58. package/src/types/modules.d.ts +424 -1
  59. package/src/utils/backup-rollback-manager.ts +11 -8
  60. package/src/utils/config-manager.ts +3 -3
  61. package/src/utils/error-handler.ts +2 -2
  62. package/src/utils/logger.ts +22 -22
  63. package/templates/batch/ci-cd.yaml +7 -7
  64. package/test-suites/api/health.spec.ts +20 -23
  65. package/test-suites/helpers/test-config.ts +14 -13
  66. package/test-suites/ui/accessibility.spec.ts +27 -22
  67. package/test-suites/ui/smoke.spec.ts +26 -21
  68. package/LICENSE +0 -21
  69. package/dist/ai/ai-service.d.ts +0 -152
  70. package/dist/ai/ai-service.d.ts.map +0 -1
  71. package/dist/ai/ai-service.js +0 -430
  72. package/dist/ai/ai-service.js.map +0 -1
  73. package/dist/ai/claude-client.d.ts +0 -130
  74. package/dist/ai/claude-client.d.ts.map +0 -1
  75. package/dist/ai/claude-client.js +0 -340
  76. package/dist/ai/claude-client.js.map +0 -1
  77. package/dist/ai/conversation-manager.d.ts +0 -164
  78. package/dist/ai/conversation-manager.d.ts.map +0 -1
  79. package/dist/ai/conversation-manager.js +0 -614
  80. package/dist/ai/conversation-manager.js.map +0 -1
  81. package/dist/ai/index.d.ts +0 -5
  82. package/dist/ai/index.d.ts.map +0 -1
  83. package/dist/ai/index.js +0 -8
  84. package/dist/ai/index.js.map +0 -1
  85. package/dist/cli.d.ts +0 -36
  86. package/dist/cli.d.ts.map +0 -1
  87. package/dist/cli.js +0 -192
  88. package/dist/cli.js.map +0 -1
  89. package/dist/commands/ai.d.ts +0 -89
  90. package/dist/commands/ai.d.ts.map +0 -1
  91. package/dist/commands/ai.js +0 -799
  92. package/dist/commands/ai.js.map +0 -1
  93. package/dist/commands/alignment.d.ts +0 -78
  94. package/dist/commands/alignment.d.ts.map +0 -1
  95. package/dist/commands/alignment.js +0 -817
  96. package/dist/commands/alignment.js.map +0 -1
  97. package/dist/commands/analyze-optimized.d.ts +0 -14
  98. package/dist/commands/analyze-optimized.d.ts.map +0 -1
  99. package/dist/commands/analyze-optimized.js +0 -600
  100. package/dist/commands/analyze-optimized.js.map +0 -1
  101. package/dist/commands/analyze.d.ts +0 -65
  102. package/dist/commands/analyze.d.ts.map +0 -1
  103. package/dist/commands/analyze.js +0 -435
  104. package/dist/commands/analyze.js.map +0 -1
  105. package/dist/commands/batch.d.ts +0 -71
  106. package/dist/commands/batch.d.ts.map +0 -1
  107. package/dist/commands/batch.js +0 -738
  108. package/dist/commands/batch.js.map +0 -1
  109. package/dist/commands/chat.d.ts +0 -71
  110. package/dist/commands/chat.d.ts.map +0 -1
  111. package/dist/commands/chat.js +0 -674
  112. package/dist/commands/chat.js.map +0 -1
  113. package/dist/commands/claude-init.d.ts +0 -28
  114. package/dist/commands/claude-init.d.ts.map +0 -1
  115. package/dist/commands/claude-init.js +0 -591
  116. package/dist/commands/claude-init.js.map +0 -1
  117. package/dist/commands/claude-setup.d.ts +0 -119
  118. package/dist/commands/claude-setup.d.ts.map +0 -1
  119. package/dist/commands/claude-setup.js +0 -1073
  120. package/dist/commands/claude-setup.js.map +0 -1
  121. package/dist/commands/computer-setup-commands.d.ts +0 -53
  122. package/dist/commands/computer-setup-commands.d.ts.map +0 -1
  123. package/dist/commands/computer-setup-commands.js +0 -705
  124. package/dist/commands/computer-setup-commands.js.map +0 -1
  125. package/dist/commands/computer-setup.d.ts +0 -7
  126. package/dist/commands/computer-setup.d.ts.map +0 -1
  127. package/dist/commands/computer-setup.js +0 -849
  128. package/dist/commands/computer-setup.js.map +0 -1
  129. package/dist/commands/create-command.d.ts +0 -7
  130. package/dist/commands/create-command.d.ts.map +0 -1
  131. package/dist/commands/create-command.js +0 -158
  132. package/dist/commands/create-command.js.map +0 -1
  133. package/dist/commands/create.d.ts +0 -74
  134. package/dist/commands/create.d.ts.map +0 -1
  135. package/dist/commands/create.js +0 -556
  136. package/dist/commands/create.js.map +0 -1
  137. package/dist/commands/dashboard.d.ts +0 -91
  138. package/dist/commands/dashboard.d.ts.map +0 -1
  139. package/dist/commands/dashboard.js +0 -538
  140. package/dist/commands/dashboard.js.map +0 -1
  141. package/dist/commands/govern.d.ts +0 -70
  142. package/dist/commands/govern.d.ts.map +0 -1
  143. package/dist/commands/govern.js +0 -481
  144. package/dist/commands/govern.js.map +0 -1
  145. package/dist/commands/governance.d.ts +0 -17
  146. package/dist/commands/governance.d.ts.map +0 -1
  147. package/dist/commands/governance.js +0 -703
  148. package/dist/commands/governance.js.map +0 -1
  149. package/dist/commands/guardian.d.ts +0 -20
  150. package/dist/commands/guardian.d.ts.map +0 -1
  151. package/dist/commands/guardian.js +0 -597
  152. package/dist/commands/guardian.js.map +0 -1
  153. package/dist/commands/init.d.ts +0 -59
  154. package/dist/commands/init.d.ts.map +0 -1
  155. package/dist/commands/init.js +0 -650
  156. package/dist/commands/init.js.map +0 -1
  157. package/dist/commands/orchestrator.d.ts +0 -7
  158. package/dist/commands/orchestrator.d.ts.map +0 -1
  159. package/dist/commands/orchestrator.js +0 -571
  160. package/dist/commands/orchestrator.js.map +0 -1
  161. package/dist/commands/performance-optimizer.d.ts +0 -30
  162. package/dist/commands/performance-optimizer.d.ts.map +0 -1
  163. package/dist/commands/performance-optimizer.js +0 -650
  164. package/dist/commands/performance-optimizer.js.map +0 -1
  165. package/dist/commands/plugins.d.ts +0 -87
  166. package/dist/commands/plugins.d.ts.map +0 -1
  167. package/dist/commands/plugins.js +0 -685
  168. package/dist/commands/plugins.js.map +0 -1
  169. package/dist/commands/rag.d.ts +0 -7
  170. package/dist/commands/rag.d.ts.map +0 -1
  171. package/dist/commands/rag.js +0 -748
  172. package/dist/commands/rag.js.map +0 -1
  173. package/dist/commands/session.d.ts +0 -41
  174. package/dist/commands/session.d.ts.map +0 -1
  175. package/dist/commands/session.js +0 -441
  176. package/dist/commands/session.js.map +0 -1
  177. package/dist/commands/setup.d.ts +0 -29
  178. package/dist/commands/setup.d.ts.map +0 -1
  179. package/dist/commands/setup.js +0 -397
  180. package/dist/commands/setup.js.map +0 -1
  181. package/dist/commands/test-init.d.ts +0 -9
  182. package/dist/commands/test-init.d.ts.map +0 -1
  183. package/dist/commands/test-init.js +0 -222
  184. package/dist/commands/test-init.js.map +0 -1
  185. package/dist/commands/test.d.ts +0 -25
  186. package/dist/commands/test.d.ts.map +0 -1
  187. package/dist/commands/test.js +0 -217
  188. package/dist/commands/test.js.map +0 -1
  189. package/dist/commands/vp.d.ts +0 -7
  190. package/dist/commands/vp.d.ts.map +0 -1
  191. package/dist/commands/vp.js +0 -571
  192. package/dist/commands/vp.js.map +0 -1
  193. package/dist/commands/watch.d.ts +0 -76
  194. package/dist/commands/watch.d.ts.map +0 -1
  195. package/dist/commands/watch.js +0 -613
  196. package/dist/commands/watch.js.map +0 -1
  197. package/dist/commands/worktree.d.ts +0 -63
  198. package/dist/commands/worktree.d.ts.map +0 -1
  199. package/dist/commands/worktree.js +0 -774
  200. package/dist/commands/worktree.js.map +0 -1
  201. package/dist/context/context-manager.d.ts +0 -155
  202. package/dist/context/context-manager.d.ts.map +0 -1
  203. package/dist/context/context-manager.js +0 -383
  204. package/dist/context/context-manager.js.map +0 -1
  205. package/dist/context/index.d.ts +0 -3
  206. package/dist/context/index.d.ts.map +0 -1
  207. package/dist/context/index.js +0 -6
  208. package/dist/context/index.js.map +0 -1
  209. package/dist/context/session-manager.d.ts +0 -207
  210. package/dist/context/session-manager.d.ts.map +0 -1
  211. package/dist/context/session-manager.js +0 -686
  212. package/dist/context/session-manager.js.map +0 -1
  213. package/dist/index.d.ts +0 -8
  214. package/dist/index.d.ts.map +0 -1
  215. package/dist/index.js +0 -51
  216. package/dist/index.js.map +0 -1
  217. package/dist/interactive/interactive-mode.d.ts +0 -76
  218. package/dist/interactive/interactive-mode.d.ts.map +0 -1
  219. package/dist/interactive/interactive-mode.js +0 -732
  220. package/dist/interactive/interactive-mode.js.map +0 -1
  221. package/dist/nlp/command-mapper.d.ts +0 -174
  222. package/dist/nlp/command-mapper.d.ts.map +0 -1
  223. package/dist/nlp/command-mapper.js +0 -624
  224. package/dist/nlp/command-mapper.js.map +0 -1
  225. package/dist/nlp/command-parser.d.ts +0 -106
  226. package/dist/nlp/command-parser.d.ts.map +0 -1
  227. package/dist/nlp/command-parser.js +0 -417
  228. package/dist/nlp/command-parser.js.map +0 -1
  229. package/dist/nlp/index.d.ts +0 -5
  230. package/dist/nlp/index.d.ts.map +0 -1
  231. package/dist/nlp/index.js +0 -8
  232. package/dist/nlp/index.js.map +0 -1
  233. package/dist/nlp/intent-classifier.d.ts +0 -59
  234. package/dist/nlp/intent-classifier.d.ts.map +0 -1
  235. package/dist/nlp/intent-classifier.js +0 -384
  236. package/dist/nlp/intent-classifier.js.map +0 -1
  237. package/dist/nlp/intent-parser.d.ts +0 -152
  238. package/dist/nlp/intent-parser.d.ts.map +0 -1
  239. package/dist/nlp/intent-parser.js +0 -744
  240. package/dist/nlp/intent-parser.js.map +0 -1
  241. package/dist/plugins/plugin-manager.d.ts +0 -120
  242. package/dist/plugins/plugin-manager.d.ts.map +0 -1
  243. package/dist/plugins/plugin-manager.js +0 -595
  244. package/dist/plugins/plugin-manager.js.map +0 -1
  245. package/dist/types/index.d.ts +0 -224
  246. package/dist/types/index.d.ts.map +0 -1
  247. package/dist/types/index.js +0 -3
  248. package/dist/types/index.js.map +0 -1
  249. package/dist/utils/backup-rollback-manager.d.ts +0 -72
  250. package/dist/utils/backup-rollback-manager.d.ts.map +0 -1
  251. package/dist/utils/backup-rollback-manager.js +0 -289
  252. package/dist/utils/backup-rollback-manager.js.map +0 -1
  253. package/dist/utils/claude-config-installer.d.ts +0 -98
  254. package/dist/utils/claude-config-installer.d.ts.map +0 -1
  255. package/dist/utils/claude-config-installer.js +0 -678
  256. package/dist/utils/claude-config-installer.js.map +0 -1
  257. package/dist/utils/config-manager.d.ts +0 -73
  258. package/dist/utils/config-manager.d.ts.map +0 -1
  259. package/dist/utils/config-manager.js +0 -339
  260. package/dist/utils/config-manager.js.map +0 -1
  261. package/dist/utils/error-handler.d.ts +0 -46
  262. package/dist/utils/error-handler.d.ts.map +0 -1
  263. package/dist/utils/error-handler.js +0 -169
  264. package/dist/utils/error-handler.js.map +0 -1
  265. package/dist/utils/logger.d.ts +0 -25
  266. package/dist/utils/logger.d.ts.map +0 -1
  267. package/dist/utils/logger.js +0 -105
  268. package/dist/utils/logger.js.map +0 -1
  269. package/src/commands/computer-setup-commands.ts +0 -872
@@ -1,849 +0,0 @@
1
- "use strict";
2
- /**
3
- * Computer setup command for provisioning new developer machines
4
- * Integrates new-starter functionality into the unified wundr CLI
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.createComputerSetupCommand = createComputerSetupCommand;
8
- const tslib_1 = require("tslib");
9
- const computer_setup_1 = require("@wundr.io/computer-setup");
10
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
11
- const commander_1 = require("commander");
12
- const fs = tslib_1.__importStar(require("fs/promises"));
13
- const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
14
- const os = tslib_1.__importStar(require("os"));
15
- const ora_1 = tslib_1.__importDefault(require("ora"));
16
- const path = tslib_1.__importStar(require("path"));
17
- // import { getLogger } from '@wundr/core';
18
- const logger = { info: console.log, error: console.error, warn: console.warn };
19
- // const logger = getLogger('cli:computer-setup');
20
- function createComputerSetupCommand() {
21
- const command = new commander_1.Command('computer-setup')
22
- .alias('setup-machine')
23
- .alias('provision')
24
- .description('Set up a new developer machine with all required tools and configurations')
25
- .option('-p, --profile <profile>', 'Use a specific profile (frontend, backend, fullstack, devops, ml)')
26
- .option('-t, --team <team>', 'Apply team-specific configurations')
27
- .option('-m, --mode <mode>', 'Setup mode (interactive, automated, minimal)', 'interactive')
28
- .option('--dry-run', 'Show what would be installed without making changes')
29
- .option('--skip-existing', 'Skip tools that are already installed')
30
- .option('--parallel', 'Install tools in parallel where possible')
31
- .option('--verbose', 'Show detailed output')
32
- .option('--report', 'Generate a detailed setup report')
33
- .action(async (options) => {
34
- await runComputerSetup(options);
35
- });
36
- // Subcommands
37
- command
38
- .command('profile')
39
- .description('Manage developer profiles')
40
- .action(async () => {
41
- await manageProfiles();
42
- });
43
- command
44
- .command('validate')
45
- .description('Validate current machine setup')
46
- .action(async () => {
47
- await validateSetup();
48
- });
49
- command
50
- .command('doctor')
51
- .description('Diagnose and fix common setup issues')
52
- .action(async () => {
53
- await runDoctor();
54
- });
55
- command
56
- .command('team-config')
57
- .description('Download and apply team configuration')
58
- .argument('<team>', 'Team identifier')
59
- .action(async (team) => {
60
- await applyTeamConfig(team);
61
- });
62
- return command;
63
- }
64
- async function runComputerSetup(options) {
65
- const spinner = (0, ora_1.default)('Initializing computer setup...').start();
66
- try {
67
- const manager = new computer_setup_1.ComputerSetupManager();
68
- await manager.initialize();
69
- spinner.stop();
70
- // Get or create profile
71
- let profile;
72
- if (options.profile) {
73
- // Get profile by name - ProfileManager will handle normalization
74
- profile = await manager.getProfile(options.profile);
75
- if (!profile) {
76
- console.log(chalk_1.default.yellow(`Profile '${options.profile}' not found. Using default.`));
77
- profile = await manager.getDefaultProfile();
78
- }
79
- }
80
- else if (options.mode === 'interactive' || options.interactive) {
81
- profile = await createInteractiveProfile();
82
- }
83
- else {
84
- profile = await manager.getDefaultProfile();
85
- }
86
- // Detect platform
87
- const platform = {
88
- os: process.platform,
89
- arch: process.arch,
90
- version: process.version,
91
- };
92
- console.log(chalk_1.default.cyan('\n🖥️ Computer Setup for Engineering Teams\n'));
93
- console.log(chalk_1.default.gray('━'.repeat(50)));
94
- console.log(chalk_1.default.white('Profile:'), chalk_1.default.green(profile.name));
95
- console.log(chalk_1.default.white('Role:'), chalk_1.default.green(profile.role));
96
- console.log(chalk_1.default.white('Platform:'), chalk_1.default.green(`${platform.os} ${platform.arch}`));
97
- console.log(chalk_1.default.white('Mode:'), chalk_1.default.green(options.mode));
98
- console.log(chalk_1.default.gray('━'.repeat(50)));
99
- if (options.dryRun) {
100
- console.log(chalk_1.default.yellow('\n⚠️ DRY RUN MODE - No changes will be made\n'));
101
- }
102
- // Confirm before proceeding
103
- if (options.mode === 'interactive' && !options.dryRun) {
104
- const { proceed } = await inquirer_1.default.prompt([
105
- {
106
- type: 'confirm',
107
- name: 'proceed',
108
- message: 'Ready to set up your machine?',
109
- default: true,
110
- },
111
- ]);
112
- if (!proceed) {
113
- console.log(chalk_1.default.yellow('Setup cancelled'));
114
- return;
115
- }
116
- }
117
- // Set up progress monitoring
118
- manager.on('progress', progress => {
119
- const bar = generateProgressBar(progress.percentage);
120
- console.log(chalk_1.default.cyan(`\n[${bar}] ${progress.percentage}%`));
121
- console.log(chalk_1.default.gray(`Current: ${progress.currentStep}`));
122
- console.log(chalk_1.default.gray(`Steps: ${progress.completedSteps}/${progress.totalSteps}`));
123
- });
124
- // Run setup
125
- spinner.text = 'Setting up your machine...';
126
- spinner.start();
127
- const result = await manager.setup({
128
- profile,
129
- platform,
130
- mode: options.mode,
131
- skipExisting: options.skipExisting || false,
132
- dryRun: options.dryRun || false,
133
- verbose: options.verbose || false,
134
- parallel: options.parallel || false,
135
- generateReport: options.report || false,
136
- });
137
- spinner.stop();
138
- // Display results
139
- if (result.success) {
140
- console.log(chalk_1.default.green('\n✅ Computer setup completed successfully!\n'));
141
- }
142
- else {
143
- console.log(chalk_1.default.red('\n❌ Computer setup completed with errors\n'));
144
- }
145
- console.log(chalk_1.default.white('Summary:'));
146
- console.log(chalk_1.default.green(` ✓ Completed: ${result.completedSteps?.length || 0} steps`));
147
- if (result.skippedSteps && result.skippedSteps.length > 0) {
148
- console.log(chalk_1.default.yellow(` ⊘ Skipped: ${result.skippedSteps.length} steps`));
149
- }
150
- if (result.failedSteps && result.failedSteps.length > 0) {
151
- console.log(chalk_1.default.red(` ✗ Failed: ${result.failedSteps.length} steps`));
152
- }
153
- if (result.warnings && result.warnings.length > 0) {
154
- console.log(chalk_1.default.yellow('\n⚠️ Warnings:'));
155
- result.warnings.forEach(w => console.log(chalk_1.default.yellow(` - ${w}`)));
156
- }
157
- if (result.errors && result.errors.length > 0) {
158
- console.log(chalk_1.default.red('\n❌ Errors:'));
159
- result.errors.forEach(e => console.log(chalk_1.default.red(` - ${e?.message || e}`)));
160
- }
161
- if (result.report) {
162
- console.log(chalk_1.default.cyan('\n📄 Setup report generated successfully'));
163
- }
164
- // Set up Fleet Mode if enabled
165
- if (profile.preferences?.aiTools?.fleetMode) {
166
- try {
167
- await setupFleetMode(profile);
168
- }
169
- catch (fleetError) {
170
- console.error(chalk_1.default.red('\n⚠️ Fleet Mode setup encountered issues:'), fleetError);
171
- console.log(chalk_1.default.yellow('You can retry with: wundr computer-setup --profile <your-profile>'));
172
- }
173
- }
174
- // Display next steps
175
- console.log(chalk_1.default.cyan('\n📝 Next Steps:'));
176
- const nextSteps = [
177
- 'Restart your terminal to apply configurations',
178
- 'Run "wundr computer-setup validate" to verify',
179
- 'Sign in to your team communication tools',
180
- 'Clone your team repositories',
181
- 'Review team onboarding documentation',
182
- ];
183
- nextSteps.forEach((step, i) => {
184
- console.log(chalk_1.default.white(` ${i + 1}. ${step}`));
185
- });
186
- console.log(chalk_1.default.gray('\n━'.repeat(50)));
187
- console.log(chalk_1.default.cyan('Welcome to the team! 🎉'));
188
- console.log(chalk_1.default.gray('━'.repeat(50)));
189
- }
190
- catch (error) {
191
- spinner.stop();
192
- logger.error('Computer setup failed', error);
193
- console.error(chalk_1.default.red('Setup failed:'), error);
194
- process.exit(1);
195
- }
196
- }
197
- async function createInteractiveProfile() {
198
- console.log(chalk_1.default.cyan("\n👤 Let's create your developer profile\n"));
199
- const answers = await inquirer_1.default.prompt([
200
- {
201
- type: 'input',
202
- name: 'name',
203
- message: 'What is your name?',
204
- validate: input => input.length > 0,
205
- },
206
- {
207
- type: 'input',
208
- name: 'email',
209
- message: 'What is your email?',
210
- validate: input => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input),
211
- },
212
- {
213
- type: 'list',
214
- name: 'role',
215
- message: 'What is your role?',
216
- choices: [
217
- { name: 'Frontend Developer', value: 'frontend' },
218
- { name: 'Backend Developer', value: 'backend' },
219
- { name: 'Full Stack Developer', value: 'fullstack' },
220
- { name: 'DevOps Engineer', value: 'devops' },
221
- { name: 'Machine Learning Engineer', value: 'ml' },
222
- { name: 'Mobile Developer', value: 'mobile' },
223
- ],
224
- },
225
- {
226
- type: 'input',
227
- name: 'team',
228
- message: 'What team are you joining? (optional)',
229
- default: '',
230
- },
231
- {
232
- type: 'list',
233
- name: 'shell',
234
- message: 'Which shell do you prefer?',
235
- choices: ['zsh', 'bash', 'fish'],
236
- },
237
- {
238
- type: 'list',
239
- name: 'editor',
240
- message: 'Which editor do you use?',
241
- choices: [
242
- { name: 'Visual Studio Code', value: 'vscode' },
243
- { name: 'Vim', value: 'vim' },
244
- { name: 'Neovim', value: 'neovim' },
245
- { name: 'Sublime Text', value: 'sublime' },
246
- { name: 'IntelliJ IDEA', value: 'intellij' },
247
- ],
248
- },
249
- {
250
- type: 'checkbox',
251
- name: 'languages',
252
- message: 'Which programming languages do you need?',
253
- choices: [
254
- { name: 'Node.js', value: 'node', checked: true },
255
- { name: 'Python', value: 'python' },
256
- { name: 'Go', value: 'go' },
257
- { name: 'Rust', value: 'rust' },
258
- { name: 'Java', value: 'java' },
259
- ],
260
- },
261
- {
262
- type: 'checkbox',
263
- name: 'tools',
264
- message: 'Which tools do you need?',
265
- choices: [
266
- { name: 'Docker', value: 'docker', checked: true },
267
- { name: 'Kubernetes', value: 'kubernetes' },
268
- { name: 'AWS CLI', value: 'aws' },
269
- { name: 'Google Cloud SDK', value: 'gcloud' },
270
- { name: 'PostgreSQL', value: 'postgresql' },
271
- { name: 'Redis', value: 'redis' },
272
- ],
273
- },
274
- {
275
- type: 'confirm',
276
- name: 'aiTools',
277
- message: 'Do you want to set up AI development tools (Claude Code, Claude Flow)?',
278
- default: true,
279
- },
280
- {
281
- type: 'confirm',
282
- name: 'fleetMode',
283
- message: 'Enable Fleet-Scale Autonomous Engineering mode?',
284
- default: false,
285
- when: (answers) => answers.aiTools,
286
- },
287
- {
288
- type: 'confirm',
289
- name: 'slack',
290
- message: 'Do you need Slack configuration?',
291
- default: true,
292
- },
293
- ]);
294
- // Build profile from answers
295
- return {
296
- name: answers.name,
297
- email: answers.email,
298
- role: answers.role,
299
- team: answers.team,
300
- preferences: {
301
- shell: answers.shell,
302
- editor: answers.editor,
303
- theme: 'auto',
304
- gitConfig: {
305
- userName: answers.name,
306
- userEmail: answers.email,
307
- signCommits: true,
308
- defaultBranch: 'main',
309
- aliases: {},
310
- },
311
- aiTools: {
312
- claudeCode: answers.aiTools,
313
- claudeFlow: answers.aiTools,
314
- mcpTools: answers.aiTools ? ['all'] : [],
315
- swarmAgents: answers.aiTools ? ['default'] : [],
316
- memoryAllocation: '2GB',
317
- fleetMode: answers.fleetMode || false,
318
- },
319
- },
320
- tools: {
321
- languages: buildLanguageConfig(answers.languages),
322
- packageManagers: {
323
- npm: true,
324
- pnpm: true,
325
- yarn: false,
326
- brew: process.platform === 'darwin',
327
- },
328
- containers: {
329
- docker: answers.tools.includes('docker'),
330
- dockerCompose: answers.tools.includes('docker'),
331
- kubernetes: answers.tools.includes('kubernetes'),
332
- },
333
- cloudCLIs: {
334
- aws: answers.tools.includes('aws'),
335
- gcloud: answers.tools.includes('gcloud'),
336
- },
337
- databases: {
338
- postgresql: answers.tools.includes('postgresql'),
339
- redis: answers.tools.includes('redis'),
340
- },
341
- monitoring: {},
342
- communication: {
343
- slack: answers.slack
344
- ? {
345
- workspaces: [],
346
- profile: {
347
- displayName: answers.name,
348
- statusText: 'New team member',
349
- statusEmoji: ':wave:',
350
- },
351
- }
352
- : undefined,
353
- },
354
- },
355
- };
356
- }
357
- function buildLanguageConfig(languages) {
358
- const config = {};
359
- if (languages.includes('node')) {
360
- config.node = {
361
- versions: ['20', '18'],
362
- defaultVersion: '20',
363
- globalPackages: ['pnpm', 'typescript', 'tsx'],
364
- };
365
- }
366
- if (languages.includes('python')) {
367
- config.python = {
368
- versions: ['3.11', '3.10'],
369
- defaultVersion: '3.11',
370
- virtualEnv: 'venv',
371
- };
372
- }
373
- if (languages.includes('go')) {
374
- config.go = {
375
- version: 'latest',
376
- goPath: '$HOME/go',
377
- };
378
- }
379
- if (languages.includes('rust')) {
380
- config.rust = {
381
- version: 'stable',
382
- components: ['rustfmt', 'clippy'],
383
- };
384
- }
385
- if (languages.includes('java')) {
386
- config.java = {
387
- version: '17',
388
- jdk: 'adoptium',
389
- };
390
- }
391
- return config;
392
- }
393
- /**
394
- * Sets up Fleet-Scale Autonomous Engineering mode
395
- * Installs Orchestrator Daemon scripts, Memory Bank templates, and IPRE governance defaults
396
- */
397
- async function setupFleetMode(profile) {
398
- const wundrDir = path.join(os.homedir(), '.wundr');
399
- const orchestratorDaemonDir = path.join(wundrDir, 'orchestrator-daemon');
400
- const governanceDir = path.join(wundrDir, 'governance');
401
- const templatesDir = path.join(wundrDir, 'templates');
402
- console.log(chalk_1.default.cyan('\n🚀 Setting up Fleet-Scale Autonomous Engineering mode...\n'));
403
- // Create directory structure
404
- await fs.mkdir(orchestratorDaemonDir, { recursive: true });
405
- await fs.mkdir(governanceDir, { recursive: true });
406
- await fs.mkdir(path.join(templatesDir, 'memory-bank'), { recursive: true });
407
- await fs.mkdir(path.join(templatesDir, 'sub-agents'), { recursive: true });
408
- // 1. Install Orchestrator Daemon configuration
409
- const orchestratorConfig = {
410
- version: '1.0.0',
411
- identity: {
412
- name: profile.name,
413
- email: profile.email,
414
- role: 'Orchestrator-Supervisor',
415
- },
416
- resourceLimits: {
417
- maxSessions: 10,
418
- tokenBudget: {
419
- subscription: 0.8, // 80% for Orchestrator & Session Managers
420
- api: 0.2, // 20% for sub-agent swarms
421
- },
422
- },
423
- systemLimits: {
424
- fileDescriptors: 65000,
425
- diskSpaceBufferGB: 10,
426
- maxWorktreesPerMachine: 200,
427
- },
428
- measurableObjectives: {
429
- responseTime: '<30s to Slack mentions',
430
- rateLimit: "Zero 'Rate Limit Exceeded' per week",
431
- routingAccuracy: '100% correct task routing',
432
- },
433
- hardConstraints: [
434
- 'Never exhaust API quota',
435
- 'Always maintain audit trail',
436
- 'Escalate blocked requests within 5 minutes',
437
- ],
438
- };
439
- await fs.writeFile(path.join(orchestratorDaemonDir, 'config.yaml'), generateYamlContent(orchestratorConfig), 'utf-8');
440
- console.log(chalk_1.default.green(' ✓ Orchestrator Daemon configuration installed'));
441
- // 2. Copy Orchestrator Charter template
442
- const orchestratorCharter = `---
443
- name: orchestrator-supervisor
444
- role: Tier1-Orchestrator
445
- identity:
446
- name: '${profile.name}'
447
- email: '${profile.email}'
448
- slackHandle: '@orchestrator-supervisor'
449
-
450
- responsibilities:
451
- - triage_requests
452
- - manage_session_lifecycle
453
- - allocate_token_budget
454
- - human_communication
455
- - fleet_status_reporting
456
-
457
- resourceLimits:
458
- maxSessions: 10
459
- tokenBudget:
460
- subscription: 80%
461
- api: 20%
462
-
463
- measurableObjectives:
464
- responseTime: '<30s to Slack mentions'
465
- rateLimit: "Zero 'Rate Limit Exceeded' per week"
466
- routingAccuracy: '100% correct task routing'
467
-
468
- hardConstraints:
469
- - 'Never exhaust API quota'
470
- - 'Always maintain audit trail'
471
- - 'Escalate blocked requests within 5 minutes'
472
- ---
473
- `;
474
- await fs.writeFile(path.join(orchestratorDaemonDir, 'orchestrator-charter.md'), orchestratorCharter, 'utf-8');
475
- console.log(chalk_1.default.green(' ✓ Orchestrator Charter template deployed'));
476
- // 3. Set up token budgeting configuration
477
- const tokenBudgetConfig = {
478
- version: '1.0.0',
479
- subscription: {
480
- type: 'claude-code-max-20x',
481
- promptsPerFiveHours: 800,
482
- warningThreshold: 0.8,
483
- criticalThreshold: 0.95,
484
- },
485
- api: {
486
- monthlyBudget: 500,
487
- haikuRatePerMillion: 0.25,
488
- sonnetRatePerMillion: 3.0,
489
- },
490
- modelAllocation: {
491
- tier1: {
492
- model: 'claude-3-5-sonnet',
493
- source: 'subscription',
494
- priority: 'critical',
495
- },
496
- tier2: {
497
- model: 'claude-3-5-sonnet',
498
- source: 'subscription',
499
- priority: 'high',
500
- },
501
- tier3: {
502
- model: 'claude-3-5-haiku',
503
- source: 'api',
504
- priority: 'normal',
505
- },
506
- },
507
- throttlingPolicy: {
508
- onWarning: ['pause_non_critical_sessions', 'queue_new_requests'],
509
- onCritical: ['pause_all_except_critical', 'notify_orchestrator_human'],
510
- },
511
- };
512
- await fs.writeFile(path.join(orchestratorDaemonDir, 'token-budget.yaml'), generateYamlContent(tokenBudgetConfig), 'utf-8');
513
- console.log(chalk_1.default.green(' ✓ Token budgeting configuration set up'));
514
- // 4. Deploy Memory Bank templates
515
- const sessionTemplate = `# Active Context - Session {{SESSION_ID}}
516
-
517
- ## Current Focus
518
- <!-- Updated by session manager -->
519
-
520
- ## Working Memory
521
- - Last action:
522
- - Next planned step:
523
- - Blockers:
524
-
525
- ## Context Window State
526
- - Tokens used: X / 200,000
527
- - Compression needed: Yes/No
528
-
529
- ## Handoff Notes
530
- <!-- For session resumption -->
531
- `;
532
- const progressTemplate = `# Progress Tracker - Session {{SESSION_ID}}
533
-
534
- ## Milestones
535
- | Status | Milestone | Target Date | Notes |
536
- |--------|-----------|-------------|-------|
537
-
538
- ## Completed Tasks
539
- <!-- Archive of completed work -->
540
-
541
- ## Blockers
542
- <!-- Current impediments -->
543
- `;
544
- const subAgentDelegationTemplate = `# Sub-Agent Delegation Tracker
545
-
546
- ## Active Sub-Agents
547
- | ID | Type | Task | Status | Worktree | Started |
548
- |----|------|------|--------|----------|---------|
549
-
550
- ## Completed Tasks
551
- <!-- Archive of completed sub-agent work -->
552
-
553
- ## Resource Usage
554
- - Active worktrees: X / 20
555
- - API calls (session): X
556
- `;
557
- const ipreAlignmentTemplate = `# IPRE Alignment State
558
-
559
- ## Active Policies
560
- <!-- Hard constraints for this session -->
561
-
562
- ## Reward Weights
563
- \`\`\`yaml
564
- customer_value: 0.35
565
- code_quality: 0.30
566
- timeline: 0.20
567
- technical_debt: 0.15
568
- \`\`\`
569
-
570
- ## Alignment Score
571
- - Current: 85/100
572
- - Last evaluation: {{TIMESTAMP}}
573
- - Trend: Improving
574
-
575
- ## Escalation History
576
- <!-- Guardian review log -->
577
- `;
578
- await fs.writeFile(path.join(templatesDir, 'memory-bank', 'activeContext.md'), sessionTemplate, 'utf-8');
579
- await fs.writeFile(path.join(templatesDir, 'memory-bank', 'progress.md'), progressTemplate, 'utf-8');
580
- await fs.writeFile(path.join(templatesDir, 'memory-bank', 'subAgentDelegation.md'), subAgentDelegationTemplate, 'utf-8');
581
- await fs.writeFile(path.join(templatesDir, 'memory-bank', 'ipre-alignment.md'), ipreAlignmentTemplate, 'utf-8');
582
- console.log(chalk_1.default.green(' ✓ Memory Bank templates deployed'));
583
- // 5. Initialize IPRE governance defaults
584
- const ipreDefaults = {
585
- version: '1.0.0',
586
- intent: {
587
- mission: 'Deliver high-quality software that solves customer problems',
588
- values: [
589
- 'customer_first',
590
- 'technical_excellence',
591
- 'sustainable_velocity',
592
- ],
593
- },
594
- policies: {
595
- security: [
596
- 'No secrets in code',
597
- 'No SQL injection vulnerabilities',
598
- 'No XSS attack vectors',
599
- ],
600
- compliance: [
601
- 'All changes require PR review',
602
- 'No force pushes to main/master',
603
- 'Test coverage minimum 80%',
604
- ],
605
- operational: [
606
- 'No deployments on Fridays after 2pm',
607
- 'Rollback plan required for production changes',
608
- ],
609
- },
610
- rewards: {
611
- customer_value: 0.35,
612
- code_quality: 0.25,
613
- delivery_speed: 0.2,
614
- technical_debt_reduction: 0.15,
615
- documentation: 0.05,
616
- },
617
- evaluators: [
618
- {
619
- type: 'policy_compliance',
620
- frequency: 'per_commit',
621
- action: 'block_on_violation',
622
- },
623
- {
624
- type: 'reward_alignment',
625
- frequency: 'hourly',
626
- threshold: 0.7,
627
- action: 'escalate_to_guardian',
628
- },
629
- {
630
- type: 'drift_detection',
631
- frequency: 'daily',
632
- patterns: ['reward_hacking', 'escalation_suppression'],
633
- action: 'alert_architect',
634
- },
635
- ],
636
- };
637
- await fs.writeFile(path.join(governanceDir, 'ipre-defaults.yaml'), generateYamlContent(ipreDefaults), 'utf-8');
638
- console.log(chalk_1.default.green(' ✓ IPRE governance defaults initialized'));
639
- // 6. Configure system resource limits guidance
640
- const resourceGuidance = `# System Resource Configuration for Fleet Mode
641
-
642
- ## File Descriptor Limits
643
- For optimal fleet operation with up to 200 worktrees, configure:
644
-
645
- ### macOS / Linux
646
- \`\`\`bash
647
- # Add to ~/.zshrc or ~/.bashrc
648
- ulimit -n 65000
649
- \`\`\`
650
-
651
- ### Persistent Configuration (macOS)
652
- \`\`\`bash
653
- # Create /Library/LaunchDaemons/limit.maxfiles.plist with:
654
- # soft limit: 65000
655
- # hard limit: 200000
656
- \`\`\`
657
-
658
- ### Persistent Configuration (Linux)
659
- \`\`\`bash
660
- # Add to /etc/security/limits.conf
661
- * soft nofile 65000
662
- * hard nofile 200000
663
- \`\`\`
664
-
665
- ## Disk Space Requirements
666
- - Minimum: 500GB SSD
667
- - Recommended: 4TB+ SSD (for 200 worktrees at ~2GB each)
668
- - Buffer: Keep 10GB free at all times
669
-
670
- ## Git Worktree Best Practices
671
- - Session Managers sync with remote (fetch/pull)
672
- - Sub-Agents rarely git fetch (reduces index lock contention)
673
- - Use fractional worktree pattern:
674
- - Read-only agents: Share Session Manager's worktree
675
- - Write-access agents: Get dedicated worktrees
676
-
677
- ## Monitoring Commands
678
- \`\`\`bash
679
- # Check current file descriptor limit
680
- ulimit -n
681
-
682
- # Check open files
683
- lsof | wc -l
684
-
685
- # Check disk space
686
- df -h
687
-
688
- # List active worktrees
689
- git worktree list
690
- \`\`\`
691
- `;
692
- await fs.writeFile(path.join(wundrDir, 'RESOURCE_LIMITS.md'), resourceGuidance, 'utf-8');
693
- console.log(chalk_1.default.green(' ✓ System resource limits guidance configured'));
694
- console.log(chalk_1.default.cyan('\n✅ Fleet-Scale Autonomous Engineering mode setup complete!\n'));
695
- console.log(chalk_1.default.white('Files created:'));
696
- console.log(chalk_1.default.gray(' ~/.wundr/orchestrator-daemon/config.yaml'));
697
- console.log(chalk_1.default.gray(' ~/.wundr/orchestrator-daemon/orchestrator-charter.md'));
698
- console.log(chalk_1.default.gray(' ~/.wundr/orchestrator-daemon/token-budget.yaml'));
699
- console.log(chalk_1.default.gray(' ~/.wundr/templates/memory-bank/'));
700
- console.log(chalk_1.default.gray(' ~/.wundr/governance/ipre-defaults.yaml'));
701
- console.log(chalk_1.default.gray(' ~/.wundr/RESOURCE_LIMITS.md'));
702
- console.log(chalk_1.default.yellow('\n⚠️ Review ~/.wundr/RESOURCE_LIMITS.md for system configuration recommendations.'));
703
- }
704
- /**
705
- * Simple YAML generator for configuration objects
706
- */
707
- function generateYamlContent(obj, indent = 0) {
708
- let yaml = '';
709
- const spaces = ' '.repeat(indent);
710
- for (const [key, value] of Object.entries(obj)) {
711
- if (value === null || value === undefined) {
712
- yaml += `${spaces}${key}: null\n`;
713
- }
714
- else if (typeof value === 'object' && !Array.isArray(value)) {
715
- yaml += `${spaces}${key}:\n`;
716
- yaml += generateYamlContent(value, indent + 1);
717
- }
718
- else if (Array.isArray(value)) {
719
- yaml += `${spaces}${key}:\n`;
720
- for (const item of value) {
721
- if (typeof item === 'object') {
722
- yaml += `${spaces} -\n`;
723
- const itemYaml = generateYamlContent(item, indent + 2);
724
- yaml += itemYaml;
725
- }
726
- else {
727
- yaml += `${spaces} - '${item}'\n`;
728
- }
729
- }
730
- }
731
- else if (typeof value === 'string') {
732
- yaml += `${spaces}${key}: '${value}'\n`;
733
- }
734
- else {
735
- yaml += `${spaces}${key}: ${value}\n`;
736
- }
737
- }
738
- return yaml;
739
- }
740
- async function manageProfiles() {
741
- const manager = new computer_setup_1.ComputerSetupManager();
742
- await manager.initialize();
743
- const profiles = await manager.getAvailableProfiles();
744
- console.log(chalk_1.default.cyan('\n📋 Developer Profiles\n'));
745
- if (profiles.length === 0) {
746
- console.log(chalk_1.default.yellow('No profiles found. Create one with "wundr computer-setup"'));
747
- return;
748
- }
749
- profiles.forEach((profile, i) => {
750
- console.log(chalk_1.default.white(`${i + 1}. ${profile.name}`));
751
- console.log(chalk_1.default.gray(` Role: ${profile.role}`));
752
- console.log(chalk_1.default.gray(` Email: ${profile.email}`));
753
- if (profile.team) {
754
- console.log(chalk_1.default.gray(` Team: ${profile.team}`));
755
- }
756
- });
757
- }
758
- async function validateSetup() {
759
- const spinner = (0, ora_1.default)('Validating machine setup...').start();
760
- try {
761
- const manager = new computer_setup_1.ComputerSetupManager();
762
- await manager.initialize();
763
- // Get current profile
764
- const profiles = await manager.getAvailableProfiles();
765
- if (profiles.length === 0) {
766
- spinner.stop();
767
- console.log(chalk_1.default.yellow('No profile found. Run "wundr computer-setup" first.'));
768
- return;
769
- }
770
- const profile = profiles[0]; // Use most recent
771
- if (!profile) {
772
- console.log(chalk_1.default.yellow('No profile found. Run "wundr computer-setup" first.'));
773
- return;
774
- }
775
- const isValid = await manager.validateSetup(profile);
776
- spinner.stop();
777
- if (isValid) {
778
- console.log(chalk_1.default.green('✅ Machine setup is valid!'));
779
- }
780
- else {
781
- console.log(chalk_1.default.red('❌ Machine setup has issues'));
782
- console.log(chalk_1.default.yellow('\nRun "wundr computer-setup doctor" to diagnose and fix issues'));
783
- }
784
- }
785
- catch (error) {
786
- spinner.stop();
787
- console.error(chalk_1.default.red('Validation failed:'), error);
788
- }
789
- }
790
- async function runDoctor() {
791
- console.log(chalk_1.default.cyan('\n🏥 Computer Setup Doctor\n'));
792
- console.log(chalk_1.default.gray('Diagnosing your machine setup...\n'));
793
- const checks = [
794
- { name: 'Node.js', command: 'node --version', required: true },
795
- { name: 'npm', command: 'npm --version', required: true },
796
- { name: 'pnpm', command: 'pnpm --version', required: false },
797
- { name: 'Git', command: 'git --version', required: true },
798
- { name: 'Docker', command: 'docker --version', required: false },
799
- { name: 'Claude Code', command: 'claude --version', required: false },
800
- { name: 'GitHub CLI', command: 'gh --version', required: false },
801
- ];
802
- for (const check of checks) {
803
- const spinner = (0, ora_1.default)(`Checking ${check.name}...`).start();
804
- try {
805
- const { execa } = (await Promise.resolve().then(() => tslib_1.__importStar(require('execa'))));
806
- const { stdout } = await execa(check.command.split(' ')[0], check.command.split(' ').slice(1));
807
- spinner.succeed(`${check.name}: ${stdout.trim()}`);
808
- }
809
- catch (error) {
810
- if (check.required) {
811
- spinner.fail(`${check.name}: Not found (REQUIRED)`);
812
- }
813
- else {
814
- spinner.warn(`${check.name}: Not found (optional)`);
815
- }
816
- }
817
- }
818
- console.log(chalk_1.default.cyan('\n💊 Recommendations:\n'));
819
- console.log('1. Install missing required tools');
820
- console.log('2. Run "wundr computer-setup" to complete setup');
821
- console.log('3. Check PATH environment variable');
822
- }
823
- async function applyTeamConfig(team) {
824
- console.log(chalk_1.default.cyan(`\n👥 Applying team configuration: ${team}\n`));
825
- const spinner = (0, ora_1.default)('Downloading team configuration...').start();
826
- try {
827
- // This would fetch team config from a central repository
828
- // For now, we'll simulate it
829
- await new Promise(resolve => setTimeout(resolve, 2000));
830
- spinner.succeed('Team configuration downloaded');
831
- console.log(chalk_1.default.green('✅ Team configuration applied successfully!'));
832
- console.log(chalk_1.default.cyan('\nTeam tools installed:'));
833
- console.log(' - Internal CLI tools');
834
- console.log(' - Team-specific VS Code extensions');
835
- console.log(' - Pre-commit hooks');
836
- console.log(' - Team aliases and scripts');
837
- }
838
- catch (error) {
839
- spinner.fail('Failed to apply team configuration');
840
- console.error(chalk_1.default.red('Error:'), error);
841
- }
842
- }
843
- function generateProgressBar(percentage) {
844
- const width = 30;
845
- const filled = Math.round((width * percentage) / 100);
846
- const empty = width - filled;
847
- return '█'.repeat(filled) + '░'.repeat(empty);
848
- }
849
- //# sourceMappingURL=computer-setup.js.map