feat(skills): migrate Crush to config-driven native skills
Move Crush installer from .crush/commands to .crush/skills with SKILL.md directory output. Add legacy cleanup and 9 test assertions.
This commit is contained in:
parent
6cc343d61f
commit
41c9b6bcfd
|
|
@ -1015,6 +1015,66 @@ async function runTests() {
|
||||||
|
|
||||||
console.log('');
|
console.log('');
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Test 20: Crush Native Skills Install
|
||||||
|
// ============================================================
|
||||||
|
console.log(`${colors.yellow}Test Suite 20: Crush Native Skills${colors.reset}\n`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
clearCache();
|
||||||
|
const platformCodes20 = await loadPlatformCodes();
|
||||||
|
const crushInstaller = platformCodes20.platforms.crush?.installer;
|
||||||
|
|
||||||
|
assert(crushInstaller?.target_dir === '.crush/skills', 'Crush target_dir uses native skills path');
|
||||||
|
|
||||||
|
assert(crushInstaller?.skill_format === true, 'Crush installer enables native skill output');
|
||||||
|
|
||||||
|
assert(
|
||||||
|
Array.isArray(crushInstaller?.legacy_targets) && crushInstaller.legacy_targets.includes('.crush/commands'),
|
||||||
|
'Crush installer cleans legacy command output',
|
||||||
|
);
|
||||||
|
|
||||||
|
const tempProjectDir20 = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-crush-test-'));
|
||||||
|
const installedBmadDir20 = await createTestBmadFixture();
|
||||||
|
const legacyDir20 = path.join(tempProjectDir20, '.crush', 'commands', 'bmad-legacy-dir');
|
||||||
|
await fs.ensureDir(legacyDir20);
|
||||||
|
await fs.writeFile(path.join(tempProjectDir20, '.crush', 'commands', 'bmad-legacy.md'), 'legacy\n');
|
||||||
|
await fs.writeFile(path.join(legacyDir20, 'SKILL.md'), 'legacy\n');
|
||||||
|
|
||||||
|
const ideManager20 = new IdeManager();
|
||||||
|
await ideManager20.ensureInitialized();
|
||||||
|
const result20 = await ideManager20.setup('crush', tempProjectDir20, installedBmadDir20, {
|
||||||
|
silent: true,
|
||||||
|
selectedModules: ['bmm'],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(result20.success === true, 'Crush setup succeeds against temp project');
|
||||||
|
|
||||||
|
const skillFile20 = path.join(tempProjectDir20, '.crush', 'skills', 'bmad-master', 'SKILL.md');
|
||||||
|
assert(await fs.pathExists(skillFile20), 'Crush install writes SKILL.md directory output');
|
||||||
|
|
||||||
|
const skillContent20 = await fs.readFile(skillFile20, 'utf8');
|
||||||
|
const nameMatch20 = skillContent20.match(/^name:\s*(.+)$/m);
|
||||||
|
assert(nameMatch20 && nameMatch20[1].trim() === 'bmad-master', 'Crush skill name frontmatter matches directory name exactly');
|
||||||
|
|
||||||
|
assert(!(await fs.pathExists(path.join(tempProjectDir20, '.crush', 'commands'))), 'Crush setup removes legacy commands dir');
|
||||||
|
|
||||||
|
const result20b = await ideManager20.setup('crush', tempProjectDir20, installedBmadDir20, {
|
||||||
|
silent: true,
|
||||||
|
selectedModules: ['bmm'],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(result20b.success === true, 'Crush reinstall/upgrade succeeds over existing skills');
|
||||||
|
assert(await fs.pathExists(skillFile20), 'Crush reinstall preserves SKILL.md output');
|
||||||
|
|
||||||
|
await fs.remove(tempProjectDir20);
|
||||||
|
await fs.remove(installedBmadDir20);
|
||||||
|
} catch (error) {
|
||||||
|
assert(false, 'Crush native skills migration test succeeds', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Summary
|
// Summary
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,11 @@ platforms:
|
||||||
category: ide
|
category: ide
|
||||||
description: "AI development assistant"
|
description: "AI development assistant"
|
||||||
installer:
|
installer:
|
||||||
target_dir: .crush/commands
|
legacy_targets:
|
||||||
|
- .crush/commands
|
||||||
|
target_dir: .crush/skills
|
||||||
template_type: default
|
template_type: default
|
||||||
|
skill_format: true
|
||||||
|
|
||||||
cursor:
|
cursor:
|
||||||
name: "Cursor"
|
name: "Cursor"
|
||||||
|
|
|
||||||
|
|
@ -119,18 +119,19 @@ Support assumption: full Agent Skills support. CodeBuddy docs confirm workspace
|
||||||
|
|
||||||
## Crush
|
## Crush
|
||||||
|
|
||||||
Support assumption: full Agent Skills support. BMAD currently installs commands to `.crush/commands`; target should move to the platform's native skills location.
|
Support assumption: full Agent Skills support. Crush scans project-local `.crush/skills/` exclusively ([GitHub issue #2072](https://github.com/charmbracelet/crush/issues/2072) confirms this and requests adding `~/.agents/skills/`). BMAD has now migrated from `.crush/commands` to `.crush/skills`.
|
||||||
|
|
||||||
**Install:** `brew install charmbracelet/tap/crush` (macOS/Linux) or `winget install charmbracelet.crush` (Windows)
|
**Install:** `brew install charmbracelet/tap/crush` (macOS/Linux) or `winget install charmbracelet.crush` (Windows)
|
||||||
|
|
||||||
- [ ] Confirm Crush project-local versus global skills path and BMAD's preferred install target
|
- [x] Confirm Crush project-local skills path is `.crush/skills/{skill-name}/SKILL.md` — per GitHub issue #2072 confirming `.crush/skills/` is the only scan path
|
||||||
- [ ] Implement installer migration to native skills output
|
- [x] Implement installer migration to native skills output
|
||||||
- [ ] Add legacy cleanup for `.crush/commands`
|
- [x] Add legacy cleanup for `.crush/commands`
|
||||||
- [ ] Test fresh install
|
- [x] Test fresh install — 43 skills installed to `.crush/skills/`
|
||||||
- [ ] Test reinstall/upgrade from legacy command output
|
- [x] Test reinstall/upgrade from legacy command output
|
||||||
- [ ] Confirm ancestor conflict protection where applicable
|
- [x] Confirm no ancestor conflict protection is needed because Crush only scans project-local `.crush/skills/`, no ancestor inheritance
|
||||||
- [ ] Implement/extend automated tests
|
- [ ] **NEEDS MANUAL IDE VERIFICATION** — install Crush via brew and confirm skills appear in UI
|
||||||
- [ ] Commit
|
- [x] Implement/extend automated tests — 9 assertions in test suite 20
|
||||||
|
- [x] Commit
|
||||||
|
|
||||||
## Kiro
|
## Kiro
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue