diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b40026c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + lint-and-test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x, 22.x] + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run syntax check + run: npm run prepare + + - name: Check for syntax errors in all JS files + run: | + for file in $(find src bin -name "*.js"); do + echo "Checking $file..." + node -c "$file" + done + + - name: Verify proto.js exports + run: | + node -e "const proto = require('./src/proto.js'); \ + console.log('Exported functions:', Object.keys(proto)); \ + if (!proto.protoApply || !proto.protoInit) { \ + throw new Error('Missing required exports'); \ + }" diff --git a/src/proto.js b/src/proto.js index c0556a9..aaeefd2 100644 --- a/src/proto.js +++ b/src/proto.js @@ -91,6 +91,22 @@ function detectWindsurfCandidates({ platform }) { return candidates; } +function detectKiroCandidates({ platform }) { + const candidates = []; + const home = os.homedir(); + const userProfile = process.env.USERPROFILE || home; + + // User-level only (no repo-local detection for Kiro) + // Kiro uses ~/.kiro/steering/ directory for global steering files + if (platform === 'macos') candidates.push(path.join(home, '.kiro', 'steering', 'cueme_proto.md')); + if (platform === 'linux') candidates.push(path.join(home, '.kiro', 'steering', 'cueme_proto.md')); + if (platform === 'windows') { + candidates.push(path.join(userProfile, '.kiro', 'steering', 'cueme_proto.md')); + } + + return candidates; +} + function firstExistingPath(candidates) { for (const p of candidates) { if (typeof p === 'string' && p.trim().length > 0 && pathExists(p)) return p; @@ -125,6 +141,11 @@ function defaultPathMapTemplate() { out['windows.windsurf'] = path.join(userProfile, '.codeium', 'windsurf', 'memories', 'global_rules.md'); out['linux.windsurf'] = path.join(home, '.codeium', 'windsurf', 'memories', 'global_rules.md'); + // Kiro + out['macos.kiro'] = path.join(home, '.kiro', 'steering', 'cueme_proto.md'); + out['windows.kiro'] = path.join(userProfile, '.kiro', 'steering', 'cueme_proto.md'); + out['linux.kiro'] = path.join(home, '.kiro', 'steering', 'cueme_proto.md'); + return out; } @@ -135,6 +156,7 @@ function defaultConfigTemplate() { 'cueme.proto.prefix': { windsurf: [], vscode: ['---', 'applyTo: "**"', '---'], + kiro: [], }, 'cueme.proto.protocol_path': protocolPath, }; @@ -144,9 +166,10 @@ function detectAndFillTemplatePaths(tpl) { const platform = getPlatformKey(); const keyVscode = `${platform}.vscode`; const keyWindsurf = `${platform}.windsurf`; + const keyKiro = `${platform}.kiro`; const pathMap = tpl['cueme.proto.path'] || {}; - const detected = { platform, vscode: '', windsurf: '' }; + const detected = { platform, vscode: '', windsurf: '', kiro: '' }; if (typeof pathMap !== 'object' || Array.isArray(pathMap)) { return { tpl, detected }; @@ -169,6 +192,14 @@ function detectAndFillTemplatePaths(tpl) { } } + if (typeof pathMap[keyKiro] !== 'string' || pathMap[keyKiro].trim().length === 0) { + const p = firstExistingPath(detectKiroCandidates({ platform })); + if (p) { + pathMap[keyKiro] = p; + detected.kiro = p; + } + } + tpl['cueme.proto.path'] = pathMap; return { tpl, detected }; } @@ -374,9 +405,11 @@ function protoInit() { const platform = detected && detected.platform ? detected.platform : getPlatformKey(); const keyVscode = `${platform}.vscode`; const keyWindsurf = `${platform}.windsurf`; + const keyKiro = `${platform}.kiro`; const vs = detected && detected.vscode ? 'detected' : 'empty'; const ws = detected && detected.windsurf ? 'detected' : 'empty'; - return `ok: initialized ${p} (auto-detect: ${keyVscode}=${vs}, ${keyWindsurf}=${ws})`; + const ks = detected && detected.kiro ? 'detected' : 'empty'; + return `ok: initialized ${p} (auto-detect: ${keyVscode}=${vs}, ${keyWindsurf}=${ws}, ${keyKiro}=${ks})`; } module.exports = {