"""Package a complete first-install kit; preserve sealed incremental releases.""" from pathlib import Path import argparse import hashlib import io import json import re import tarfile import zipfile ROOT = Path(__file__).resolve().parents[1] OUT = ROOT / 'docs/workshop-onboarding-20261109' RELEASE = 'ksf-workshop-onboarding-20261109-r1' sha = lambda raw: hashlib.sha256(raw).hexdigest() encode = lambda value: (json.dumps(value, ensure_ascii=False, indent=2) + '\n').encode('utf-8') def stage(): workshop_dir = ROOT / 'skills/ksf-workshop-runtime' prior = ROOT / 'docs/workshop-skill-release-20261109-r7' ready = json.loads((prior / 'release-ready.json').read_bytes()) assert sha((prior / ready['zip']).read_bytes()) == ready['sha256'] with zipfile.ZipFile(prior / ready['zip']) as z: r7 = json.loads(z.read('release.json'))['candidate'] assert len(r7) == 43 workshop = {} package = {} for name, expected in r7.items(): raw = (workshop_dir / name).read_bytes() assert sha(raw) == expected, name assert not any(term in name.lower() for term in ['credential-binding', 'private.pem', 'envelope']) workshop[name] = expected package['skills/ksf-workshop-runtime/' + name] = raw source = json.loads((OUT / 'source-audit/voc-source.json').read_bytes()) raw = (OUT / 'source-audit/voc-skill-0.3.42.tgz').read_bytes() assert sha(raw) == source['sha256'] and len(raw) == source['bytes'] voc_files = {} with tarfile.open(fileobj=io.BytesIO(raw), mode='r:gz') as archive: for member in archive.getmembers(): assert member.isfile() and member.name.startswith('package/') name = member.name[len('package/'):] assert name not in voc_files and '..' not in Path(name).parts and not name.startswith('/') voc_files[name] = sha(archive.extractfile(member).read()) assert len(voc_files) == 169 links = 0 for name in workshop: if name.endswith('.md'): p = workshop_dir / name for target in re.findall(r'\]\(([^)]+)\)', p.read_text(encoding='utf-8')): if '://' in target or target.startswith('#'): continue resolved = (p.parent / target.split('#', 1)[0]).resolve() assert resolved.is_file() and resolved.is_relative_to(workshop_dir.resolve()) links += 1 meta = {'schema': 'ksf.workshop-onboarding.v1', 'releaseId': RELEASE, 'workshop': {'name': 'ksf-workshop-runtime', 'version': 'r7', 'files': workshop, 'sourceReleaseSha256': ready['sha256'], 'relativeLinks': links}, 'voc': {**{k: source[k] for k in ['name', 'version', 'url', 'integrity', 'sha256', 'bytes']}, 'files': voc_files, 'distribution': 'download-from-official-npm-no-third-party-artifact-included'}, 'installation': {'freshInstallSupported': True, 'existingMatchingVersion': 'verify-only', 'existingDifferentVersion': 'stop-preserve-and-use-host-upgrade-path', 'hostSkillsDirectory': 'must-be-provided-by-host', 'hostConfigurationModifiedByInstaller': False}, 'credentialsIncluded': False, 'databaseIncluded': False, 'remoteInstalled': False, 'doubaoNativeSupportVerified': False} package.update({'release.json': encode(meta), 'README.md': (OUT / 'README.md').read_bytes(), 'install.py': (ROOT / 'scripts/workshop-onboarding/install.py').read_bytes(), 'check-voc.cjs': (ROOT / 'scripts/workshop-onboarding/check-voc.cjs').read_bytes(), '初始化提示词.txt': (OUT / '一键初始化正文.txt').read_bytes()}) validation = OUT / 'local-validation.json' if validation.exists(): value = json.loads(validation.read_bytes()) assert value['ok'] and value['installerSha256'] == sha(package['install.py']) assert value['runtimeCheckSha256'] == sha(package['check-voc.cjs']) package[validation.name] = validation.read_bytes() package['FILES.sha256'] = ''.join(sha(raw) + ' ' + name + '\n' for name, raw in sorted(package.items())).encode() for name, raw in package.items(): p = OUT / 'package' / name p.parent.mkdir(parents=True, exist_ok=True) p.write_bytes(raw) return package, meta def main(): parser = argparse.ArgumentParser() parser.add_argument('--pack', action='store_true') args = parser.parse_args() package, meta = stage() if not args.pack: print(json.dumps({'ok': True, 'staged': len(package), 'workshopFiles': 43, 'vocOriginalFiles': 169})) return assert 'local-validation.json' in package, 'Validation required before release' target = OUT / (RELEASE + '.zip') assert not target.exists(), 'Never overwrite a released archive' with zipfile.ZipFile(target, 'x', zipfile.ZIP_DEFLATED) as z: for name, raw in sorted(package.items()): info = zipfile.ZipInfo(name, (2026, 11, 9, 0, 0, 0)) info.external_attr = 0o100600 << 16 z.writestr(info, raw, compress_type=zipfile.ZIP_DEFLATED) with zipfile.ZipFile(target) as z: assert z.testzip() is None and set(z.namelist()) == set(package) assert all(z.read(name) == raw for name, raw in package.items()) receipt = {'ok': True, 'releaseId': RELEASE, 'filename': target.name, 'bytes': target.stat().st_size, 'sha256': sha(target.read_bytes()), 'packageEntries': len(package), 'workshopFiles': 43, 'vocVersion': meta['voc']['version'], 'vocDownloadedFromOfficialSource': True, 'thirdPartyArtifactIncluded': False, 'gitPublished': False, 'remoteInstalled': False, 'doubaoActualInstallationVerified': False} (OUT / 'package-receipt.json').write_bytes(encode(receipt)) print(json.dumps(receipt, ensure_ascii=False, indent=2)) if __name__ == '__main__': main()