From 8b91228d9316ac523041b2ca3eaad1b9d58e9e7f Mon Sep 17 00:00:00 2001 From: Dean Rie Date: Mon, 26 Oct 2026 11:23:38 +0300 Subject: [PATCH] fix(github-plugin): keep same-named components from different sub-plugins instead of dropping the later one --- apps/cursor/src/lib/github-plugin/parse.ts | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/apps/cursor/src/lib/github-plugin/parse.ts b/apps/cursor/src/lib/github-plugin/parse.ts index 6fb62149..400ed42e 100644 --- a/apps/cursor/src/lib/github-plugin/parse.ts +++ b/apps/cursor/src/lib/github-plugin/parse.ts @@ -382,10 +382,14 @@ export async function parseGitHubPlugin( } const components: ParsedComponent[] = []; + // Which sub-plugin dir each component came from ("" for the repo root), so + // a slug that collides across sub-plugins can be told apart below. + const prefixOf = new Map(); const prefixes = ["", ...subPluginDirs]; for (const prefix of prefixes) { + const firstIndex = components.length; const ruleFiles = tree.filter( (f) => f.type === "blob" && @@ -552,15 +556,28 @@ export async function parseGitHubPlugin( // ignore } } + + for (const c of components.slice(firstIndex)) prefixOf.set(c, prefix); } + // Slugs come from file or directory names, so two sub-plugins that both + // ship, say, `skills/setup/SKILL.md` produce the same `skill:setup` key. The + // first occurrence keeps its slug; a later one from a sub-plugin dir gets + // the dir as a prefix (the hooks component already does this). Only a key + // that still collides after that is dropped. const seen = new Set(); - const deduped = components.filter((c) => { - const key = `${c.type}:${c.slug}`; - if (seen.has(key)) return false; - seen.add(key); - return true; - }); + const deduped: ParsedComponent[] = []; + for (const c of components) { + let slug = c.slug; + if (seen.has(`${c.type}:${slug}`)) { + const prefix = prefixOf.get(c) ?? ""; + if (!prefix) continue; + slug = slugify(`${prefix} ${c.slug}`); + if (seen.has(`${c.type}:${slug}`)) continue; + } + seen.add(`${c.type}:${slug}`); + deduped.push(slug === c.slug ? c : { ...c, slug }); + } if (deduped.length === 0) { const scannedPrefixes = prefixes