zhouyang.xie 54ab6a1a75 门户拆包: 壳受管, 内嵌件与 20MB 合成结果移出版本管理 преди 1 месец
..
README.md 54ab6a1a75 门户拆包: 壳受管, 内嵌件与 20MB 合成结果移出版本管理 преди 1 месец
manifest.json 54ab6a1a75 门户拆包: 壳受管, 内嵌件与 20MB 合成结果移出版本管理 преди 1 месец
shell.html 54ab6a1a75 门户拆包: 壳受管, 内嵌件与 20MB 合成结果移出版本管理 преди 1 месец

README.md

release/portal_src —— 门户的"受管外壳 + 不入库内嵌件"(2026-09-11)

这是什么

release/portal.html(20.23 MB 单文件门户)里 99.3% 是内嵌的交付文档正文 —— 28 个 <template>(治理清单分册、单机/整机报告、仿真台面板…),只有约 138 KB 是门户自己的壳 (样式、脚本、导航、面板结构)。原先整份文件都在版本库里,于是每次重算产物都往 git 里塞 20 MB。

本目录把两者拆开:壳受管、内嵌件与合成结果不入库,而且拆→装能回到逐字节相同的文件。

路径 入库 说明
shell.html ✅ 门户外壳 138.5 KB。内嵌件处留标记 <!--@TEMPLATE:<id>-->;资料索引处留 <!--@GOVERNANCE_SOURCES-->
manifest.json ✅ 各件 sha256、条数、期望的 portal.html sha256、行尾约定、说明
README.md ✅ 本文件
templates/<id>.html ❌ 产物 28 个内嵌交付文档正文,共 20.04 MB(交付件内容)
governance_sources.json ❌ 产物 脱敏资料索引 + source_sha256,1.5 KB
../portal.html ❌ 产物 装配结果;服务/网关直接读它

未入库的三项不随包体缺失:它们就在本目录/上一层,随包分发、参与运行;只是不进版本库。 manifest.json 里留了它们的 sha256,用来做漂移检测。

重建

.venv\Scripts\python.exe scripts\portal_build.py            :: 装配 → release\portal.html (含契约结论段)
.venv\Scripts\python.exe scripts\portal_build.py --verify   :: 装配到临时文件, 与现有门户逐字节比对
.venv\Scripts\python.exe scripts\portal_build.py --check    :: 各源件与 manifest 的 sha256 漂移检查
.venv\Scripts\python.exe scripts\portal_build.py --extract  :: 从现有门户重新拆出本目录 (一次性/重置用)
.venv\Scripts\python.exe scripts\portal_build.py --no-claims:: 只装外壳与内嵌件, 不注入契约结论段

期望结果:--verify 打印两行相同的 sha256 并给出 逐字节一致,退出码 0。

当前基线(本包,出厂状态):

release/portal.html   20,226,052 B   sha256 9b6aabeb6ca18d15…

两个必须知道的坑

  1. 行尾必须是 LF。门户通体 LF(0 处 CRLF)。Python 文本模式在 Windows 上写文件会把 \n 转成 \r\n —— 20 MB 文件整体改写,/api/version 里的 portal_sha256 与页面指纹全变。 所以 portal_build.py 全程字节级读写(rd/wr),两个就地注入器 (guanlan_portal_fix_anchors.py、guanlan_portal_inject_claims.py)写文件都带 newline="", 装配末尾还有一道 CRLF 自检 —— 触发就直接报错,不留一个"看起来一样"的文件。
  2. 契约结论段是产物,不在壳里。<section id="contract-claims"> 由 scripts/guanlan_portal_inject_claims.py 在装配最后注入,内容来自 outputs/<场站>/guanlan/derived/portal_claims.json(事实契约派生物)。 因此 --extract 会把它从壳里剥掉,装配时重新生成;没有产物时装配出的门户会缺这一段, 这正是"产物不在则内容不在"的预期行为。

相关

  • 契约与产物地图:docs/数据目录结构与落位约定_v0.2.md §6
  • 产物进出 git 的约定与那次误提交的复盘:仓根 .gitignore 注释 + _修复记录_20260911/README.md
  • 人工检查空状态:scripts/products_state.py --off/--on/--status