CNB 流水线 Solver「读不到本轮信息 / 没有题」怎么排查:scenario/.current-round.json 不存在、scenario/ 只有 .gitkeep、当天无 push→日期分支
日期:2026-09-20 08:00(CST,UTC+8) 环境:CNB(cnb.cool)默认 NPC 镜像
cnbcool/default-npc:latest,services: docker(DinD) 技术栈关键词:CNB 流水线、cnb.yml、crontab: 0 0,8,16 * * *、npc:go、CodeBuddy-Creator / CodeBuddy-Solver、 stage 交接、.current-round.json、孤儿分支、构建 pending、cnb build get-build-logs、cnb issues list-issues一句话结论:Solver 报「读取不到本轮信息」时,先别急着解题 —— 用「状态文件 + 问题环境 + 远端分支 + 历史 Issue + 当天构建记录」做五要素判定; 全空时要如实记录诊断,而不是硬造一题刷成交。
一、问题背景
本仓库是「每天 3 个计算机实战问题」的自动化训练闭环。.cnb.yml 里一条定时流水线每天 3 次(00:00 / 08:00 / 16:00)触发:
main:
"crontab: 0 0,8,16 * * *":
- name: scenario-daily-round
stages:
- name: generate-scenario # Stage 1:CodeBuddy-Creator 出题
type: npc:go
- name: solve-scenario # Stage 2:CodeBuddy-Solver 解题
type: npc:go
两个 stage 共享同一个工作目录。Creator 通过写一个不提交的状态文件把本轮信息交接给 Solver:
{"branch":"2026-09-20-0800","issue":70,"scenario_dir":"scenario/2026-09-20-0800","topic":"..."}
# 路径 scenario/.current-round.json,已在 .gitignore 中被忽略
2026-09-20 08:00 场轮到 Solver(solve-scenario)启动时,典型症状:
cat scenario/.current-round.json→ No such file or directoryls -A scenario/→ 只有.gitkeepgit branch --show-current→ main(不在任何日期分支上)git ls-remote origin 'refs/heads/2026-09-20-0800'→ 空
Solver 面对的是「空手接活」。先判断这是不是异常,再决定怎么做。
二、复现步骤(诊断命令,可原样照跑)
全部命令在 CNB 流水线容器内执行,
cnbCLI 已登录(cnb status)。
1. 看有没有交接文件、工作区有没有本轮环境
test -f scenario/.current-round.json && cat scenario/.current-round.json || echo "NO_STATE_FILE"
ls -A scenario/
git branch --show-current
实测输出:
NO_STATE_FILE
.gitkeep
main
2. 远端有没有本轮分支
git fetch origin --prune
git ls-remote --heads origin | grep 2026-09-20
实测输出:
23b0432369985fc60be5483555c117f90b02dd53 refs/heads/2026-09-20-0000
→ 当天只有 2026-09-20-0000(00:00 场,第69题,已完成)—— 没有 2026-09-20-0800。
3. 历史 Issue / 本轮 Issue、历史最大题号
# 本轮(0800)Issue 是否存在
cnb issues list-issues --repo zhenxijs/3dayTest/3day-test \
--page-size 5 --order-by=-created_at --state open
# → total: 1(只有 #82 第66题 2026-09-19-0000,与本轮无关)
# 历史最大题号
cnb issues list-issues --repo zhenxijs/3dayTest/3day-test \
--page-size 6 --order-by=-created_at --state closed
实测输出(截取):
total: 79
- number: "85" title: 【实战题·第69题】…(2026-09-20-0000) created_at: "2026-09-19T16:31:35Z"
- number: "84" title: 【实战题·第68题】…(2026-09-19-1600)
- number: "83" title: 【实战题·第67题】…(2026-09-19-0800)
→ 历史最大题号 = 69(#85)。没有 2026-09-20-0800 的 Issue,08:00 场的题从未发布。
4. 关键:当天的构建记录
cnb build get-build-logs --repo zhenxijs/3dayTest/3day-test \
--createTime 2026-09-20 --endTime 2026-09-20 --page-size 30
实测输出(关键字段,快照 total: 5):
- sn: cnb-6h8-1k2u1ppcc
createTime: "2026-09-20T00:00:06.000Z" # = 本地 08:00:06
status: pending duration: 3207000 # ≈ 53.5 分钟(运行中)
event: "crontab: 0 0,8,16 * * *" # ★ 本场定时构建(就是当前这条)
targetRef: main
- sn: cnb-mq4-1k2t8a2le
createTime: "2026-09-19T16:34:36.000Z" status: success event: push targetRef: main
- sn: cnb-eho-1k2t89fpl
createTime: "2026-09-19T16:34:17.000Z" status: success event: push targetRef: 2026-09-20-0000
- sn: cnb-unp-1k2t8463p
createTime: "2026-09-19T16:31:23.000Z" status: success event: push targetRef: 2026-09-20-0000
- sn: cnb-2ug-1k2t6bkqa
createTime: "2026-09-19T16:00:31.000Z" status: success duration: 2126504 # ≈ 35.4 分钟
event: "crontab: 0 0,8,16 * * *" # ★ 00:00 场定时构建
targetRef: main
读法(三个坑都在这):
createTime是 UTC,本地是 UTC+8:2026-09-20T00:00:06Z实际是 08:00:06 CST,正是本场。- 当天
total: 5里只有两条crontab定时构建:cnb-2ug-1k2t6bkqa(00:00 场)与cnb-6h8-1k2u1ppcc(08:00 场,当前);另三条是push触发的质检/文档构建。 - 所有
push构建都指向2026-09-20-0000或main,没有一条指向2026-09-20-0800—— 平台侧证明:08:00 场的 Creator 从未 push 过任何东西。
5. 交叉验证:正常一轮应留下 push→日期分支 痕迹
cnb build get-build-logs --repo zhenxijs/3dayTest/3day-test \
--createTime 2026-09-19 --endTime 2026-09-19 --page-size 30
# → total: 12,可见每场次的三段式:crontab → push→<日期分支> → push→main
实测(截取):
2026-09-19T00:00:04Z crontab → cnb-hoo-1k2rfd0fn(00:00 场)
2026-09-19T00:10:50Z push → 2026-09-19-0800
2026-09-19T00:15:52Z push → 2026-09-19-0800
2026-09-19T08:00:01Z crontab → cnb-4sg-1k2sarqs7(08:00 场)
2026-09-19T08:58:41Z push → 2026-09-19-1600
→ 正常一轮必然留下 push→<日期分支> 的痕迹。今天 08:00 场完全没有,与「Creator 未产出」一致。
6. 顺带确认 Docker 可用(排除「环境没起来」)
docker version --format '{{.Client.Version}} / {{.Server.Version}}'
# → 29.6.2 / 29.6.2-7 正常
三、根本原因
本轮(2026-09-20-0800)的 Creator 阶段没有产出任何交接物。
五要素交叉验证:
| 检查项 | 期望 | 实测 | 判定 |
|---|---|---|---|
scenario/.current-round.json | 存在且含 branch/issue | 不存在 | ❌ |
scenario/2026-09-20-0800/ | README + Dockerfile + compose + 代码 | 只有 .gitkeep | ❌ |
远端分支 2026-09-20-0800 | 存在 | 不存在 | ❌ |
| Issue「第70题(2026-09-20-0800)」 | 已发布 | 不存在(最大 #85 = 第69题/0000) | ❌ |
| 平台构建痕迹 | 有 push→2026-09-20-0800 | 无 | ❌ |
机制推断(与前一轮 2026-09-15-0800 的「第58题位」同型):
两个
npc:gostage 共享同一工作目录,而 Creator 的交接物 (scenario/2026-09-20-0800/、.current-round.json)在 push 之前只活在这块目录里, 且.current-round.json还被.gitignore忽略、永远不进版本库。 一旦本场 Creator 未执行到「commit + push + 发 Issue」,或工作区被重置、被并发实例覆盖, 本轮的题、分支、Issue 就会同时归零且无任何残留 —— Solver 只能空手。本场跑到 08:53(
duration ≈ 53.5 min)仍未结束,00:00 场也跑了 35.4 分钟; 单轮耗时长,一旦某场超时,就会被后续场次追尾。
一句话:Solver 读到「空手」=「本轮 Creator 未产出」+「共享工作目录未留任何可查痕迹」的组合结果。
⚠️ 这不是某道题的解答,也不是「某道题挂了」,而是流水线 stage 交接机制的可靠性缺陷。
四、解决办法
1) 本轮处理方式(对工作负责的姿势)
- 不发明题号、不硬造题目、不改历史产物:
- 不臆造「第70题」并编造一套假环境 —— 那样写出的 SOLUTION / 经验文档是脱离真实环境的伪证据, 会污染整个经验库的可信度;
- 不动
2026-09-20-0000(第69题)的任何文件。
- 只沉淀「诊断过程本身」:可复现命令链 + 实测输出 + 判定表(就是本篇)。
- 给结论留落点:本轮 Issue 不存在,走「分支内文档 + commit message」通道(见第六节)。
- 指出缺陷位置,便于配置侧加固。
2) 流水线侧加固建议(改 .cnb.yml)
建议 1:Solver 开头做「交接物」硬校验,缺料即快速失败
# solve-scenario stage 开头(示意)
test -f scenario/.current-round.json \
|| { echo "FATAL: Creator 未留下 scenario/.current-round.json,本轮无题可解"; exit 1; }
BRANCH=$(python3 -c "import json;print(json.load(open('scenario/.current-round.json'))['branch'])")
git rev-parse --verify "origin/$BRANCH" >/dev/null \
|| { echo "FATAL: 远端不存在分支 $BRANCH"; exit 1; }
test -d "scenario/$BRANCH" \
|| { echo "FATAL: 缺少问题环境 scenario/$BRANCH/"; exit 1; }
建议 2:给交接文件加「新鲜度」字段,防跨场次串读
.current-round.json 增加 created_at / run_id,Solver 校验其是否等于本次运行,
避免读到上一场遗留的文件。
建议 3:加流水线互斥锁,消除并发撞车
lock:
key: scenario-daily-round
wait: false
建议 4:交接物双保险
状态文件不提交、极脆弱。Creator 应同时把轮次信息落到 Issue 正文 与 commit message; Solver 在状态文件缺失时按「当天日期查最近 Issue + 远端分支」兜底(本轮诊断正是这个兜底思路)。
五、验证
# 1) 无交接文件
test -f scenario/.current-round.json || echo "NO_STATE_FILE" # → NO_STATE_FILE
# 2) 无本轮环境
ls -A scenario/ # → .gitkeep
# 3) 无本轮分支
git ls-remote --heads origin | grep 2026-09-20-0800 # → 空
# 4) 无本轮 Issue(历史最大 #85 第69题)
cnb issues list-issues --repo zhenxijs/3dayTest/3day-test --page-size 5 --order-by=-created_at --state open
# → total: 1(仅 #82 第66题)
# 5) 当天两条 crontab 构建,无 push→2026-09-20-0800
cnb build get-build-logs --repo zhenxijs/3dayTest/3day-test --createTime 2026-09-20 --endTime 2026-09-20
# → total: 5(crontab×2 + push×3,push 均指向 2026-09-20-0000 / main)
# 6) 环境可用性反向验证
docker version --format '{{.Client.Version}} / {{.Server.Version}}' # → 29.6.2 / 29.6.2-7
结论:不是 Docker/网络问题,也不存在「已就绪但未被读取」的题; 本轮确实无题可解,已按实情记录而非伪造产出。
六、经验与避坑
- Solver 报「读不到本轮信息」时,先做五要素判定,再决定动作: 状态文件 → 问题环境目录 → 远端分支 → 历史 Issue → 当天构建记录。 全空 = 本轮无题,不要硬造。
scenario/.current-round.json是「不提交」的进程内交接物,生命周期只有「同一工作目录内的相邻 stage」。 任何git checkout/git reset/ 工作区重刷都可能让它蒸发;它不是可靠持久化载体。- 别把「构建是新创建」当成「构建属于本场次」:
createTime是 UTC,本地 UTC+8。2026-09-20T00:00:06Z其实是 08:00:06 CST。时区看错一步,结论就反了。 status: pending不能当「已产出」的证据,也不能当「成功构建」引用。- 别把
pipelineTotalCount读成「当天构建条数」:它是单条构建内部的 pipeline 条数 (同一构建的多 job),与当天有多少条构建记录是两个维度。数当天条数看列表的total。 - 「有没有
push→<日期分支>构建」是判断 Creator 是否产出的强证据: 正常一轮必有「commit + push 分支」的动作。当天一条都没有 → Creator 根本没跑完。 - 时间线自相矛盾就是信号:当「上一场的产物时间」晚于「本场次的触发时间」, 基本可断定存在多实例撞车 / 前一场未结束。
- 共享工作目录的 NPC 流水线一定要做并发互斥(
lock: { key: ... }), 否则「未提交的进程内状态」会被并发实例互相覆盖,产生「偶发莫名其妙的空手接活」。 - Issue 缺位时,结论要走「三级替代通道」,不能悬空: ① 分支上的 commit message → ② 分支内 SOLUTION.md / 经验文档 → ③ 分支评论 / 构建说明。 两条红线:不新建 Issue(题号序列属 Creator 职责,凭空造号会污染序列); 不把结论评论到上一场 Issue(会造成串场)。
- 文档要写「实情」而不是「战果」:本轮没有可解题的环境,就记录诊断链路与加固建议。 伪造一道题再写「修复前后 PASS 对比」,是最坏的做法——它会污染整个经验库的可信度。
cnbCLI 的--repo必须是三段式(组织/仓库组/仓库), 写成两段会得到status: 404 / errmsg: Resource not found.。- Solver 侧不创建/不提交与本轮无关的残留目录:工作区若有未跟踪的一次性脚手架(如
.tmpimg/), 不要顺手提交,也不要据此推断题号;保持git status干净,便于后续排障。
附:本轮事实快照
| 项 | 值 |
|---|---|
| 运行时间 | 2026-09-20 08:53 CST |
| 触发事件 | crontab: 0 0,8,16 * * *(08:00 场) |
| 当前 stage | solve-scenario(CodeBuddy-Solver) |
| 本场 crontab 构建 | cnb-6h8-1k2u1ppcc(2026-09-20T00:00:06Z = 本地 08:00:06;pending,≈53.5 min) |
| 当天构建总数 | 5:cnb-6h8-1k2u1ppcc(crontab 08:00) + cnb-2ug-1k2t6bkqa(crontab 00:00) + cnb-mq4-1k2t8a2le(push→main) + cnb-eho-1k2t89fpl/cnb-unp-1k2t8463p(push→2026-09-20-0000) |
| 对照:00:00 场构建 | cnb-2ug-1k2t6bkqa(2026-09-19T16:00:31Z = 本地 00:00:31,success,≈35.4 min) |
| 本轮 Issue | 不存在(--state open → 仅 #82 第66题) |
| 构建地址 | https://cnb.cool/zhenxijs/3dayTest/3day-test/-/build/logs/cnb-6h8-1k2u1ppcc |
| 当前分支 | 2026-09-20-0800(承载诊断文档的孤儿分支) |
| 历史最大题号 | 69(Issue #85,分支 2026-09-20-0000,closed) |
| 本轮状态 | 无题可解(Creator 交接物缺失),仅产出诊断文档 |
