aios-core 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.aios-core/cli/commands/migrate/analyze.js +6 -6
  2. package/.aios-core/cli/commands/migrate/backup.js +2 -2
  3. package/.aios-core/cli/commands/migrate/execute.js +4 -4
  4. package/.aios-core/cli/commands/migrate/index.js +5 -5
  5. package/.aios-core/cli/commands/migrate/rollback.js +6 -6
  6. package/.aios-core/cli/commands/migrate/update-imports.js +2 -2
  7. package/.aios-core/cli/commands/migrate/validate.js +2 -2
  8. package/.aios-core/cli/commands/pro/index.js +52 -0
  9. package/.aios-core/cli/index.js +1 -1
  10. package/.aios-core/core/ids/registry-updater.js +29 -3
  11. package/.aios-core/core/migration/migration-config.yaml +2 -2
  12. package/.aios-core/core/migration/module-mapping.yaml +2 -2
  13. package/.aios-core/core/registry/README.md +2 -2
  14. package/.aios-core/core/synapse/context/context-builder.js +34 -0
  15. package/.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
  16. package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
  17. package/.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
  18. package/.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
  19. package/.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
  20. package/.aios-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
  21. package/.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
  22. package/.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
  23. package/.aios-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
  24. package/.aios-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
  25. package/.aios-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
  26. package/.aios-core/core/synapse/diagnostics/report-formatter.js +484 -0
  27. package/.aios-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
  28. package/.aios-core/core/synapse/engine.js +73 -20
  29. package/.aios-core/core/synapse/runtime/hook-runtime.js +60 -0
  30. package/.aios-core/core-config.yaml +6 -0
  31. package/.aios-core/data/agent-config-requirements.yaml +2 -2
  32. package/.aios-core/data/aios-kb.md +4 -4
  33. package/.aios-core/data/entity-registry.yaml +5 -5
  34. package/.aios-core/development/agents/architect.md +10 -10
  35. package/.aios-core/development/agents/devops.md +93 -50
  36. package/.aios-core/development/agents/qa.md +94 -40
  37. package/.aios-core/development/agents/ux-design-expert.md +25 -25
  38. package/.aios-core/development/scripts/activation-runtime.js +63 -0
  39. package/.aios-core/development/scripts/generate-greeting.js +9 -8
  40. package/.aios-core/development/scripts/unified-activation-pipeline.js +102 -2
  41. package/.aios-core/development/tasks/{db-expansion-pack-integration.md → db-squad-integration.md} +5 -5
  42. package/.aios-core/development/tasks/{integrate-expansion-pack.md → integrate-squad.md} +2 -2
  43. package/.aios-core/development/tasks/next.md +3 -3
  44. package/.aios-core/development/tasks/pr-automation.md +2 -2
  45. package/.aios-core/development/tasks/publish-npm.md +257 -0
  46. package/.aios-core/development/tasks/release-management.md +4 -4
  47. package/.aios-core/development/tasks/setup-github.md +1 -1
  48. package/.aios-core/development/tasks/squad-creator-migrate.md +1 -1
  49. package/.aios-core/development/tasks/squad-creator-sync-ide-command.md +14 -14
  50. package/.aios-core/development/tasks/update-aios.md +1 -1
  51. package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +1 -1
  52. package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +5 -5
  53. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +21 -21
  54. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +25 -25
  55. package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +4 -4
  56. package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +3 -3
  57. package/.aios-core/docs/standards/STANDARDS-INDEX.md +13 -13
  58. package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +1 -1
  59. package/.aios-core/framework-config.yaml +4 -0
  60. package/.aios-core/infrastructure/scripts/codex-skills-sync/index.js +182 -0
  61. package/.aios-core/infrastructure/scripts/codex-skills-sync/validate.js +172 -0
  62. package/.aios-core/infrastructure/scripts/ide-sync/README.md +14 -0
  63. package/.aios-core/infrastructure/scripts/ide-sync/index.js +6 -0
  64. package/.aios-core/infrastructure/scripts/tool-resolver.js +4 -4
  65. package/.aios-core/infrastructure/scripts/validate-paths.js +142 -0
  66. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +11 -11
  67. package/.aios-core/infrastructure/templates/github-workflows/README.md +1 -1
  68. package/.aios-core/install-manifest.yaml +190 -106
  69. package/.aios-core/local-config.yaml.template +2 -0
  70. package/.aios-core/product/README.md +2 -2
  71. package/.aios-core/product/data/integration-patterns.md +1 -1
  72. package/.aios-core/product/templates/ide-rules/cline-rules.md +1 -1
  73. package/.aios-core/product/templates/ide-rules/codex-rules.md +65 -0
  74. package/.aios-core/product/templates/ide-rules/copilot-rules.md +1 -1
  75. package/.aios-core/product/templates/ide-rules/roo-rules.md +1 -1
  76. package/.aios-core/user-guide.md +15 -14
  77. package/.aios-core/workflow-intelligence/engine/output-formatter.js +1 -1
  78. package/.claude/hooks/enforce-architecture-first.py +196 -0
  79. package/.claude/hooks/install-hooks.sh +41 -0
  80. package/.claude/hooks/mind-clone-governance.py +192 -0
  81. package/.claude/hooks/pre-commit-mmos-guard.sh +99 -0
  82. package/.claude/hooks/pre-commit-version-check.sh +156 -0
  83. package/.claude/hooks/read-protection.py +151 -0
  84. package/.claude/hooks/slug-validation.py +176 -0
  85. package/.claude/hooks/sql-governance.py +182 -0
  86. package/.claude/hooks/synapse-engine.js +9 -20
  87. package/.claude/hooks/write-path-validation.py +194 -0
  88. package/README.md +44 -14
  89. package/bin/aios-init.js +255 -184
  90. package/bin/aios-minimal.js +2 -2
  91. package/bin/aios.js +19 -19
  92. package/package.json +7 -4
  93. package/packages/aios-pro-cli/bin/aios-pro.js +75 -2
  94. package/packages/aios-pro-cli/package.json +5 -1
  95. package/packages/aios-pro-cli/src/recover.js +100 -0
  96. package/packages/installer/src/__tests__/performance-benchmark.js +382 -0
  97. package/packages/installer/src/config/ide-configs.js +12 -1
  98. package/packages/installer/src/config/templates/core-config-template.js +2 -2
  99. package/packages/installer/src/installer/aios-core-installer.js +2 -2
  100. package/packages/installer/src/installer/file-hasher.js +97 -0
  101. package/packages/installer/src/installer/post-install-validator.js +41 -1
  102. package/packages/installer/src/pro/pro-scaffolder.js +335 -0
  103. package/packages/installer/src/utils/aios-colors.js +2 -2
  104. package/packages/installer/src/wizard/feedback.js +1 -1
  105. package/packages/installer/src/wizard/ide-config-generator.js +2 -2
  106. package/packages/installer/src/wizard/index.js +58 -19
  107. package/packages/installer/src/wizard/pro-setup.js +547 -0
  108. package/packages/installer/src/wizard/questions.js +20 -14
  109. package/packages/installer/src/wizard/validators.js +1 -1
  110. package/scripts/package-synapse.js +323 -0
  111. package/scripts/validate-package-completeness.js +317 -0
@@ -0,0 +1,547 @@
1
+ /**
2
+ * Pro Installation Wizard with License Gate
3
+ *
4
+ * 3-step wizard: (1) License Gate, (2) Install/Scaffold, (3) Verify
5
+ * Supports interactive mode, CI mode (AIOS_PRO_KEY env var), and lazy import.
6
+ *
7
+ * @module wizard/pro-setup
8
+ * @story INS-3.2 — Implement Pro Installation Wizard with License Gate
9
+ */
10
+
11
+ 'use strict';
12
+
13
+ const { createSpinner, showSuccess, showError, showWarning, showInfo } = require('./feedback');
14
+ const { colors, headings, status } = require('../utils/aios-colors');
15
+
16
+ /**
17
+ * Gold color for Pro branding.
18
+ * Falls back gracefully if chalk hex is unavailable.
19
+ */
20
+ let gold;
21
+ try {
22
+ const chalk = require('chalk');
23
+ gold = chalk.hex('#FFD700').bold;
24
+ } catch {
25
+ gold = (text) => text;
26
+ }
27
+
28
+ /**
29
+ * License key format: PRO-XXXX-XXXX-XXXX-XXXX
30
+ */
31
+ const LICENSE_KEY_PATTERN = /^PRO-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/;
32
+
33
+ /**
34
+ * Maximum retry attempts for license validation.
35
+ */
36
+ const MAX_RETRIES = 3;
37
+
38
+ /**
39
+ * Detect CI environment.
40
+ *
41
+ * @returns {boolean} true if running in CI or non-interactive terminal
42
+ */
43
+ function isCIEnvironment() {
44
+ return process.env.CI === 'true' || !process.stdout.isTTY;
45
+ }
46
+
47
+ /**
48
+ * Mask a license key for safe display.
49
+ * Shows first and last segments, masks middle two.
50
+ * Example: PRO-ABCD-****-****-WXYZ
51
+ *
52
+ * @param {string} key - License key
53
+ * @returns {string} Masked key
54
+ */
55
+ function maskLicenseKey(key) {
56
+ if (!key || typeof key !== 'string') {
57
+ return '****';
58
+ }
59
+
60
+ const trimmed = key.trim().toUpperCase();
61
+
62
+ if (!LICENSE_KEY_PATTERN.test(trimmed)) {
63
+ return '****';
64
+ }
65
+
66
+ const parts = trimmed.split('-');
67
+ return `${parts[0]}-${parts[1]}-****-****-${parts[4]}`;
68
+ }
69
+
70
+ /**
71
+ * Validate license key format before sending to API.
72
+ *
73
+ * @param {string} key - License key
74
+ * @returns {boolean} true if format is valid
75
+ */
76
+ function validateKeyFormat(key) {
77
+ if (!key || typeof key !== 'string') {
78
+ return false;
79
+ }
80
+ return LICENSE_KEY_PATTERN.test(key.trim().toUpperCase());
81
+ }
82
+
83
+ /**
84
+ * Show the Pro branding header.
85
+ */
86
+ function showProHeader() {
87
+ console.log('');
88
+ console.log(gold(' ╔══════════════════════════════════════════════╗'));
89
+ console.log(gold(' ║ AIOS Pro Installation Wizard ║'));
90
+ console.log(gold(' ║ Premium Content & Features ║'));
91
+ console.log(gold(' ╚══════════════════════════════════════════════╝'));
92
+ console.log('');
93
+ }
94
+
95
+ /**
96
+ * Show step indicator.
97
+ *
98
+ * @param {number} current - Current step (1-based)
99
+ * @param {number} total - Total steps
100
+ * @param {string} label - Step label
101
+ */
102
+ function showStep(current, total, label) {
103
+ const progress = `[${current}/${total}]`;
104
+ console.log(gold(`\n ${progress} ${label}`));
105
+ console.log(colors.dim(' ' + '─'.repeat(44)));
106
+ }
107
+
108
+ /**
109
+ * Try to load the license API client via lazy import.
110
+ *
111
+ * @returns {{ LicenseApiClient: Function, licenseApi: Object }|null} License API or null
112
+ */
113
+ function loadLicenseApi() {
114
+ try {
115
+ return require('../../../../pro/license/license-api');
116
+ } catch {
117
+ return null;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Try to load the feature gate via lazy import.
123
+ *
124
+ * @returns {{ featureGate: Object }|null} Feature gate or null
125
+ */
126
+ function loadFeatureGate() {
127
+ try {
128
+ return require('../../../../pro/license/feature-gate');
129
+ } catch {
130
+ return null;
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Try to load the pro scaffolder via lazy import.
136
+ *
137
+ * @returns {{ scaffoldProContent: Function }|null} Scaffolder or null
138
+ */
139
+ function loadProScaffolder() {
140
+ try {
141
+ return require('../pro/pro-scaffolder');
142
+ } catch {
143
+ return null;
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Step 1: License Gate — validate license key.
149
+ *
150
+ * In CI mode, reads from AIOS_PRO_KEY env var.
151
+ * In interactive mode, prompts with masked input.
152
+ *
153
+ * @param {Object} [options={}] - Options
154
+ * @param {string} [options.key] - Pre-provided key (from CLI args or env)
155
+ * @returns {Promise<Object>} Result with { success, key, activationResult }
156
+ */
157
+ async function stepLicenseGate(options = {}) {
158
+ showStep(1, 3, 'License Validation');
159
+
160
+ const isCI = isCIEnvironment();
161
+ let key = options.key || null;
162
+
163
+ // CI mode: read from env var
164
+ if (!key && isCI) {
165
+ key = process.env.AIOS_PRO_KEY || null;
166
+
167
+ if (!key) {
168
+ return {
169
+ success: false,
170
+ error: 'CI mode: AIOS_PRO_KEY environment variable not set.',
171
+ };
172
+ }
173
+ }
174
+
175
+ // Interactive mode: prompt for key
176
+ if (!key && !isCI) {
177
+ const inquirer = require('inquirer');
178
+
179
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
180
+ const { licenseKey } = await inquirer.prompt([
181
+ {
182
+ type: 'password',
183
+ name: 'licenseKey',
184
+ message: colors.primary('Enter your Pro license key:'),
185
+ mask: '*',
186
+ validate: (input) => {
187
+ if (!input || !input.trim()) {
188
+ return 'License key is required';
189
+ }
190
+ if (!validateKeyFormat(input)) {
191
+ return 'Invalid format. Expected: PRO-XXXX-XXXX-XXXX-XXXX';
192
+ }
193
+ return true;
194
+ },
195
+ },
196
+ ]);
197
+
198
+ key = licenseKey.trim().toUpperCase();
199
+
200
+ // Validate with API
201
+ const result = await validateKeyWithApi(key);
202
+
203
+ if (result.success) {
204
+ showSuccess(`License validated: ${maskLicenseKey(key)}`);
205
+ return { success: true, key, activationResult: result.data };
206
+ }
207
+
208
+ // Show error and retry
209
+ const remaining = MAX_RETRIES - attempt;
210
+ if (remaining > 0) {
211
+ showError(`${result.error} (${remaining} attempt${remaining > 1 ? 's' : ''} remaining)`);
212
+ } else {
213
+ showError(`${result.error} — no attempts remaining.`);
214
+ return { success: false, error: result.error };
215
+ }
216
+ }
217
+ }
218
+
219
+ // Validate key format
220
+ if (!validateKeyFormat(key)) {
221
+ return {
222
+ success: false,
223
+ error: `Invalid key format: ${maskLicenseKey(key)}. Expected: PRO-XXXX-XXXX-XXXX-XXXX`,
224
+ };
225
+ }
226
+
227
+ // Validate with API
228
+ const spinner = createSpinner(`Validating license ${maskLicenseKey(key)}...`);
229
+ spinner.start();
230
+
231
+ const result = await validateKeyWithApi(key);
232
+
233
+ if (result.success) {
234
+ spinner.succeed(`License validated: ${maskLicenseKey(key)}`);
235
+ return { success: true, key, activationResult: result.data };
236
+ }
237
+
238
+ spinner.fail(result.error);
239
+ return { success: false, error: result.error };
240
+ }
241
+
242
+ /**
243
+ * Validate a key against the license API.
244
+ *
245
+ * @param {string} key - License key
246
+ * @returns {Promise<Object>} Result with { success, data?, error? }
247
+ */
248
+ async function validateKeyWithApi(key) {
249
+ // Use exports._testing for testability (allows mock injection)
250
+ const loader = module.exports._testing ? module.exports._testing.loadLicenseApi : loadLicenseApi;
251
+ const licenseModule = loader();
252
+
253
+ if (!licenseModule) {
254
+ return {
255
+ success: false,
256
+ error: 'Pro license module not available. Ensure @aios-fullstack/pro is installed.',
257
+ };
258
+ }
259
+
260
+ const { LicenseApiClient } = licenseModule;
261
+ const client = new LicenseApiClient();
262
+
263
+ try {
264
+ // Check if API is reachable
265
+ const online = await client.isOnline();
266
+
267
+ if (!online) {
268
+ return {
269
+ success: false,
270
+ error: 'License server is unreachable. Check your internet connection and try again.',
271
+ };
272
+ }
273
+
274
+ // Generate a simple machine fingerprint
275
+ const os = require('os');
276
+ const crypto = require('crypto');
277
+ const machineId = crypto
278
+ .createHash('sha256')
279
+ .update(`${os.hostname()}-${os.platform()}-${os.arch()}`)
280
+ .digest('hex')
281
+ .substring(0, 32);
282
+
283
+ // Read aios-core version
284
+ let aiosCoreVersion = 'unknown';
285
+ try {
286
+ const path = require('path');
287
+ const fs = require('fs');
288
+ const pkgPath = path.join(__dirname, '..', '..', '..', '..', 'package.json');
289
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
290
+ aiosCoreVersion = pkg.version || 'unknown';
291
+ } catch {
292
+ // Keep 'unknown'
293
+ }
294
+
295
+ const activationResult = await client.activate(key, machineId, aiosCoreVersion);
296
+
297
+ return { success: true, data: activationResult };
298
+ } catch (error) {
299
+ // Handle specific error codes from license-api
300
+ if (error.code === 'INVALID_KEY') {
301
+ return { success: false, error: 'Invalid license key.' };
302
+ }
303
+ if (error.code === 'EXPIRED_KEY') {
304
+ return { success: false, error: 'License key has expired.' };
305
+ }
306
+ if (error.code === 'SEAT_LIMIT_EXCEEDED') {
307
+ return { success: false, error: 'Maximum activations reached for this key.' };
308
+ }
309
+ if (error.code === 'RATE_LIMITED') {
310
+ return { success: false, error: 'Too many requests. Please wait and try again.' };
311
+ }
312
+ if (error.code === 'NETWORK_ERROR') {
313
+ return {
314
+ success: false,
315
+ error: 'License server is unreachable. Check your internet connection and try again.',
316
+ };
317
+ }
318
+
319
+ return {
320
+ success: false,
321
+ error: `License validation failed: ${error.message || 'Unknown error'}`,
322
+ };
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Step 2: Install/Scaffold — copy pro content into the project.
328
+ *
329
+ * @param {string} targetDir - Project root directory
330
+ * @param {Object} [options={}] - Options
331
+ * @returns {Promise<Object>} Result with { success, scaffoldResult }
332
+ */
333
+ async function stepInstallScaffold(targetDir, options = {}) {
334
+ showStep(2, 3, 'Pro Content Installation');
335
+
336
+ const scaffolderModule = loadProScaffolder();
337
+
338
+ if (!scaffolderModule) {
339
+ showWarning('Pro scaffolder not available. Ensure @aios-fullstack/pro is installed.');
340
+ return { success: false, error: 'Pro scaffolder module not found.' };
341
+ }
342
+
343
+ const { scaffoldProContent } = scaffolderModule;
344
+ const path = require('path');
345
+
346
+ // Determine pro source directory
347
+ const proSourceDir = path.join(targetDir, 'node_modules', '@aios-fullstack', 'pro');
348
+
349
+ const spinner = createSpinner('Scaffolding pro content...');
350
+ spinner.start();
351
+
352
+ try {
353
+ const scaffoldResult = await scaffoldProContent(targetDir, proSourceDir, {
354
+ onProgress: (progress) => {
355
+ spinner.text = `Scaffolding: ${progress.message}`;
356
+ },
357
+ force: options.force || false,
358
+ });
359
+
360
+ if (scaffoldResult.success) {
361
+ spinner.succeed(`Pro content installed (${scaffoldResult.copiedFiles.length} files)`);
362
+
363
+ if (scaffoldResult.warnings.length > 0) {
364
+ for (const warning of scaffoldResult.warnings) {
365
+ showWarning(warning);
366
+ }
367
+ }
368
+
369
+ return { success: true, scaffoldResult };
370
+ }
371
+
372
+ spinner.fail('Scaffolding failed');
373
+ for (const error of scaffoldResult.errors) {
374
+ showError(error);
375
+ }
376
+
377
+ return { success: false, error: scaffoldResult.errors.join('; '), scaffoldResult };
378
+ } catch (error) {
379
+ spinner.fail(`Scaffolding error: ${error.message}`);
380
+ return { success: false, error: error.message };
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Step 3: Verify — check installed pro content and list features.
386
+ *
387
+ * @param {Object} [scaffoldResult] - Result from step 2
388
+ * @returns {Promise<Object>} Verification result
389
+ */
390
+ async function stepVerify(scaffoldResult) {
391
+ showStep(3, 3, 'Verification');
392
+
393
+ const result = {
394
+ success: true,
395
+ features: [],
396
+ squads: [],
397
+ configs: [],
398
+ };
399
+
400
+ // Show scaffolded content summary
401
+ if (scaffoldResult && scaffoldResult.copiedFiles) {
402
+ const files = scaffoldResult.copiedFiles;
403
+
404
+ // Categorize files
405
+ result.squads = files.filter((f) => f.startsWith('squads/'));
406
+ result.configs = files.filter(
407
+ (f) => f.endsWith('.yaml') || f.endsWith('.json'),
408
+ );
409
+
410
+ showInfo(`Files installed: ${files.length}`);
411
+
412
+ if (result.squads.length > 0) {
413
+ // Extract unique squad names
414
+ const squadNames = [...new Set(
415
+ result.squads
416
+ .map((f) => f.split('/')[1])
417
+ .filter(Boolean),
418
+ )];
419
+ showSuccess(`Squads: ${squadNames.join(', ')}`);
420
+ }
421
+
422
+ if (result.configs.length > 0) {
423
+ showSuccess(`Configs: ${result.configs.length} files`);
424
+ }
425
+ }
426
+
427
+ // Check feature gate if available
428
+ const featureModule = loadFeatureGate();
429
+
430
+ if (featureModule) {
431
+ const { featureGate } = featureModule;
432
+ featureGate.reload();
433
+
434
+ const available = featureGate.listAvailable();
435
+ result.features = available;
436
+
437
+ if (available.length > 0) {
438
+ showSuccess(`Features unlocked: ${available.length}`);
439
+ for (const feature of available.slice(0, 5)) {
440
+ console.log(colors.dim(` ${feature}`));
441
+ }
442
+ if (available.length > 5) {
443
+ console.log(colors.dim(` ... and ${available.length - 5} more`));
444
+ }
445
+ }
446
+ }
447
+
448
+ // Final status
449
+ console.log('');
450
+ console.log(gold(' ════════════════════════════════════════════════'));
451
+ console.log(status.celebrate('AIOS Pro installation complete!'));
452
+ console.log(gold(' ════════════════════════════════════════════════'));
453
+ console.log('');
454
+
455
+ return result;
456
+ }
457
+
458
+ /**
459
+ * Run the full Pro Installation Wizard.
460
+ *
461
+ * Main entry point. Orchestrates the 3-step flow:
462
+ * 1. License Gate (validate key)
463
+ * 2. Install/Scaffold (copy pro content)
464
+ * 3. Verify (list installed features)
465
+ *
466
+ * @param {Object} [options={}] - Wizard options
467
+ * @param {string} [options.key] - Pre-provided license key
468
+ * @param {string} [options.targetDir] - Project root (default: process.cwd())
469
+ * @param {boolean} [options.force] - Force overwrite existing content
470
+ * @param {boolean} [options.quiet] - Suppress non-essential output
471
+ * @returns {Promise<Object>} Wizard result
472
+ */
473
+ async function runProWizard(options = {}) {
474
+ const targetDir = options.targetDir || process.cwd();
475
+ const isCI = isCIEnvironment();
476
+
477
+ const result = {
478
+ success: false,
479
+ licenseValidated: false,
480
+ scaffolded: false,
481
+ verified: false,
482
+ };
483
+
484
+ // Show branding (skip in CI or quiet mode)
485
+ if (!isCI && !options.quiet) {
486
+ showProHeader();
487
+ }
488
+
489
+ // Step 1: License Gate
490
+ const licenseResult = await stepLicenseGate({
491
+ key: options.key || process.env.AIOS_PRO_KEY,
492
+ });
493
+
494
+ if (!licenseResult.success) {
495
+ showError(licenseResult.error);
496
+
497
+ if (!isCI) {
498
+ showInfo('Need help? Run: npx aios-pro recover');
499
+ }
500
+
501
+ result.error = licenseResult.error;
502
+ return result;
503
+ }
504
+
505
+ result.licenseValidated = true;
506
+
507
+ // Step 2: Install/Scaffold
508
+ const scaffoldResult = await stepInstallScaffold(targetDir, {
509
+ force: options.force,
510
+ });
511
+
512
+ if (!scaffoldResult.success) {
513
+ result.error = scaffoldResult.error;
514
+ return result;
515
+ }
516
+
517
+ result.scaffolded = true;
518
+
519
+ // Step 3: Verify
520
+ const verifyResult = await stepVerify(scaffoldResult.scaffoldResult);
521
+ result.verified = verifyResult.success;
522
+ result.features = verifyResult.features;
523
+ result.squads = verifyResult.squads;
524
+ result.success = true;
525
+
526
+ return result;
527
+ }
528
+
529
+ module.exports = {
530
+ runProWizard,
531
+ stepLicenseGate,
532
+ stepInstallScaffold,
533
+ stepVerify,
534
+ maskLicenseKey,
535
+ validateKeyFormat,
536
+ isCIEnvironment,
537
+ showProHeader,
538
+ // Internal helpers exported for testing
539
+ _testing: {
540
+ validateKeyWithApi,
541
+ loadLicenseApi,
542
+ loadFeatureGate,
543
+ loadProScaffolder,
544
+ MAX_RETRIES,
545
+ LICENSE_KEY_PATTERN,
546
+ },
547
+ };
@@ -186,26 +186,30 @@ function getEnvironmentQuestions() {
186
186
  }
187
187
 
188
188
  /**
189
- * Get Expansion Pack selection questions
189
+ * Get Squad selection questions
190
190
  *
191
- * Available expansion packs for v2.1:
192
- * - expansion-creator: Tools to create custom expansion packs
191
+ * Available squads for v4.0:
192
+ * - squad-creator: Tools to create custom squads
193
193
  * - etl: ETL pipeline for knowledge base creation
194
194
  *
195
+ * Note: This function is currently DISABLED. Squad selection is handled
196
+ * directly in aios-init.js using the squads/ directory.
197
+ *
195
198
  * @returns {Object[]} Array of inquirer question objects
199
+ * @deprecated Use squads/ directory directly in aios-init.js
196
200
  */
197
- function getExpansionPackQuestions() {
201
+ function getSquadQuestions() {
198
202
  return [
199
203
  {
200
204
  type: 'checkbox',
201
- name: 'selectedExpansionPacks',
202
- message: colors.primary('Select Expansion Packs to install (optional):'),
205
+ name: 'selectedSquads',
206
+ message: colors.primary('Select Squads to install (optional):'),
203
207
  choices: [
204
208
  {
205
209
  name:
206
- colors.highlight('expansion-creator') +
207
- colors.dim(' - Tools to create custom expansion packs'),
208
- value: 'expansion-creator',
210
+ colors.highlight('squad-creator') +
211
+ colors.dim(' - Tools to create custom squads'),
212
+ value: 'squad-creator',
209
213
  checked: false,
210
214
  },
211
215
  {
@@ -215,7 +219,7 @@ function getExpansionPackQuestions() {
215
219
  },
216
220
  ],
217
221
  validate: () => {
218
- // Allow empty selection (user can skip expansion pack installation)
222
+ // Allow empty selection (user can skip squad installation)
219
223
  return true;
220
224
  },
221
225
  },
@@ -277,9 +281,9 @@ function buildQuestionSequence(_context = {}) {
277
281
  // TODO: Remove entirely in future version - each project has unique MCP needs
278
282
  // questions.push(...getMCPQuestions());
279
283
 
280
- // Expansion Pack Selection (v2.1) - DISABLED: Squads replaced expansion-packs (OSR-8)
281
- // TODO: Remove entirely in future version
282
- // questions.push(...getExpansionPackQuestions());
284
+ // Squad Selection - DISABLED: Handled directly in aios-init.js
285
+ // TODO: Consider removing getSquadQuestions() entirely in future version
286
+ // questions.push(...getSquadQuestions());
283
287
 
284
288
  // Tech Preset Selection
285
289
  questions.push(...getTechPresetQuestion());
@@ -320,7 +324,9 @@ module.exports = {
320
324
  getProjectTypeQuestion,
321
325
  getIDEQuestions,
322
326
  getMCPQuestions,
323
- getExpansionPackQuestions,
327
+ getSquadQuestions,
328
+ // Backward compat alias (deprecated)
329
+ getExpansionPackQuestions: getSquadQuestions,
324
330
  getTechPresetQuestion,
325
331
  getEnvironmentQuestions,
326
332
  getPackageManagerQuestion,
@@ -4,7 +4,7 @@
4
4
  * OWASP-compliant validators for all wizard inputs
5
5
  * Protects against: command injection, path traversal, XSS, buffer overflow
6
6
  *
7
- * @see docs/stories/v2.1/sprint-1/story-1.2-interactive-wizard-foundation.md
7
+ * @see docs/stories/v4.0.4/sprint-1/story-1.2-interactive-wizard-foundation.md
8
8
  * @module wizard/validators
9
9
  */
10
10