# 观澜·如东样板 v2 (v0.2.0) 启动报错修复记录 — 2026-09-11 本目录**不属于原始交付包**, 是现场修完之后留下的记录: 每个脚本都可重复运行 (幂等), 用来复现 "改了什么" 或在别的机器/另一份拷贝上重放同一批修复。 ## 现场现象 ``` powershell -ExecutionPolicy Bypass -File install.ps1 -> 装完最后一步崩: json.decoder.JSONDecodeError: Unexpected UTF-8 BOM (decode using utf-8-sig) start.bat -> 同样崩; 随后 [X] Server did not start (reason above). Not opening the browser ``` ## 根因 (5 条, 前 3 条是同一个坑的不同后果) | # | 位置 | 问题 | |---|------|------| | 1 | `install.ps1` 第 4 步 `Set-Content configs\serve.json -Encoding UTF8` | **Windows PowerShell 5.1 的 `-Encoding UTF8` 写出带 BOM 的 UTF-8**; `guanlan.py` 用裸 `utf-8` 读 -> `JSONDecodeError`。启动器在解析配置时就死了, 所以 `check`/`serve` 全跑不起来。 | | 2 | 同一行的 `Get-Content configs\serve.json -Raw` | PS 5.1 对**无 BOM** 的 UTF-8 按 ANSI 代码页 (中文机 = GBK) 解码, 于是把文件里的中文注释读成乱码, 再 `Set-Content` 写回 -> `_note` / `_note_raw` 两个字段永久损坏 (部分字节被替换成 `?`, 不可逆)。 | | 3 | 机器全局 `PYTHONPATH=D:\Program Files\Python\Lib\site-packages;` | ① pip 认为系统那套包 "已满足", **没把传递依赖装进 `.venv`** -> venv 缺 `urllib3`/`polars`/`pyyaml`/`jinja2`/`python-dotenv` 等, 换个没设 PYTHONPATH 的 shell 直接 `ModuleNotFoundError`; ② `PYTHONPATH` 排在 sys.path 前面, 把 pin 住的版本顶掉 (实测 `requests` 2.33.0 顶掉 2.34.2)。 | | 4 | `wheels\win_amd64\` | 缺 `colorama` 轮子 (`tqdm` 在 Windows 上的依赖)。之前被根因 3 掩盖: pip 看到系统已有 colorama 就不下载, 于是离线轮子集不全; 一旦 PYTHONPATH 摘干净, `pip install --no-index` 直接 `ERROR: No matching distribution found for colorama`。 | | 5 | `release/sim_sys_server.py` 第 36 行 `from scrub_rules import scrub, residual` | **`scrub_rules.py` 根本没随包发出** (全盘搜不到, zip 里也没有) -> `/sim/sys/ 仿真·四系统合页` 502, `logs/sim_sys.log` 里是 `ModuleNotFoundError`; 网关因此 `degraded`, `guanlan.py serve` 退出码 1。 | ## 改了什么 | 文件 | 改动 | |------|------| | `guanlan.py` | 新增 `jload()` = `utf-8-sig` 读 JSON (兼容有/无 BOM), 5 处配置读取全部改走它; 配置坏了只打印提示并退回内置默认端口, 不再抛栈。新增 `_hermetic()`: 启动时把 `PYTHONPATH` 从 `sys.path` 与环境里摘掉 (子进程继承干净环境)。 | | `install.ps1` | 第 4 步不再用 PS 的 cmdlet 碰配置, 改由 `.venv` 里的 Python 读写 (读 `utf-8-sig` / 写无 BOM 的 UTF-8), 并加注释说明为什么不能改回去; 顶部加 `Remove-Item Env:PYTHONPATH`, 让 pip 老老实实把包装进 `.venv`。文件仍保持 **UTF-8 带 BOM + CRLF** (PS 5.1 解码中文的前提)。 | | `install.sh` | 同样加 `unset PYTHONPATH` (保持 LF/无 BOM)。 | | `configs/serve.json` | 去掉 BOM; 还原 `_note` / `_note_raw` 两段中文注释 (依据残留可逆部分 + 说明书 §7 的措辞)。 | | `wheels\win_amd64\colorama-0.4.6-py2.py3-none-any.whl` | 补上缺失的轮子, 离线安装才完整。 | | `release/scrub_rules.py` | **恢复缺失文件**: 不新写任何脱敏规则, 只把包内唯一那份规则表 `src/windscada/deid_public.py` 转出 `scrub` / `residual`(= `audit`) / `scrub_or_die`。若拿到交付方原版, 直接覆盖。 | | `start.bat` | `guanlan.py serve` 的退出码 1 有两种含义 (网关没起来 / 网关起来了但有模块降级)。现在先探一次 `/healthz` 区分: 真没起来才报 `[X]` 并停下; 起来了但有降级则打 `[!]` 说明, 浏览器照常打开。 | ## 备份与回滚 原文件都留了副本, 直接改名覆盖即可回到改前状态: ``` guanlan.py.bak-bomfix install.ps1.bak-bomfix configs\serve.json.bak-bomfix guanlan.py.bak-pyfix install.ps1.bak-pyfix install.sh.bak-pyfix start.bat.bak-healthz ``` ## 重放 / 验证 ``` .venv\Scripts\python.exe fix_guanlan_bom.py # 1 2 (BOM + 乱码) .venv\Scripts\python.exe fix_guanlan_pythonpath.py # 3 .venv\Scripts\python.exe fix_guanlan_startbat.py # start.bat 判定 .venv\Scripts\python.exe verify_guanlan_simsys.py # 5 个仿真页 200 + 脱敏回扫干净 ``` 三个 `fix_*` 都是幂等的 (已改过会打印 "已修过")。`wheels\colorama*.whl` 与 `release\scrub_rules.py` 属于新增文件, 没有对应的 `fix_*` 脚本。 ## 仍然存在 (不是代码问题) - `/local-ai/` 仍是 DOWN: 本机 Ollama 没运行, 且 `%USERPROFILE%\.ollama` 下**没有任何模型** (`manifests` 都没有), 所以问答与本地审核页不可用。其余 6 个页面不受影响。 启用: 启动 Ollama, 按 `configs\models.json` 的 `pull_commands` 拉模型 (需联网/大流量), 或把有网机器的 `%USERPROFILE%\.ollama\models` 整个目录拷过来。 - `release\如东` (治理清单交付件) 本来就是可选项, 不影响页面。