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
@@ -5,6 +5,8 @@ const fs = require('fs-extra');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
7
 
8
+ // summary: Sync local Codex skills for core AIOX agents.
9
+
8
10
  const {
9
11
  parseAllAgents,
10
12
  normalizeCommands,
@@ -43,6 +45,13 @@ function getSkillId(agentId) {
43
45
  return `aiox-${id}`;
44
46
  }
45
47
 
48
+ function getLegacySkillId(agentId) {
49
+ const id = String(agentId || '').trim();
50
+ if (!id) return 'aios-unknown';
51
+ if (id.startsWith('aiox-')) return id.replace(/^aiox-/, 'aios-');
52
+ return `aios-${id}`;
53
+ }
54
+
46
55
  function buildSkillContent(agentData) {
47
56
  const agent = agentData.agent || {};
48
57
  const name = agent.name || agentData.id;
@@ -179,4 +188,5 @@ module.exports = {
179
188
  parseArgs,
180
189
  getCodexHome,
181
190
  getSkillId,
191
+ getLegacySkillId,
182
192
  };
@@ -5,7 +5,9 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
 
7
7
  const { parseAllAgents } = require('../ide-sync/agent-parser');
8
- const { getSkillId } = require('./index');
8
+ const { getSkillId, getLegacySkillId } = require('./index');
9
+
10
+ const GENERATED_MARKER = '<!-- AIOX-CODEX-LOCAL-SKILLS: generated -->';
9
11
 
10
12
  function getDefaultOptions() {
11
13
  const projectRoot = process.cwd();
@@ -14,6 +16,7 @@ function getDefaultOptions() {
14
16
  sourceDir: path.join(projectRoot, '.aiox-core', 'development', 'agents'),
15
17
  skillsDir: path.join(projectRoot, '.codex', 'skills'),
16
18
  strict: false,
19
+ allowOrphaned: false,
17
20
  quiet: false,
18
21
  json: false,
19
22
  };
@@ -59,6 +62,35 @@ function validateSkillContent(content, expected) {
59
62
  return issues;
60
63
  }
61
64
 
65
+ function extractGeneratedSquadSource(content) {
66
+ const value = String(content || '');
67
+ const patterns = [
68
+ /`(squads\/[^`]+\/agents\/[^`]+\.md)`/,
69
+ /<!--\s*Source:\s*(squads\/[^>\s]+\/agents\/[^>\s]+\.md)\s*-->/,
70
+ /<!--\s*(squads\/[^>\s]+\/agents\/[^>\s]+\.md)\s*-->/,
71
+ ];
72
+
73
+ for (const pattern of patterns) {
74
+ const match = value.match(pattern);
75
+ if (match) return match[1];
76
+ }
77
+
78
+ return '';
79
+ }
80
+
81
+ function isGeneratedSquadSkill(content, projectRoot) {
82
+ if (!String(content || '').includes(GENERATED_MARKER)) {
83
+ return false;
84
+ }
85
+
86
+ const sourcePath = extractGeneratedSquadSource(content);
87
+ if (!sourcePath) {
88
+ return false;
89
+ }
90
+
91
+ return fs.existsSync(path.join(projectRoot, sourcePath));
92
+ }
93
+
62
94
  function validateCodexSkills(options = {}) {
63
95
  const resolved = { ...getDefaultOptions(), ...options };
64
96
  const errors = [];
@@ -66,7 +98,7 @@ function validateCodexSkills(options = {}) {
66
98
 
67
99
  if (!fs.existsSync(resolved.skillsDir)) {
68
100
  errors.push(`Skills directory not found: ${resolved.skillsDir}`);
69
- return { ok: false, checked: 0, expected: 0, errors, warnings, missing: [], orphaned: [] };
101
+ return { ok: false, checked: 0, expected: 0, errors, warnings, missing: [], orphaned: [], ignored: [] };
70
102
  }
71
103
 
72
104
  const agents = parseAllAgents(resolved.sourceDir).filter(isParsableAgent);
@@ -74,6 +106,7 @@ function validateCodexSkills(options = {}) {
74
106
  agentId: agent.id,
75
107
  filename: agent.filename,
76
108
  skillId: getSkillId(agent.id),
109
+ legacySkillId: getLegacySkillId(agent.id),
77
110
  }));
78
111
 
79
112
  const missing = [];
@@ -99,13 +132,37 @@ function validateCodexSkills(options = {}) {
99
132
  }
100
133
 
101
134
  const expectedIds = new Set(expected.map(item => item.skillId));
135
+ const legacyIds = new Set(expected.map(item => item.legacySkillId));
102
136
  const orphaned = [];
137
+ const legacy = [];
138
+ const ignored = [];
103
139
  if (resolved.strict) {
104
140
  const dirs = fs.readdirSync(resolved.skillsDir, { withFileTypes: true })
105
- .filter(entry => entry.isDirectory() && entry.name.startsWith('aiox-'))
141
+ .filter(entry => entry.isDirectory() && (entry.name.startsWith('aiox-') || entry.name.startsWith('aios-')))
106
142
  .map(entry => entry.name);
107
143
  for (const dir of dirs) {
108
- if (!expectedIds.has(dir)) {
144
+ if (legacyIds.has(dir)) {
145
+ legacy.push(dir);
146
+ errors.push(`Legacy skill alias directory: ${path.join(path.relative(resolved.projectRoot, resolved.skillsDir), dir)}`);
147
+ continue;
148
+ }
149
+ if (dir.startsWith('aiox-') && !expectedIds.has(dir)) {
150
+ if (resolved.allowOrphaned) {
151
+ continue;
152
+ }
153
+ const skillPath = path.join(resolved.skillsDir, dir, 'SKILL.md');
154
+ let content = '';
155
+ try {
156
+ content = fs.readFileSync(skillPath, 'utf8');
157
+ } catch (_error) {
158
+ content = '';
159
+ }
160
+
161
+ if (isGeneratedSquadSkill(content, resolved.projectRoot)) {
162
+ ignored.push(dir);
163
+ continue;
164
+ }
165
+
109
166
  orphaned.push(dir);
110
167
  errors.push(`Orphaned skill directory: ${path.join(path.relative(resolved.projectRoot, resolved.skillsDir), dir)}`);
111
168
  }
@@ -124,6 +181,8 @@ function validateCodexSkills(options = {}) {
124
181
  warnings,
125
182
  missing,
126
183
  orphaned,
184
+ legacy,
185
+ ignored,
127
186
  };
128
187
  }
129
188
 
@@ -167,6 +226,8 @@ if (require.main === module) {
167
226
  module.exports = {
168
227
  validateCodexSkills,
169
228
  validateSkillContent,
229
+ extractGeneratedSquadSource,
230
+ isGeneratedSquadSkill,
170
231
  parseArgs,
171
232
  getDefaultOptions,
172
233
  };
@@ -243,11 +243,36 @@ function writeSettingsJson(projectRoot, permissions) {
243
243
  }
244
244
 
245
245
  const updated = { ...existing };
246
-
247
- if (permissions.deny.length > 0 || permissions.allow.length > 0) {
248
- updated.permissions = permissions;
246
+ const existingPermissions =
247
+ existing && existing.permissions && typeof existing.permissions === 'object'
248
+ ? existing.permissions
249
+ : {};
250
+ const generatedPermissionsEmpty =
251
+ permissions.allow.length === 0 && permissions.deny.length === 0;
252
+
253
+ if (generatedPermissionsEmpty) {
254
+ if (Object.keys(existingPermissions).length > 0) {
255
+ updated.permissions = existingPermissions;
256
+ } else {
257
+ delete updated.permissions;
258
+ }
249
259
  } else {
250
- delete updated.permissions;
260
+ const mergedAllow = Array.from(
261
+ new Set([...(Array.isArray(existingPermissions.allow) ? existingPermissions.allow : []), ...permissions.allow]),
262
+ );
263
+ const mergedDeny = Array.from(
264
+ new Set([...(Array.isArray(existingPermissions.deny) ? existingPermissions.deny : []), ...permissions.deny]),
265
+ );
266
+
267
+ if (mergedDeny.length > 0 || mergedAllow.length > 0) {
268
+ updated.permissions = {
269
+ ...existingPermissions,
270
+ allow: mergedAllow,
271
+ deny: mergedDeny,
272
+ };
273
+ } else {
274
+ delete updated.permissions;
275
+ }
251
276
  }
252
277
 
253
278
  const newContent = JSON.stringify(updated, null, 2) + '\n';
@@ -119,8 +119,12 @@ function extractAgentInfoFallback(content) {
119
119
  * @returns {object} - Parsed agent data
120
120
  */
121
121
  function parseAgentFile(filePath) {
122
+ const relativeSourcePath = path.relative(process.cwd(), filePath);
122
123
  const result = {
123
124
  path: filePath,
125
+ sourcePath: relativeSourcePath && !relativeSourcePath.startsWith('..') && !path.isAbsolute(relativeSourcePath)
126
+ ? relativeSourcePath.split(path.sep).join('/')
127
+ : null,
124
128
  filename: path.basename(filePath),
125
129
  id: path.basename(filePath, '.md'),
126
130
  raw: null,
@@ -60,6 +60,7 @@ function loadConfig(projectRoot) {
60
60
  'claude-code': {
61
61
  enabled: true,
62
62
  path: '.claude/commands/AIOX/agents',
63
+ skillsPath: '.claude/skills',
63
64
  format: 'full-markdown-yaml',
64
65
  },
65
66
  codex: {
@@ -133,6 +134,14 @@ function getTransformer(format) {
133
134
  return transformers[format] || claudeCodeTransformer;
134
135
  }
135
136
 
137
+ function transformPrimaryContent(transformer, agent, ideName) {
138
+ if (ideName === 'claude-code' && typeof transformer.transformCommand === 'function') {
139
+ return transformer.transformCommand(agent);
140
+ }
141
+
142
+ return transformer.transform(agent);
143
+ }
144
+
136
145
  /**
137
146
  * Sync agents to a specific IDE
138
147
  * @param {object[]} agents - Parsed agent data
@@ -146,7 +155,9 @@ function syncIde(agents, ideConfig, ideName, projectRoot, options) {
146
155
  const result = {
147
156
  ide: ideName,
148
157
  targetDir: path.join(projectRoot, ideConfig.path),
158
+ skillRootDir: ideConfig.skillsPath ? path.join(projectRoot, ideConfig.skillsPath) : null,
149
159
  files: [],
160
+ skillFiles: [],
150
161
  errors: [],
151
162
  };
152
163
 
@@ -181,7 +192,7 @@ function syncIde(agents, ideConfig, ideName, projectRoot, options) {
181
192
  }
182
193
 
183
194
  try {
184
- const content = transformer.transform(agent);
195
+ const content = transformPrimaryContent(transformer, agent, ideName);
185
196
  const filename = transformer.getFilename(agent);
186
197
  const targetPath = path.join(result.targetDir, filename);
187
198
 
@@ -195,6 +206,25 @@ function syncIde(agents, ideConfig, ideName, projectRoot, options) {
195
206
  path: targetPath,
196
207
  content,
197
208
  });
209
+
210
+ if (ideName === 'claude-code' && typeof transformer.transformSkill === 'function') {
211
+ const skillContent = transformer.transformSkill(agent);
212
+ const skillRelativePath = transformer.getSkillRelativePath(agent);
213
+ const skillRootDir = result.skillRootDir || path.join(projectRoot, '.claude', 'skills');
214
+ const skillPath = path.join(skillRootDir, skillRelativePath);
215
+
216
+ if (!options.dryRun) {
217
+ fs.ensureDirSync(path.dirname(skillPath));
218
+ fs.writeFileSync(skillPath, skillContent, 'utf8');
219
+ }
220
+
221
+ result.skillFiles.push({
222
+ agent: agent.id,
223
+ filename: skillRelativePath,
224
+ path: skillPath,
225
+ content: skillContent,
226
+ });
227
+ }
198
228
  } catch (error) {
199
229
  result.errors.push({
200
230
  agent: agent.id,
@@ -211,7 +241,7 @@ function syncIde(agents, ideConfig, ideName, projectRoot, options) {
211
241
  * @param {object} options - Command options
212
242
  */
213
243
  async function commandSync(options) {
214
- const projectRoot = process.cwd();
244
+ const projectRoot = options.projectRoot || process.cwd();
215
245
  const config = loadConfig(projectRoot);
216
246
 
217
247
  if (!config.enabled) {
@@ -284,6 +314,7 @@ async function commandSync(options) {
284
314
  }
285
315
 
286
316
  const agentCount = result.files.length;
317
+ const skillCount = (result.skillFiles || []).length;
287
318
  const commandCount = (result.commandFiles || []).length;
288
319
  const redirectCount = redirectResult.written.length;
289
320
  const errorCount = result.errors.length;
@@ -295,7 +326,7 @@ async function commandSync(options) {
295
326
  }
296
327
 
297
328
  console.log(
298
- ` ${status} ${agentCount} agents${commandCount > 0 ? `, ${commandCount} commands` : ''}, ${redirectCount} redirects${errorCount > 0 ? `, ${errorCount} errors` : ''}`
329
+ ` ${status} ${agentCount} agents${skillCount > 0 ? `, ${skillCount} skills` : ''}${commandCount > 0 ? `, ${commandCount} commands` : ''}, ${redirectCount} redirects${errorCount > 0 ? `, ${errorCount} errors` : ''}`
299
330
  );
300
331
 
301
332
  if (options.verbose && result.errors.length > 0) {
@@ -307,7 +338,10 @@ async function commandSync(options) {
307
338
  }
308
339
 
309
340
  // Summary
310
- const totalFiles = results.reduce((sum, r) => sum + r.files.length + (r.commandFiles || []).length, 0);
341
+ const totalFiles = results.reduce(
342
+ (sum, r) => sum + r.files.length + (r.skillFiles || []).length + (r.commandFiles || []).length,
343
+ 0
344
+ );
311
345
  const totalRedirects =
312
346
  Object.keys(config.redirects).length * targetIdes.filter(([, c]) => c.enabled).length;
313
347
  const totalErrors = results.reduce((sum, r) => sum + r.errors.length, 0);
@@ -317,11 +351,11 @@ async function commandSync(options) {
317
351
 
318
352
  if (options.dryRun) {
319
353
  console.log(
320
- `${colors.yellow}Dry run: ${totalFiles} agents + ${totalRedirects} redirects would be written${colors.reset}`
354
+ `${colors.yellow}Dry run: ${totalFiles} files + ${totalRedirects} redirects would be written${colors.reset}`
321
355
  );
322
356
  } else {
323
357
  console.log(
324
- `${colors.green}✅ Sync complete: ${totalFiles} agents + ${totalRedirects} redirects${colors.reset}`
358
+ `${colors.green}✅ Sync complete: ${totalFiles} files + ${totalRedirects} redirects${colors.reset}`
325
359
  );
326
360
  }
327
361
 
@@ -373,7 +407,7 @@ async function commandValidate(options) {
373
407
  if (agent.error) continue;
374
408
 
375
409
  try {
376
- const content = transformer.transform(agent);
410
+ const content = transformPrimaryContent(transformer, agent, ideName);
377
411
  const filename = transformer.getFilename(agent);
378
412
  expectedFiles.push({ filename, content });
379
413
  } catch (error) {
@@ -411,6 +445,31 @@ async function commandValidate(options) {
411
445
  targetDir: path.join(projectRoot, '.gemini', 'commands'),
412
446
  };
413
447
  }
448
+
449
+ if (ideName === 'claude-code' && typeof transformer.transformSkill === 'function') {
450
+ const skillNamespace = path.posix.join('AIOX', 'agents') + '/';
451
+ const expectedSkillFiles = [];
452
+
453
+ for (const agent of agents) {
454
+ if (agent.error) continue;
455
+
456
+ try {
457
+ const skillContent = transformer.transformSkill(agent);
458
+ const skillRelativePath = transformer.getSkillRelativePath(agent);
459
+ const filename = skillRelativePath.startsWith(skillNamespace)
460
+ ? skillRelativePath.slice(skillNamespace.length)
461
+ : skillRelativePath;
462
+ expectedSkillFiles.push({ filename, content: skillContent });
463
+ } catch (error) {
464
+ // Skip agents that fail to transform
465
+ }
466
+ }
467
+
468
+ ideConfigs['claude-code-skills'] = {
469
+ expectedFiles: expectedSkillFiles,
470
+ targetDir: path.join(projectRoot, ideConfig.skillsPath || '.claude/skills', 'AIOX', 'agents'),
471
+ };
472
+ }
414
473
  }
415
474
 
416
475
  // Validate
@@ -534,6 +593,7 @@ if (require.main === module) {
534
593
  module.exports = {
535
594
  loadConfig,
536
595
  getTransformer,
596
+ transformPrimaryContent,
537
597
  syncIde,
538
598
  commandSync,
539
599
  commandValidate,
@@ -6,6 +6,27 @@
6
6
  * Target: .claude/commands/AIOX/agents/*.md
7
7
  */
8
8
 
9
+ const path = require('path');
10
+
11
+ function normalizePath(value) {
12
+ return String(value || '').split(path.sep).join('/');
13
+ }
14
+
15
+ function getSourcePath(agentData) {
16
+ if (agentData.sourcePath) {
17
+ return normalizePath(agentData.sourcePath);
18
+ }
19
+
20
+ if (agentData.path) {
21
+ const relative = path.relative(process.cwd(), agentData.path);
22
+ if (relative && !relative.startsWith('..') && !path.isAbsolute(relative)) {
23
+ return normalizePath(relative);
24
+ }
25
+ }
26
+
27
+ return `.aiox-core/development/agents/${agentData.filename}`;
28
+ }
29
+
9
30
  /**
10
31
  * Transform agent data to Claude Code format
11
32
  * For Claude Code, we use the full original file (identity transform)
@@ -13,12 +34,13 @@
13
34
  * @returns {string} - Transformed content
14
35
  */
15
36
  function transform(agentData) {
37
+ const sourcePath = getSourcePath(agentData);
16
38
  // Claude Code uses the full original file
17
39
  if (agentData.raw) {
18
40
  // Add sync footer if not present
19
- const syncFooter = `\n---\n*AIOX Agent - Synced from .aiox-core/development/agents/${agentData.filename}*\n`;
41
+ const syncFooter = `\n---\n*AIOX Agent - Synced from ${sourcePath}*\n`;
20
42
 
21
- if (!agentData.raw.includes('Synced from .aiox-core/development/agents/')) {
43
+ if (!agentData.raw.includes(`Synced from ${sourcePath}`)) {
22
44
  return agentData.raw.trimEnd() + syncFooter;
23
45
  }
24
46
  return agentData.raw;
@@ -28,6 +50,47 @@ function transform(agentData) {
28
50
  return generateMinimalContent(agentData);
29
51
  }
30
52
 
53
+ /**
54
+ * Transform agent data to a Claude Code legacy command shim.
55
+ * The full activation payload lives in the Claude Skill sidecar.
56
+ * @param {object} agentData - Parsed agent data from agent-parser
57
+ * @returns {string} - Legacy command shim content
58
+ */
59
+ function transformCommand(agentData) {
60
+ const agent = agentData.agent || {};
61
+ const sourcePath = getSourcePath(agentData);
62
+ const skillPath = `.claude/skills/${getSkillRelativePath(agentData)}`;
63
+ const name = agent.name || agentData.id;
64
+ const title = agent.title || 'AIOX Agent';
65
+ const whenToUse = normalizeInlineText(
66
+ agent.whenToUse || 'Use this AIOX agent when the task matches its responsibility.',
67
+ 360
68
+ );
69
+
70
+ return `# ${agentData.id}
71
+
72
+ <!-- ACORE-CLAUDE-AGENT-COMMAND: legacy-shim -->
73
+ <!-- Canonical Skill: ${skillPath} -->
74
+ <!-- Source: ${sourcePath} -->
75
+
76
+ **${name}** - ${title}
77
+
78
+ > ${whenToUse}
79
+
80
+ ## Compatibility Activation
81
+
82
+ This command is a legacy compatibility shim. The canonical Claude activation payload is:
83
+
84
+ \`${skillPath}\`
85
+
86
+ When this command is invoked:
87
+
88
+ 1. Read \`${skillPath}\` in full.
89
+ 2. Follow the activation instructions from that skill.
90
+ 3. If the skill file is unavailable, read \`${sourcePath}\` as fallback.
91
+ `;
92
+ }
93
+
31
94
  /**
32
95
  * Generate minimal content if raw file is unavailable
33
96
  * @param {object} agentData - Parsed agent data
@@ -36,6 +99,7 @@ function transform(agentData) {
36
99
  function generateMinimalContent(agentData) {
37
100
  const agent = agentData.agent || {};
38
101
  const persona = agentData.persona_profile || {};
102
+ const sourcePath = getSourcePath(agentData);
39
103
 
40
104
  const icon = agent.icon || '🤖';
41
105
  const name = agent.name || agentData.id;
@@ -62,12 +126,86 @@ ${icon} **${name}** - ${title}
62
126
 
63
127
  content += `
64
128
  ---
65
- *AIOX Agent - Synced from .aiox-core/development/agents/${agentData.filename}*
129
+ *AIOX Agent - Synced from ${sourcePath}*
66
130
  `;
67
131
 
68
132
  return content;
69
133
  }
70
134
 
135
+ /**
136
+ * Normalize free text for YAML frontmatter.
137
+ * @param {string} text - Raw text
138
+ * @param {number} maxLength - Maximum length
139
+ * @returns {string} - Normalized text
140
+ */
141
+ function normalizeInlineText(text, maxLength = 240) {
142
+ const value = String(text || '').replace(/\s+/g, ' ').trim();
143
+
144
+ if (value.length <= maxLength) {
145
+ return value;
146
+ }
147
+
148
+ return `${value.slice(0, maxLength - 3).trimEnd()}...`;
149
+ }
150
+
151
+ /**
152
+ * Quote a value for one-line YAML frontmatter.
153
+ * @param {string} value - Raw value
154
+ * @returns {string} - YAML-safe quoted value
155
+ */
156
+ function quoteYamlString(value) {
157
+ return JSON.stringify(normalizeInlineText(value));
158
+ }
159
+
160
+ /**
161
+ * Build a Claude skill description from the parsed agent metadata.
162
+ * @param {object} agentData - Parsed agent data
163
+ * @returns {string} - Skill description
164
+ */
165
+ function buildSkillDescription(agentData) {
166
+ const agent = agentData.agent || {};
167
+ const name = agent.name || agentData.id;
168
+ const title = agent.title || 'AIOX Agent';
169
+ const whenToUse = agent.whenToUse || 'Use this AIOX agent when the task matches its responsibility.';
170
+
171
+ return `Activate ${name} (${agentData.id}) for ${title}. ${whenToUse}`;
172
+ }
173
+
174
+ /**
175
+ * Get the relative Claude skill path for this agent under .claude/skills.
176
+ * @param {object} agentData - Parsed agent data
177
+ * @returns {string} - Relative skill path
178
+ */
179
+ function getSkillRelativePath(agentData) {
180
+ return path.posix.join('AIOX', 'agents', agentData.id, 'SKILL.md');
181
+ }
182
+
183
+ /**
184
+ * Transform agent data to a Claude Skill sidecar.
185
+ * The command file remains the compatibility surface; the skill is the new canonical Claude surface.
186
+ * @param {object} agentData - Parsed agent data from agent-parser
187
+ * @returns {string} - Skill content
188
+ */
189
+ function transformSkill(agentData) {
190
+ const sourcePath = getSourcePath(agentData);
191
+ const name = `aiox-${agentData.id}`;
192
+ const description = buildSkillDescription(agentData);
193
+ const sourceContent = agentData.raw ? agentData.raw.trimEnd() : generateMinimalContent(agentData).trimEnd();
194
+
195
+ return `---
196
+ name: ${name}
197
+ description: ${quoteYamlString(description)}
198
+ user-invocable: true
199
+ activation_type: pipeline
200
+ ---
201
+
202
+ <!-- ACORE-CLAUDE-AGENT-SKILL: generated -->
203
+ <!-- Source: ${sourcePath} -->
204
+
205
+ ${sourceContent}
206
+ `;
207
+ }
208
+
71
209
  /**
72
210
  * Get the target filename for this agent
73
211
  * @param {object} agentData - Parsed agent data
@@ -79,6 +217,10 @@ function getFilename(agentData) {
79
217
 
80
218
  module.exports = {
81
219
  transform,
220
+ transformCommand,
221
+ transformSkill,
82
222
  getFilename,
223
+ getSkillRelativePath,
224
+ getSourcePath,
83
225
  format: 'full-markdown-yaml',
84
226
  };