import fs from 'node:fs'; import crypto from 'node:crypto'; const root='skills/ksf-workshop-runtime',sha=x=>crypto.createHash('sha256').update(x).digest('hex'); // Maintain final-SKILL.md; keep the conventional loader entry synchronized. const finalEntry=fs.readFileSync(root+'/final-SKILL.md'); if(!fs.existsSync(root+'/SKILL.md')||!fs.readFileSync(root+'/SKILL.md').equals(finalEntry))fs.writeFileSync(root+'/SKILL.md',finalEntry); const hash=sha(fs.readFileSync(root+'/scripts/ksf-workshop.mjs')); const identityHash=sha(fs.readFileSync(root+'/scripts/ksf-identity.mjs')); const file=root+'/scripts/ksf-secure.mjs'; fs.writeFileSync(file,fs.readFileSync(file,'utf8') .replace(/const WORKSHOP_ENTRY_HASH = '[^']+';/,"const WORKSHOP_ENTRY_HASH = '"+hash+"';") .replace(/const IDENTITY_MODULE_HASH = '[^']+';/,"const IDENTITY_MODULE_HASH = '"+identityHash+"';")); // Keep the declared public package complete; never enumerate local identity/credential files. const declared=fs.existsSync(root+'/FILES.sha256')?fs.readFileSync(root+'/FILES.sha256','utf8').trim().split(/\r?\n/).filter(Boolean).map(line=>{ const match=line.match(/^[a-f0-9]{64}\s+\*?(.+)$/);if(!match||match[1].includes('..')||/^[\\/]|:/.test(match[1]))throw Error('非法公开清单路径');return match[1]; }).filter(file=>!['references/workshop-dialogue-prompts.json','references/workshop-case-evidence.md'].includes(file)):[]; const files=[...new Set([...declared,'SKILL.md','references/identity.md','references/workshop-tasks.md','references/write-tasks.md','references/business-data-dictionary.json','references/full-schema-and-intake.md','runtime-lock.json','scripts/describe-business-schema.mjs','scripts/ksf-identity.mjs','scripts/ksf-identity-bridge.mjs','scripts/ksf-secure.mjs','scripts/ksf-workshop.mjs','scripts/ksf.mjs','scripts/report-contract.mjs','scripts/save-report.mjs','references/workshop-report-parity.md'])].sort(); for (const file of ['references/workshop-dialogue.md','references/workshop-evidence-counting.md']) if (!files.includes(file)) files.push(file); files.sort(); const entries=files.map(file=>sha(fs.readFileSync(root+'/'+file))+' '+file); fs.writeFileSync(root+'/FILES.sha256',entries.join('\n')+'\n'); console.log(JSON.stringify({skill:root,files:entries.length,workshopEntrySha256:hash,identityModuleSha256:identityHash,legacyEntryPreserved:sha(fs.readFileSync(root+'/scripts/ksf.mjs'))==='7ef128f7d022bfbc15c0ec813bfd87995c6297c6efe407a563c840f014aba477'}));