# 需求:驾驶舱发布两天没落地却报「完成」-deploy_dashboard.py-把-wrangler-fetch-failed-吞成代理兜底且退-0

状态: done(2026-10-20 已落地:2026-10-17 重构收口:deploy_dashboard.py 裸运行/未知参数/渲染失败/输入比产物新一律拒发并退 1,失败不再渲染成『完成(代理兜底)』;--verify 取线上字节逐页比对,MATCH 才算成功。本日 09:4x 实跑 --from-render --verify 九页全 MATCH)
归属: 主会话(ops)
来源: 数据自动发现(ops/data/auto-findings.json)
日期: 2026-10-16
建议: 做,2026-10-16 15:47 做 onboard-hub 时按「驾驶舱即时刷新」跑部署,脚本打印「[deploy] 完成 → https://pinnadash-ops.pages.dev/dashboard/(代理兜底)」且退出码 0,但线上页面实测仍是 2026-10-13 14:39 的版本(本地已是 10-16 15:47、在池 98 票 proposed 4;线上还在 91 票 proposed 2)——老板唯一的状态入口连续三天在展示旧状态。带 -First 40 单独跑 deploy_dashboard.py 抓到真因:wrangler 报「Please check your network connection and try again / X [ERROR] fetch failed」(npx 通道,Volta 下 npx.EXE),日志 C:\Users\lin\.wrangler\logs\wrangler-2026-10-16_07-49-56_772.log。两个缺陷:①发布真的失败了(网络侧,可能代理/DNS);②脚本把失败渲染成「完成」+括号注解,退出码 0,静默吞错,与「状态入口滞后=老板看到的系统在撒谎」「禁止静默吞错」两条直接冲突。同一函数在 14:00 场也是同样形态(代理兜底字样),说明这不是偶发。修法:失败必须非 0 退出并在驾驶舱/日报挂红,而不是把失败写成人话注解。

## 现状

2026-10-16 15:47,本会话按「驾驶舱即时刷新」规则跑 `python ops/dashboard.py && python ops/deploy_dashboard.py`,脚本输出 **`[deploy] 完成 → https://pinnadash-ops.pages.dev/dashboard/(代理兜底)`**、退出码 **0**;线上实测却是**三天前**的版本:

| 口径 | 在池 | proposed | 生成于 |
|---|---|---|---|
| 线上 `https://pinnadash-ops.pages.dev/dashboard/demand`(HTTP 200,17511 字节) | 91 票 | 2 | **2026-10-13 14:39** |
| 本地 `ops/dashboard/demand.html` | 98 票 | 4 | 2026-10-16 15:47 |

真因(把 `deploy_dashboard.py` 单独跑并放开输出抓到):

```
[deploy] 失败(C:\Program Files\Volta\npx.EXE): ...Please check your network connection and try again.
X [ERROR] fetch failed
Logs were written to "C:\Users\lin\.wrangler\logs\wrangler-2026-10-16_07-49-56_772.log"
[deploy] 完成 → https://pinnadash-ops.pages.dev/dashboard/(代理兜底)
exit=0
```

两个缺陷,前者是环境、后者是纪律:

1. **发布真的失败**:wrangler 4.151.0 经 `npx`(Volta 下 `npx.EXE`)上传 Pages 时 `fetch failed`(网络/代理/DNS 侧),没有落到线上。
2. **失败被写成「完成」且退 0**:脚本捕获失败后打印「完成 + (代理兜底)」并正常退出,于是**驾驶舱这个老板唯一状态入口连续三天展示旧状态,而每个会话收到的都是「部署完成」**。这与两条硬规则直接冲突:「状态入口滞后=老板看到的系统在撒谎」「禁止静默吞错(catch 必须记日志/上抛/说明)」。14:00 场也出现同样的 `(代理兜底)` 字样,说明不是偶发。

## 方案

1. **先修纪律,再修网络**(顺序不能反,否则修好网络也照样埋着这个雷):`deploy_dashboard.py` 里失败分支**必须非 0 退出**,失败原因作为错误上抛/入日志,禁止把失败渲染成「完成」;「代理兜底」若确是一种合法降级(例如备用发布通道),必须**同时**:①打印明确标注「本次未发布到 Pages,线上仍是 <线上版本生成时刻>」②退出码非 0(或写入 `ops/data/` 的发布台账供驾驶舱挂红)——降级可以存在,静默不可以。
2. **加「发布即核验」闭环**:deploy 成功后回读线上页面(抓 `生成于` 时刻或内容指纹)与本地生成物比对,**不一致即失败**。判据要写进脚本,不靠人记得手动 curl。
3. **在驾驶舱/日报暴露发布健康**:`system_health.py` 增一项「驾驶舱线上版本时刻 vs 本地生成时刻」,滞后即挂红——这样即使脚本退 0,状态入口也能自曝滞后。
4. **网络侧排查(需 boss 环境信息)**:确认本机到 Cloudflare API/Pages 的通道(代理设置、DNS、Volta 下 npx 是否被拦),必要时改用 wrangler 本地安装的直连可执行文件而不是 `npx` 转发;此项属本机环境,agent 可先跑 `python ops/env.py` 侧的可达性探测定位。
5. **边界**:`ops/deploy_dashboard.py`、`ops/system_health.py` 归主会话(ops)与「系统健康」owner;本会话**只报不改**(当时 ops/ 有并发未提交 WIP,按并发认领协议不越界)。

## 验收标准

- [ ] 人为制造一次发布失败(断网或指向坏 endpoint),`deploy_dashboard.py` **退出码非 0**,输出里不出现「完成」字样,且失败原因带 err 原文
- [ ] 发布成功后脚本**自动回读线上**并打印「线上版本时刻 / 本地生成时刻 / 一致」;两者不一致时退出码非 0
- [ ] `https://pinnadash-ops.pages.dev/dashboard/demand` 的「生成于」与当次本地生成时刻一致(线上实测,不是本地断言)
- [ ] `system_health` 出现「驾驶舱线上滞后」指标,并在人为滞后时挂红(有负向用例)
