From 5d0583f0659d14c364c0e88496381bdddb252e6a Mon Sep 17 00:00:00 2001 From: Wenjunyun123 Date: Fri, 12 Jun 2026 10:14:05 +0800 Subject: [PATCH] Fix nested skill bundle scanning Why: Skills X-ray currently treats repository-style skill bundles as broken when the bundle root lacks SKILL.md, even if the real skills live under skills/*/SKILL.md. What: Detect nested skill bundles before marking a directory as residue, then scan the nested skills root with a bundle-aware label. Tested: node --check server.js Tested: npm run check:vendor-patch Tested: temporary fixture confirmed superpowers-style bundles no longer produce a missing-SKILL.md residue while ordinary broken skill directories still do. Co-authored-by: OmX --- server.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/server.js b/server.js index 440affa..4802dc8 100755 --- a/server.js +++ b/server.js @@ -1481,6 +1481,20 @@ function skillFrontmatter(txt) { return { desc }; } +async function scanNestedSkillBundle(fp, source, label, out, disabled) { + const nestedRoot = path.join(fp, 'skills'); + let nestedNames; + try { nestedNames = await fsp.readdir(nestedRoot, { withFileTypes: true }); } catch { return false; } + let hasSkills = false; + for (const x of nestedNames) { + if (!x.isDirectory() || x.name.startsWith('.')) continue; + try { await fsp.access(path.join(nestedRoot, x.name, 'SKILL.md')); hasSkills = true; break; } catch { /* not a skill */ } + } + if (!hasSkills) return false; + await scanSkillRoot(nestedRoot, source, `${label}/${path.basename(fp)}`, out, disabled); + return true; +} + async function scanSkillRoot(root, source, label, out, disabled = false) { let names; try { names = await fsp.readdir(root, { withFileTypes: true }); } catch { return; } @@ -1524,6 +1538,7 @@ async function scanSkillRoot(root, source, label, out, disabled = false) { } } } catch { + if (await scanNestedSkillBundle(fp, source, label, out, disabled)) continue; item.residue = true; item.issues.push('缺 SKILL.md——不是有效 skill'); }