|
|
@@ -95,7 +95,51 @@ function findSkillsInDir(dir, sourceType, maxDepth = 3) {
|
|
|
return skills;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Resolve a skill name to its file path, handling shadowing
|
|
|
+ * (personal skills override superpowers skills).
|
|
|
+ *
|
|
|
+ * @param {string} skillName - Name like "superpowers:brainstorming" or "my-skill"
|
|
|
+ * @param {string} superpowersDir - Path to superpowers skills directory
|
|
|
+ * @param {string} personalDir - Path to personal skills directory
|
|
|
+ * @returns {{skillFile: string, sourceType: string, skillPath: string} | null}
|
|
|
+ */
|
|
|
+function resolveSkillPath(skillName, superpowersDir, personalDir) {
|
|
|
+ // Strip superpowers: prefix if present
|
|
|
+ const forceSuperpowers = skillName.startsWith('superpowers:');
|
|
|
+ const actualSkillName = forceSuperpowers ? skillName.replace(/^superpowers:/, '') : skillName;
|
|
|
+
|
|
|
+ // Try personal skills first (unless explicitly superpowers:)
|
|
|
+ if (!forceSuperpowers && personalDir) {
|
|
|
+ const personalPath = path.join(personalDir, actualSkillName);
|
|
|
+ const personalSkillFile = path.join(personalPath, 'SKILL.md');
|
|
|
+ if (fs.existsSync(personalSkillFile)) {
|
|
|
+ return {
|
|
|
+ skillFile: personalSkillFile,
|
|
|
+ sourceType: 'personal',
|
|
|
+ skillPath: actualSkillName
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Try superpowers skills
|
|
|
+ if (superpowersDir) {
|
|
|
+ const superpowersPath = path.join(superpowersDir, actualSkillName);
|
|
|
+ const superpowersSkillFile = path.join(superpowersPath, 'SKILL.md');
|
|
|
+ if (fs.existsSync(superpowersSkillFile)) {
|
|
|
+ return {
|
|
|
+ skillFile: superpowersSkillFile,
|
|
|
+ sourceType: 'superpowers',
|
|
|
+ skillPath: actualSkillName
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+}
|
|
|
+
|
|
|
module.exports = {
|
|
|
extractFrontmatter,
|
|
|
- findSkillsInDir
|
|
|
+ findSkillsInDir,
|
|
|
+ resolveSkillPath
|
|
|
};
|