| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- """Build a strictly enumerated public Skill upgrade; never reads installed credentials."""
- from pathlib import Path
- import datetime
- import hashlib
- import json
- import zipfile
- ROOT = Path(__file__).resolve().parents[1]
- OUT = ROOT / 'docs/workshop-skill-release-20261108-r1'
- NAME = 'ksf-workshop-unified-20261108-r1'
- sha = lambda body: hashlib.sha256(body).hexdigest()
- def main():
- skill = ROOT / 'skills/ksf-workshop-runtime'
- candidate = {}
- files = {}
- for line in (skill / 'FILES.sha256').read_text(encoding='utf-8').splitlines():
- digest, name = line.split(' ', 1)
- assert name not in candidate and '..' not in Path(name).parts and not Path(name).is_absolute()
- raw = (skill / name).read_bytes()
- assert sha(raw) == digest
- candidate[name] = digest
- files['skill/' + name] = raw
- assert len(candidate) == 37
- raw = (skill / 'FILES.sha256').read_bytes()
- candidate['FILES.sha256'] = sha(raw)
- files['skill/FILES.sha256'] = raw
- received = ROOT / 'docs/workshop-skill-review-20261108/received-15ffc90f'
- export = json.loads((received / 'EXPORT.json').read_text(encoding='utf-8-sig'))
- baseline = {}
- for entry in export['files']:
- raw = (received / 'ksf-workshop-runtime' / entry['path']).read_bytes()
- assert sha(raw) == entry['sha256']
- baseline[entry['path']] = entry['sha256']
- assert len(baseline) == 14
- prior_path = ROOT / 'docs/agent-library-read-repair-20261108/receipts/r2/agent-library-read-receipt.json'
- prior = json.loads(prior_path.read_text(encoding='utf-8-sig'))
- assert prior['ok'] and prior['installedFilesUnchanged']
- assert prior['skillFingerprint'] == 'b4266efed78c19c0162aa2200cf0be83b0e7afa2473cef134459eb14c97ce69c'
- expected = {'schema': 'ksf.agent-library-read-expected.v1',
- 'generation': prior['contract']['generation'],
- 'sourceReceiptSha256': sha(prior_path.read_bytes()),
- 'skillFingerprint': candidate['SKILL.md'],
- 'installedFingerprints': prior['installedFingerprints']}
- release = {'schema': 'ksf.unified-workshop-release.v1', 'releaseId': NAME,
- 'createdAt': datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))).isoformat(),
- 'baseline': baseline, 'candidate': candidate,
- 'legacySkillSha256': prior['skillFingerprint'],
- 'runtimeReplacementAllowed': False, 'paidCallsAllowed': False,
- 'businessWritesDuringUpgrade': False}
- files.update({
- 'release.json': (json.dumps(release, ensure_ascii=False, indent=2) + '\n').encode(),
- 'expected-agent-read.json': (json.dumps(expected, ensure_ascii=False, indent=2) + '\n').encode(),
- 'upgrade-skill.mjs': (ROOT / 'scripts/upgrade-unified-workshop-skill.mjs').read_bytes(),
- 'probe-agent-library-read.py': (ROOT / 'scripts/probe-agent-library-read.py').read_bytes(),
- 'README.md': (OUT / '王刚001-升级与实机验收.md').read_bytes(),
- 'local-rehearsal-summary.json': (OUT / 'local-rehearsal-summary.json').read_bytes(),
- })
- for name in ('scope-request.json', 'keyword-request.json'):
- files[name] = (prior_path.parent / name).read_bytes()
- for name in files:
- assert not any(term in name.lower() for term in ('credential-binding', 'private.pem', 'envelope', 'channel-config'))
- files['FILES.sha256'] = ''.join(sha(raw) + ' ' + name + '\n' for name, raw in sorted(files.items())).encode()
- dest = OUT / (NAME + '.zip')
- assert not dest.exists(), 'Use a new revision; do not overwrite a released archive'
- with zipfile.ZipFile(dest, 'x', zipfile.ZIP_DEFLATED) as archive:
- for name, raw in sorted(files.items()):
- info = zipfile.ZipInfo(name, (2026, 11, 8, 0, 0, 0))
- info.external_attr = 0o100600 << 16
- archive.writestr(info, raw, compress_type=zipfile.ZIP_DEFLATED)
- with zipfile.ZipFile(dest) as archive:
- assert archive.testzip() is None
- for line in archive.read('FILES.sha256').decode().splitlines():
- digest, name = line.split(' ', 1)
- assert sha(archive.read(name)) == digest
- receipt = {'schema': 'ksf.unified-workshop-package-receipt.v1', 'ok': True,
- 'filename': dest.name, 'bytes': dest.stat().st_size, 'sha256': sha(dest.read_bytes()),
- 'entries': len(files), 'outerManifestMatched': len(files) - 1,
- 'skillManifestMatched': len(candidate) - 1, 'baselineFilesPinned': len(baseline),
- 'runtimeCodeReplaced': False, 'credentialsIncluded': False, 'deployed': False,
- 'agentLoaded': False, 'businessDatabaseWrites': 0, 'paidCalls': 0}
- (OUT / 'package-receipt.json').write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + '\n', encoding='utf-8')
- print(json.dumps(receipt, ensure_ascii=False))
- if __name__ == '__main__':
- main()
|