chore: 撤回 §8.11 delegate,只留验证过的批量工具(bump 0.58.31)

0.58.30 曾整体落地 delegate(隔离检索子循环),现 revert + force-push 抹除。
机制没错、对标 Claude Code subagent 也成立,但触发信号没坐实:自评回看
diag_search_args.py,motivating 案子 document_search 122 次呈"一批批不同材料
体系并行搜"形态,更像批量扇出而非结果驱动探索——若属实正解应与 mp_search 同为
批量工具 document_search_batch,delegate 是过度设计;叠加子循环 transcript 不落盘
(诊断驱动的功能反不可诊断)、20 轮上限对 122 次偏低、强制 flash 对难检索降质等
未验证坑。

重建前置收紧:先用 diag 确认某检索 task 的 query 是真探索(依赖前序结果、无法
一次列全)而非可枚举批量,是批量走批量工具、只有真探索才 delegate。批量工具
(0.58.28)验证过、保留。PROGRESS/DESIGN §8.11 记该教训免日后盲目重建。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-07-15 14:58:21 +08:00
parent d3bd40fad7
commit 7500b3b134
3 changed files with 4 additions and 1 deletions

View File

@ -321,6 +321,8 @@ scheduled_jobs(§8.5) channel_bindings(§8.7,判别列+JSONB)
**触发条件(无信号不实施)**:RepeatGuard + brief 纪律上线后,`scripts/diag_*.py` 数据仍显示检索型 task 是烧 token 大户 / 检索中间数据占上下文大头。数据收敛则本条永久搁置。 **触发条件(无信号不实施)**:RepeatGuard + brief 纪律上线后,`scripts/diag_*.py` 数据仍显示检索型 task 是烧 token 大户 / 检索中间数据占上下文大头。数据收敛则本条永久搁置。
**⚠️ 实现后撤回(0.58.30 落地 → 0.58.31 revert,记录教训)**:2026-07-15 曾完整实现(FilteredExecutor + 内存态子 Session + loop 拦截 + 降 flash),又整体撤回。撤回原因不是机制错(设计是对的、对标 Claude Code subagent 也成立),而是**触发信号没坐实**:自评时回看 `diag_search_args.py` 数据,motivating 案子 `document_search` 122 次呈"一批批不同材料体系并行搜"形态,**更像批量扇出而非结果驱动的探索**——若属实,它的正解和 mp_search 一样是**批量工具 `document_search_batch`**(便宜、可预测、可诊断),delegate 对它是过度设计。加上子循环 transcript 不落盘(诊断驱动的功能反而不可诊断)、20 轮上限对 122 次负载可能偏低、强制 flash 对难检索可能降质——一堆未验证的坑。**重建的前置条件收紧为**:先用 diag 确认某检索型 task 的 query 序列是**真探索**(query 依赖前序结果、无法一次性列全),而非可批量枚举;是批量就走批量工具,只有真探索才值得 delegate。**教训**:§5"无信号不实施"要落到"信号已被数据证伪 batchable 的可能性"这一步,不能凭"看起来像探索"就上 agentic 子循环——同 mp_search 的判断(批量扇出≠检索发散)。批量工具那条(0.58.28)验证过、保留。
**不选**: **不选**:
- 完整多 agent 编排:状态管理爆炸(§6),且 zcbot 无真实并行需求——用户没有"同时审 3 篇"诉求,职责隔离已由 skill 体系覆盖。 - 完整多 agent 编排:状态管理爆炸(§6),且 zcbot 无真实并行需求——用户没有"同时审 3 篇"诉求,职责隔离已由 skill 体系覆盖。
- 继续加码 skill 纪律/熔断规则:行为约束对抗不了架构性上下文污染,规则越堆越像 §7.8 的黑名单(fundamentally broken)。 - 继续加码 skill 纪律/熔断规则:行为约束对抗不了架构性上下文污染,规则越堆越像 §7.8 的黑名单(fundamentally broken)。

View File

@ -23,6 +23,7 @@
### 2026-07 ### 2026-07
- **07-15 / 0.58.31**:**撤回 §8.11 delegate(0.58.30 曾整体落地,revert + force-push 抹除)**。delegate(隔离检索子循环:FilteredExecutor + 内存态子 Session + loop 拦截 + 降 flash)机制本身没错、对标 Claude Code subagent 也成立,但**触发信号没坐实就上了**:自评时回看 `diag_search_args.py`,motivating 案子 `document_search` 122 次呈"一批批不同材料体系并行搜"形态,更像**批量扇出而非结果驱动探索**——若属实其正解与 mp_search 同为**批量工具 `document_search_batch`**(便宜/可预测/可诊断),delegate 是过度设计;叠加子循环 transcript 不落盘(诊断驱动的功能反不可诊断)、20 轮上限对 122 次负载偏低、强制 flash 对难检索可能降质等未验证坑。故整体撤回,只留验证过的批量工具(0.58.28)。**重建前置收紧**:先用 diag 确认某检索 task 的 query 是真探索(依赖前序结果、无法一次列全)而非可枚举批量,是批量走批量工具、只有真探索才 delegate(DESIGN §8.11 记该教训)。撤法:`git reset --hard` 到 0.58.29 + `--force-with-lease` 推,delegate commit 从历史抹除(远程 tip 确认无他人后续提交才 force);保留本条 PROGRESS 记录"试过并撤回"免日后盲目重建。
- **07-15 / 0.58.29**:**修对话正文文件锚点两处回归(含 `·` 的 pptx 丢 chip + 正文文件链接点击整页 404)**。① chip 丢失:`media.js` 的 `_TAIL_CLS` 把间隔号 `·`(U+00B7)当尾部排除字符,而它是文件名合法分隔符(`AI赋能陶瓷产业·…-图标增强版.pptx`)→ 在 `·` 处截断成目录不挂 chip。去掉 `·`(尾部标点另有 strip 兜底);node 验证 OLD→`[]`、NEW→两路径全出。② 链接 404:模型把相对路径写成 `[<rel>](<rel>)`,`renderMd` 出 `<a>`,但 `chat.js``#chat-stream` 点击委托无 `<a>` 拦截 → 原生跳转打到 API 不存在路由返 FastAPI 默认 `{"detail":"Not Found"}`。加拦截 `.msg .body a[href]`:外链开新标签,内部相对路径 `openFilePreview(rel)`(复用预览 modal,pptx 转 PDF),`#` 锚点走默认。纯前端修复,不碰对外契约。 - **07-15 / 0.58.29**:**修对话正文文件锚点两处回归(含 `·` 的 pptx 丢 chip + 正文文件链接点击整页 404)**。① chip 丢失:`media.js` 的 `_TAIL_CLS` 把间隔号 `·`(U+00B7)当尾部排除字符,而它是文件名合法分隔符(`AI赋能陶瓷产业·…-图标增强版.pptx`)→ 在 `·` 处截断成目录不挂 chip。去掉 `·`(尾部标点另有 strip 兜底);node 验证 OLD→`[]`、NEW→两路径全出。② 链接 404:模型把相对路径写成 `[<rel>](<rel>)`,`renderMd` 出 `<a>`,但 `chat.js``#chat-stream` 点击委托无 `<a>` 拦截 → 原生跳转打到 API 不存在路由返 FastAPI 默认 `{"detail":"Not Found"}`。加拦截 `.msg .body a[href]`:外链开新标签,内部相对路径 `openFilePreview(rel)`(复用预览 modal,pptx 转 PDF),`#` 锚点走默认。纯前端修复,不碰对外契约。
- **07-15 / 0.58.28**:**`mp_search_summary` 加批量入参 `formulas=[...]`(检索型烧 token 头号根因的定点解)**(诊断:`diag_tool_repeat.py` 全库扫,pymatgen task `fe2d8b73` 687 次 tool_call 里 `mp_search_summary`**562 次**、重复率 91%——逐化学式一 formula 一轮走 agent loop 建氧化物表,562 份中间 JSON 全流经主上下文且每轮重发)。根因不是"检索发散"而是**工具只收单 `formula` + host-side 持 MP key(§7.5 #7 禁在 run_python 里循环)→ 被迫一式一调**。**这类"已知清单批量扇出"的正解是工具批量化,不是 delegate 子循环**(delegate 只把 562 轮搬进子上下文、基础 token 一分不省;批量化直接把 562 次并成 1 次工具调用+全部中间数据落盘不进对话)。实现:`formulas: list[str]`(≤300/次,超则报错分批)触发 batch 分支,复用**单个 MPRester 会话**逐式查(`num_chunks=1` fair-use 护栏不变)、每式按 `energy_above_hull` 升序(稳定相优先)、**单式出错不连坐整批**(记 `{"formula","error"}` 继续);结果聚合写 `working_dir/materials/mp_search_batch_<hash8>.json`(内容寻址、同批幂等)、**只回紧凑 per-formula 摘要 + 路径**(N 个有结果/M 个空错 + 空错清单前 20),引导模型用 `read`/`run_python` 直读文件、勿逐条 dump。单查询路径(`formula`/`material_ids`/`elements`)**字节不变**保向后兼容;`working_dir` 设可选(裸构造 `MaterialsProjectSearchSummaryTool()` 不破,测试/smoke 无 working_dir 时降级内联返回)。`agent_builder` 注入 `working_dir_path`(同 `mp_get_structure`);pymatgen SKILL.md 加"多式用 `formulas` 批量"引导(WHY+WHAT,不写死步骤);`tests/test_secret_host_tools.py` +1(去重/落盘/稳定相排序/单式错误隔离/无 key 泄漏),原单查询测试补回 `chunk_size` 断言。additive 内部工具能力,不碰对外 API/DB 契约。**背景**:这是"检索型烧 token"三头(mp_search 562 批量扇出 / document_search 122 探索检索 / research code 试错抖动)里第一头的定点解;探索检索型留待 §8.11 delegate,代码试错归 RepeatGuard,不混为一谈。 - **07-15 / 0.58.28**:**`mp_search_summary` 加批量入参 `formulas=[...]`(检索型烧 token 头号根因的定点解)**(诊断:`diag_tool_repeat.py` 全库扫,pymatgen task `fe2d8b73` 687 次 tool_call 里 `mp_search_summary`**562 次**、重复率 91%——逐化学式一 formula 一轮走 agent loop 建氧化物表,562 份中间 JSON 全流经主上下文且每轮重发)。根因不是"检索发散"而是**工具只收单 `formula` + host-side 持 MP key(§7.5 #7 禁在 run_python 里循环)→ 被迫一式一调**。**这类"已知清单批量扇出"的正解是工具批量化,不是 delegate 子循环**(delegate 只把 562 轮搬进子上下文、基础 token 一分不省;批量化直接把 562 次并成 1 次工具调用+全部中间数据落盘不进对话)。实现:`formulas: list[str]`(≤300/次,超则报错分批)触发 batch 分支,复用**单个 MPRester 会话**逐式查(`num_chunks=1` fair-use 护栏不变)、每式按 `energy_above_hull` 升序(稳定相优先)、**单式出错不连坐整批**(记 `{"formula","error"}` 继续);结果聚合写 `working_dir/materials/mp_search_batch_<hash8>.json`(内容寻址、同批幂等)、**只回紧凑 per-formula 摘要 + 路径**(N 个有结果/M 个空错 + 空错清单前 20),引导模型用 `read`/`run_python` 直读文件、勿逐条 dump。单查询路径(`formula`/`material_ids`/`elements`)**字节不变**保向后兼容;`working_dir` 设可选(裸构造 `MaterialsProjectSearchSummaryTool()` 不破,测试/smoke 无 working_dir 时降级内联返回)。`agent_builder` 注入 `working_dir_path`(同 `mp_get_structure`);pymatgen SKILL.md 加"多式用 `formulas` 批量"引导(WHY+WHAT,不写死步骤);`tests/test_secret_host_tools.py` +1(去重/落盘/稳定相排序/单式错误隔离/无 key 泄漏),原单查询测试补回 `chunk_size` 断言。additive 内部工具能力,不碰对外 API/DB 契约。**背景**:这是"检索型烧 token"三头(mp_search 562 批量扇出 / document_search 122 探索检索 / research code 试错抖动)里第一头的定点解;探索检索型留待 §8.11 delegate,代码试错归 RepeatGuard,不混为一谈。
- **07-15 / 0.58.27**:**对话卡片「复制」按钮(仿 GPT/DeepSeek 悬停操作栏)**(用户提议:卡片上加复制等按钮)。`renderMessages` 给每条 user 卡、以及有正文的 assistant 卡末尾挂 `.msg-actions` 栏(纯 tool_calls 轮 / error 卡不挂),默认 `opacity:0` 悬停/`focus-within` 才现、触屏(`hover:none`)常显淡态。复制取的是**正文原文**:点击经 `#chat-stream` 既有 click 委托据卡片 `data-idx``state.loadedMessages``payload.content`(Markdown 源,**不从渲染后的 `.body` HTML 反推**),`navigator.clipboard.writeText` 主路径 + `execCommand("copy")` 降级,按钮短暂反馈「✓ 已复制/复制失败」后复位。直播卡不带此栏——流结束后 `loadMessages` 整屏重渲成持久卡自然带上,省一处直播态特判。**范围收敛的理由**:后端是纯追加式会话,无「重跑最后一轮 / 截断历史 / 编辑分叉」语义,故本期只做零后端耦合的复制;重新生成 / 编辑重发若无后端截断支持会变成「复读上一句 / 历史里又追加一条」的语义欺骗,留待后端补重跑/截断能力再单独立项。只改 `chat.js`(生成+委托+剪贴板)+ `dev.html`(CSS),对外无契约变化。 - **07-15 / 0.58.27**:**对话卡片「复制」按钮(仿 GPT/DeepSeek 悬停操作栏)**(用户提议:卡片上加复制等按钮)。`renderMessages` 给每条 user 卡、以及有正文的 assistant 卡末尾挂 `.msg-actions` 栏(纯 tool_calls 轮 / error 卡不挂),默认 `opacity:0` 悬停/`focus-within` 才现、触屏(`hover:none`)常显淡态。复制取的是**正文原文**:点击经 `#chat-stream` 既有 click 委托据卡片 `data-idx``state.loadedMessages``payload.content`(Markdown 源,**不从渲染后的 `.body` HTML 反推**),`navigator.clipboard.writeText` 主路径 + `execCommand("copy")` 降级,按钮短暂反馈「✓ 已复制/复制失败」后复位。直播卡不带此栏——流结束后 `loadMessages` 整屏重渲成持久卡自然带上,省一处直播态特判。**范围收敛的理由**:后端是纯追加式会话,无「重跑最后一轮 / 截断历史 / 编辑分叉」语义,故本期只做零后端耦合的复制;重新生成 / 编辑重发若无后端截断支持会变成「复读上一句 / 历史里又追加一条」的语义欺骗,留待后端补重跑/截断能力再单独立项。只改 `chat.js`(生成+委托+剪贴板)+ `dev.html`(CSS),对外无契约变化。

View File

@ -1,3 +1,3 @@
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。 # zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
# 改版本只动这一行。 # 改版本只动这一行。
__version__ = "0.58.29" __version__ = "0.58.31"