import fs from 'node:fs'; import path from 'node:path'; import crypto from 'node:crypto'; import { fileURLToPath } from 'node:url'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const skill = 'skills/ksf-workshop-runtime'; const sha = bytes => crypto.createHash('sha256').update(bytes).digest('hex'); const [flag, directory, ...extra] = process.argv.slice(2); if (flag !== '--out' || !directory || !path.isAbsolute(directory) || extra.length || fs.existsSync(directory)) { throw new Error('Use --out ABSOLUTE_NEW_DIRECTORY'); } const entries = fs.readFileSync(path.join(root, skill, 'FILES.sha256'), 'utf8').trim().split(/\r?\n/).map(line => { const match = line.match(/^([a-f0-9]{64}) ([A-Za-z0-9_./-]+)$/); if (!match || match[2].split('/').includes('..')) throw new Error('Invalid Skill manifest'); if (sha(fs.readFileSync(path.join(root, skill, match[2]))) !== match[1]) throw new Error('Skill hash mismatch'); return skill + '/' + match[2]; }); if (new Set(entries).size !== 10) throw new Error('Expected ten Skill manifest entries'); const files = [...entries, skill + '/FILES.sha256', 'scripts/install-workshop-skill.mjs', 'scripts/build-workshop-skill.mjs', 'scripts/package-workshop-skill.mjs', 'docs/workshop-skill-employee-identity-20261103.md', 'docs/workshop-skill-validation-20261103.json', 'docs/wecom-identity-integration-20261103.md', ].sort(); for (const file of files) { const stat = fs.lstatSync(path.join(root, file)); if (!stat.isFile() || stat.isSymbolicLink() || /credential-binding|participants\/|agents\//.test(file)) throw new Error('Unexpected package file'); } fs.mkdirSync(directory, { recursive: true }); for (const file of files) { const target = path.join(directory, file); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.copyFileSync(path.join(root, file), target, fs.constants.COPYFILE_EXCL); } fs.writeFileSync(path.join(directory, 'FILES.sha256'), files.map(file => sha(fs.readFileSync(path.join(directory, file))) + ' ' + file).join('\n') + '\n', { flag: 'wx' }); console.log(JSON.stringify({ ok: true, release: 'ksf.workshop-skill.employee.20261103.r1', directory, files: files.length + 1, productionWrites: 0, deployed: false }));