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.
- package/.aiox-core/cli/commands/pro/buyer.js +379 -0
- package/.aiox-core/cli/commands/pro/index.js +191 -52
- package/.aiox-core/cli/commands/validate/index.js +2 -0
- package/.aiox-core/core/code-intel/helpers/dev-helper.js +1 -1
- package/.aiox-core/core/code-intel/helpers/devops-helper.js +0 -1
- package/.aiox-core/core/code-intel/helpers/planning-helper.js +1 -1
- package/.aiox-core/core/code-intel/helpers/qa-helper.js +2 -2
- package/.aiox-core/core/config/schemas/framework-config.schema.json +1 -0
- package/.aiox-core/core/config/template-overrides.js +1 -1
- package/.aiox-core/core/doctor/checks/ide-sync.js +81 -25
- package/.aiox-core/core/doctor/checks/rules-files.js +0 -1
- package/.aiox-core/core/doctor/checks/skills-count.js +83 -15
- package/.aiox-core/core/graph-dashboard/cli.js +1 -2
- package/.aiox-core/core/graph-dashboard/data-sources/code-intel-source.js +1 -1
- package/.aiox-core/core/ids/layer-classifier.js +1 -1
- package/.aiox-core/core/pro/pro-updater.js +578 -0
- package/.aiox-core/core/synapse/context/context-tracker.js +107 -9
- package/.aiox-core/core/synapse/layers/layer-processor.js +1 -1
- package/.aiox-core/core-config.yaml +15 -1
- package/.aiox-core/data/capability-detection.js +15 -15
- package/.aiox-core/data/entity-registry.yaml +18 -2
- package/.aiox-core/data/registry-update-log.jsonl +5 -0
- package/.aiox-core/data/tok3-token-comparison.js +0 -4
- package/.aiox-core/data/tool-search-validation.js +1 -1
- package/.aiox-core/development/agents/aiox-master.md +44 -6
- package/.aiox-core/development/agents/data-engineer.md +4 -4
- package/.aiox-core/development/agents/devops.md +52 -2
- package/.aiox-core/development/agents/po.md +1 -1
- package/.aiox-core/development/agents/qa.md +5 -11
- package/.aiox-core/development/agents/sm.md +3 -3
- package/.aiox-core/development/agents/ux-design-expert.md +1 -1
- package/.aiox-core/development/scripts/unified-activation-pipeline.js +29 -3
- package/.aiox-core/development/tasks/dev-develop-story.md +46 -7
- package/.aiox-core/development/tasks/devops-pro-access-grant.md +93 -0
- package/.aiox-core/development/tasks/devops-pro-activate.md +42 -0
- package/.aiox-core/development/tasks/devops-pro-check-access.md +34 -0
- package/.aiox-core/development/tasks/devops-pro-request-reset.md +34 -0
- package/.aiox-core/development/tasks/devops-pro-resend-verification.md +32 -0
- package/.aiox-core/development/tasks/devops-pro-reset-password.md +36 -0
- package/.aiox-core/development/tasks/devops-pro-validate-login.md +36 -0
- package/.aiox-core/development/tasks/devops-pro-verify-status.md +33 -0
- package/.aiox-core/development/tasks/qa-gate.md +54 -4
- package/.aiox-core/development/tasks/validate-next-story.md +39 -2
- package/.aiox-core/framework-config.yaml +1 -0
- package/.aiox-core/infrastructure/scripts/codex-skills-sync/README.md +69 -0
- package/.aiox-core/infrastructure/scripts/codex-skills-sync/bootstrap.js +727 -0
- package/.aiox-core/infrastructure/scripts/codex-skills-sync/index.js +10 -0
- package/.aiox-core/infrastructure/scripts/codex-skills-sync/validate.js +65 -4
- package/.aiox-core/infrastructure/scripts/generate-settings-json.js +29 -4
- package/.aiox-core/infrastructure/scripts/ide-sync/agent-parser.js +4 -0
- package/.aiox-core/infrastructure/scripts/ide-sync/index.js +67 -7
- package/.aiox-core/infrastructure/scripts/ide-sync/transformers/claude-code.js +145 -3
- package/.aiox-core/infrastructure/scripts/repair-agent-references.js +263 -0
- package/.aiox-core/infrastructure/scripts/validate-claude-integration.js +60 -8
- package/.aiox-core/infrastructure/scripts/validate-paths.js +13 -0
- package/.aiox-core/install-manifest.yaml +134 -82
- package/.aiox-core/utils/filters/index.js +2 -1
- package/.claude/commands/AIOX/agents/aiox-master.md +21 -0
- package/.claude/commands/AIOX/agents/analyst.md +21 -0
- package/.claude/commands/AIOX/agents/architect.md +21 -0
- package/.claude/commands/AIOX/agents/data-engineer.md +21 -0
- package/.claude/commands/AIOX/agents/dev.md +21 -0
- package/.claude/commands/AIOX/agents/devops.md +21 -0
- package/.claude/commands/AIOX/agents/pm.md +21 -0
- package/.claude/commands/AIOX/agents/po.md +21 -0
- package/.claude/commands/AIOX/agents/qa.md +21 -0
- package/.claude/commands/AIOX/agents/sm.md +21 -0
- package/.claude/commands/AIOX/agents/squad-creator.md +21 -0
- package/.claude/commands/AIOX/agents/ux-design-expert.md +21 -0
- package/.claude/commands/AIOX/scripts/agent-config-loader.js +624 -0
- package/.claude/commands/AIOX/scripts/generate-greeting.js +160 -0
- package/.claude/commands/AIOX/scripts/greeting-builder.js +866 -0
- package/.claude/commands/AIOX/scripts/session-context-loader.js +286 -0
- package/.claude/commands/AIOX/stories/story-6.1.4.md +1404 -0
- package/.claude/commands/cohort-squad/agents/cohort-manager.md +156 -0
- package/.claude/commands/design-system/agents/brad-frost.md +1097 -0
- package/.claude/commands/design-system/agents/dan-mall.md +857 -0
- package/.claude/commands/design-system/agents/dave-malouf.md +2272 -0
- package/.claude/commands/design-system/agents/design-chief.md +102 -0
- package/.claude/commands/design-system/agents/nano-banana-generator.md +162 -0
- package/.claude/commands/greet.md +101 -0
- package/.claude/commands/synapse/manager.md +75 -0
- package/.claude/commands/synapse/tasks/add-rule.md +94 -0
- package/.claude/commands/synapse/tasks/create-command.md +109 -0
- package/.claude/commands/synapse/tasks/create-domain.md +127 -0
- package/.claude/commands/synapse/tasks/diagnose-synapse.md +245 -0
- package/.claude/commands/synapse/tasks/edit-rule.md +109 -0
- package/.claude/commands/synapse/tasks/suggest-domain.md +116 -0
- package/.claude/commands/synapse/tasks/toggle-domain.md +83 -0
- package/.claude/commands/synapse/templates/domain-template +8 -0
- package/.claude/commands/synapse/templates/manifest-entry-template +4 -0
- package/.claude/commands/synapse/utils/manifest-parser-reference.md +134 -0
- package/.claude/hooks/precompact-session-digest.cjs +2 -2
- package/.claude/skills/AIOX/agents/aiox-master/SKILL.md +511 -0
- package/.claude/skills/AIOX/agents/analyst/SKILL.md +281 -0
- package/.claude/skills/AIOX/agents/architect/SKILL.md +482 -0
- package/.claude/skills/AIOX/agents/data-engineer/SKILL.md +503 -0
- package/.claude/skills/AIOX/agents/dev/SKILL.md +568 -0
- package/.claude/skills/AIOX/agents/devops/SKILL.md +597 -0
- package/.claude/skills/AIOX/agents/pm/SKILL.md +385 -0
- package/.claude/skills/AIOX/agents/po/SKILL.md +343 -0
- package/.claude/skills/AIOX/agents/qa/SKILL.md +451 -0
- package/.claude/skills/AIOX/agents/sm/SKILL.md +295 -0
- package/.claude/skills/AIOX/agents/squad-creator/SKILL.md +352 -0
- package/.claude/skills/AIOX/agents/ux-design-expert/SKILL.md +503 -0
- package/.claude/skills/architect-first/SKILL.md +275 -0
- package/.claude/skills/architect-first/assets/architecture-template.md +505 -0
- package/.claude/skills/architect-first/assets/config-template.yaml +351 -0
- package/.claude/skills/architect-first/references/architecture-checklist.md +216 -0
- package/.claude/skills/architect-first/references/pre-implementation-checklist.md +119 -0
- package/.claude/skills/architect-first/references/stop-rules-guide.md +291 -0
- package/.claude/skills/architect-first/references/testing-strategy-guide.md +477 -0
- package/.claude/skills/architect-first/scripts/architecture_validator.py +490 -0
- package/.claude/skills/architect-first/scripts/check_coupling.py +306 -0
- package/.claude/skills/architect-first/scripts/validate_risk_mitigation.py +382 -0
- package/.claude/skills/checklist-runner/SKILL.md +113 -0
- package/.claude/skills/clone-mind.md +329 -0
- package/.claude/skills/coderabbit-review/SKILL.md +106 -0
- package/.claude/skills/course-generation-workflow.md +76 -0
- package/.claude/skills/enhance-workflow.md +466 -0
- package/.claude/skills/mcp-builder/LICENSE.txt +202 -0
- package/.claude/skills/mcp-builder/SKILL.md +328 -0
- package/.claude/skills/mcp-builder/reference/evaluation.md +602 -0
- package/.claude/skills/mcp-builder/reference/mcp_best_practices.md +915 -0
- package/.claude/skills/mcp-builder/reference/node_mcp_server.md +916 -0
- package/.claude/skills/mcp-builder/reference/python_mcp_server.md +752 -0
- package/.claude/skills/mcp-builder/scripts/connections.py +151 -0
- package/.claude/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/.claude/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/.claude/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/.claude/skills/ralph.md +181 -0
- package/.claude/skills/skill-creator/LICENSE.txt +202 -0
- package/.claude/skills/skill-creator/SKILL.md +209 -0
- package/.claude/skills/skill-creator/scripts/init_skill.py +303 -0
- package/.claude/skills/skill-creator/scripts/package_skill.py +110 -0
- package/.claude/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/.claude/skills/squad.md +301 -0
- package/.claude/skills/synapse/SKILL.md +132 -0
- package/.claude/skills/synapse/assets/README.md +50 -0
- package/.claude/skills/synapse/references/brackets.md +100 -0
- package/.claude/skills/synapse/references/commands.md +118 -0
- package/.claude/skills/synapse/references/domains.md +126 -0
- package/.claude/skills/synapse/references/layers.md +186 -0
- package/.claude/skills/synapse/references/manifest.md +142 -0
- package/.claude/skills/tech-search/SKILL.md +431 -0
- package/.claude/skills/tech-search/prompts/page-extract.md +133 -0
- package/README.en.md +2 -2
- package/README.md +8 -2
- package/bin/aiox.js +55 -4
- package/bin/utils/framework-guard.js +4 -2
- package/bin/utils/pro-detector.js +119 -28
- package/bin/utils/validate-publish.js +6 -6
- package/docs/aiox-agent-flows/devops-system.md +18 -0
- package/docs/aiox-workflows/README.md +1 -0
- package/docs/aiox-workflows/pro-access-grant-workflow.md +218 -0
- package/docs/guides/pro/access-grant-ops-playbook.md +370 -0
- package/docs/guides/pro/install-gate-setup.md +12 -6
- package/docs/guides/pro/squad-creator-handoff-pro-access-ops.md +134 -0
- package/docs/guides/supabase-ops-handoff.md +768 -0
- package/package.json +12 -1
- package/packages/aiox-pro-cli/bin/aiox-pro.js +33 -12
- package/packages/installer/src/config/configure-environment.js +118 -50
- package/packages/installer/src/installer/aiox-core-installer.js +124 -27
- package/packages/installer/src/installer/brownfield-upgrader.js +66 -9
- package/packages/installer/src/installer/dependency-installer.js +4 -0
- package/packages/installer/src/pro/pro-scaffolder.js +5 -5
- package/packages/installer/src/updater/index.js +151 -10
- package/packages/installer/src/wizard/ide-config-generator.js +73 -7
- package/packages/installer/src/wizard/index.js +119 -31
- package/packages/installer/src/wizard/pro-setup.js +118 -47
- package/packages/installer/src/wizard/validation/validators/dependency-validator.js +32 -25
- package/packages/installer/src/wizard/validation/validators/file-structure-validator.js +26 -0
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +84 -1
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +1 -1
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +85 -19
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +4 -4
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +5 -5
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +4 -4
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +11 -11
- package/pro/README.md +12 -1
- package/pro/license/index.js +3 -11
- package/pro/license/license-api.js +25 -0
- package/pro/license/license-cache.js +135 -31
- package/pro/license/license-crypto.js +59 -3
- package/pro/package.json +5 -4
- package/pro/squads/README.md +16 -16
- package/pro/squads/index.js +1 -1
- package/scripts/e2e/installed-skills-smoke.js +264 -0
- package/scripts/package-synapse.js +3 -3
- package/scripts/validate-package-completeness.js +8 -11
- package/.aiox-core/lib/build.json +0 -1
|
@@ -53,10 +53,38 @@ function loadManifest(basePath, manifestName = 'install-manifest.yaml') {
|
|
|
53
53
|
* @returns {Object|null} - Installed manifest or null if not found
|
|
54
54
|
*/
|
|
55
55
|
function loadInstalledManifest(targetDir) {
|
|
56
|
-
|
|
56
|
+
const installedManifest = loadManifest(
|
|
57
57
|
path.join(targetDir, '.aiox-core'),
|
|
58
58
|
'.installed-manifest.yaml',
|
|
59
59
|
);
|
|
60
|
+
|
|
61
|
+
if (installedManifest) {
|
|
62
|
+
return installedManifest;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const versionJsonPath = path.join(targetDir, '.aiox-core', 'version.json');
|
|
66
|
+
if (!fs.existsSync(versionJsonPath)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const versionInfo = fs.readJsonSync(versionJsonPath);
|
|
72
|
+
if (!versionInfo || !versionInfo.version || !versionInfo.fileHashes) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
installed_version: versionInfo.version,
|
|
78
|
+
files: Object.entries(versionInfo.fileHashes).map(([filePath, hash]) => ({
|
|
79
|
+
path: filePath,
|
|
80
|
+
hash,
|
|
81
|
+
modified_by_user: false,
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.warn(`Error loading version.json from ${versionJsonPath}:`, error.message);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
60
88
|
}
|
|
61
89
|
|
|
62
90
|
/**
|
|
@@ -150,13 +178,42 @@ function generateUpgradeReport(sourceManifest, installedManifest, targetDir) {
|
|
|
150
178
|
const absolutePath = path.join(aioxCoreDir, filePath);
|
|
151
179
|
|
|
152
180
|
if (!installedEntry) {
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
181
|
+
// File is not tracked by the installed manifest.
|
|
182
|
+
// In older releases some files existed on disk without being recorded
|
|
183
|
+
// in version metadata. Preserve those local files instead of
|
|
184
|
+
// overwriting them as "new" framework files.
|
|
185
|
+
if (fs.existsSync(absolutePath)) {
|
|
186
|
+
try {
|
|
187
|
+
const currentHash = `sha256:${hashFile(absolutePath)}`;
|
|
188
|
+
if (hashesMatch(currentHash, sourceEntry.hash)) {
|
|
189
|
+
report.unchangedFiles++;
|
|
190
|
+
} else {
|
|
191
|
+
report.userModifiedFiles.push({
|
|
192
|
+
path: filePath,
|
|
193
|
+
type: sourceEntry.type,
|
|
194
|
+
sourceHash: sourceEntry.hash,
|
|
195
|
+
installedHash: null,
|
|
196
|
+
reason: 'Local file exists but is not tracked by installed manifest',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
report.userModifiedFiles.push({
|
|
201
|
+
path: filePath,
|
|
202
|
+
type: sourceEntry.type,
|
|
203
|
+
sourceHash: sourceEntry.hash,
|
|
204
|
+
installedHash: null,
|
|
205
|
+
reason: 'Local file exists but could not be hashed',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
// New file in source
|
|
210
|
+
report.newFiles.push({
|
|
211
|
+
path: filePath,
|
|
212
|
+
type: sourceEntry.type,
|
|
213
|
+
hash: sourceEntry.hash,
|
|
214
|
+
size: sourceEntry.size,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
160
217
|
} else if (!hashesMatch(sourceEntry.hash, installedEntry.hash)) {
|
|
161
218
|
// File changed in source
|
|
162
219
|
// Check if user modified the local copy
|
|
@@ -287,7 +344,7 @@ async function applyUpgrade(report, sourceDir, targetDir, options = {}) {
|
|
|
287
344
|
result.mergeWarnings = result.mergeWarnings || [];
|
|
288
345
|
for (const conflict of conflicts) {
|
|
289
346
|
result.mergeWarnings.push(
|
|
290
|
-
`core-config.yaml: ${conflict.identifier} — ${conflict.reason}
|
|
347
|
+
`core-config.yaml: ${conflict.identifier} — ${conflict.reason}`,
|
|
291
348
|
);
|
|
292
349
|
}
|
|
293
350
|
}
|
|
@@ -271,6 +271,7 @@ async function installDependencies(options = {}) {
|
|
|
271
271
|
success: true,
|
|
272
272
|
offlineMode: true,
|
|
273
273
|
packageManager,
|
|
274
|
+
projectPath,
|
|
274
275
|
};
|
|
275
276
|
}
|
|
276
277
|
|
|
@@ -290,6 +291,7 @@ async function installDependencies(options = {}) {
|
|
|
290
291
|
return {
|
|
291
292
|
success: true,
|
|
292
293
|
packageManager,
|
|
294
|
+
projectPath,
|
|
293
295
|
};
|
|
294
296
|
} else {
|
|
295
297
|
spinner.fail('Installation failed');
|
|
@@ -300,6 +302,7 @@ async function installDependencies(options = {}) {
|
|
|
300
302
|
return {
|
|
301
303
|
success: false,
|
|
302
304
|
packageManager,
|
|
305
|
+
projectPath,
|
|
303
306
|
error: result.error,
|
|
304
307
|
errorCategory: errorInfo.category,
|
|
305
308
|
errorMessage: errorInfo.message,
|
|
@@ -315,6 +318,7 @@ async function installDependencies(options = {}) {
|
|
|
315
318
|
|
|
316
319
|
return {
|
|
317
320
|
success: false,
|
|
321
|
+
projectPath,
|
|
318
322
|
error: error.message,
|
|
319
323
|
errorCategory: errorInfo.category,
|
|
320
324
|
errorMessage: errorInfo.message,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Pro Content Scaffolder
|
|
3
3
|
*
|
|
4
4
|
* Copies premium content (squads, configs, feature registry) from
|
|
5
|
-
* node_modules/@aiox-
|
|
5
|
+
* node_modules/@aiox-squads/pro/ (or a legacy Pro scope) into the user's project after
|
|
6
6
|
* license activation.
|
|
7
7
|
*
|
|
8
8
|
* @module packages/installer/src/pro/pro-scaffolder
|
|
@@ -55,7 +55,7 @@ const SCAFFOLD_ITEMS = [
|
|
|
55
55
|
* Scaffold pro content into user project.
|
|
56
56
|
*
|
|
57
57
|
* @param {string} targetDir - Project root directory
|
|
58
|
-
* @param {string} proSourceDir - Path to pro package content (node_modules/@aiox-
|
|
58
|
+
* @param {string} proSourceDir - Path to pro package content (node_modules/@aiox-squads/pro or legacy scopes)
|
|
59
59
|
* @param {Object} [options={}] - Scaffold options
|
|
60
60
|
* @param {Function} [options.onProgress] - Progress callback ({item, status, message})
|
|
61
61
|
* @param {boolean} [options.force=false] - Force overwrite even if content exists
|
|
@@ -80,7 +80,7 @@ async function scaffoldProContent(targetDir, proSourceDir, options = {}) {
|
|
|
80
80
|
// Validate pro source exists
|
|
81
81
|
if (!await fs.pathExists(proSourceDir)) {
|
|
82
82
|
result.errors.push(
|
|
83
|
-
`Pro package not found at ${proSourceDir}. Run "
|
|
83
|
+
`Pro package not found at ${proSourceDir}. Run "npx aiox-pro install" or "aiox pro setup" first.`,
|
|
84
84
|
);
|
|
85
85
|
return result;
|
|
86
86
|
}
|
|
@@ -160,7 +160,7 @@ async function scaffoldProContent(targetDir, proSourceDir, options = {}) {
|
|
|
160
160
|
result.errors.push(`Rollback errors: ${rollbackResult.errors.join(', ')}`);
|
|
161
161
|
}
|
|
162
162
|
result.warnings.push(
|
|
163
|
-
`Scaffolding failed: ${error.message}. ${rollbackResult.removed} files cleaned up
|
|
163
|
+
`Scaffolding failed: ${error.message}. ${rollbackResult.removed} files cleaned up.`,
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -425,7 +425,7 @@ async function installSquadCommands(targetDir) {
|
|
|
425
425
|
for (const agentFile of agentFiles) {
|
|
426
426
|
await fs.copy(
|
|
427
427
|
path.join(agentsDir, agentFile),
|
|
428
|
-
path.join(destDir, agentFile)
|
|
428
|
+
path.join(destDir, agentFile),
|
|
429
429
|
);
|
|
430
430
|
files.push(path.relative(targetDir, path.join(destDir, agentFile)).replace(/\\/g, '/'));
|
|
431
431
|
}
|
|
@@ -22,6 +22,91 @@ const https = require('https');
|
|
|
22
22
|
const { execSync } = require('child_process');
|
|
23
23
|
const { hashFile, hashesMatch } = require('../installer/file-hasher');
|
|
24
24
|
const { PostInstallValidator, formatReport: formatValidationReport } = require('../installer/post-install-validator');
|
|
25
|
+
const {
|
|
26
|
+
loadSourceManifest,
|
|
27
|
+
loadInstalledManifest,
|
|
28
|
+
generateUpgradeReport,
|
|
29
|
+
applyUpgrade,
|
|
30
|
+
updateInstalledManifest,
|
|
31
|
+
} = require('../installer/brownfield-upgrader');
|
|
32
|
+
|
|
33
|
+
function manifestToInstalledManifest(manifest) {
|
|
34
|
+
if (!manifest || !Array.isArray(manifest.files)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
installed_version: manifest.version || 'unknown',
|
|
40
|
+
files: manifest.files
|
|
41
|
+
.filter((entry) => entry && entry.path && entry.hash)
|
|
42
|
+
.map((entry) => ({
|
|
43
|
+
path: entry.path,
|
|
44
|
+
hash: entry.hash,
|
|
45
|
+
type: entry.type,
|
|
46
|
+
modified_by_user: false,
|
|
47
|
+
})),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function extractManifestFileHashes(manifest) {
|
|
52
|
+
if (!manifest || !Array.isArray(manifest.files)) {
|
|
53
|
+
return {};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const fileHashes = {};
|
|
57
|
+
for (const entry of manifest.files) {
|
|
58
|
+
if (entry && entry.path && entry.hash) {
|
|
59
|
+
fileHashes[entry.path] = entry.hash;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return fileHashes;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function selectInstalledManifest(projectManifest, packageManifest) {
|
|
67
|
+
if (!projectManifest) {
|
|
68
|
+
return packageManifest;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!packageManifest) {
|
|
72
|
+
return projectManifest;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const projectFiles = Array.isArray(projectManifest.files) ? projectManifest.files : [];
|
|
76
|
+
const packageFiles = Array.isArray(packageManifest.files) ? packageManifest.files : [];
|
|
77
|
+
|
|
78
|
+
if (packageFiles.length === 0) {
|
|
79
|
+
return projectManifest;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (projectFiles.length === 0) {
|
|
83
|
+
return packageManifest;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const mergedFiles = new Map();
|
|
87
|
+
|
|
88
|
+
for (const entry of packageFiles) {
|
|
89
|
+
if (entry && entry.path) {
|
|
90
|
+
mergedFiles.set(entry.path, entry);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for (const entry of projectFiles) {
|
|
95
|
+
if (entry && entry.path && !mergedFiles.has(entry.path)) {
|
|
96
|
+
mergedFiles.set(entry.path, entry);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
...projectManifest,
|
|
102
|
+
installed_version:
|
|
103
|
+
packageManifest.installed_version ||
|
|
104
|
+
packageManifest.version ||
|
|
105
|
+
projectManifest.installed_version ||
|
|
106
|
+
projectManifest.version,
|
|
107
|
+
files: Array.from(mergedFiles.values()),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
25
110
|
|
|
26
111
|
/**
|
|
27
112
|
* Update status types
|
|
@@ -78,6 +163,8 @@ class AIOXUpdater {
|
|
|
78
163
|
this.versionInfo = null;
|
|
79
164
|
this.changelog = null;
|
|
80
165
|
this.backupDir = null;
|
|
166
|
+
this.lastSourcePackageRoot = null;
|
|
167
|
+
this.lastSourceManifest = null;
|
|
81
168
|
}
|
|
82
169
|
|
|
83
170
|
/**
|
|
@@ -467,15 +554,21 @@ class AIOXUpdater {
|
|
|
467
554
|
}
|
|
468
555
|
|
|
469
556
|
result.filesUpdated = updateApplied.filesUpdated;
|
|
470
|
-
result.filesPreserved = customizations.customized.length;
|
|
557
|
+
result.filesPreserved = updateApplied.filesSkipped?.length || customizations.customized.length;
|
|
558
|
+
this.lastSourcePackageRoot = updateApplied.sourcePackageRoot || this.lastSourcePackageRoot;
|
|
559
|
+
this.lastSourceManifest = updateApplied.sourceManifest || this.lastSourceManifest;
|
|
471
560
|
|
|
472
561
|
// Update version.json
|
|
473
562
|
onProgress('finalizing', 'Updating version info...');
|
|
474
|
-
await this.updateVersionInfo(checkResult.latest
|
|
563
|
+
await this.updateVersionInfo(checkResult.latest, {
|
|
564
|
+
fileHashes: extractManifestFileHashes(this.lastSourceManifest),
|
|
565
|
+
});
|
|
475
566
|
|
|
476
567
|
// Validate installation after update
|
|
477
568
|
onProgress('validating', 'Validating installation...');
|
|
478
|
-
const validationResult = await this.validateAfterUpdate(
|
|
569
|
+
const validationResult = await this.validateAfterUpdate({
|
|
570
|
+
sourceDir: this.lastSourcePackageRoot,
|
|
571
|
+
});
|
|
479
572
|
result.validationPassed = validationResult.success;
|
|
480
573
|
result.integrityScore = validationResult.integrityScore;
|
|
481
574
|
|
|
@@ -525,6 +618,7 @@ class AIOXUpdater {
|
|
|
525
618
|
const filesToBackup = [
|
|
526
619
|
'version.json',
|
|
527
620
|
'install-manifest.yaml',
|
|
621
|
+
'install-manifest.yaml.minisig',
|
|
528
622
|
];
|
|
529
623
|
|
|
530
624
|
for (const file of filesToBackup) {
|
|
@@ -586,6 +680,9 @@ class AIOXUpdater {
|
|
|
586
680
|
};
|
|
587
681
|
|
|
588
682
|
try {
|
|
683
|
+
const previousPackageRoot = path.join(this.projectRoot, 'node_modules', 'aiox-core');
|
|
684
|
+
const previousSourceManifest = loadSourceManifest(path.join(previousPackageRoot, '.aiox-core'));
|
|
685
|
+
|
|
589
686
|
// Use npm to update the package
|
|
590
687
|
const cmd = `npm install aiox-core@${targetVersion} --save-exact`;
|
|
591
688
|
this.log(`Running: ${cmd}`);
|
|
@@ -596,11 +693,54 @@ class AIOXUpdater {
|
|
|
596
693
|
timeout: 120000, // 2 minutes
|
|
597
694
|
});
|
|
598
695
|
|
|
599
|
-
|
|
600
|
-
|
|
696
|
+
const sourcePackageRoot = path.join(this.projectRoot, 'node_modules', 'aiox-core');
|
|
697
|
+
const sourceAioxCore = path.join(sourcePackageRoot, '.aiox-core');
|
|
698
|
+
const sourceManifest = loadSourceManifest(sourceAioxCore);
|
|
699
|
+
|
|
700
|
+
if (!sourceManifest) {
|
|
701
|
+
result.error = 'Updated package does not contain install-manifest.yaml';
|
|
702
|
+
return result;
|
|
703
|
+
}
|
|
601
704
|
|
|
602
|
-
|
|
603
|
-
|
|
705
|
+
const installedManifest = selectInstalledManifest(
|
|
706
|
+
loadInstalledManifest(this.projectRoot),
|
|
707
|
+
manifestToInstalledManifest(previousSourceManifest),
|
|
708
|
+
);
|
|
709
|
+
const report = generateUpgradeReport(sourceManifest, installedManifest, this.projectRoot);
|
|
710
|
+
const applyResult = await applyUpgrade(report, sourceAioxCore, this.projectRoot, {
|
|
711
|
+
includeModified: true,
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
if (!applyResult.success) {
|
|
715
|
+
result.error = applyResult.errors.map((entry) => `${entry.path}: ${entry.error}`).join('; ');
|
|
716
|
+
return result;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
await fs.copy(
|
|
720
|
+
path.join(sourceAioxCore, 'install-manifest.yaml'),
|
|
721
|
+
path.join(this.aioxCoreDir, 'install-manifest.yaml'),
|
|
722
|
+
{ overwrite: true },
|
|
723
|
+
);
|
|
724
|
+
|
|
725
|
+
const sourceSignaturePath = path.join(sourceAioxCore, 'install-manifest.yaml.minisig');
|
|
726
|
+
const targetSignaturePath = path.join(this.aioxCoreDir, 'install-manifest.yaml.minisig');
|
|
727
|
+
if (await fs.pathExists(sourceSignaturePath)) {
|
|
728
|
+
await fs.copy(
|
|
729
|
+
sourceSignaturePath,
|
|
730
|
+
targetSignaturePath,
|
|
731
|
+
{ overwrite: true },
|
|
732
|
+
);
|
|
733
|
+
} else if (await fs.pathExists(targetSignaturePath)) {
|
|
734
|
+
await fs.remove(targetSignaturePath);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
updateInstalledManifest(this.projectRoot, sourceManifest, `aiox-core@${targetVersion}`);
|
|
738
|
+
|
|
739
|
+
result.success = true;
|
|
740
|
+
result.filesUpdated = applyResult.filesInstalled.length;
|
|
741
|
+
result.filesSkipped = applyResult.filesSkipped;
|
|
742
|
+
result.sourceManifest = sourceManifest;
|
|
743
|
+
result.sourcePackageRoot = sourcePackageRoot;
|
|
604
744
|
|
|
605
745
|
return result;
|
|
606
746
|
} catch (error) {
|
|
@@ -615,7 +755,7 @@ class AIOXUpdater {
|
|
|
615
755
|
* @param {string} newVersion - New version
|
|
616
756
|
* @returns {Promise<void>}
|
|
617
757
|
*/
|
|
618
|
-
async updateVersionInfo(newVersion) {
|
|
758
|
+
async updateVersionInfo(newVersion, options = {}) {
|
|
619
759
|
const versionJsonPath = path.join(this.aioxCoreDir, 'version.json');
|
|
620
760
|
|
|
621
761
|
const versionInfo = {
|
|
@@ -623,7 +763,7 @@ class AIOXUpdater {
|
|
|
623
763
|
installedAt: new Date().toISOString(),
|
|
624
764
|
updatedAt: new Date().toISOString(),
|
|
625
765
|
mode: this.versionInfo?.mode || 'project-development',
|
|
626
|
-
fileHashes: {},
|
|
766
|
+
fileHashes: options.fileHashes || {},
|
|
627
767
|
};
|
|
628
768
|
|
|
629
769
|
await fs.writeJson(versionJsonPath, versionInfo, { spaces: 2 });
|
|
@@ -646,7 +786,7 @@ class AIOXUpdater {
|
|
|
646
786
|
};
|
|
647
787
|
|
|
648
788
|
try {
|
|
649
|
-
const validator = new PostInstallValidator(this.projectRoot, null, {
|
|
789
|
+
const validator = new PostInstallValidator(this.projectRoot, options.sourceDir || null, {
|
|
650
790
|
verifyHashes: true,
|
|
651
791
|
detectExtras: false,
|
|
652
792
|
verbose: options.verbose || this.options.verbose,
|
|
@@ -809,4 +949,5 @@ module.exports = {
|
|
|
809
949
|
FileAction,
|
|
810
950
|
formatCheckResult,
|
|
811
951
|
formatUpdateResult,
|
|
952
|
+
selectInstalledManifest,
|
|
812
953
|
};
|
|
@@ -16,6 +16,7 @@ const { spawnSync } = require('child_process');
|
|
|
16
16
|
const { getIDEConfig } = require('../config/ide-configs');
|
|
17
17
|
const { validateProjectName } = require('./validators');
|
|
18
18
|
const { getMergeStrategy, hasMergeStrategy } = require('../merger/index.js');
|
|
19
|
+
const { syncSkills } = require('../../../../.aiox-core/infrastructure/scripts/codex-skills-sync/index');
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Render template with variables
|
|
@@ -83,7 +84,11 @@ async function backupFile(filePath) {
|
|
|
83
84
|
async function promptFileExists(filePath, options = {}) {
|
|
84
85
|
const { projectType, forceMerge, noMerge } = options;
|
|
85
86
|
const canMerge = !noMerge && hasMergeStrategy(filePath);
|
|
86
|
-
const
|
|
87
|
+
const normalizedProjectType = String(projectType || '').toLowerCase();
|
|
88
|
+
const isBrownfield =
|
|
89
|
+
normalizedProjectType === 'brownfield' ||
|
|
90
|
+
normalizedProjectType === 'existing_aiox' ||
|
|
91
|
+
normalizedProjectType === 'existing-aiox';
|
|
87
92
|
|
|
88
93
|
// If force merge is set and merge is available, return merge directly
|
|
89
94
|
if (forceMerge && canMerge) {
|
|
@@ -264,7 +269,7 @@ async function copyAgentFiles(projectRoot, agentFolder, ideConfig = null) {
|
|
|
264
269
|
const targetPath = path.join(targetDir, filename);
|
|
265
270
|
await fs.writeFile(targetPath, content, 'utf8');
|
|
266
271
|
copiedFiles.push(targetPath);
|
|
267
|
-
} catch (
|
|
272
|
+
} catch (_transformError) {
|
|
268
273
|
// Fallback: copy raw file with .agent.md extension
|
|
269
274
|
const targetPath = path.join(targetDir, `${agentName}.agent.md`);
|
|
270
275
|
await fs.copy(sourcePath, targetPath);
|
|
@@ -538,7 +543,7 @@ async function generateIDEConfigs(selectedIDEs, wizardState, options = {}) {
|
|
|
538
543
|
|
|
539
544
|
// BUG-3 fix (INS-1): Copy .claude/hooks/ folder (SYNAPSE engine + precompact)
|
|
540
545
|
spinner.start('Copying Claude Code hooks...');
|
|
541
|
-
const hookFiles = await copyClaudeHooksFolder(projectRoot);
|
|
546
|
+
const hookFiles = await copyClaudeHooksFolder(projectRoot, wizardState);
|
|
542
547
|
createdFiles.push(...hookFiles);
|
|
543
548
|
if (hookFiles.length > 0) {
|
|
544
549
|
createdFolders.push(path.join(projectRoot, '.claude', 'hooks'));
|
|
@@ -656,9 +661,10 @@ function showSuccessSummary(result) {
|
|
|
656
661
|
* BUG-3 fix (INS-1): Copy .claude/hooks/ folder during installation
|
|
657
662
|
* Only copies JS hooks that work without external dependencies (Python, etc.)
|
|
658
663
|
* @param {string} projectRoot - Project root directory
|
|
664
|
+
* @param {Object} [wizardState={}] - Current wizard state
|
|
659
665
|
* @returns {Promise<string[]>} List of copied files
|
|
660
666
|
*/
|
|
661
|
-
async function copyClaudeHooksFolder(projectRoot) {
|
|
667
|
+
async function copyClaudeHooksFolder(projectRoot, wizardState = {}) {
|
|
662
668
|
const sourceDir = path.join(__dirname, '..', '..', '..', '..', '.claude', 'hooks');
|
|
663
669
|
const targetDir = path.join(projectRoot, '.claude', 'hooks');
|
|
664
670
|
const copiedFiles = [];
|
|
@@ -674,13 +680,17 @@ async function copyClaudeHooksFolder(projectRoot) {
|
|
|
674
680
|
|
|
675
681
|
await fs.ensureDir(targetDir);
|
|
676
682
|
|
|
677
|
-
|
|
678
|
-
const HOOKS_TO_COPY = [
|
|
683
|
+
const HOOKS_FREE = [
|
|
679
684
|
'synapse-engine.cjs',
|
|
680
685
|
'code-intel-pretool.cjs',
|
|
681
|
-
'precompact-session-digest.cjs',
|
|
682
686
|
'README.md',
|
|
683
687
|
];
|
|
688
|
+
const HOOKS_PRO_ONLY = [
|
|
689
|
+
'precompact-session-digest.cjs',
|
|
690
|
+
];
|
|
691
|
+
const HOOKS_TO_COPY = shouldCopyProHooks(wizardState)
|
|
692
|
+
? [...HOOKS_FREE, ...HOOKS_PRO_ONLY]
|
|
693
|
+
: HOOKS_FREE;
|
|
684
694
|
|
|
685
695
|
const files = await fs.readdir(sourceDir);
|
|
686
696
|
|
|
@@ -702,6 +712,31 @@ async function copyClaudeHooksFolder(projectRoot) {
|
|
|
702
712
|
return copiedFiles;
|
|
703
713
|
}
|
|
704
714
|
|
|
715
|
+
/**
|
|
716
|
+
* Decide whether Pro-only hooks should be copied.
|
|
717
|
+
* Explicit wizard tier wins; otherwise fall back to runtime Pro detection.
|
|
718
|
+
* Supports wizardState.proTier as a legacy alias from older Pro setup state.
|
|
719
|
+
*
|
|
720
|
+
* @param {Object} [wizardState={}] - Current wizard state
|
|
721
|
+
* @returns {boolean} true when Pro-only hooks should be installed
|
|
722
|
+
*/
|
|
723
|
+
function shouldCopyProHooks(wizardState = {}) {
|
|
724
|
+
const tier = String(wizardState.tier || wizardState.proTier || '').toLowerCase();
|
|
725
|
+
if (tier === 'pro') return true;
|
|
726
|
+
if (['free', 'community', 'core'].includes(tier)) return false;
|
|
727
|
+
|
|
728
|
+
if (wizardState.pro && typeof wizardState.pro.enabled === 'boolean') {
|
|
729
|
+
return wizardState.pro.enabled;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
try {
|
|
733
|
+
const { isProAvailable } = require('../../../../bin/utils/pro-detector');
|
|
734
|
+
return isProAvailable();
|
|
735
|
+
} catch {
|
|
736
|
+
return false;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
705
740
|
/**
|
|
706
741
|
* Hook event mapping: fileName → { event, matcher, timeout }
|
|
707
742
|
* Maps each .cjs hook file to its correct Claude Code event.
|
|
@@ -1090,6 +1125,35 @@ async function copySkillFiles(projectRoot, _sourceRoot) {
|
|
|
1090
1125
|
return { count, skipped: false };
|
|
1091
1126
|
}
|
|
1092
1127
|
|
|
1128
|
+
/**
|
|
1129
|
+
* Generate project-local Codex skills from canonical agent definitions.
|
|
1130
|
+
* This repo uses local-first Codex activation, so installed projects must
|
|
1131
|
+
* include `.codex/skills` without requiring a manual post-install sync.
|
|
1132
|
+
* @param {string} projectRoot - Project root directory
|
|
1133
|
+
* @returns {{count: number, skipped: boolean}} Generation result
|
|
1134
|
+
*/
|
|
1135
|
+
function generateCodexSkills(projectRoot) {
|
|
1136
|
+
const sourceDir = path.join(projectRoot, '.aiox-core', 'development', 'agents');
|
|
1137
|
+
const localSkillsDir = path.join(projectRoot, '.codex', 'skills');
|
|
1138
|
+
|
|
1139
|
+
if (!fs.existsSync(sourceDir)) {
|
|
1140
|
+
return { count: 0, skipped: true };
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
const result = syncSkills({
|
|
1144
|
+
projectRoot,
|
|
1145
|
+
sourceDir,
|
|
1146
|
+
localSkillsDir,
|
|
1147
|
+
dryRun: false,
|
|
1148
|
+
quiet: true,
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
return {
|
|
1152
|
+
count: result.generated || 0,
|
|
1153
|
+
skipped: false,
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1093
1157
|
/**
|
|
1094
1158
|
* Copy extra .claude/commands/ files during installation (Story INS-4.3, Gap #12)
|
|
1095
1159
|
* Uses an allowlist of distributable top-level directories to prevent leaking
|
|
@@ -1174,8 +1238,10 @@ module.exports = {
|
|
|
1174
1238
|
promptFileExists,
|
|
1175
1239
|
generateTemplateVariables,
|
|
1176
1240
|
copyClaudeHooksFolder,
|
|
1241
|
+
shouldCopyProHooks,
|
|
1177
1242
|
createClaudeSettingsLocal,
|
|
1178
1243
|
copySkillFiles,
|
|
1244
|
+
generateCodexSkills,
|
|
1179
1245
|
copyExtraCommandFiles,
|
|
1180
1246
|
copyGeminiHooksFolder,
|
|
1181
1247
|
createGeminiSettings,
|