"""Seal the r10 workshop manual, including a standalone preview and deployment instructions."""
import argparse
import hashlib
import json
from pathlib import Path
import zipfile
ROOT = Path(__file__).resolve().parents[1]
SOURCE = ROOT / 'docs/workshop-manual-20261109'
OUT = ROOT / 'docs/workshop-manual-20261110-r1'
RELEASE = 'ksf-workshop-manual-20261110-r1'
NAMES = ['index.html', 'content.js', 'manual.js', 'manual.css']
sha = lambda b: hashlib.sha256(b).hexdigest()
encode = lambda v: (json.dumps(v, ensure_ascii=False, indent=2) + '\n').encode('utf-8')
DEPLOY = '''# 康师傅工作坊 r10 · 联合上线执行单
本执行单只更新工作坊技能说明与静态操作手册;数据库迁移、后端运行补丁已经验收,不重跑迁移或重启数据服务。
## 资源
以本执行单所在的固定 Git 提交目录为根目录,读取 manual-release.json;下载其 archive.path,核字节数及 SHA-256。在新临时目录安全解压并逐项核 FILES.sha256,不覆盖未知目录或改用分支最新地址。包内 manual/ 是四文件站点,ksf-workshop-manual-r10.html 是同内容的单文件预览。
配套技能固定安装说明:
{guide}
该说明对应 Skill r10、唯一内部入口 ksf-workshop-runtime,支持完整 r7/r8/r9 备份升级,外部官方 VOC 固定0.3.42。技能与手册联合版本均为r10。
## 1. 更新原工作坊Agent技能
在原Agent环境按上述安装说明核包、预检、备份升级,再验证43文件。使用已确认的实际技能根,不覆盖身份、授权、绑定及额外文件,不改其他技能。六个业务脚本与runtime-lock.json共7文件必须保持原指纹。保留已退役的旧研究目录为脚本兼容路径,不恢复其SKILL.md;已部署研究运行补丁保持原样。
同版只核验;未知版本或已改动说明停止覆盖并回传差异,不放宽校验。外部VOC如已符合固定版本及已记录的.mcp.json路径适配就复用。更新后的新任务应实际发现并加载r10;文件校验、宿主加载分别反馈。
仅做只读 smoke:默认研究 contract 核 backend=parse-postgresql、mode=ssh-channel(原Agent通道)及实际当前代际;业务 workshop-contract 读取成功。不要新建会话/项目/报告、采集、发布新代际或重跑验收保存记录。
## 2. 发布静态手册
建议正式地址为 https://kangshifu.fmode.cn/workshop-manual/ ,以维护人核实的Nginx/静态目录和路由为准。manual/四文件保持同目录,以新版本目录暂存后整体切换;存在旧手册先备份,不能直接覆盖来源不明的文件。独立静态路径不要误落回看板SPA首页;不更换看板根首页、不改数据库/API代理。亦可使用已有授权的静态发布域名,回传真实可访问地址。
HTML用text/html、CSS用text/css、JS用application/javascript,均UTF-8。入口和版本资源及时回源;若存在CDN,只刷新这四个手册文件。该站点不含密钥、登录或业务数据,不会写数据库。
## 3. 一次回传验收
- Skill:版本r10,43文件逐项一致,7运行文件未变;新任务实际加载状态;研究/业务只读合同结果。
- 手册:真实网页URL,4文件HTTP200、Content-Type和SHA与清单一致;浏览器打开不是看板回退页。
- 浏览器:15章导航、完整复制、桌面与390px,无脚本错误;安装提示词指向本执行单固定的r10资源。
- 范围:准备2节、研究13节、三个半天单一路线;没有49天行动计划或两分支;个人勾选只存本机。
- 保持:数据库和既有业务记录不改,身份/连接不改。挂站完成与豆包员工电脑安装生效分开反馈;全量小组展示和豆包实跑按后续任务验收。
'''
def stage():
released = json.loads((ROOT / 'docs/workshop-onboarding-20261109-r5/online-release-receipt.json').read_bytes())
assert released['published'] and released['allPublicFilesReadBack'] and released['workshopSkillVersion'] == 'r10'
source = {n: (SOURCE / n).read_bytes() for n in NAMES}
assert b'__R10_INSTALL_GUIDE__' not in source['content.js']
assert released['guideUrl'].encode() in source['content.js']
html = source['index.html'].decode('utf-8')
html = html.replace('', '')
for name in ['content.js', 'manual.js']:
script = source[name].decode('utf-8').replace('', '')
html = html.replace('