mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-10 03:13:29 +08:00
feat: wire manifest resolution into install execution (#509)
This commit is contained in:
@@ -10,9 +10,12 @@ const path = require('path');
|
||||
const {
|
||||
loadInstallManifests,
|
||||
listInstallComponents,
|
||||
listLegacyCompatibilityLanguages,
|
||||
listInstallModules,
|
||||
listInstallProfiles,
|
||||
resolveInstallPlan,
|
||||
resolveLegacyCompatibilitySelection,
|
||||
validateInstallModuleIds,
|
||||
} = require('../../scripts/lib/install-manifests');
|
||||
|
||||
function test(name, fn) {
|
||||
@@ -75,6 +78,15 @@ function runTests() {
|
||||
'Should include capability:security');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('lists supported legacy compatibility languages', () => {
|
||||
const languages = listLegacyCompatibilityLanguages();
|
||||
assert.ok(languages.includes('typescript'));
|
||||
assert.ok(languages.includes('python'));
|
||||
assert.ok(languages.includes('go'));
|
||||
assert.ok(languages.includes('golang'));
|
||||
assert.ok(languages.includes('kotlin'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('resolves a real project profile with target-specific skips', () => {
|
||||
const projectRoot = '/workspace/app';
|
||||
const plan = resolveInstallPlan({ profileId: 'developer', target: 'cursor', projectRoot });
|
||||
@@ -97,6 +109,18 @@ function runTests() {
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('resolves antigravity profiles by skipping incompatible dependency trees', () => {
|
||||
const projectRoot = '/workspace/app';
|
||||
const plan = resolveInstallPlan({ profileId: 'core', target: 'antigravity', projectRoot });
|
||||
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, ['rules-core', 'agents-core', 'commands-core']);
|
||||
assert.ok(plan.skippedModuleIds.includes('hooks-runtime'));
|
||||
assert.ok(plan.skippedModuleIds.includes('platform-configs'));
|
||||
assert.ok(plan.skippedModuleIds.includes('workflow-quality'));
|
||||
assert.strictEqual(plan.targetAdapterId, 'antigravity-project');
|
||||
assert.strictEqual(plan.targetRoot, path.join(projectRoot, '.agent'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('resolves explicit modules with dependency expansion', () => {
|
||||
const plan = resolveInstallPlan({ moduleIds: ['security'] });
|
||||
assert.ok(plan.selectedModuleIds.includes('security'), 'Should include requested module');
|
||||
@@ -106,6 +130,50 @@ function runTests() {
|
||||
'Should include nested dependency');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('validates explicit module IDs against the real manifest catalog', () => {
|
||||
const moduleIds = validateInstallModuleIds(['security', 'security', 'platform-configs']);
|
||||
assert.deepStrictEqual(moduleIds, ['security', 'platform-configs']);
|
||||
assert.throws(
|
||||
() => validateInstallModuleIds(['ghost-module']),
|
||||
/Unknown install module: ghost-module/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('resolves legacy compatibility selections into manifest module IDs', () => {
|
||||
const selection = resolveLegacyCompatibilitySelection({
|
||||
target: 'cursor',
|
||||
legacyLanguages: ['typescript', 'go', 'golang'],
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(selection.legacyLanguages, ['typescript', 'go', 'golang']);
|
||||
assert.ok(selection.moduleIds.includes('rules-core'));
|
||||
assert.ok(selection.moduleIds.includes('agents-core'));
|
||||
assert.ok(selection.moduleIds.includes('commands-core'));
|
||||
assert.ok(selection.moduleIds.includes('hooks-runtime'));
|
||||
assert.ok(selection.moduleIds.includes('platform-configs'));
|
||||
assert.ok(selection.moduleIds.includes('workflow-quality'));
|
||||
assert.ok(selection.moduleIds.includes('framework-language'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('keeps antigravity legacy compatibility selections target-safe', () => {
|
||||
const selection = resolveLegacyCompatibilitySelection({
|
||||
target: 'antigravity',
|
||||
legacyLanguages: ['typescript'],
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(selection.moduleIds, ['rules-core', 'agents-core', 'commands-core']);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects unknown legacy compatibility languages', () => {
|
||||
assert.throws(
|
||||
() => resolveLegacyCompatibilitySelection({
|
||||
target: 'cursor',
|
||||
legacyLanguages: ['brainfuck'],
|
||||
}),
|
||||
/Unknown legacy language: brainfuck/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('resolves included and excluded user-facing components', () => {
|
||||
const plan = resolveInstallPlan({
|
||||
profileId: 'core',
|
||||
@@ -146,7 +214,7 @@ function runTests() {
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('throws when a dependency does not support the requested target', () => {
|
||||
if (test('skips a requested module when its dependency chain does not support the target', () => {
|
||||
const repoRoot = createTestRepo();
|
||||
writeJson(path.join(repoRoot, 'manifests', 'install-modules.json'), {
|
||||
version: 1,
|
||||
@@ -182,10 +250,9 @@ function runTests() {
|
||||
}
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => resolveInstallPlan({ repoRoot, profileId: 'core', target: 'claude' }),
|
||||
/does not support target claude/
|
||||
);
|
||||
const plan = resolveInstallPlan({ repoRoot, profileId: 'core', target: 'claude' });
|
||||
assert.deepStrictEqual(plan.selectedModuleIds, []);
|
||||
assert.deepStrictEqual(plan.skippedModuleIds, ['parent']);
|
||||
cleanupTestRepo(repoRoot);
|
||||
})) passed++; else failed++;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ function runTests() {
|
||||
'scripts/install-apply.js',
|
||||
'--target', 'cursor',
|
||||
'--profile', 'developer',
|
||||
'--modules', 'platform-configs, workflow-quality ,platform-configs',
|
||||
'--with', 'lang:typescript',
|
||||
'--without', 'capability:media',
|
||||
'--config', 'ecc-install.json',
|
||||
@@ -43,6 +44,7 @@ function runTests() {
|
||||
assert.strictEqual(parsed.target, 'cursor');
|
||||
assert.strictEqual(parsed.profileId, 'developer');
|
||||
assert.strictEqual(parsed.configPath, 'ecc-install.json');
|
||||
assert.deepStrictEqual(parsed.moduleIds, ['platform-configs', 'workflow-quality']);
|
||||
assert.deepStrictEqual(parsed.includeComponentIds, ['lang:typescript']);
|
||||
assert.deepStrictEqual(parsed.excludeComponentIds, ['capability:media']);
|
||||
assert.strictEqual(parsed.dryRun, true);
|
||||
@@ -58,9 +60,9 @@ function runTests() {
|
||||
languages: ['typescript', 'python']
|
||||
});
|
||||
|
||||
assert.strictEqual(request.mode, 'legacy');
|
||||
assert.strictEqual(request.mode, 'legacy-compat');
|
||||
assert.strictEqual(request.target, 'claude');
|
||||
assert.deepStrictEqual(request.languages, ['typescript', 'python']);
|
||||
assert.deepStrictEqual(request.legacyLanguages, ['typescript', 'python']);
|
||||
assert.deepStrictEqual(request.moduleIds, []);
|
||||
assert.strictEqual(request.profileId, null);
|
||||
})) passed++; else failed++;
|
||||
@@ -80,7 +82,7 @@ function runTests() {
|
||||
assert.strictEqual(request.profileId, 'developer');
|
||||
assert.deepStrictEqual(request.includeComponentIds, ['lang:typescript']);
|
||||
assert.deepStrictEqual(request.excludeComponentIds, ['capability:media']);
|
||||
assert.deepStrictEqual(request.languages, []);
|
||||
assert.deepStrictEqual(request.legacyLanguages, []);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('merges config-backed component selections with CLI overrides', () => {
|
||||
@@ -111,6 +113,20 @@ function runTests() {
|
||||
assert.strictEqual(request.configPath, '/workspace/app/ecc-install.json');
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('validates explicit module IDs against the manifest catalog', () => {
|
||||
assert.throws(
|
||||
() => normalizeInstallRequest({
|
||||
target: 'cursor',
|
||||
profileId: null,
|
||||
moduleIds: ['ghost-module'],
|
||||
includeComponentIds: [],
|
||||
excludeComponentIds: [],
|
||||
languages: [],
|
||||
}),
|
||||
/Unknown install module: ghost-module/
|
||||
);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects mixing legacy languages with manifest flags', () => {
|
||||
assert.throws(
|
||||
() => normalizeInstallRequest({
|
||||
|
||||
@@ -60,16 +60,18 @@ function main() {
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
const payload = parseJson(result.stdout);
|
||||
assert.strictEqual(payload.dryRun, true);
|
||||
assert.strictEqual(payload.plan.mode, 'legacy');
|
||||
assert.deepStrictEqual(payload.plan.languages, ['typescript']);
|
||||
assert.strictEqual(payload.plan.mode, 'legacy-compat');
|
||||
assert.deepStrictEqual(payload.plan.legacyLanguages, ['typescript']);
|
||||
assert.ok(payload.plan.selectedModuleIds.includes('framework-language'));
|
||||
}],
|
||||
['routes implicit top-level args to install', () => {
|
||||
const result = runCli(['--dry-run', '--json', 'typescript']);
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
const payload = parseJson(result.stdout);
|
||||
assert.strictEqual(payload.dryRun, true);
|
||||
assert.strictEqual(payload.plan.mode, 'legacy');
|
||||
assert.deepStrictEqual(payload.plan.languages, ['typescript']);
|
||||
assert.strictEqual(payload.plan.mode, 'legacy-compat');
|
||||
assert.deepStrictEqual(payload.plan.legacyLanguages, ['typescript']);
|
||||
assert.ok(payload.plan.selectedModuleIds.includes('framework-language'));
|
||||
}],
|
||||
['delegates plan command', () => {
|
||||
const result = runCli(['plan', '--list-profiles', '--json']);
|
||||
|
||||
@@ -89,18 +89,26 @@ function runTests() {
|
||||
const result = run(['typescript'], { cwd: projectDir, homeDir });
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
|
||||
const rulesDir = path.join(homeDir, '.claude', 'rules');
|
||||
assert.ok(fs.existsSync(path.join(rulesDir, 'common', 'coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(rulesDir, 'typescript', 'testing.md')));
|
||||
const claudeRoot = path.join(homeDir, '.claude');
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'rules', 'common', 'coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'rules', 'typescript', 'testing.md')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'commands', 'plan.md')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'scripts', 'hooks', 'session-end.js')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'skills', 'tdd-workflow', 'SKILL.md')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'skills', 'coding-standards', 'SKILL.md')));
|
||||
assert.ok(fs.existsSync(path.join(claudeRoot, 'plugin.json')));
|
||||
|
||||
const statePath = path.join(homeDir, '.claude', 'ecc', 'install-state.json');
|
||||
const state = readJson(statePath);
|
||||
assert.strictEqual(state.target.id, 'claude-home');
|
||||
assert.deepStrictEqual(state.request.legacyLanguages, ['typescript']);
|
||||
assert.strictEqual(state.request.legacyMode, true);
|
||||
assert.deepStrictEqual(state.request.modules, []);
|
||||
assert.ok(state.resolution.selectedModules.includes('rules-core'));
|
||||
assert.ok(state.resolution.selectedModules.includes('framework-language'));
|
||||
assert.ok(
|
||||
state.operations.some(operation => (
|
||||
operation.destinationPath === path.join(rulesDir, 'common', 'coding-style.md')
|
||||
operation.destinationPath === path.join(claudeRoot, 'rules', 'common', 'coding-style.md')
|
||||
)),
|
||||
'Should record common rule file operation'
|
||||
);
|
||||
@@ -118,22 +126,28 @@ function runTests() {
|
||||
const result = run(['--target', 'cursor', 'typescript'], { cwd: projectDir, homeDir });
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'rules', 'common-coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'rules', 'typescript-testing.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'rules', 'common', 'coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'rules', 'typescript', 'testing.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'agents', 'architect.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'commands', 'plan.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'hooks.json')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'hooks', 'session-start.js')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'skills', 'article-writing', 'SKILL.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'skills', 'tdd-workflow', 'SKILL.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'skills', 'coding-standards', 'SKILL.md')));
|
||||
|
||||
const statePath = path.join(projectDir, '.cursor', 'ecc-install-state.json');
|
||||
const state = readJson(statePath);
|
||||
const normalizedProjectDir = fs.realpathSync(projectDir);
|
||||
assert.strictEqual(state.target.id, 'cursor-project');
|
||||
assert.strictEqual(state.target.root, path.join(normalizedProjectDir, '.cursor'));
|
||||
assert.deepStrictEqual(state.request.legacyLanguages, ['typescript']);
|
||||
assert.strictEqual(state.request.legacyMode, true);
|
||||
assert.ok(state.resolution.selectedModules.includes('framework-language'));
|
||||
assert.ok(
|
||||
state.operations.some(operation => (
|
||||
operation.destinationPath === path.join(normalizedProjectDir, '.cursor', 'hooks', 'session-start.js')
|
||||
operation.destinationPath === path.join(normalizedProjectDir, '.cursor', 'commands', 'plan.md')
|
||||
)),
|
||||
'Should record hook file copy operation'
|
||||
'Should record manifest command file copy operation'
|
||||
);
|
||||
} finally {
|
||||
cleanup(homeDir);
|
||||
@@ -149,20 +163,22 @@ function runTests() {
|
||||
const result = run(['--target', 'antigravity', 'typescript'], { cwd: projectDir, homeDir });
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'rules', 'common-coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'rules', 'typescript-testing.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'workflows', 'code-review.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'skills', 'architect.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'skills', 'article-writing', 'SKILL.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'rules', 'common', 'coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'rules', 'typescript', 'testing.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'commands', 'plan.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'agents', 'architect.md')));
|
||||
|
||||
const statePath = path.join(projectDir, '.agent', 'ecc-install-state.json');
|
||||
const state = readJson(statePath);
|
||||
assert.strictEqual(state.target.id, 'antigravity-project');
|
||||
assert.deepStrictEqual(state.request.legacyLanguages, ['typescript']);
|
||||
assert.strictEqual(state.request.legacyMode, true);
|
||||
assert.deepStrictEqual(state.resolution.selectedModules, ['rules-core', 'agents-core', 'commands-core']);
|
||||
assert.ok(
|
||||
state.operations.some(operation => (
|
||||
operation.destinationPath.endsWith(path.join('.agent', 'workflows', 'code-review.md'))
|
||||
operation.destinationPath.endsWith(path.join('.agent', 'commands', 'plan.md'))
|
||||
)),
|
||||
'Should record workflow file copy operation'
|
||||
'Should record manifest command file copy operation'
|
||||
);
|
||||
} finally {
|
||||
cleanup(homeDir);
|
||||
@@ -181,6 +197,8 @@ function runTests() {
|
||||
});
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
assert.ok(result.stdout.includes('Dry-run install plan'));
|
||||
assert.ok(result.stdout.includes('Mode: legacy-compat'));
|
||||
assert.ok(result.stdout.includes('Legacy languages: typescript'));
|
||||
assert.ok(!fs.existsSync(path.join(projectDir, '.cursor', 'hooks.json')));
|
||||
assert.ok(!fs.existsSync(path.join(projectDir, '.cursor', 'ecc-install-state.json')));
|
||||
} finally {
|
||||
@@ -240,6 +258,31 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('installs antigravity manifest profiles while skipping incompatible modules', () => {
|
||||
const homeDir = createTempDir('install-apply-home-');
|
||||
const projectDir = createTempDir('install-apply-project-');
|
||||
|
||||
try {
|
||||
const result = run(['--target', 'antigravity', '--profile', 'core'], { cwd: projectDir, homeDir });
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'rules', 'common', 'coding-style.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'agents', 'architect.md')));
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.agent', 'commands', 'plan.md')));
|
||||
assert.ok(!fs.existsSync(path.join(projectDir, '.agent', 'skills', 'tdd-workflow', 'SKILL.md')));
|
||||
|
||||
const state = readJson(path.join(projectDir, '.agent', 'ecc-install-state.json'));
|
||||
assert.strictEqual(state.request.profile, 'core');
|
||||
assert.strictEqual(state.request.legacyMode, false);
|
||||
assert.deepStrictEqual(state.resolution.selectedModules, ['rules-core', 'agents-core', 'commands-core']);
|
||||
assert.ok(state.resolution.skippedModules.includes('workflow-quality'));
|
||||
assert.ok(state.resolution.skippedModules.includes('platform-configs'));
|
||||
} finally {
|
||||
cleanup(homeDir);
|
||||
cleanup(projectDir);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('installs explicit modules for cursor using manifest operations', () => {
|
||||
const homeDir = createTempDir('install-apply-home-');
|
||||
const projectDir = createTempDir('install-apply-project-');
|
||||
@@ -270,6 +313,12 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects unknown explicit manifest modules before resolution', () => {
|
||||
const result = run(['--modules', 'ghost-module']);
|
||||
assert.strictEqual(result.code, 1);
|
||||
assert.ok(result.stderr.includes('Unknown install module: ghost-module'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('installs from ecc-install.json and persists component selections', () => {
|
||||
const homeDir = createTempDir('install-apply-home-');
|
||||
const projectDir = createTempDir('install-apply-project-');
|
||||
|
||||
Reference in New Issue
Block a user