一句话答案:有人盯着的时候真能跑通,没人盯着就不能用。派发 → 容器 → 交付这条关键路是真的(M5、P3 两次真实出片为证),但它现在缺三样东西:不会自愈、没法重新部署、镜像供应链断了一截。三件都是工程活,不需要推倒重来。
代码里其实写了一整套自愈:卡死任务回收、重试次数用完判失败、定时任务派发、审核超时处理。但这套东西只活在一个叫 main.py scheduler 的独立进程里——我把 admin、worker2、worker3 三台机器的进程、systemd、PM2 全部翻了一遍:没有任何人在跑它。API 进程里也没有内嵌(启动代码里零接线,我逐行查过)。
这不是理论风险,库里现在就躺着两具尸体:
e3e203dd(r8_proof):状态 running,从 6 月 7 日卡到现在 4 天,一动不动。按代码本意,10 分钟后就该被回收重排。8cb14946(auto_ad_revision_router):在 default 队列里 queued 了 7 天——这个队列根本没有 worker,而且就算 scheduler 跑起来,"排了队但没人接"这种情况也没有任何超时和告警。这两个就是你在 Admin 页面看到的红卡。换句话说:现在发现卡死任务的机制,是你的眼睛。
连带后果:worker 半路挂掉 = 它手里的任务永久卡死;定时任务(recurring)在 2.0 上根本不会被派发。
我把四个地方的代码指纹(sha256)逐一对了一遍,结果是:没有任何一个 git 提交能复原线上任何一台机器正在跑的代码。
要害不在"乱",在"不可恢复":/tmp 一被清(重启就可能清),后 8 次部署的来源就永远没了;工作区一丢,2.0 的核心实现就只剩线上那份没有历史的拷贝。
具体数字:未提交的 7384 行里约 5000 行是承重墙——claim 隔离、镜像 reconcile、写围栏租约、/resolve 路由、整个 2.0 API 面。而且连这个工作区都只对应 6 月 8 日的中间版本,之后 8 次部署(bodysha → R10 → S4 → R0 → R9 M1-M4)每一步都是"拷贝上一个 release 目录、替换两个文件、加一层 drop-in"手工拼的。这条 16 步链我和 codex 各自独立核对过,每一步的 sha 都对上了。
repo 里没有任何部署物:没有部署脚本、没有 systemd 单元文件、没有环境变量模板,只有一份手工 runbook。线上的真实形态是:
.bak 文件也混在目录里。CI(GitHub Actions → GHCR)确实建了,但它只把镜像 digest 打印到构建日志里,不写进数据库的 runtime_profiles 表——登记和激活全靠手敲 SQL。更糟的是 CI 构建不传依赖清单哈希(默认 unknown),而容器里的身份自检会把 unknown 判为不合格直接退出——CI 产出的镜像在 image_owned 模式下天生不可用。线上能跑,是因为用的全是手工构建、手工推到 DockerHub 的镜像。等于说:自动化管道是装好但坏的,真供应链是一个人的手。
| 编号 | 问题 | 什么时候咬你 |
|---|---|---|
| P1-1 | 排了队但没 worker 接的任务,永远没人发现(scheduler 修好后依然存在——回收只看 running,不看 queued) | 队列名拼错 / worker 没起,任务静默消失 |
| P1-2 | worker 和控制面失联只打一条日志,之后继续按旧镜像跑任务;拉镜像失败也只是攒错误 | 升级镜像那天,部分机器悄悄跑旧版本 |
| P1-3 | NFS 双重单点:worker 启动硬依赖两个挂载,w2/w3 还都挂着 admin 的共享目录 | admin 一挂,worker 不能重启 + 在途任务 I/O 全烂 |
| P1-4 | claim 查询的 4 路 OR 条件用不上索引(迁移文件自己承认) | 队列一深,每次领任务都是全表扫 |
| P1-5 | 1.x 的 scheduler 若连到共享库,会去碰 2.0 的定时任务(没有版本过滤) | 现在没人连(我查过),但这是埋着的雷 |
| P1-6 | 写租约续约失败时静默退出,agent 继续干活但之后每次写都 409 | 长任务后半程全部写入失败,白跑 |
| P1-7 | 老模板迁移靠"踩一个坑补一条规则":宿主路径改写是硬编码清单,没有通用预检 | 每迁一个带宿主路径/环境变量的老模板,先跑挂一次 |
| P1-8 | 每个任务容器把宿主的 ~/.claude、CODEX_HOME 以读写挂进去 | 凭据/状态串扰,"全隔离"的说法被它一票否决 |
| P1-9 | TEMPLATE_RELEASE_ENVIRONMENT 默认 test,上 prod 忘改就会拿 test 快照派活,无护栏 | 未来切 prod 的第一天 |
完整清单(含 P2 工程债 6 条和每条的代码位置)在 /tmp/cc-review-tobatsu2-newworld-FULL-20260611.md。
所以判词不是"全错重做",是:骨架对,但现在是一台需要作者本人在场才能运转的原型机。
| # | 动作 | 修掉哪个 P0/P1 |
|---|---|---|
| 1 | 先锁源码:把工作区 +7384 行按模块拆成可审的提交推上分支;后 8 次部署的 /tmp 补丁同样入库 | P0-2(防丢失,其余一切的前提) |
| 2 | 把 scheduler 跑起来:一个 systemd 单元连 2.0 库,验证 e3e203dd 这类卡死被自动回收 | P0-1(自愈层上线) |
| 3 | 坍缩部署面:18 层 drop-in 收成 1 个环境文件 + 1 个干净单元;release 制作写成脚本进 repo;worker 统一到 systemd | P0-3(重启从此可预测) |
| 4 | 接通镜像管道:CI 补依赖清单哈希 + digest 自动登记为 candidate | P1 之首(供应链闭环) |
| 5 | queued 无人接的侦测告警、容器摘掉宿主 ~/.claude 挂载、其余 P1 按 owner 节奏 | P1 渐进清账 |
全程规矩不变:codex 改、cc 逐件验收;每件只修观察到的真问题,禁止顺手加框架、加旗标、加"未来可能用上"的东西。