fix(skill): pin packaged commands to the shipping package version (#1346)

Fixes #1338.

Use canonical product identity for bundled command versions and keep build-cache fixtures aligned. Verified 10 focused tests, actual CLI installation/repair/uninstall scenarios and all 19 final-head CI checks.

Co-authored-by: Yi-111-a <97448247+Yi-111-a@users.noreply.github.com>
This commit is contained in:
yi111
2026-10-10 04:47:10 +08:00
committed by GitHub
co-authored by Yi-111-a
parent 048b79878c
commit f39e71ce18
3 changed files with 10 additions and 9 deletions
+4 -4
View File
@@ -20,8 +20,8 @@ const cacheBust = String(Date.now());
const { CATALOG_IDENTITY } = await import(
`${pathToFileURL(join(root, "dist/catalogIdentity.js")).href}?${cacheBust}`
);
const { PACKAGE_METADATA } = await import(
`${pathToFileURL(join(root, "dist/generatedPackageMetadata.js")).href}?${cacheBust}`
const { PRODUCT_IDENTITY } = await import(
`${pathToFileURL(join(root, "dist/identity.js")).href}?${cacheBust}`
);
if (/^\s{2}(?:tool_count|catalog_digest):/mu.test(current))
throw new Error(
@@ -31,8 +31,8 @@ const versionLine = /^ {2}version: "[^"\r\n]+"$/mu;
if (!versionLine.test(current))
throw new Error("Missing authored skill version");
// A shipped skill must run the version it ships with, not whatever `@latest` resolves to.
const latestSpecifier = `${PACKAGE_METADATA.name}@latest`;
const pinnedSpecifier = `${PACKAGE_METADATA.name}@${PACKAGE_METADATA.version}`;
const latestSpecifier = PRODUCT_IDENTITY.packageSpecifier;
const pinnedSpecifier = PRODUCT_IDENTITY.registrationPackageSpecifier;
const source = current
.replace(
versionLine,
@@ -151,6 +151,8 @@ const createBuildCacheFixture = async (): Promise<string> => {
const scripts = asRecord(packageJson?.scripts);
if (
packageJson === undefined ||
typeof packageJson.name !== "string" ||
typeof packageJson.version !== "string" ||
typeof scripts?.["build:cached"] !== "string"
)
throw new Error("package is missing its cached build command");
@@ -189,12 +191,11 @@ const createBuildCacheFixture = async (): Promise<string> => {
);
await writeFile(
join(root, "scripts/cache-fixture-build.mjs"),
`import { mkdir, readFile, writeFile } from "node:fs/promises";
const { name, version } = JSON.parse(await readFile("package.json", "utf8"));
`import { mkdir, writeFile } from "node:fs/promises";
await mkdir("dist", { recursive: true });
await writeFile("dist/cache-fixture.js", "built");
await writeFile("dist/catalogIdentity.js", "export const CATALOG_IDENTITY = { counts: { mcp_tools: 1 } };\\n");
await writeFile("dist/generatedPackageMetadata.js", "export const PACKAGE_METADATA = " + JSON.stringify({ name, version }) + ";\\n");
await writeFile("dist/identity.js", ${JSON.stringify(`export const PRODUCT_IDENTITY = ${JSON.stringify({ packageSpecifier: `${packageJson.name}@latest`, registrationPackageSpecifier: `${packageJson.name}@${packageJson.version}` })};\n`)});
`,
);
await createNodeModulesLinks(root);
@@ -27,8 +27,8 @@ async function fixture(eol = "\n") {
await mkdir(join(root, "dist"));
await writeFile(join(root, "package.json"), '{"type":"module"}\n');
await writeFile(
join(root, "dist/generatedPackageMetadata.js"),
'export const PACKAGE_METADATA = { name: "rea-agents", version: "6.2.0" };\n',
join(root, "dist/identity.js"),
'export const PRODUCT_IDENTITY = { packageSpecifier: "rea-agents@latest", registrationPackageSpecifier: "rea-agents@6.2.0" };\n',
);
await writeFile(join(sourceRoot, "SKILL.md"), authored.replaceAll("\n", eol));
await writeFile(