格式:日期 | 模型 | 任务一句话 | 结果 | 观察(契约质量/验证是否跑/循环/压缩/误拦)
| 日期 | 模型 | 任务 | 结果 | 观察 |
|---|---|---|---|---|
| 2026-08-07 | ThinkingCap-27B | bench 首跑 t1(off) | PASS 185s | gate 拦 2 次;12 回合 13 工具;未调 task_complete 仍过 |
| 2026-08-07 | ThinkingCap-27B | bench 首跑 t2-t5(off) | 3/4,t3 FAIL | t3 模型只回 “Key” 零工具调用——thinking=off 下 review 崩溃 |
| 2026-08-07 | ThinkingCap-27B | bench 全量(low) | 5/5 PASS | low 比 off 快 30-40% 且修复 t3;t3 gate 拦 1 次(越界写入被拦、只读放行)——死锁回归通过 |
2026-08-07 关键诊断:headless 挂起根因
现象:pi --mode json 无头跑 ThinkingCap 时挂起,turns=0;小模型 Qwen3-0.6B 秒回。
排查链:
- curl 直连 8050 一切正常(chat/completions、completions、stream,各种参数均 200)
- 代理抓包:pi 请求体完整捕获(105KB、33 工具),用 urllib 原样重放给 oMLX 正常返回——oMLX 无问题
- 对比
--print模式:正常;--mode json+ 默认 thinking:挂起 - 杀僵尸 pi 进程后重测:默认 thinking 仍挂
根因:defaultThinkingLevel: high + ThinkingCap(推理型模型)→ oMLX 进入 thinking 流(reasoning_content),pi 对 oMLX 的 thinking 流式响应消费挂起(keepalive chunk 后无进展,stopReason=pending)。小模型无 reasoning 所以正常。历史成功会话 019fda4c 恰好是 thinking=off。
二次发现(更致命):thinking=off 虽绕过挂起,但让 ThinkingCap 的 review 类能力崩溃(t3 只回 “Key”)。--thinking low 是最佳档:不挂起 + 保留推理能力 + 更快。bench 驱动已默认 low。
经验:bench 无头跑本地推理模型,thinking 档位是首要变量;代理抓包要先写请求日志再转发(否则挂起时看不到)。
2026-08-07 证据驱动修复:验证节奏死锁(bench t2)
现象:t2(删除 app)errors=27 全量基线,其中 22 次是 task_verify 被拒,死循环。
根因(机制 vs 模型打架):协议要求”修改后运行验证”,但 verify() 机制强制”状态变更后须有成功的只读调用”。模型删完文件直接 task_verify → 机制拒 → 模型不知道要先跑只读检查 → 死循环。
修复链(5 轮迭代,errors 27→0):
- 协议补验证节奏说明(状态变更后先跑只读检查再 task_verify)
- 只读 bash 判定放宽:
&&/||链(每段只读则整体只读)、单&后台仍拦截 2>&1/2>/dev/null归一化;true/:白名单verify()放宽:一次只读调用可支撑多个 condition(仍要求变更后有只读证据)!negation 段、;链(每段只读)、node test.js/npm test测试验证白名单
结果:t2 errors 27→0;t4 errors 7→1(耗时 289→109s);t5 errors 1;全 5 任务 PASS。
经验:bench 的价值在暴露”机制与真实模型行为”的错位;本地模型验证惯用法(test && echo、! grep、; 链、node test.js)必须被 harness 识别为只读,否则 harness 会主动制造死循环。v0.2.1 已提交。
2026-08-07 quality-monitor:证据否定 vs 防御价值
证据:扫描 bench 历史 277 个 turn_end——0 次空响应;316 个工具调用中 14 个空参数全部是 task_complete(本就无参数,合理)。ThinkingCap 栈不犯 little-coder 检测的空响应/空参数错。
决策:不照搬 little-coder 的 quality-monitor,但仍实现了薄层版本(约 20 行检测逻辑 + telemetry 计数 + turn_end steer 纠正):
- 理由 1:防御价值——模型劣化或换更小模型时护栏仍在
- 理由 2:遥测价值——/local-report 增加 quality 计数,可监控
- 剥离:repetitive_loop 归 LoopGuard(已有),不重复实现
v0.2.2 已提交。教训:bench 让”该不该实现某机制”从拍脑袋变成数据决策——先查历史 transcript 有没有对应失败模式,再决定实现深度。
2026-08-07 v0.2.2 全量基准(修复后基线)
结果:5/5 PASS,errors 38→7(-82%),总耗时 826s(-11%)(ThinkingCap + low)
| 任务 | 基线 err | v0.2.2 err | 耗时 | gate |
|---|---|---|---|---|
| t1 | 2 | 1 | 118s | 1 |
| t2 | 27 | 0 | 200s | 0 |
| t3 | 1 | 1 | 100s | 1 |
| t4 | 7 | 4 | 240s | 2 |
| t5 | 1 | 1 | 167s | 1 |
回归验证通过:
- t3 gate_blocks=1 → 只读判定放宽后越界写入仍被拦(安全未削弱)
- t2 errors=0 → 验证死锁彻底修复
- t4 gate=2 是模型 2 次越界尝试被拦,非回归
全量确认:output-parser(G1)证据继续为零——本轮 5 任务 56 个工具调用全成功解析,无畸形调用。优先级维持:checkpoint(G4)为下一候选。
2026-08-08 read-guard(G3)实现 + checkpoint(G4)跳过决策
G4 checkpoint 跳过:
- 文件快照解析证据弱:edit 失败全是参数缺失(原子替换不落盘),无”改坏恢复”场景
- 跨会话恢复受 pi 扩展 API 限制:只有
appendEntry只写记录,无读回接口,无法 native 实现,与薄层哲学冲突 - 会话内跨 compaction 已工作:taskLedger 内存对象,session_compact 不重置
- 长任务超时风险证伪:最新全量最长 240s/900s;t1 曾 900s 是早期 thinking=high 挂起 bug(turns=0),非真实长任务
G3 read-guard 薄层实现(v0.2.3):
- 证据:历史 1 轮 t4 的 2 次 edit 无 read(err=5),其余轮全 read-first → 失败模式存在但罕见
- 实现:ReadGuard 跟踪已 read 路径,edit/write 未 read → block + steer;默认关(readGuard.enabled=false)
- 验证:readGuard on 跑 t4 → PASS、0 拦截(模型天然先读)、无回归
- 定性:防御机制,与 quality-monitor 同级
机制清单终局:G1/G4/turn-cap 全部证据否定;G3/G2 为防御性(默认关);真正主导的是验证节奏 + 只读判定(errors -82%)。