fix(setup): name each skill directory in the uninstall summary (#2118)

Uninstall checks every skill destination but labeled each result only as
"skill" (or "Claude Code skill"), so a retained or failed destination
could not be located. Label each result with the directory it refers to.

Fixes #2111

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822 2026-10-12 04:55:15 -07:00 committed by GitHub
parent 60259a91d9
commit 5190843f8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 7 deletions

View File

@ -504,14 +504,11 @@ const removeManagedSkills = async (
environment: Readonly<NodeJS.ProcessEnv>,
platform: NodeJS.Platform,
): Promise<UninstallItem> => {
// Every destination shares one summary item, so each result is labeled by
// the directory it refers to.
const results = await Promise.all(
skillDestinations(home, undefined, environment, platform).map(
({ client, path }) =>
removeManagedSkill(
path,
client === "claude_code" ? "Claude Code skill" : "skill",
fileSystem,
),
skillDestinations(home, undefined, environment, platform).map(({ path }) =>
removeManagedSkill(path, path, fileSystem),
),
);
const failed = results.find(({ status }) => status === "failed");

View File

@ -9,6 +9,7 @@ import {
} from "node:fs/promises";
import { join } from "node:path";
import { expect } from "vitest";
import { PRODUCT_IDENTITY } from "../../../src/identity.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
@ -259,3 +260,39 @@ for (const group of groups) {
},
);
}
cliTest("uninstall names each retained skill directory", async ({ cli }) => {
const home = await createTestTempDirectory("rea-uninstall-skill-paths-");
const shared = join(home, ".agents", "skills", PRODUCT_IDENTITY.skillName);
const claude = join(home, ".claude", "skills", PRODUCT_IDENTITY.skillName);
for (const directory of [shared, claude]) {
await mkdir(directory, { recursive: true });
await writeFile(join(directory, "SKILL.md"), "---\nname: unrelated\n---\n");
}
const result = await cli.run({
arguments: ["uninstall", "--json"],
cwd: home,
environment: {
HOME: home,
USERPROFILE: home,
CLAUDE_CONFIG_DIR: join(home, ".claude"),
},
timeoutMs: 20_000,
});
expect(result.exitCode, result.stderr).toBe(0);
const report = result.json as {
items?: readonly { name: string; status: string; detail: string }[];
};
const skill = report.items?.find(({ name }) => name === "skill");
expect(skill?.status).toBe("retained");
for (const directory of [shared, claude]) {
expect(skill?.detail).toContain(
`${directory}: retained (Skill manifest is not REA-owned.)`,
);
expect(await readFile(join(directory, "SKILL.md"), "utf8")).toBe(
"---\nname: unrelated\n---\n",
);
}
});