| ... | ... | @@ -66,6 +66,105 @@ it.layer(NodeServices.layer)("discoverClaudeSkills", (it) => { |
| 66 | 66 | }), |
| 67 | 67 | ); |
| 68 | 68 | |
| 69 | it.effect("discovers project skills from the workspace .agents directory", () => |
| 70 | Effect.gen(function* () { |
| 71 | const fs = yield* FileSystem.FileSystem; |
| 72 | const path = yield* Path.Path; |
| 73 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-claude-skills-" }); |
| 74 | const configDir = path.join(tempDir, "claude-home"); |
| 75 | const workspace = path.join(tempDir, "workspace"); |
| 76 | |
| 77 | yield* writeSkill( |
| 78 | path.join(workspace, ".agents", "skills"), |
| 79 | "review", |
| 80 | ["---", "name: review", "description: Review the changes.", "---"].join("\n"), |
| 81 | ); |
| 82 | |
| 83 | const skills = yield* discoverClaudeSkills({ homePath: configDir }, workspace); |
| 84 | |
| 85 | assert.deepEqual(skills, [ |
| 86 | { |
| 87 | name: "review", |
| 88 | path: path.join(workspace, ".agents", "skills", "review", "SKILL.md"), |
| 89 | enabled: true, |
| 90 | scope: "project", |
| 91 | description: "Review the changes.", |
| 92 | }, |
| 93 | ]); |
| 94 | }), |
| 95 | ); |
| 96 | |
| 97 | it.effect("prefers workspace .claude skills on three-way name collisions", () => |
| 98 | Effect.gen(function* () { |
| 99 | const fs = yield* FileSystem.FileSystem; |
| 100 | const path = yield* Path.Path; |
| 101 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-claude-skills-" }); |
| 102 | const configDir = path.join(tempDir, "claude-home"); |
| 103 | const workspace = path.join(tempDir, "workspace"); |
| 104 | |
| 105 | yield* writeSkill( |
| 106 | path.join(configDir, "skills"), |
| 107 | "deploy", |
| 108 | ["---", "name: deploy", "description: User deploy.", "---"].join("\n"), |
| 109 | ); |
| 110 | yield* writeSkill( |
| 111 | path.join(workspace, ".agents", "skills"), |
| 112 | "deploy", |
| 113 | ["---", "name: deploy", "description: Agents deploy.", "---"].join("\n"), |
| 114 | ); |
| 115 | yield* writeSkill( |
| 116 | path.join(workspace, ".claude", "skills"), |
| 117 | "deploy", |
| 118 | ["---", "name: deploy", "description: Claude deploy.", "---"].join("\n"), |
| 119 | ); |
| 120 | |
| 121 | const skills = yield* discoverClaudeSkills({ homePath: configDir }, workspace); |
| 122 | |
| 123 | assert.deepEqual(skills, [ |
| 124 | { |
| 125 | name: "deploy", |
| 126 | path: path.join(workspace, ".claude", "skills", "deploy", "SKILL.md"), |
| 127 | enabled: true, |
| 128 | scope: "project", |
| 129 | description: "Claude deploy.", |
| 130 | }, |
| 131 | ]); |
| 132 | }), |
| 133 | ); |
| 134 | |
| 135 | it.effect("prefers workspace .agents skills over user skills on name collisions", () => |
| 136 | Effect.gen(function* () { |
| 137 | const fs = yield* FileSystem.FileSystem; |
| 138 | const path = yield* Path.Path; |
| 139 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-claude-skills-" }); |
| 140 | const configDir = path.join(tempDir, "claude-home"); |
| 141 | const workspace = path.join(tempDir, "workspace"); |
| 142 | |
| 143 | yield* writeSkill( |
| 144 | path.join(configDir, "skills"), |
| 145 | "deploy", |
| 146 | ["---", "name: deploy", "description: User deploy.", "---"].join("\n"), |
| 147 | ); |
| 148 | yield* writeSkill( |
| 149 | path.join(workspace, ".agents", "skills"), |
| 150 | "deploy", |
| 151 | ["---", "name: deploy", "description: Agents deploy.", "---"].join("\n"), |
| 152 | ); |
| 153 | |
| 154 | const skills = yield* discoverClaudeSkills({ homePath: configDir }, workspace); |
| 155 | |
| 156 | assert.deepEqual(skills, [ |
| 157 | { |
| 158 | name: "deploy", |
| 159 | path: path.join(workspace, ".agents", "skills", "deploy", "SKILL.md"), |
| 160 | enabled: true, |
| 161 | scope: "project", |
| 162 | description: "Agents deploy.", |
| 163 | }, |
| 164 | ]); |
| 165 | }), |
| 166 | ); |
| 167 | |
| 69 | 168 | it.effect("prefers project skills over user skills on name collisions", () => |
| 70 | 169 | Effect.gen(function* () { |
| 71 | 170 | const fs = yield* FileSystem.FileSystem; |