跳转至

发布与打包机制的独立复核

日期:2026-10-18。范围是发布机制与当前本地资产的只读检查;没有执行发布、Nginx reload、浏览器访问或重跑正文实验。不修改作者/交叉正文指纹,本报告不作为最终线上验收收据。

读取范围

完整读取 scripts/prepare_course.py、assemble_course.py、review_artifacts.py、verify_review_fingerprints.py、browser_check.py、deployment/pi.baoer.me.conf。为确认依赖与相邻责任,另读 course_config.py、mkdocs.yml、mkdocs_hooks.py、review_sources.py、verify_download_packages.py。这些读取只说明下述具体机制核对,不扩张为所有发布脚本审计。

当前确认的机制

固定版本与压缩包

  • course_config.py 固定 source=pi-1.3.0、commit=71023aec1546d6d677a65669c5665c0927ce0dd0、edition=20261018-pi130,research 来源仅为本次 research/v1.3.0。
  • prepare 从实际 examples 输入构建实验 ZIP;Path.rglob('*') 包含 .gitignore,当前该文件已纳入。package-lock 包含在 ZIP,但不整篇复制进实验源码附录,二者职责不同。
  • assemble 的显式章节顺序包含 21/22 和全部当前正文;Markdown ZIP 包含分章、完整单页、研究附件、源码阅读器、内嵌实验 ZIP,以及重建所需 mkdocs.yml、requirements.lock、mkdocs hook。它排除对自身 ZIP 的递归打包。
  • delivery-final.json 被 prepare 明确跳过:最终公网收据需在 ZIP 固定之后单独生成,不把最终 ZIP 哈希回填进同一 ZIP 导致循环。
  • review_artifacts 对实验 ZIP 文件集合及每项字节做比较,对 site 源码阅读器提取 code 行逐行比较,并检查 raw Markdown 下载与合并正文一致。它不单独完成整个 Markdown ZIP 内容完整性验收;后者还依赖 assemble 后的临时解压 strict build、下载重建及公开资产比对。

只读检查时,实验 ZIP 33 项、0 重名,与当前打包/审查文件集合一致,全部字节相同,包含 .gitignore。Markdown ZIP 当时 336 项、0 重名,含 21/22 与重建配置,证据目录只有 v1.3.0;没有 node_modules、.agent、.sessions、.checkpoints、.env 或旧版 v1.0.1 目录。80 个源码阅读器与选定列表恰好匹配,没有多余旧阅读器。

该时点 Markdown ZIP 仅 docs/labs/15-production.md 落后于刚修正的取消图,已告知 root 在最终冻结后重新 assemble。这是正在生成中的资产状态,不将其当作最终已发布结果。最终完整源码报告的附件尚在归档中,也不按内容缺陷判定。

至少三份独立审查

verify_review_fingerprints.py 重新枚举全部 primary Markdown 与 examples,比较当前 SHA256,不仅检查报告文件存在。core/product/labs/source 四个 reviewer 槽位逐个计数;同一个 reviewer 不会因为列两次文件获得两个票。

作者排除表覆盖 core 的六章、product 的六章、labs 的三章。labs 自己的 examples 不计独立,只有由 root 编写的 env/chord 两个 fixture 被明确豁免作者排除。作者范围出现在自己的独立清单会产生错误,不会静默算作一票。任一文件少于三名独立 reviewer 会失败;source 全文审还必须覆盖全部当前输入。提供 canonicalFilesSha256 时也会重新核对。

只读模拟当前枚举得到 56 个主输入,现有作者交叉清单没有作者范围误计。第四完整清单当时尚未归档,所以最低计数仍为 2;这是预期未完结状态,正式发布应等该清单与受影响文件复验归档,再通过实际 gate。机制验证不了人是否真的独立读过源代码,也不解析自然语言 PASS 的真实性;独立分工、报告内容及最终结论仍由审查过程负责。

Nginx 归档与隐藏路径

HTTP 将常规请求重定向 HTTPS,ACME challenge 是明确例外。HTTPS 的 /archive/v1.0.1/ 使用单独 alias 指向 /var/www/pi-course-archive/1.0.1/,不受当前站点 rsync 删除目录影响;无尾斜线入口有重定向。

归档 location 没有 ^~,因此 location ~ /\. 的隐藏路径拒绝仍能覆盖归档下 .git 等路径。/archive/v1.0.1/ 的版本点号位于 v1 后,既不是 slash-dot,也不是隐藏路径。/assets/...zip|md 使用 no-store,归档资产不被根 /assets/ 正则误路由。本次只核对配置文本,不证明线上已加载该配置或证书仍有效。

浏览器路由与交付证据

browser_check 从实际 site/index.html 派生路由,使用 .as_posix().strip('/'),不会把 v1.3.0 的点号当扩展名删除。只读列出的路由确实含 /appendix/v1.3.0/product-review-final/ 等路径,没有 v1/3/0 式误拆。expected_diagrams 同样按 route 字符串定位原始 Markdown。

机制逐页检查 HTTP 状态、diagram-ready、Mermaid 数量与 SVG 数量、错误图、最小文字大小和横向溢出;另测搜索、移动导航、深色图、源码行跳转和浏览器下载实际字节。COURSE_QA_SKIP_DOWNLOADS=1 会明确记录 downloadsSkipped,不能将这种运行称为下载验收。浏览器可执行文件路径固定在本机,换环境须配置/安装对应 Chromium;本报告不声称完成一次浏览器实跑。

已报机制问题与修法

  1. 排除规则不同步。 指纹 gate 排除 .dsh、*.pyc、*.record.json,初读的 prepare/review_artifacts 文件枚举却不排除这些项,可能出现打包文件无需三份审查的覆盖缺口。当前目录没有这样的额外输入,所以当前实验 ZIP 集合比对仍全过。建议提取一个共享输入过滤函数供打包、artifact 检查和审查 gate 使用。
  2. HEAD 不等于干净源码。 初读的 prepare 只 assert HEAD==COMMIT,随后读取工作树;review_artifacts 也对比同一工作树。固定 checkout 若有未提交修改,两者可能一致通过却不是 commit 原文。当前 git -C pi-1.3.0 status --porcelain 为空,当前没有此偏差。建议 prepare 拒绝 tracked 修改,或直接从 Git blob 生成原文。
  3. 生成目录不会自动清旧条目。 prepare 覆写本次选中的阅读器与证据,没有清理失去来源的旧文件;assemble 又会遍历全部 assets。当前独立核对 selected/actual 差集为空,证据仅 v1.3.0,因此没有发现当前混版。以后换版或删除某份生成附件时,需显式清理或增加多余文件集合检查。

上述问题已交 root 修正;以下为修正后独立复验。没有在本轮执行额外 npm 安装、全文测试或线上发布。

修正后复验与限定结论

  • 打包、artifact 比较和指纹 gate 现在均调用 course_config.example_inputs(),共享 runtime 目录、.pyc 和 .record.json 排除规则。重新只读枚举仍为33个examples、56个主输入;原正文/实验SHA清单没有因机制修正改变。
  • prepare 在任何正文生成前拒绝 tracked dirty checkout,并拒绝SELECTED中未被固定release追踪的reader。review_artifacts 直接以 git show <固定COMMIT>:<path> 获取比较对象,不再以同一工作树自证正确。
  • prepare 删除不在SELECTED中的旧reader HTML,并从原始证据重建当前edition的两份生成目录,避免已移除的本轮报告残留。其他edition目录仍需要换版时显式迁移/清理;当前已核对没有旧版目录,不将这一维护限制当作当前混版。
  • 对修正后的6个Python文件执行只读 compile 语法检查,通过;独立从Git固定对象读取80个原文,与当前site阅读器逐行比较,0不匹配。没有运行prepare去改变正文,也没有运行浏览器或发布命令。

限定结论:上述机制问题已修复并复验,当前可继续最终生成与交付验收。 这不是最终发布PASS:第15章修正后仍须统一重打包、第四报告归档、通过三独立审查gate、严格构建/下载重建与实际线上/browser检查。历史归档服务及最终公网字节也需最终交付收据证明。

本次复验对应的机制文件SHA256如下;仅绑定本报告机制输入,不修改正文独立清单:

文件 SHA256
scripts/prepare_course.py 69c465428d7426c40f8ae78306954793814a9d3fe5035c2f1cb7faf4ccba8b74
scripts/assemble_course.py 73fd9b718a2f46c3d7cf8825e1da12bce2cee7722a67ec4ac346106d96c7e5c5
scripts/review_artifacts.py 48521155da62110651c8a5457b7770a8331a9a8e3b09f78ff070da486bfe9f6c
scripts/verify_review_fingerprints.py e9da5591c38e12a0ac127b2ff9552edb04c704ffc331740784b0851f579f7e68
scripts/browser_check.py 768b24ed0f3bcf530644cc2d2fab0dd3c6617a67c194928b3bfead8a31be6ead
scripts/course_config.py acbbf10ea5b7c8213e7103f2f4f1f6833b1ee0292af7c73050d427459d4dd196
deployment/pi.baoer.me.conf cc72b49c261990a5e922d8352e768c572da28abf052780aae2cd87803f0b5edd