| 12345678910111213141516171819202122 |
- 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','scripts/render-report-html.mjs']) 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'}));
|