aiox-core 5.0.7 → 5.0.8

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 (191) hide show
  1. package/.aiox-core/cli/commands/pro/buyer.js +379 -0
  2. package/.aiox-core/cli/commands/pro/index.js +191 -52
  3. package/.aiox-core/cli/commands/validate/index.js +2 -0
  4. package/.aiox-core/core/code-intel/helpers/dev-helper.js +1 -1
  5. package/.aiox-core/core/code-intel/helpers/devops-helper.js +0 -1
  6. package/.aiox-core/core/code-intel/helpers/planning-helper.js +1 -1
  7. package/.aiox-core/core/code-intel/helpers/qa-helper.js +2 -2
  8. package/.aiox-core/core/config/schemas/framework-config.schema.json +1 -0
  9. package/.aiox-core/core/config/template-overrides.js +1 -1
  10. package/.aiox-core/core/doctor/checks/ide-sync.js +81 -25
  11. package/.aiox-core/core/doctor/checks/rules-files.js +0 -1
  12. package/.aiox-core/core/doctor/checks/skills-count.js +83 -15
  13. package/.aiox-core/core/graph-dashboard/cli.js +1 -2
  14. package/.aiox-core/core/graph-dashboard/data-sources/code-intel-source.js +1 -1
  15. package/.aiox-core/core/ids/layer-classifier.js +1 -1
  16. package/.aiox-core/core/pro/pro-updater.js +578 -0
  17. package/.aiox-core/core/synapse/context/context-tracker.js +107 -9
  18. package/.aiox-core/core/synapse/layers/layer-processor.js +1 -1
  19. package/.aiox-core/core-config.yaml +15 -1
  20. package/.aiox-core/data/capability-detection.js +15 -15
  21. package/.aiox-core/data/entity-registry.yaml +18 -2
  22. package/.aiox-core/data/registry-update-log.jsonl +5 -0
  23. package/.aiox-core/data/tok3-token-comparison.js +0 -4
  24. package/.aiox-core/data/tool-search-validation.js +1 -1
  25. package/.aiox-core/development/agents/aiox-master.md +44 -6
  26. package/.aiox-core/development/agents/data-engineer.md +4 -4
  27. package/.aiox-core/development/agents/devops.md +52 -2
  28. package/.aiox-core/development/agents/po.md +1 -1
  29. package/.aiox-core/development/agents/qa.md +5 -11
  30. package/.aiox-core/development/agents/sm.md +3 -3
  31. package/.aiox-core/development/agents/ux-design-expert.md +1 -1
  32. package/.aiox-core/development/scripts/unified-activation-pipeline.js +29 -3
  33. package/.aiox-core/development/tasks/dev-develop-story.md +46 -7
  34. package/.aiox-core/development/tasks/devops-pro-access-grant.md +93 -0
  35. package/.aiox-core/development/tasks/devops-pro-activate.md +42 -0
  36. package/.aiox-core/development/tasks/devops-pro-check-access.md +34 -0
  37. package/.aiox-core/development/tasks/devops-pro-request-reset.md +34 -0
  38. package/.aiox-core/development/tasks/devops-pro-resend-verification.md +32 -0
  39. package/.aiox-core/development/tasks/devops-pro-reset-password.md +36 -0
  40. package/.aiox-core/development/tasks/devops-pro-validate-login.md +36 -0
  41. package/.aiox-core/development/tasks/devops-pro-verify-status.md +33 -0
  42. package/.aiox-core/development/tasks/qa-gate.md +54 -4
  43. package/.aiox-core/development/tasks/validate-next-story.md +39 -2
  44. package/.aiox-core/framework-config.yaml +1 -0
  45. package/.aiox-core/infrastructure/scripts/codex-skills-sync/README.md +69 -0
  46. package/.aiox-core/infrastructure/scripts/codex-skills-sync/bootstrap.js +727 -0
  47. package/.aiox-core/infrastructure/scripts/codex-skills-sync/index.js +10 -0
  48. package/.aiox-core/infrastructure/scripts/codex-skills-sync/validate.js +65 -4
  49. package/.aiox-core/infrastructure/scripts/generate-settings-json.js +29 -4
  50. package/.aiox-core/infrastructure/scripts/ide-sync/agent-parser.js +4 -0
  51. package/.aiox-core/infrastructure/scripts/ide-sync/index.js +67 -7
  52. package/.aiox-core/infrastructure/scripts/ide-sync/transformers/claude-code.js +145 -3
  53. package/.aiox-core/infrastructure/scripts/repair-agent-references.js +263 -0
  54. package/.aiox-core/infrastructure/scripts/validate-claude-integration.js +60 -8
  55. package/.aiox-core/infrastructure/scripts/validate-paths.js +13 -0
  56. package/.aiox-core/install-manifest.yaml +134 -82
  57. package/.aiox-core/utils/filters/index.js +2 -1
  58. package/.claude/commands/AIOX/agents/aiox-master.md +21 -0
  59. package/.claude/commands/AIOX/agents/analyst.md +21 -0
  60. package/.claude/commands/AIOX/agents/architect.md +21 -0
  61. package/.claude/commands/AIOX/agents/data-engineer.md +21 -0
  62. package/.claude/commands/AIOX/agents/dev.md +21 -0
  63. package/.claude/commands/AIOX/agents/devops.md +21 -0
  64. package/.claude/commands/AIOX/agents/pm.md +21 -0
  65. package/.claude/commands/AIOX/agents/po.md +21 -0
  66. package/.claude/commands/AIOX/agents/qa.md +21 -0
  67. package/.claude/commands/AIOX/agents/sm.md +21 -0
  68. package/.claude/commands/AIOX/agents/squad-creator.md +21 -0
  69. package/.claude/commands/AIOX/agents/ux-design-expert.md +21 -0
  70. package/.claude/commands/AIOX/scripts/agent-config-loader.js +624 -0
  71. package/.claude/commands/AIOX/scripts/generate-greeting.js +160 -0
  72. package/.claude/commands/AIOX/scripts/greeting-builder.js +866 -0
  73. package/.claude/commands/AIOX/scripts/session-context-loader.js +286 -0
  74. package/.claude/commands/AIOX/stories/story-6.1.4.md +1404 -0
  75. package/.claude/commands/cohort-squad/agents/cohort-manager.md +156 -0
  76. package/.claude/commands/design-system/agents/brad-frost.md +1097 -0
  77. package/.claude/commands/design-system/agents/dan-mall.md +857 -0
  78. package/.claude/commands/design-system/agents/dave-malouf.md +2272 -0
  79. package/.claude/commands/design-system/agents/design-chief.md +102 -0
  80. package/.claude/commands/design-system/agents/nano-banana-generator.md +162 -0
  81. package/.claude/commands/greet.md +101 -0
  82. package/.claude/commands/synapse/manager.md +75 -0
  83. package/.claude/commands/synapse/tasks/add-rule.md +94 -0
  84. package/.claude/commands/synapse/tasks/create-command.md +109 -0
  85. package/.claude/commands/synapse/tasks/create-domain.md +127 -0
  86. package/.claude/commands/synapse/tasks/diagnose-synapse.md +245 -0
  87. package/.claude/commands/synapse/tasks/edit-rule.md +109 -0
  88. package/.claude/commands/synapse/tasks/suggest-domain.md +116 -0
  89. package/.claude/commands/synapse/tasks/toggle-domain.md +83 -0
  90. package/.claude/commands/synapse/templates/domain-template +8 -0
  91. package/.claude/commands/synapse/templates/manifest-entry-template +4 -0
  92. package/.claude/commands/synapse/utils/manifest-parser-reference.md +134 -0
  93. package/.claude/hooks/precompact-session-digest.cjs +2 -2
  94. package/.claude/skills/AIOX/agents/aiox-master/SKILL.md +511 -0
  95. package/.claude/skills/AIOX/agents/analyst/SKILL.md +281 -0
  96. package/.claude/skills/AIOX/agents/architect/SKILL.md +482 -0
  97. package/.claude/skills/AIOX/agents/data-engineer/SKILL.md +503 -0
  98. package/.claude/skills/AIOX/agents/dev/SKILL.md +568 -0
  99. package/.claude/skills/AIOX/agents/devops/SKILL.md +597 -0
  100. package/.claude/skills/AIOX/agents/pm/SKILL.md +385 -0
  101. package/.claude/skills/AIOX/agents/po/SKILL.md +343 -0
  102. package/.claude/skills/AIOX/agents/qa/SKILL.md +451 -0
  103. package/.claude/skills/AIOX/agents/sm/SKILL.md +295 -0
  104. package/.claude/skills/AIOX/agents/squad-creator/SKILL.md +352 -0
  105. package/.claude/skills/AIOX/agents/ux-design-expert/SKILL.md +503 -0
  106. package/.claude/skills/architect-first/SKILL.md +275 -0
  107. package/.claude/skills/architect-first/assets/architecture-template.md +505 -0
  108. package/.claude/skills/architect-first/assets/config-template.yaml +351 -0
  109. package/.claude/skills/architect-first/references/architecture-checklist.md +216 -0
  110. package/.claude/skills/architect-first/references/pre-implementation-checklist.md +119 -0
  111. package/.claude/skills/architect-first/references/stop-rules-guide.md +291 -0
  112. package/.claude/skills/architect-first/references/testing-strategy-guide.md +477 -0
  113. package/.claude/skills/architect-first/scripts/architecture_validator.py +490 -0
  114. package/.claude/skills/architect-first/scripts/check_coupling.py +306 -0
  115. package/.claude/skills/architect-first/scripts/validate_risk_mitigation.py +382 -0
  116. package/.claude/skills/checklist-runner/SKILL.md +113 -0
  117. package/.claude/skills/clone-mind.md +329 -0
  118. package/.claude/skills/coderabbit-review/SKILL.md +106 -0
  119. package/.claude/skills/course-generation-workflow.md +76 -0
  120. package/.claude/skills/enhance-workflow.md +466 -0
  121. package/.claude/skills/mcp-builder/LICENSE.txt +202 -0
  122. package/.claude/skills/mcp-builder/SKILL.md +328 -0
  123. package/.claude/skills/mcp-builder/reference/evaluation.md +602 -0
  124. package/.claude/skills/mcp-builder/reference/mcp_best_practices.md +915 -0
  125. package/.claude/skills/mcp-builder/reference/node_mcp_server.md +916 -0
  126. package/.claude/skills/mcp-builder/reference/python_mcp_server.md +752 -0
  127. package/.claude/skills/mcp-builder/scripts/connections.py +151 -0
  128. package/.claude/skills/mcp-builder/scripts/evaluation.py +373 -0
  129. package/.claude/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  130. package/.claude/skills/mcp-builder/scripts/requirements.txt +2 -0
  131. package/.claude/skills/ralph.md +181 -0
  132. package/.claude/skills/skill-creator/LICENSE.txt +202 -0
  133. package/.claude/skills/skill-creator/SKILL.md +209 -0
  134. package/.claude/skills/skill-creator/scripts/init_skill.py +303 -0
  135. package/.claude/skills/skill-creator/scripts/package_skill.py +110 -0
  136. package/.claude/skills/skill-creator/scripts/quick_validate.py +65 -0
  137. package/.claude/skills/squad.md +301 -0
  138. package/.claude/skills/synapse/SKILL.md +132 -0
  139. package/.claude/skills/synapse/assets/README.md +50 -0
  140. package/.claude/skills/synapse/references/brackets.md +100 -0
  141. package/.claude/skills/synapse/references/commands.md +118 -0
  142. package/.claude/skills/synapse/references/domains.md +126 -0
  143. package/.claude/skills/synapse/references/layers.md +186 -0
  144. package/.claude/skills/synapse/references/manifest.md +142 -0
  145. package/.claude/skills/tech-search/SKILL.md +431 -0
  146. package/.claude/skills/tech-search/prompts/page-extract.md +133 -0
  147. package/README.en.md +2 -2
  148. package/README.md +8 -2
  149. package/bin/aiox.js +55 -4
  150. package/bin/utils/framework-guard.js +4 -2
  151. package/bin/utils/pro-detector.js +119 -28
  152. package/bin/utils/validate-publish.js +6 -6
  153. package/docs/aiox-agent-flows/devops-system.md +18 -0
  154. package/docs/aiox-workflows/README.md +1 -0
  155. package/docs/aiox-workflows/pro-access-grant-workflow.md +218 -0
  156. package/docs/guides/pro/access-grant-ops-playbook.md +370 -0
  157. package/docs/guides/pro/install-gate-setup.md +12 -6
  158. package/docs/guides/pro/squad-creator-handoff-pro-access-ops.md +134 -0
  159. package/docs/guides/supabase-ops-handoff.md +768 -0
  160. package/package.json +12 -1
  161. package/packages/aiox-pro-cli/bin/aiox-pro.js +33 -12
  162. package/packages/installer/src/config/configure-environment.js +118 -50
  163. package/packages/installer/src/installer/aiox-core-installer.js +124 -27
  164. package/packages/installer/src/installer/brownfield-upgrader.js +66 -9
  165. package/packages/installer/src/installer/dependency-installer.js +4 -0
  166. package/packages/installer/src/pro/pro-scaffolder.js +5 -5
  167. package/packages/installer/src/updater/index.js +151 -10
  168. package/packages/installer/src/wizard/ide-config-generator.js +73 -7
  169. package/packages/installer/src/wizard/index.js +119 -31
  170. package/packages/installer/src/wizard/pro-setup.js +118 -47
  171. package/packages/installer/src/wizard/validation/validators/dependency-validator.js +32 -25
  172. package/packages/installer/src/wizard/validation/validators/file-structure-validator.js +26 -0
  173. package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +84 -1
  174. package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +1 -1
  175. package/packages/installer/tests/unit/doctor/doctor-checks.test.js +85 -19
  176. package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +4 -4
  177. package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +5 -5
  178. package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +4 -4
  179. package/packages/installer/tests/unit/merger/yaml-merger.test.js +11 -11
  180. package/pro/README.md +12 -1
  181. package/pro/license/index.js +3 -11
  182. package/pro/license/license-api.js +25 -0
  183. package/pro/license/license-cache.js +135 -31
  184. package/pro/license/license-crypto.js +59 -3
  185. package/pro/package.json +5 -4
  186. package/pro/squads/README.md +16 -16
  187. package/pro/squads/index.js +1 -1
  188. package/scripts/e2e/installed-skills-smoke.js +264 -0
  189. package/scripts/package-synapse.js +3 -3
  190. package/scripts/validate-package-completeness.js +8 -11
  191. package/.aiox-core/lib/build.json +0 -1
@@ -22,7 +22,13 @@ const {
22
22
  const { setLanguage, t } = require('./i18n');
23
23
  const yaml = require('js-yaml');
24
24
  const { showWelcome, showCompletion, showCancellation } = require('./feedback');
25
- const { generateIDEConfigs, showSuccessSummary, copySkillFiles, copyExtraCommandFiles } = require('./ide-config-generator');
25
+ const {
26
+ generateIDEConfigs,
27
+ showSuccessSummary,
28
+ copySkillFiles,
29
+ generateCodexSkills,
30
+ copyExtraCommandFiles,
31
+ } = require('./ide-config-generator');
26
32
  const {
27
33
  configureEnvironment,
28
34
  } = require('../config/configure-environment');
@@ -30,6 +36,7 @@ const {
30
36
  installDependencies,
31
37
  } = require('../installer/dependency-installer');
32
38
  const { commandSync, commandValidate } = require('../../../../.aiox-core/infrastructure/scripts/ide-sync/index');
39
+ const { syncSkills: syncCodexSkills } = require('../../../../.aiox-core/infrastructure/scripts/codex-skills-sync/index');
33
40
  const {
34
41
  installAioxCore,
35
42
  hasPackageJson,
@@ -329,12 +336,43 @@ async function runWizard(options = {}) {
329
336
  }
330
337
  }
331
338
 
339
+ if (options.dryRun) {
340
+ const preview = {
341
+ dryRun: true,
342
+ projectType: answers.projectType,
343
+ selectedIDEs: answers.selectedIDEs || [],
344
+ selectedTechPreset: answers.selectedTechPreset || 'none',
345
+ steps: [
346
+ 'install-aiox-core',
347
+ 'generate-ide-configs',
348
+ 'generate-boundary-rules',
349
+ 'copy-skills-and-commands',
350
+ 'run-ide-sync',
351
+ 'bootstrap-entity-registry',
352
+ 'configure-environment',
353
+ 'install-dependencies',
354
+ 'validate-installation',
355
+ ],
356
+ };
357
+
358
+ if (!options.quiet) {
359
+ console.log('\n🧪 Dry run mode');
360
+ console.log(' No files will be modified.');
361
+ console.log(` Project type: ${preview.projectType}`);
362
+ console.log(` IDEs: ${preview.selectedIDEs.length > 0 ? preview.selectedIDEs.join(', ') : 'none'}`);
363
+ console.log(` Tech preset: ${preview.selectedTechPreset}`);
364
+ }
365
+
366
+ return preview;
367
+ }
368
+
332
369
  // Story 1.4: Install AIOX core framework (agents, tasks, workflows, templates)
333
370
  console.log('\n📦 Installing AIOX core framework...');
334
371
  let aioxCoreResult = null;
335
372
  try {
336
373
  aioxCoreResult = await installAioxCore({
337
374
  targetDir: process.cwd(),
375
+ projectType: answers.projectType || 'greenfield',
338
376
  onProgress: (_status) => {
339
377
  // Silent progress - spinner handles feedback
340
378
  },
@@ -522,6 +560,24 @@ async function runWizard(options = {}) {
522
560
  answers.skillsCopied = 0;
523
561
  }
524
562
 
563
+ // Local-first Codex flow: generate project-local /skills activators automatically
564
+ if ((answers.selectedIDEs || []).includes('codex')) {
565
+ console.log('\n🧠 Generating Codex skills...');
566
+ try {
567
+ const codexSkillsResult = generateCodexSkills(process.cwd());
568
+ if (codexSkillsResult.skipped) {
569
+ console.log(' ℹ️ Codex skills: canonical agent source not found (skipped)');
570
+ } else {
571
+ console.log(`✅ Codex skills: ${codexSkillsResult.count} generated`);
572
+ }
573
+ answers.codexSkillsGenerated = codexSkillsResult.count;
574
+ answers.codexSkillsSkipped = codexSkillsResult.skipped;
575
+ } catch (error) {
576
+ console.warn(`⚠️ Codex skills generation failed: ${error.message}`);
577
+ answers.codexSkillsGenerated = 0;
578
+ }
579
+ }
580
+
525
581
  // Story INS-4.3: Copy extra commands (Gap #12)
526
582
  console.log('\n📋 Copying extra commands...');
527
583
  try {
@@ -554,7 +610,7 @@ async function runWizard(options = {}) {
554
610
  try {
555
611
  await commandValidate({ quiet: true });
556
612
  answers.ideSyncValidation = 'pass';
557
- } catch (validateError) {
613
+ } catch (_validateError) {
558
614
  answers.ideSyncValidation = 'drift';
559
615
  } finally {
560
616
  console.log = _origLog;
@@ -570,6 +626,23 @@ async function runWizard(options = {}) {
570
626
  process.chdir(savedCwd);
571
627
  }
572
628
 
629
+ // ACORE-SKILLS.7: Generate Codex local skills in installed projects.
630
+ console.log('\n🧩 Running Codex skills sync...');
631
+ try {
632
+ const codexSkillsResult = syncCodexSkills({
633
+ sourceDir: path.join(targetProjectRoot, '.aiox-core', 'development', 'agents'),
634
+ localSkillsDir: path.join(targetProjectRoot, '.codex', 'skills'),
635
+ dryRun: false,
636
+ });
637
+ answers.codexSkillsStatus = 'synced';
638
+ answers.codexSkillsGenerated = codexSkillsResult.generated;
639
+ console.log(`✅ Codex skills: ${codexSkillsResult.generated} generated`);
640
+ } catch (codexSkillsError) {
641
+ console.warn(`⚠️ Codex skills sync failed: ${codexSkillsError.message} — run 'npm run sync:skills:codex' post-install`);
642
+ answers.codexSkillsStatus = 'failed';
643
+ answers.codexSkillsGenerated = 0;
644
+ }
645
+
573
646
  // Story INS-4.6: Entity Registry Bootstrap — populate entity-registry.yaml on install
574
647
  // Story INS-4.12: Fix module resolution + bootstrap timing
575
648
  // Bootstrap runs AFTER .aiox-core deps are installed (aiox-core-installer.js:324-345)
@@ -722,38 +795,44 @@ async function runWizard(options = {}) {
722
795
  console.error(` ${depsResult.errorMessage}`);
723
796
  console.error(` Solution: ${depsResult.solution}`);
724
797
 
725
- // Ask user if they want to retry
726
- const { retryDeps } = await inquirer.prompt([
727
- {
728
- type: 'confirm',
729
- name: 'retryDeps',
730
- message: 'Retry dependency installation?',
731
- default: true,
732
- },
733
- ]);
734
-
735
- if (retryDeps) {
736
- // Recursive retry with exponential backoff (built into installDependencies)
737
- const retryResult = await installDependencies({
738
- packageManager: answers.packageManager,
739
- projectPath: projectPath,
740
- });
741
-
742
- if (retryResult.success) {
743
- console.log(`\n✅ Dependencies installed with ${retryResult.packageManager}!`);
744
- answers.depsInstalled = true;
745
- answers.depsResult = retryResult;
798
+ if (options.quiet || options.ci || process.env.CI === '1') {
799
+ answers.depsInstalled = false;
800
+ answers.depsResult = depsResult;
801
+ console.log('\n⚠️ Skipping dependency retry in non-interactive mode.');
802
+ } else {
803
+ // Ask user if they want to retry
804
+ const { retryDeps } = await inquirer.prompt([
805
+ {
806
+ type: 'confirm',
807
+ name: 'retryDeps',
808
+ message: 'Retry dependency installation?',
809
+ default: true,
810
+ },
811
+ ]);
812
+
813
+ if (retryDeps) {
814
+ // Recursive retry with exponential backoff (built into installDependencies)
815
+ const retryResult = await installDependencies({
816
+ packageManager: answers.packageManager,
817
+ projectPath: projectPath,
818
+ });
819
+
820
+ if (retryResult.success) {
821
+ console.log(`\n✅ Dependencies installed with ${retryResult.packageManager}!`);
822
+ answers.depsInstalled = true;
823
+ answers.depsResult = retryResult;
824
+ } else {
825
+ console.log(
826
+ '\n⚠️ Installation still failed. You can run `npm install` manually later.',
827
+ );
828
+ answers.depsInstalled = false;
829
+ answers.depsResult = retryResult;
830
+ }
746
831
  } else {
747
- console.log(
748
- '\n⚠️ Installation still failed. You can run `npm install` manually later.',
749
- );
832
+ console.log('\n⚠️ Skipping dependency installation. Run manually with `npm install`.');
750
833
  answers.depsInstalled = false;
751
- answers.depsResult = retryResult;
834
+ answers.depsResult = depsResult;
752
835
  }
753
- } else {
754
- console.log('\n⚠️ Skipping dependency installation. Run manually with `npm install`.');
755
- answers.depsInstalled = false;
756
- answers.depsResult = depsResult;
757
836
  }
758
837
  }
759
838
  } catch (error) {
@@ -910,6 +989,14 @@ async function runWizard(options = {}) {
910
989
  console.log('\n🔍 Validating installation...\n');
911
990
 
912
991
  try {
992
+ const expectedSkillDirs = [];
993
+ if ((answers.selectedIDEs || []).includes('claude-code')) {
994
+ expectedSkillDirs.push('.claude/skills');
995
+ }
996
+ if ((answers.selectedIDEs || []).includes('codex')) {
997
+ expectedSkillDirs.push(path.join('.codex', 'skills'));
998
+ }
999
+
913
1000
  const validation = await validateInstallation(
914
1001
  {
915
1002
  files: {
@@ -917,6 +1004,7 @@ async function runWizard(options = {}) {
917
1004
  env: '.env',
918
1005
  coreConfig: '.aiox-core/core-config.yaml',
919
1006
  mcpConfig: '.mcp.json',
1007
+ skillDirs: expectedSkillDirs,
920
1008
  },
921
1009
  configs: {
922
1010
  env: answers.envResult,
@@ -39,7 +39,7 @@ const LICENSE_SERVER_URL = process.env.AIOX_LICENSE_API_URL || 'https://aiox-lic
39
39
  /**
40
40
  * Inline License Client — lightweight HTTP client for pre-bootstrap license checks.
41
41
  *
42
- * Used when @aiox-fullstack/pro is not yet installed (first install scenario).
42
+ * Used when @aiox-squads/pro is not yet installed (first install scenario).
43
43
  * Implements the same interface subset as LicenseApiClient using Node.js native https.
44
44
  */
45
45
  class InlineLicenseClient {
@@ -57,12 +57,12 @@ class InlineLicenseClient {
57
57
  */
58
58
  _request(method, urlPath, body, headers = {}) {
59
59
  return new Promise((resolve, reject) => {
60
- const https = require('https');
61
60
  const url = new URL(urlPath, this.baseUrl);
61
+ const transport = url.protocol === 'http:' ? require('http') : require('https');
62
62
 
63
63
  const options = {
64
64
  hostname: url.hostname,
65
- port: url.port || 443,
65
+ port: url.port || (url.protocol === 'http:' ? 80 : 443),
66
66
  path: url.pathname + url.search,
67
67
  method,
68
68
  headers: {
@@ -73,7 +73,7 @@ class InlineLicenseClient {
73
73
  timeout: 15000,
74
74
  };
75
75
 
76
- const req = https.request(options, (res) => {
76
+ const req = transport.request(options, (res) => {
77
77
  let data = '';
78
78
  res.on('data', (chunk) => { data += chunk; });
79
79
  res.on('end', () => {
@@ -135,10 +135,19 @@ class InlineLicenseClient {
135
135
  * Login with email and password.
136
136
  * @param {string} email
137
137
  * @param {string} password
138
- * @returns {Promise<{sessionToken: string, emailVerified: boolean}>}
138
+ * @returns {Promise<{accessToken: string, sessionToken: string, emailVerified: boolean}>}
139
139
  */
140
140
  async login(email, password) {
141
- return this._request('POST', '/api/v1/auth/login', { email, password });
141
+ return this._request('POST', '/api/v1/auth/login', { email, password })
142
+ .then((result) => {
143
+ const accessToken = result.accessToken || result.sessionToken;
144
+ return {
145
+ ...result,
146
+ accessToken,
147
+ // Backward-compatible alias for existing wizard flows.
148
+ sessionToken: accessToken,
149
+ };
150
+ });
142
151
  }
143
152
 
144
153
  /**
@@ -160,11 +169,17 @@ class InlineLicenseClient {
160
169
  */
161
170
  async activateByAuth(token, machineId, version) {
162
171
  return this._request('POST', '/api/v1/auth/activate-pro', {
172
+ accessToken: token,
163
173
  machineId,
164
174
  version,
175
+ aioxCoreVersion: version,
165
176
  }, {
177
+ // Preserve legacy compatibility with older server deployments.
166
178
  Authorization: `Bearer ${token}`,
167
- });
179
+ }).then((result) => ({
180
+ ...result,
181
+ key: result.key || result.licenseKey,
182
+ }));
168
183
  }
169
184
 
170
185
  /**
@@ -175,8 +190,7 @@ class InlineLicenseClient {
175
190
  * @returns {Promise<Object>} Activation result
176
191
  */
177
192
  async activate(licenseKey, machineId, version) {
178
- // Keep the inline fallback aligned with the runtime license client contract.
179
- return this._request('POST', '/v1/license/activate', {
193
+ return this._request('POST', '/api/v1/licenses/activate', {
180
194
  key: licenseKey,
181
195
  machineId,
182
196
  version,
@@ -185,13 +199,32 @@ class InlineLicenseClient {
185
199
 
186
200
  /**
187
201
  * Check if user's email has been verified.
188
- * @param {string} sessionToken - Session token
202
+ * @param {string} accessToken - Session token
189
203
  * @returns {Promise<{verified: boolean}>}
190
204
  */
191
- async checkEmailVerified(sessionToken) {
192
- return this._request('GET', '/api/v1/auth/email-verified', null, {
193
- Authorization: `Bearer ${sessionToken}`,
194
- });
205
+ async checkEmailVerified(accessToken) {
206
+ try {
207
+ const result = await this._request('POST', '/api/v1/auth/verify-status', {
208
+ accessToken,
209
+ });
210
+ return {
211
+ ...result,
212
+ verified: result.verified ?? result.emailVerified,
213
+ };
214
+ } catch (error) {
215
+ // Older server versions used GET /email-verified with bearer auth.
216
+ if (!error.message || !error.message.includes('HTTP 404')) {
217
+ throw error;
218
+ }
219
+
220
+ const result = await this._request('GET', '/api/v1/auth/email-verified', null, {
221
+ Authorization: `Bearer ${accessToken}`,
222
+ });
223
+ return {
224
+ ...result,
225
+ verified: result.verified ?? result.emailVerified,
226
+ };
227
+ }
195
228
  }
196
229
 
197
230
  /**
@@ -318,14 +351,14 @@ function showStep(current, total, label) {
318
351
  *
319
352
  * Resolution order:
320
353
  * 1. Relative path (framework-dev mode: ../../../../pro/license/{name})
321
- * 2. @aiox-fullstack/pro package (brownfield: node_modules/@aiox-fullstack/pro/license/{name})
354
+ * 2. @aiox-squads/pro package (brownfield: node_modules/@aiox-squads/pro/license/{name})
322
355
  * 3. Absolute path via aiox-core in node_modules (brownfield upgrade)
323
- * 4. Absolute path via @aiox-fullstack/pro in user project (npx context)
356
+ * 4. Absolute path via @aiox-squads/pro in user project (npx context)
324
357
  *
325
358
  * Path 4 is critical for npx execution: when running `npx aiox-core install`,
326
359
  * require() resolves from the npx temp directory, not process.cwd(). After
327
- * bootstrap installs @aiox-fullstack/pro in the user's project, only an
328
- * absolute path to process.cwd()/node_modules/@aiox-fullstack/pro/... works.
360
+ * bootstrap installs @aiox-squads/pro in the user's project, only an
361
+ * absolute path to process.cwd()/node_modules/@aiox-squads/pro/... works.
329
362
  *
330
363
  * @param {string} moduleName - Module filename without extension (e.g., 'license-api')
331
364
  * @returns {Object|null} Loaded module or null
@@ -354,8 +387,8 @@ function loadProModule(moduleName) {
354
387
  return frameworkModule;
355
388
  }
356
389
 
357
- // 2. npm packages — try canonical then fallback
358
- const npmScopes = ['@aiox-fullstack/pro', '@aios-fullstack/pro'];
390
+ // 2. npm packages — try canonical then fallbacks
391
+ const npmScopes = ['@aiox-squads/pro', '@aiox-fullstack/pro', '@aios-fullstack/pro'];
359
392
  for (const scope of npmScopes) {
360
393
  const requestPath = `${scope}/license/${moduleName}`;
361
394
  const loadedModule = tryRequire(requestPath);
@@ -373,7 +406,7 @@ function loadProModule(moduleName) {
373
406
 
374
407
  // 4. npm package in user project via absolute path (npx context — require resolves from
375
408
  // temp dir, so we need absolute path to where bootstrap installed the package)
376
- const absScopeDirs = ['@aiox-fullstack', '@aios-fullstack'];
409
+ const absScopeDirs = ['@aiox-squads', '@aiox-fullstack', '@aios-fullstack'];
377
410
  for (const scopeDir of absScopeDirs) {
378
411
  const absPath = path.join(process.cwd(), 'node_modules', scopeDir, 'pro', 'license', moduleName);
379
412
  const loadedModule = tryRequire(absPath);
@@ -459,7 +492,7 @@ function generateMachineId() {
459
492
  /**
460
493
  * Get a license API client instance.
461
494
  *
462
- * Prefers the full LicenseApiClient from @aiox-fullstack/pro when available.
495
+ * Prefers the full LicenseApiClient from @aiox-squads/pro when available.
463
496
  * Falls back to InlineLicenseClient (native https) for pre-bootstrap scenarios.
464
497
  *
465
498
  * @returns {Object} Client instance with isOnline, checkEmail, login, signup, activateByAuth
@@ -475,7 +508,7 @@ function getLicenseClient() {
475
508
  return new LicenseApiClient();
476
509
  }
477
510
 
478
- // Fallback: use inline client for pre-bootstrap (no @aiox-fullstack/pro yet)
511
+ // Fallback: use inline client for pre-bootstrap (no @aiox-squads/pro yet)
479
512
  return new InlineLicenseClient();
480
513
  }
481
514
 
@@ -584,6 +617,63 @@ async function ensureKeyValidationParity(client, activationResult, machineId, ai
584
617
  }
585
618
  }
586
619
 
620
+ /**
621
+ * Resolve the Pro content source directory.
622
+ *
623
+ * Priority:
624
+ * 1. Bundled pro/ content in the aiox-core checkout or package
625
+ * 2. Auto-initialize the git submodule when running from a source checkout
626
+ * 3. Installed @aiox-squads/pro package in the target project
627
+ *
628
+ * @param {string} targetDir - Project root directory
629
+ * @returns {{proSourceDir: string|null, bootstrapError?: string}} Resolution result
630
+ */
631
+ function resolveProSourceDir(targetDir) {
632
+ const path = require('path');
633
+ const fs = require('fs');
634
+ const { execFileSync } = require('child_process');
635
+
636
+ const repoRoot = path.resolve(__dirname, '..', '..', '..', '..');
637
+ const bundledProDir = path.join(repoRoot, 'pro');
638
+ const npmProDirs = [
639
+ path.join(targetDir, 'node_modules', '@aiox-squads', 'pro'),
640
+ path.join(targetDir, 'node_modules', '@aiox-fullstack', 'pro'),
641
+ path.join(targetDir, 'node_modules', '@aios-fullstack', 'pro'),
642
+ ];
643
+ const bundledSquadsDir = path.join(bundledProDir, 'squads');
644
+ const gitmodulesPath = path.join(repoRoot, '.gitmodules');
645
+
646
+ if (fs.existsSync(bundledSquadsDir)) {
647
+ return { proSourceDir: bundledProDir };
648
+ }
649
+
650
+ if (fs.existsSync(gitmodulesPath) && fs.existsSync(bundledProDir)) {
651
+ try {
652
+ execFileSync('git', ['submodule', 'update', '--init', '--recursive', 'pro'], {
653
+ cwd: repoRoot,
654
+ stdio: 'ignore',
655
+ });
656
+
657
+ if (fs.existsSync(bundledSquadsDir)) {
658
+ return { proSourceDir: bundledProDir };
659
+ }
660
+ } catch (error) {
661
+ return {
662
+ proSourceDir: null,
663
+ bootstrapError: error.message || 'git submodule update failed',
664
+ };
665
+ }
666
+ }
667
+
668
+ for (const npmProDir of npmProDirs) {
669
+ if (fs.existsSync(npmProDir)) {
670
+ return { proSourceDir: npmProDir };
671
+ }
672
+ }
673
+
674
+ return { proSourceDir: null };
675
+ }
676
+
587
677
  /**
588
678
  * Step 1: License Gate — authenticate and validate license.
589
679
  *
@@ -728,7 +818,7 @@ async function stepLicenseGateWithEmail() {
728
818
  let checkResult;
729
819
  try {
730
820
  checkResult = await client.checkEmail(trimmedEmail);
731
- } catch (checkError) {
821
+ } catch (_checkError) {
732
822
  checkSpinner.info(t('proBuyerCheckUnavailable'));
733
823
  return fallbackAuthWithoutBuyerCheck(client, trimmedEmail);
734
824
  }
@@ -1431,32 +1521,12 @@ async function validateKeyWithApi(key) {
1431
1521
  async function stepInstallScaffold(targetDir, options = {}) {
1432
1522
  showStep(2, 3, t('proContentInstallation'));
1433
1523
 
1434
- const path = require('path');
1435
- const fs = require('fs');
1436
-
1437
- // Resolve pro source directory from multiple locations:
1438
- // 1. Bundled in aiox-core package (pro/ submodule — npx and local dev)
1439
- // 2. npm package — canonical @aiox-fullstack/pro or fallback @aios-fullstack/pro
1440
- const bundledProDir = path.resolve(__dirname, '..', '..', '..', '..', 'pro');
1441
- const npmProCandidates = [
1442
- path.join(targetDir, 'node_modules', '@aiox-fullstack', 'pro'),
1443
- path.join(targetDir, 'node_modules', '@aios-fullstack', 'pro'),
1444
- ];
1445
-
1446
- let proSourceDir;
1447
- if (fs.existsSync(bundledProDir) && fs.existsSync(path.join(bundledProDir, 'squads'))) {
1448
- proSourceDir = bundledProDir;
1449
- } else {
1450
- proSourceDir = npmProCandidates.find((candidate) => (
1451
- fs.existsSync(path.join(candidate, 'package.json'))
1452
- && fs.existsSync(path.join(candidate, 'squads'))
1453
- ));
1454
- }
1524
+ const { proSourceDir, bootstrapError } = resolveProSourceDir(targetDir);
1455
1525
 
1456
1526
  if (!proSourceDir) {
1457
1527
  return {
1458
1528
  success: false,
1459
- error: t('proPackageNotFound'),
1529
+ error: bootstrapError ? `${t('proPackageNotFound')} ${bootstrapError}` : t('proPackageNotFound'),
1460
1530
  };
1461
1531
  }
1462
1532
 
@@ -1610,7 +1680,7 @@ async function runProWizard(options = {}) {
1610
1680
  showProHeader();
1611
1681
  }
1612
1682
 
1613
- // Step 1: License Gate (uses InlineLicenseClient if @aiox-fullstack/pro not yet installed)
1683
+ // Step 1: License Gate (uses InlineLicenseClient if @aiox-squads/pro not yet installed)
1614
1684
  const licenseResult = await stepLicenseGate({
1615
1685
  key: options.key || process.env.AIOX_PRO_KEY,
1616
1686
  email: options.email || process.env.AIOX_PRO_EMAIL,
@@ -1687,6 +1757,7 @@ module.exports = {
1687
1757
  loadLicenseCache,
1688
1758
  loadProScaffolder,
1689
1759
  getLicenseClient,
1760
+ resolveProSourceDir,
1690
1761
  InlineLicenseClient,
1691
1762
  generateMachineId,
1692
1763
  persistLicenseCache,
@@ -29,6 +29,7 @@ async function validateDependencies(depsContext = {}) {
29
29
  errors: [],
30
30
  warnings: [],
31
31
  };
32
+ const projectRoot = depsContext.projectPath || depsContext.targetDir || process.cwd();
32
33
 
33
34
  try {
34
35
  // Check if dependencies were installed (skip for greenfield with no deps defined)
@@ -43,8 +44,8 @@ async function validateDependencies(depsContext = {}) {
43
44
  }
44
45
 
45
46
  // Check node_modules existence
46
- const nodeModulesPath = path.join(process.cwd(), 'node_modules');
47
- const packageJsonPath = path.join(process.cwd(), 'package.json');
47
+ const nodeModulesPath = path.join(projectRoot, 'node_modules');
48
+ const packageJsonPath = path.join(projectRoot, 'package.json');
48
49
 
49
50
  // For greenfield projects, check if package.json has dependencies
50
51
  let hasDependencies = false;
@@ -92,13 +93,13 @@ async function validateDependencies(depsContext = {}) {
92
93
  });
93
94
 
94
95
  // Validate package.json integrity
95
- await validatePackageJson(results);
96
+ await validatePackageJson(results, projectRoot);
96
97
 
97
- // Check critical dependencies
98
- await checkCriticalDependencies(results);
98
+ // Validate any explicit dependency contract supplied by the caller.
99
+ await checkRequiredDependencies(results, projectRoot, depsContext.requiredDependencies);
99
100
 
100
101
  // Run npm audit (non-blocking - warnings only)
101
- await runSecurityAudit(results, depsContext.packageManager);
102
+ await runSecurityAudit(results, depsContext.packageManager, projectRoot);
102
103
 
103
104
  // Count installed packages
104
105
  await countInstalledPackages(results, nodeModulesPath);
@@ -121,8 +122,8 @@ async function validateDependencies(depsContext = {}) {
121
122
  * Validate package.json
122
123
  * @private
123
124
  */
124
- async function validatePackageJson(results) {
125
- const packageJsonPath = 'package.json';
125
+ async function validatePackageJson(results, projectRoot) {
126
+ const packageJsonPath = path.join(projectRoot, 'package.json');
126
127
 
127
128
  if (!fs.existsSync(packageJsonPath)) {
128
129
  results.errors.push({
@@ -165,22 +166,28 @@ async function validatePackageJson(results) {
165
166
  }
166
167
 
167
168
  /**
168
- * Check critical dependencies
169
+ * Check explicitly required dependencies for the target project.
170
+ *
171
+ * This validator is used against the installed project, not the installer
172
+ * workspace itself. A caller may provide a narrow manifest of packages that
173
+ * must exist after installation; when none is supplied we skip this check to
174
+ * avoid false warnings about the installer's own internal dependencies.
169
175
  * @private
170
176
  */
171
- async function checkCriticalDependencies(results) {
172
- const criticalDeps = [
173
- 'inquirer',
174
- 'chalk',
175
- 'yaml',
176
- 'fs-extra',
177
- '@clack/prompts',
178
- ];
179
-
180
- const nodeModulesPath = path.join(process.cwd(), 'node_modules');
177
+ async function checkRequiredDependencies(results, projectRoot, requiredDependencies = []) {
178
+ if (!Array.isArray(requiredDependencies) || requiredDependencies.length === 0) {
179
+ results.checks.push({
180
+ component: 'Dependency Contract',
181
+ status: 'skipped',
182
+ message: 'No explicit required dependency manifest provided',
183
+ });
184
+ return;
185
+ }
186
+
187
+ const nodeModulesPath = path.join(projectRoot, 'node_modules');
181
188
  const missingDeps = [];
182
189
 
183
- for (const dep of criticalDeps) {
190
+ for (const dep of requiredDependencies) {
184
191
  const depPath = path.join(nodeModulesPath, dep);
185
192
  if (!fs.existsSync(depPath)) {
186
193
  missingDeps.push(dep);
@@ -190,15 +197,15 @@ async function checkCriticalDependencies(results) {
190
197
  if (missingDeps.length > 0) {
191
198
  results.warnings.push({
192
199
  severity: 'high',
193
- message: `Critical dependencies missing: ${missingDeps.join(', ')}`,
200
+ message: `Required dependencies missing: ${missingDeps.join(', ')}`,
194
201
  code: 'CRITICAL_DEPS_MISSING',
195
202
  solution: 'Re-run dependency installation',
196
203
  });
197
204
  } else {
198
205
  results.checks.push({
199
- component: 'Critical Dependencies',
206
+ component: 'Dependency Contract',
200
207
  status: 'success',
201
- message: `All ${criticalDeps.length} critical dependencies installed`,
208
+ message: `All ${requiredDependencies.length} required dependencies installed`,
202
209
  });
203
210
  }
204
211
  }
@@ -207,13 +214,13 @@ async function checkCriticalDependencies(results) {
207
214
  * Run security audit
208
215
  * @private
209
216
  */
210
- async function runSecurityAudit(results, packageManager = 'npm') {
217
+ async function runSecurityAudit(results, packageManager = 'npm', projectRoot = process.cwd()) {
211
218
  try {
212
219
  const auditCommand = packageManager === 'yarn' ? 'yarn audit --json' : 'npm audit --json';
213
220
 
214
221
  const { stdout } = await execAsync(auditCommand, {
215
222
  timeout: 10000,
216
- cwd: process.cwd(),
223
+ cwd: projectRoot,
217
224
  });
218
225
 
219
226
  let auditResults;
@@ -15,6 +15,7 @@ const fs = require('fs');
15
15
  * @param {string} fileContext.env - .env file path
16
16
  * @param {string} fileContext.coreConfig - core-config.yaml path
17
17
  * @param {string} fileContext.mcpConfig - .mcp.json path
18
+ * @param {Array<string>} fileContext.skillDirs - Skill directories expected after install
18
19
  * @returns {Promise<Object>} Validation result
19
20
  */
20
21
  async function validateFiles(fileContext = {}) {
@@ -51,6 +52,31 @@ async function validateFiles(fileContext = {}) {
51
52
  }
52
53
  }
53
54
 
55
+ if (fileContext.skillDirs && fileContext.skillDirs.length > 0) {
56
+ for (const skillDir of fileContext.skillDirs) {
57
+ const exists = fs.existsSync(skillDir);
58
+ const isDirectory = exists ? fs.statSync(skillDir).isDirectory() : false;
59
+ const check = {
60
+ component: 'Skills',
61
+ file: skillDir,
62
+ status: exists && isDirectory ? 'success' : 'failed',
63
+ message: exists && isDirectory ? 'Directory exists' : 'Directory missing',
64
+ };
65
+
66
+ results.checks.push(check);
67
+
68
+ if (!exists || !isDirectory) {
69
+ results.success = false;
70
+ results.errors.push({
71
+ severity: 'high',
72
+ message: `Expected skill directory missing: ${skillDir}`,
73
+ file: skillDir,
74
+ code: 'SKILL_DIR_MISSING',
75
+ });
76
+ }
77
+ }
78
+ }
79
+
54
80
  // Validate .env file (Story 1.6)
55
81
  const envPath = fileContext.env || '.env';
56
82
  const envExists = fs.existsSync(envPath);