diff --git a/scripts/verify-repository-skill.mjs b/scripts/verify-repository-skill.mjs index c18d7c62dd..861d633fb4 100644 --- a/scripts/verify-repository-skill.mjs +++ b/scripts/verify-repository-skill.mjs @@ -3,6 +3,26 @@ import { dirname, join, relative } from "node:path"; import { exec, execNpm, pathExists } from "./lib/verify-package-core.mjs"; +/** Install the separately locked Skills CLI so verification resolves no registry metadata. */ +const lockedSkillsCli = async (root, workspace) => { + const tool = join(workspace, "skills-cli"); + await mkdir(tool, { recursive: true }); + for (const file of ["package.json", "package-lock.json"]) + await cp(join(root, "scripts/verify-tools/skills", file), join(tool, file)); + await execNpm( + ["ci", "--prefer-offline", "--ignore-scripts", "--no-audit", "--no-fund"], + { cwd: tool, timeout: 120_000 }, + ); + const installed = join(tool, "node_modules/skills"); + const manifest = JSON.parse( + await readFile(join(installed, "package.json"), "utf8"), + ); + return { + version: manifest.version, + entry: join(installed, manifest.bin.skills), + }; +}; + /** Exercise Skills' default root discovery without ignored build outputs. */ export async function verifyRepositorySkill({ root, workspace }) { const snapshot = join(workspace, "repository"); @@ -33,15 +53,14 @@ export async function verifyRepositorySkill({ root, workspace }) { throw new Error("repository skill check must run without generated skills"); await mkdir(consumer, { recursive: true }); await mkdir(home, { recursive: true }); - const skillsVersion = "1.7.2"; - await execNpm( + const { version: skillsVersion, entry } = await lockedSkillsCli( + root, + workspace, + ); + await exec( + process.execPath, [ - "exec", - "--yes", - "--package", - `skills@${skillsVersion}`, - "--", - "skills", + entry, "add", snapshot, "--skill", diff --git a/scripts/verify-tools/skills/package-lock.json b/scripts/verify-tools/skills/package-lock.json new file mode 100644 index 0000000000..817386596b --- /dev/null +++ b/scripts/verify-tools/skills/package-lock.json @@ -0,0 +1,112 @@ +{ + "name": "rea-verify-skills-cli", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "rea-verify-skills-cli", + "dependencies": { + "skills": "1.7.2" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/skills": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/skills/-/skills-1.7.2.tgz", + "integrity": "sha512-j+GzyF/oNahsjjjup6y3lJpFkC1lQjIkf4kAMXICA1hboBqi0fAGXAGoE4x9FRZiP1br/YE9+L3/Tqq6PIAe0A==", + "license": "MIT", + "dependencies": { + "tar": "^7.5.20", + "yaml": "^2.8.3" + }, + "bin": { + "add-skill": "bin/cli.mjs", + "skills": "bin/cli.mjs" + }, + "engines": { + "node": ">=22.20.0" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + } + } +} diff --git a/scripts/verify-tools/skills/package.json b/scripts/verify-tools/skills/package.json new file mode 100644 index 0000000000..88f6b63297 --- /dev/null +++ b/scripts/verify-tools/skills/package.json @@ -0,0 +1,8 @@ +{ + "name": "rea-verify-skills-cli", + "private": true, + "description": "Lockfile-pinned Skills CLI for the repository skill check in verify:package.", + "dependencies": { + "skills": "1.7.2" + } +}