From 9b04f022c4e9dd83164da6e8d533421a63092d46 Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Fri, 6 Mar 2026 04:17:55 -0700 Subject: [PATCH] Migrate Windsurf installer to native skills --- test/test-installation-components.js | 70 +++++++++++++++++++ .../installers/lib/ide/platform-codes.yaml | 5 +- .../docs/native-skills-migration-checklist.md | 16 ++--- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/test/test-installation-components.js b/test/test-installation-components.js index 646bd9ef7..2e91d6016 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -12,9 +12,12 @@ */ const path = require('node:path'); +const os = require('node:os'); const fs = require('fs-extra'); const { YamlXmlBuilder } = require('../tools/cli/lib/yaml-xml-builder'); const { ManifestGenerator } = require('../tools/cli/installers/lib/core/manifest-generator'); +const { IdeManager } = require('../tools/cli/installers/lib/ide/manager'); +const { clearCache, loadPlatformCodes } = require('../tools/cli/installers/lib/ide/platform-codes'); // ANSI colors const colors = { @@ -45,6 +48,26 @@ function assert(condition, testName, errorMessage = '') { } } +/** + * Resolve the shared installed BMAD payload for this worktree layout. + */ +async function findInstalledBmadDir(startDir) { + let current = path.resolve(startDir); + + while (true) { + const candidate = path.join(current, '_bmad'); + if (await fs.pathExists(path.join(candidate, '_config', 'workflow-manifest.csv'))) { + return candidate; + } + + const parent = path.dirname(current); + if (parent === current) { + throw new Error(`Could not locate installed _bmad payload from ${startDir}`); + } + current = parent; + } +} + /** * Test Suite */ @@ -157,6 +180,53 @@ async function runTests() { console.log(''); + // ============================================================ + // Test 4: Windsurf Native Skills Install + // ============================================================ + console.log(`${colors.yellow}Test Suite 4: Windsurf Native Skills${colors.reset}\n`); + + try { + clearCache(); + const platformCodes = await loadPlatformCodes(); + const windsurfInstaller = platformCodes.platforms.windsurf?.installer; + + assert(windsurfInstaller?.target_dir === '.windsurf/skills', 'Windsurf target_dir uses native skills path'); + + assert(windsurfInstaller?.skill_format === true, 'Windsurf installer enables native skill output'); + + assert( + Array.isArray(windsurfInstaller?.legacy_targets) && windsurfInstaller.legacy_targets.includes('.windsurf/workflows'), + 'Windsurf installer cleans legacy workflow output', + ); + + const tempProjectDir = await fs.mkdtemp(path.join(os.tmpdir(), 'bmad-windsurf-test-')); + const installedBmadDir = await findInstalledBmadDir(projectRoot); + const legacyDir = path.join(tempProjectDir, '.windsurf', 'workflows', 'bmad-legacy-dir'); + await fs.ensureDir(legacyDir); + await fs.writeFile(path.join(tempProjectDir, '.windsurf', 'workflows', 'bmad-legacy.md'), 'legacy\n'); + await fs.writeFile(path.join(legacyDir, 'SKILL.md'), 'legacy\n'); + + const ideManager = new IdeManager(); + await ideManager.ensureInitialized(); + const result = await ideManager.setup('windsurf', tempProjectDir, installedBmadDir, { + silent: true, + selectedModules: ['bmm'], + }); + + assert(result.success === true, 'Windsurf setup succeeds against temp project'); + + const skillFile = path.join(tempProjectDir, '.windsurf', 'skills', 'bmad-master', 'SKILL.md'); + assert(await fs.pathExists(skillFile), 'Windsurf install writes SKILL.md directory output'); + + assert(!(await fs.pathExists(path.join(tempProjectDir, '.windsurf', 'workflows'))), 'Windsurf setup removes legacy workflows dir'); + + await fs.remove(tempProjectDir); + } catch (error) { + assert(false, 'Windsurf native skills migration test succeeds', error.message); + } + + console.log(''); + // ============================================================ // Test 5: QA Agent Compilation // ============================================================ diff --git a/tools/cli/installers/lib/ide/platform-codes.yaml b/tools/cli/installers/lib/ide/platform-codes.yaml index 116af5669..fbcd0c06f 100644 --- a/tools/cli/installers/lib/ide/platform-codes.yaml +++ b/tools/cli/installers/lib/ide/platform-codes.yaml @@ -197,8 +197,11 @@ platforms: category: ide description: "AI-powered IDE with cascade flows" installer: - target_dir: .windsurf/workflows + legacy_targets: + - .windsurf/workflows + target_dir: .windsurf/skills template_type: windsurf + skill_format: true # ============================================================================ # Installer Config Schema diff --git a/tools/docs/native-skills-migration-checklist.md b/tools/docs/native-skills-migration-checklist.md index 8b920530a..74e750ad1 100644 --- a/tools/docs/native-skills-migration-checklist.md +++ b/tools/docs/native-skills-migration-checklist.md @@ -50,15 +50,15 @@ Support assumption: full Agent Skills support. BMAD currently installs legacy co ## Windsurf -Support assumption: full Agent Skills support. BMAD currently installs workflow files to `.windsurf/workflows`; target should move to `.windsurf/skills`. +Support assumption: full Agent Skills support. Windsurf docs confirm workspace skills at `.windsurf/skills` and global skills at `~/.codeium/windsurf/skills`. BMAD has now migrated from `.windsurf/workflows` to `.windsurf/skills`. -- [ ] Confirm Windsurf native skills directory and inheritance behavior -- [ ] Implement installer migration to native skills output -- [ ] Add legacy cleanup for `.windsurf/workflows` -- [ ] Test fresh install -- [ ] Test reinstall/upgrade from legacy workflow output -- [ ] Confirm ancestor conflict protection where applicable -- [ ] Implement/extend automated tests +- [x] Confirm Windsurf native skills directory as `.windsurf/skills` +- [x] Implement installer migration to native skills output +- [x] Add legacy cleanup for `.windsurf/workflows` +- [x] Test fresh install +- [x] Test reinstall/upgrade from legacy workflow output +- [x] Confirm no ancestor conflict protection is needed because manual Windsurf verification showed child-local `@` skills loaded while a parent-only skill was not inherited +- [x] Implement/extend automated tests - [ ] Commit ## Cline