| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- // Execute the exact staged/extracted updater against isolated accepted-r2 bytes.
- import fs from 'node:fs';
- import path from 'node:path';
- import os from 'node:os';
- import crypto from 'node:crypto';
- import assert from 'node:assert/strict';
- import {fileURLToPath,pathToFileURL} from 'node:url';
- const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
- const releaseDir=path.join(root,'docs/workshop-skill-release-20261109-r3');
- const packageDir=fs.realpathSync(process.argv[2]||path.join(releaseDir,'package'));
- const output=path.resolve(process.argv[3]||path.join(releaseDir,'staged-rehearsal.json'));
- const updater=await import(pathToFileURL(path.join(packageDir,'update-skill.mjs')));
- const hash=b=>crypto.createHash('sha256').update(b).digest('hex');
- const digest=p=>hash(fs.readFileSync(p));
- function fileMap(dir){const out={};for(const e of fs.readdirSync(dir,{withFileTypes:true})){const p=path.join(dir,e.name);if(e.isDirectory())for(const[n,h]of Object.entries(fileMap(p)))out[e.name+'/'+n]=h;else out[e.name]=digest(p);}return out;}
- const temp=fs.mkdtempSync(path.join(os.tmpdir(),'ksf-docs-package-rehearsal-'));
- try{
- const dataRoot=path.join(temp,'data'),targetDir=path.join(dataRoot,'skills/ksf-workshop-runtime'),libraryDir=path.join(dataRoot,'skills/ksf-voc-library');
- fs.mkdirSync(path.dirname(targetDir),{recursive:true});
- fs.cpSync(path.join(releaseDir,'rehearsal-baseline'),targetDir,{recursive:true});
- fs.cpSync(path.join(root,'skills/ksf-voc-library'),libraryDir,{recursive:true});fs.unlinkSync(path.join(libraryDir,'SKILL.md'));
- fs.writeFileSync(path.join(libraryDir,'FILES.sha256'),Object.entries(fileMap(libraryDir)).filter(([n])=>n!=='FILES.sha256').map(([n,h])=>h+' '+n+'\n').join(''));
- fs.writeFileSync(path.join(targetDir,'credential-binding.json'),'{"fixtureOnly":true}',{mode:0o600});
- const before=fileMap(dataRoot),options={packageDir,targetDir};
- const dry=updater.publicPlan(updater.planUpdate(options));assert.equal(dry.changedFiles,9);assert.deepEqual(fileMap(dataRoot),before);
- const applied=updater.applyUpdate(options),verify=updater.verifyUpdate({backup:applied.backup});
- assert.equal(verify.installedFilesVerified,39);assert.equal(verify.changedFilesVerified,9);
- const after=fileMap(dataRoot);assert.equal(updater.applyUpdate(options).alreadyApplied,true);assert.deepEqual(fileMap(dataRoot),after);
- const rolled=updater.rollbackUpdate({backup:applied.backup});assert.equal(rolled.legacyEntrypointRetired,true);
- const restored=fileMap(dataRoot);for(const[n,h]of Object.entries(before))assert.equal(restored[n],h,n);
- assert.equal(fs.existsSync(path.join(targetDir,'references/workshop-feedback.md')),false);
- const result={ok:true,checkedAt:new Date().toISOString(),packageDirectory:packageDir,
- execution:{platform:process.platform,node:process.version,scope:'imported packaged updater functions in isolated temporary directories; not original-instance CLI'},
- workshopBaseline:'exact 38 accepted r2 ZIP members, each SHA checked by packager',
- researchFixture:'self-consistent public fixture; four independently pinned runtime hashes, not a full remote export',
- dryReadOnly:true,plannedUpdates:8,plannedCreates:1,applySucceeded:true,installedFilesVerified:39,
- idempotent:true,rollbackRestoredOriginalBytes:true,legacyEntrypointRemainedRetired:true,
- updaterSha256:digest(path.join(packageDir,'update-skill.mjs')),
- runnerSha256:digest(path.join(packageDir,'run-update.py')),
- skillSha256:verify.skillSha256,manifestSha256:verify.manifestSha256,
- productionCalls:0,productionDatabaseWrites:0,paidCalls:0,remoteInstalled:false};
- fs.writeFileSync(output,JSON.stringify(result,null,2)+'\n');console.log(JSON.stringify(result,null,2));
- }finally{
- const abs=fs.realpathSync(temp);assert.ok(abs.startsWith(fs.realpathSync(os.tmpdir())+path.sep)&&path.basename(abs).startsWith('ksf-docs-package-rehearsal-'));
- fs.rmSync(abs,{recursive:true});
- }
|