- df-ai 新增 ContextManager::push_system_anchor 统一出口:末条为悬空 ToolCallHead 时插其前,否则尾部追加(不位移前缀) - 5 处 system 尾部 push 全量收口(压缩成功/兜底提交、警示单点、主题标记、续轮 nudge),从源头杜绝后台压缩摘要/警示楔入工具三元组致上游 400 insufficient tool messages - 单测 push_system_anchor 两态锁定;cargo test -p df-ai --lib context 155 passed / cargo check -p devflow EXIT 0 - 看板归档:全量完成态条目与段落迁 docs/07-项目管理/todo归档/2026-10-10.md(零措辞改动机械搬运,未完成项110条零丢失/完成项37条全入归档/行数守恒)
48 KiB
todo 归档(2026-10-10)
本文件由 2026-10-10 归档拆批迁移:docs/todo.md 中「完成态」条目/段落(编号 [x]、勾选 [x]、标题带 ✅ 且段内零未完成项)。拆分判据=块完成态机械判定(零措辞改动,纯行搬运)。主板保留全部 [ ]/[~]/[→] 未完成项与设计/指针段。
✅ 2026-06-20 BUG-260620-05 F-260619-03 工程内路径误弹窗(reload_allowed_dirs 丢 workspace_root·b22e9ae 回归)
现象:AI Chat file_info 等文件工具访问工程内路径(如 docs/02-架构设计/单对话并行多轮-设计-2026-06-20.md)触发授权弹窗,用户称"本来就有访问权限,为什么还来申请"。
根因:state.rs:586-619 reload_allowed_dirs 合并 kv_dirs(KV allowed_dirs)+ project_dirs(projects.bind_directory) 为 all_dirs,仅当 all_dirs.is_empty() 时(:618)才插入 workspace_root。KV 配过 allowed_dirs 或有绑定项目 → all_dirs 非空 → workspace_root 不入 persistent → 工程内路径(在 workspace_root 下)is_authorized(:356 starts_with)失败 → check_path_authorization 返 NeedsAuthorization → 弹窗。
注释承诺失配::346-348 / :583 / :617 注释均称"KV 未配时保持 workspace_root 免授权(向后兼容)",但 :618 条件用 all_dirs(含 project_dirs),project_dirs 非空也丢 root。b22e9ae "reload 尊重用户 persistent" 引入的回归。
用户政策指令(2026-06-20):"默认直接访问,明确知道无权限才申请"。指向工程内(workspace_root 下)默认免授权,仅 workspace_root 外非白名单路径才弹窗。
修法(层1·1 行确定性 bug):state.rs:618 去掉 if all_dirs.is_empty() 条件包裹,无条件 set.insert(workspace_root_path())(工程内始终免授权,对齐用户政策 + 注释承诺)。不破坏现有能力:workspace_root 经 set/get_allowed_dirs(:664/680 filter root)本就不可见不可删,"用户删 root"语义未落地,保 root 无冲突。
层2 待决策(政策范围):用户"默认直接访问"是否要求更宽语义——workspace_root 外的非黑名单路径也默认放行(翻转 is_authorized 为黑名单制,实质去白名单)?涉 P0 去固定根决策方向,见待决策.md。dev 自用场景层1 即满足。
关联:F-260619-03(todo :528 b22e9ae 回归源)/ 待决策 workspace_root 分发适配(方案b 用户项目绑定)/ memory devflow-project-path-binding
状态:✅ 已实施(层1 无条件插入 workspace_root + 层2 白名单制 persistent/session/once + 黑名单兼底,对齐 2026-06-28 用户决策)
✅ 2026-10-09 复核销账:方案已演进为更优的动态推导(优于原「无条件插入 workspace_root」)——state.rs:579 注释实证「不再硬塞编译期 workspace_root(CARGO_MANIFEST_DIR)」,原因:编译机路径分发后失效反成脏白名单。工程根授权改由两途径:projects.bind_directory(绑项目自动授权)+ Settings.allowed_dirs(手动白名单),is_authorized 另有系统目录黑名单兜底(层2)。原 bug 根因(工程内路径因 all_dirs.is_empty() 条件丢 root 而误弹窗)已随该演进消除。销账。
✅ aichat API Key 401 排查(2026-06-16·非 bug 已销账)
用户报对话失败「调用失败: API Key 无效或无权限」+ 重设 key 无效。排查结论:代码链路全对(保存 keyring✓ / 读取 resolve_provider_secret✓ / 鉴权头 openai=Bearer·anthropic=x-api-key✓ / URL 智能拼接✓),401 来自服务端,非 devflow bug。根因四选一(key 无效 / provider_type 不匹配 / base_url 错 / model 名错)。详见 aichat-apikey-401排查-2026-06-15.md。
✅ 2026-10-09 销账:本条为排查结论登记(非代码缺陷)——已定性「非 devflow bug,401 来自服务端」。属环境/配置类问题,无代码修复动作。销账(降级非 🔴)。
✅ 架构坏味道全面扫描(2026-06-18·6路并行 Explore agent·57K行代码·报告类归档)
来源: God文件/长函数 + 循环依赖/耦合 + DRY违反 + 错误处理不一致 + 命名API/类型安全 + 测试覆盖/死代码。6 维度全覆盖。
✅ 2026-10-09 降级销账:本条为扫描报告登记(6 路 Explore agent 产出的改进清单),非缺陷条目。报告内 P1 项(SMELL-P1-6 / conditions 条件引擎)已各自独立销账(见下方 ✅ 标注),无遗留阻断项。降级非 🔴(报告类归档)。
🟡 P1 应该改进 (9项):
✅ SMELL-P1-6 — [P1🟢 已决·待推进] String 类型滥用替 newtype/enum —— execution_id/status/tool_type 等 5+ 处改强类型(b 路线:仅 Rust 内部 newtype)
🆕 sweep 派生登记(2026-06-18·workflow w2xkw4ybh data 抽出 + wo7d6zdqm 多维度 sweep):
- ✅ conditions 条件引擎 — ✅ 全部完成:引擎完备+feature flag 默认开+executor 集成+前端 UI(WorkflowDagDisplay.vue 可编辑)+i18n 补齐
✅ 2026-06-24 aichat 可靠性修复(消息重叠×5 + 授权弹窗卡死 + 工具执行心跳误报 · 诊断workflow→论证workflow)
- BUG-260624-02 残留 ✅ 已销账(2026-08-15):ToolCard pending 态倒计时落地(
_approvalTimers升级携带 startedAt/timeoutMs +getApprovalRemainingMs真值起点,expireSecs/expireLevel computed,≤60s.is-urgent红;不限时回退正计时;i18n expireIn zh/en)+ detached 窗口核验无缺口(AiDetached→AiChat 独立 startListener,ai-chat-event app 级广播,主窗口 detach 时 stopListener 不竞态,结论注释 useAiWindow:107-115)- F-09 根因:streaming/currentText 全局单例改 per-conv ✅ 2026-08-07 核验销账(per_conv HashMap + 前端 convStates Map enum 轨 + AiConvStateChanged 事件 per-conv 路由,根治多会话串扰)(根治多会话串扰,见 docs/待决策.md)
- CR-260622-01-P2-2 [P2低优·评估降级] — HTML/markdown/JSON 等非代码文件无 session 级缓存。2026-06-24 评估:已有
TOOL_RESULT_COMPRESS_ENABLED(mod.rs:98/1029-1078 view-only 摘要,>2KB tool_result 压缩,LLM 视图摘要非全文回灌 prompt)部分缓解;read_symbol 治代码文件(主场景,降 24.4x)。非代码文件完整 session 缓存(path→hash+content+patch失效)设计复杂 + LLM patch 后重读确认行为不确定(缓存命中提示可能不够 LLM 仍重读),归 B 路线 prompt 策略(约束 patch 后不重读)更合适,工具侧完整缓存低优暂缓。
✅ 2026-08-09 AI 自审/工作流推进链路缺陷(✅ P0×3 已修,2026-10-05 核验销账)
用户「检查 AI self-review 遇到的问题」触发对工作流推进链路的深度审查。原结论「三条推进链全部不可用」已过时——P0×3 全部已修(task_id 注入 workflow.rs:340 + AiNode 自审落库含 agent 模式 + TaskDetail 审批 UI 随
2eea011审批重设计批落地),核验详录迁 07-项目管理/todo归档/2026-10-05.md。以下原始诊断保留作档案,修复状态见归档勘误。
涉及文件:
src-tauri/src/commands/workflow.rs(run_workflow_inner 核心)crates/df-nodes/src/task_workflow_templates.rs(三模板)crates/df-nodes/src/ai_node.rs/ai_self_review_node.rs/ai_node_helpers.rs/human_node.rscrates/df-workflow/src/executor.rs/dag.rs/registry.rs/dag_def.rssrc/views/TaskDetail.vue/src/stores/project/workflow.ts/src/views/ProjectDetail.vue
P0 run_agentic_loop 包 catch_unwind ✅已修(2026-10-05 核验:loop 主体 unwind_to_result 包裹,panic 转 teardown_round 补终态,5 单测锁定 mod.rs:3135-3165)
-
位置:
agentic/mod.rsrun_agentic_loop 主体(无 catch_unwind) -
现状:任一轮 prepare/stream/finalize/tools 段 panic → task 死亡 → GeneratingGuard::drop 只迁 Idle+emit AiConvStateChanged,不 emit AiError/AiCompleted,heartbeat 随作用域死亡——「工具完成后流断+无终止事件」的精确根因形状(前端探测式续跑已兜住后果,此为后端根治)。
-
修复:整体包
std::panic::catch_unwind(AssertUnwindSafe(...)),unwind 时 emit AiError{error_type:Internal} 再收敛;guard Drop 兜底保留。核心 loop 改动,需谨慎设计+场景回放测试。 -
P1[需拍板→已实施] 熔断无收尾轮 ✅ 2026-10-06:max_rounds 打满不再直接截断,补一次无工具(tools=None)收尾 LLM 调用——system 指令「输出最终任务总结报告」,成功则 push 报告+落库后走原收尾;失败(全候选耗尽/MidStream)静默落回原截断路径(报告是增益非闸门,零新增停靠)。预算:仅 1 轮 max_retries=0,无放大(agentic/mod.rs 达上限分支)
-
P1[需拍板→已实施] 报告被视图压缩吞掉 ✅ 2026-10-06:summarize_tool_results 加新近度豁免(RECENCY_EXEMPT_TOOL_RESULTS=2)——末尾 2 条 tool_result 恒不压缩(豁免在冻结决策之前,不进决策表),委托报告/末轮工具结果全文可见;单测 summarize_recency_exempt_keeps_last_two_tool_results 锁定行为(stall_detector.rs)
-
P2 namespace 10MB 全局 LRU 淘汰:报告蒸发为「重新调用」死路+多代理共池互踩 ✅设计完成(2026-10-04 设计文档):pin 机制+EvictionLog 富提示(替代裸 EVICTED_PLACEHOLDER)+owner 软隔离三招,零 schema 变更;2 拍板点(pin 上限保护/报告外默认 pin 范围),约 0.5-1 天 ✅ 2026-10-06 实施完成 e0b29b4(pin+EvictionLog+owner 软隔离三招全落地,子代理报告出口 pin 收编;验收 cargo check 零 error)
新缺陷(2026-10-05 22:2x 用户截图实证,与 N/D 清单同级)
- 工具输出 ANSI 转义裸露(乱码):run_command 类工具输出含 ANSI 码(\x1b[7m 等)原样透传前端显示为 ␛[7m。修:执行器统一 strip_ansi(或注入 TERM=dumb/--color=never)+前端渲染层兜底过滤;验收:cargo test 输出在面板无 ␛ 残留。 ✅ 2026-10-06 补销: 已随
70d6e98修复(ANSI 源头抑制+strip 兜底), 当时漏销 - 会话标题 content 泄漏:会话标题显示原始正文片段(如
<details> <summa…,84cb104c 会话同症)——标题生成输入未清洗或兜底直接取 content 头部。修:title 生成失败/超时兜底改为清洗后的首行摘要,含 HTML/Markdown 标签时剥离;验收:长会话标题无标签裸露。 ✅ 2026-10-06 补销: 已随70d6e98修复(标题剥标签 sanitize(title.rs)), 当时漏销
附:截图实证单会话 206 轮/1500 万 tokens——C 批次(上下文管理)紧迫性最强活证,随 C-r0 优先消化。
✅ 提交后跟进(2026-10-05 23:0x 走查发现,cb260ab 已入库但未修·10/11/12 已修销账)
- loop_state 对新会话/编排会话静默失效(高) ✅修复(2026-10-06,提交「修复: loop_state 懒创建继承与入口早退清理」):懒创建继承 running(conversation.rs)+入口早退清残留(agentic/mod.rs)+list_parked 消费方=TopBar「可恢复」分区(V49 读侧)。验收:cargo check EXIT 0+vue-tsc EXIT 0。
- 【中】conversation_repo.rs:817 注释矛盾 ✅修复(2026-10-06 同批):update_full 剥离 loop_state 列,封 lost-update 窗口,注释与实现一致。
- 【中】前端 i18n 双侧同缺 aiChat.reattachToMain 键 ✅修复(2026-10-06 同批):zh/en 补键。
以上为 72 文件走查结论(报告要点 23:0x 已交群),提交规范 18 笔全合规,质量项按本清单跟进。
- ①过程流式 ✅ 2026-10-06 实施:run_stream_refresher 消费面扩容(AiTextDelta + AiAgentRound + AiToolCallStarted/Completed 四事件,conv 路由过滤共用)——过程流不刷屏:卡片改「头部一行摘要 + 正文增量」结构,头行=轮次 + ⚙当前工具执行中/已完成 N 步(历史步骤折叠为计数,决策价值过滤);过程事件标脏强制重刷(纯工具轮无文本也有"活着"信号,治 206 轮长任务卡片静止猜卡死);签名去重防同 tick 事件风暴空刷;超限保尾截断口径不变。4 单测锁格式契约(首轮无头行/工具执行中/轮间空档/截断)。验收:cargo check EXIT 0 + feishu 7 passed。参照 u-claw 进度卡治理;桌面过程视图同步对齐见「桌面端能力同步清单」。
- 纠偏注入通道(用户 2026-10-05 深夜点名,飞书对话补充消息目前只能排队不能注入运行中任务)✅ 2026-10-06 实施:引擎层
inject_runtime_message(chat.rs,活跃守卫 conv_states.is_active → 短锁 push per_conv.messages → save_conversation 增量落库,loop 下轮 build_for_request 自然带上,u-claw 补拉同构);飞书侧 handle_message 白名单后加注入旁路(chat_map 命中且 conv 活跃 → 注入 + 卡片确认「下一轮生效」,非活跃 Err 落回常规 spawn 路径零行为变更)。不改锁语义/不打断 loop;桌面任务卡补充入口待 14 异步委托批配。验收:cargo check EXIT 0 + chat 17 passed + feishu 3 passed(含注入前缀格式契约单测)。
14 升级(用户拍板 2026-10-06 凌晨):桌面也要异步能力,不做双端分叉——异步委托是引擎层能力,桌面与飞书都是它的前端视图。实现要点:①引擎层 spawn 即受理返回,完成走通知桥广播(oneshot 改事件+等待者订阅) ②桌面任务卡 UI:受理/进行中 N 轮/完成+系统通知,发消息后可切会话/最小化 ③飞书为同一语义投影(受理卡/完成原地更新) ④锁语义保守起步=单会话单在途+排队,多并发看用量再说 ⑤yml 开关灰度。依赖链:16 纠偏通道(受理后补充入口)→13 过程流式(进行中视图)→本项。验收:桌面发任务→切走→完成收系统通知;飞书同构;双端行为一致。
设计约束(用户拍板 2026-10-06 凌晨):任务会话高度复杂,代码设计一定要优雅——①状态机显式化:受理/运行/暂停/完成/失败用枚举统一,禁散落 bool 拼凑 ②单一事实源:任务状态只在引擎层,桌面/飞书 UI 都是投影(订阅不轮询) ③事件驱动贯通:13/14/16 共用同一事件总线,不做渠道私有旁路 ④优雅优先于速度:宁可工期换结构,不做特判堆补丁(优雅架构铁律)。
桌面端能力同步清单(与渠道对齐,2026-10-06):16 纠偏注入做在 AiSession 会话层桌面天然受益;13 过程流式桌面过程视图同步对齐;14 任务卡+系统通知已在升级注记;另两件桌面专属:①V49 可恢复入口——走查实锤 list_parked 读侧零消费,桌面侧栏补「可恢复」列表消费它(断点续跑闭环最后一块)✅已做 e0b29b4(分组展示+点击恢复) ②缺陷9 会话标题泄漏桌面同症随批修。
- 渠道错误话术吞因(09:51 实证)✅ 2026-10-06 修复:①spawn Err 分类话术——并发护栏拒绝(「正在生成」)→「⏳ 该会话已有任务进行中,本条将在任务完成后处理;可稍后重发,或先 /status 查看进度」;其余失败→附截断原始原因(不吞因)。②探活告警口径修正——inflight 计数点从 spawn 前提前到 handle_message 白名单通过处(RAII 覆盖占位卡 HTTP+per-chat 锁排队窗口,原该窗口任务在跑却报「无在途会话」);旧计数点删除防双重计数。验收:cargo check EXIT 0 + feishu 7 passed。
附:09:48 桌面纠偏「不是 haogame 是 redtimer」被运行中 loop 下一轮直接接住——16 纠偏注入的桌面形态天然存在,飞书侧对齐即可。
- G5 V49「可恢复」入口(桌面侧栏消费 list_parked,断点续跑闭环最后一块)✅ e0b29b4 可恢复分组+点击恢复已落地
⚠️ 退回重处理(2026-10-06 用户令,G2/G3 治理标准首次执行)
- 三笔提交(cec4d11 委托引擎/84df9b5 租约/622507c UI)已 reset --mixed 退回(内容全在工作区,零丢失,未推远端无需处理远端)
- 重做要求:①先修 🔴10 loop_state 失效(G2 门禁:🔴不清零不得提交新功能)②描述按 G3 如实:实际干了 14+16+事件广播三件须逐件列全 ③i18n reattachToMain 键随批补上 ④修完按主题重新分组提交,销账 [x] 附验收输出(G4)
- 飞书 outbound 统一出口(11:23 实证)✅ 2026-10-06 收口:勘察确认对话/受理/完成/注入回执已统一走 deliver_result(降级/裁剪/卡片链内聚);病灶「挂机进度汇总独立发送路径」在当前 main 不存在(属退回的挂机实验代码)。本批防复发收口:①新增 push_to_chat pub(crate) 正典出口(主动推送形态——挂机进度汇总/巡检通知将来落地时禁再开独立路径,强制走降级/裁剪/卡片链) ②ACTIVE_CLIENT OnceLock 全局句柄(渠道启动就绪,推送复用长连接 client 不临时建连,未启动静默跳过)。验收:cargo check EXIT 0 + feishu 7 passed。
附:挂机汇报自报 🔴10 已修验证通过+43 文件产出——挂机模式推进有效,路径修复别误伤它。
- 委托制伪受理断层(13:38 实证):受理卡在引擎确认可启动之前发出——12:57 任务停滞 Generating 时,「进度」spawn 被引擎拒但受理卡已发,之后零通知零进度(比 09:51 立即报错更隐蔽)。修:受理前过 can_accept_request,不可启动→直接回「前任务在跑,已排队/稍后」;可启动→才发受理卡+watcher 接力。附带:委托制下 inflight 生命周期改跟任务走(handle_message 提前返回致 18 修正再次失效,13:18 误报复现)。验收:同场景复测,占用期发消息得到明确排队提示而非静默受理。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
符号语义规范(2026-10-06 用户反馈:受理卡「✅ 已受理」歧义,随 19 统一出口一并落地):
- 🚀 受理/开工(任务开始才用,禁 ✅)|⏳ 进行中/排队/等待|✅ 仅限完成且成功|❌ 失败(必须附原因)|⚠️ 警告/需注意(附数据)|📎 附录/附加信息
- 原则:符号=状态的一眼判据,同一符号跨场景语义必须一致;受理卡改为「🚀 已受理,后台执行中」;完成推送才允许 ✅ 开头。
飞书交互面全量盘查(2026-10-06,11 条缺陷按恼人度降序,修复前话术避免引用 /status)
- 🔴 过程推送散乱刷屏(14:06 用户截图反馈「信息太散乱爆炸了」):push_to_chat(:797)每调用必新开独立卡片,通道无聚合语义——昨日调试把链路测试/修复上线/加固明细等 L3 过程逐条直推 4+ 条进群,与 U3 分级相悖。修双层:①机制=push_to_chat 增滚动汇总卡——同 chat 维护在途事务卡 message_id(内存即可,重启另起),进度用已有 update_card(:730)原地追加;首推需 send_markdown_card 返回新卡 id(现 :683 is_ok() 丢弃,比照 reply_markdown_card);文本以 ✅/❌ 开头=终态,更新后清句柄下条另起新卡;更新失败回退新发并重绑(比照 deliver_result 兜底)。②纪律=L3 过程默认不推群,落日志+进度文件;push 收敛「需决策/完成✅」两时机,调试确需的验证推也进汇总卡不新开。验收:同事务多步进度群时间线只占 1 张卡,过程类推送零直达。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 🔴 /status 被话术推荐但不存在(chat.rs:387/:486 两处):用户发了被当任务烧一轮 LLM。修:实现 /status(读 conv 状态返回进度摘要,配合委托制价值高)或先改话术删除引用。验收:发 /status 得进度卡而非 spawn。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 🔴 35min 兜底回查会投出上一任务旧回答冒充本次结果(feishu_channel.rs:483/:939):回查整 conv 最后 assistant 文本无任务边界。修:回查限定受理时间戳之后的 assistant,无则给真实状态话术。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 🔴 watcher 首超时后永不弃守(:486 continue 与注释"二次超时弃守"相反)+错误路径只发 AiError 无 AiAgentFinished→每 35min 重刷过期文案+任务泄漏。修:二次超时真弃守+AiError 也广播 Finished(status=error)。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 无取消/审批通路:跑偏无法叫停(飞书零 stop 通道);审批挂起对飞书用户不可见(流式卡冻结无解释)。修:/cancel 对接 ai_stop_loop;审批事件上卡片(「需审批:xxx,回复 批准/拒绝」)。 /cancel 停止通路+watcher 收口+审批推送与批准/拒绝决议(路径类授权留原语差异), ✅ 2026-10-07 细项批(待提交)
- 非文本消息静默丢(:243):发图/文件零反馈。修:回「暂仅支持文本,媒体能力规划中」(D7 前的兜底)。 非文本兜底已存在于基线(:255 回「暂仅支持文本」), ✅ 2026-10-07 核验补销
- ⏳话术承诺排队实际不入队——话术与行为不符。修:改话术为实况(「可稍后重发」)或实现真排队(与 20 受理断层同修)。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 快任务兜底死分支(:449 elapsed>=3s 入场即查恒假,「秒级任务直投终版」不可达)。修:受理卡发送后计时或事件驱动判定。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0)
- 注入末轮竞态:loop 已在末轮则补充指令无人消费静默丢失。修:注入后检查 loop 剩余轮次,末轮则自动续一轮。 注入末轮顺延轮次预算(共享余量+轮顶动态判定+封顶 8), 5 单测锁定, ✅ 2026-10-07 细项批(待提交)
- push_to_chat 取 KV map 首条(:792):多 chat 绑定可能发错会话。修:按 conv 反查 chat。 push_to_chat 按 conv 反查+多绑定取最近活跃(签名加 conv_hint 零涟漪), ✅ 2026-10-07 细项批(待提交)
- 细节批::389 反引号不闭合;/new 大小写与附言容错;/new 时旧任务在跑无提示;标点半全角混排。 反引号闭合//new 容错与旧任务提示/半全角归一(parse_command 3 单测), ✅ 2026-10-07 细项批(待提交)
- 13a-1 刷新可观测:refresher 的 update_card 失败从"静默跳过"改为 feishu_log 记录+连续失败计数(≥3 连败告警)——当前刷了还是没刷、刷败全不可知,排查无从下手。 ✅ 2026-10-07 实施(feishu_channel.rs 单文件):刷失败 feishu_log 落盘(连败次数/chat/msg/chars)+连败 ≥3 告警一次(REFRESH_FAIL_ALERT_THRESHOLD=3,== 阈值触发后继续累计不重复)+刷新恢复记「此前连败 N 次」+成功归零。验收:cargo check -p devflow EXIT 0 + cargo test --lib feishu 16 passed 0 failed。
-
(自动续作) AI-Ops→devflow 派工通道(多 bot 编排正统通道,2026-10-06 缺口实证):AI-Ops 无法直接触发 devflow 开工(飞书 bot 消息不互触发/WebChat 无/remote_bridge 走 tunnel 不外用)。方案二选一:①u-claw 侧新增 ask_devflow(与既有 ask_uclaw 对等,经 remote_bridge 协议下发启动指令) ②devflow 侧看板轮询引擎(定时扫 todo.md 新🔴/高优条目自动开工,CLAUDE.md 领单纪律的运行时化=B5b 同源)。建议 ② 与 B5b 合并实现(同一套自动续作引擎)。验收:AI-Ops 写看板后 15min 内 devflow 自主开工,零人工中转。 ✅ 2026-10-07 方案②实施并与 B5b 合并落地(unattended.rs 636 行,B5b+31 同一引擎):看板解析器(编号条目四态+🔴 判据=标记后首字符防误判)/G2 门禁领单选择器(🔴 未清零只领红 fail-closed)/轮询调度器(tokio 常驻,KV 热读配置 df-unattended-{enabled,poll-secs,claim-scope,todo-path},默认关+300s)/收敛回读钩子 notify_batch_done 接 agentic emit_ai_completed_once 单点/parked 自动恢复优先/连续 3 次 spawn 失败熔断/领单原子写+spawn 失败回滚/引擎独立后台会话 pin_active=false。验收证据:①接线 rg 实测 lib.rs:77 unattended::start + agentic/mod.rs 收敛钩子调用 ②
cargo test --lib unattended= 9 passed 0 failed(本轮实测修正 parse_statuses_and_red_marker 断言:🔴 判据仅认标记后首字符,正文提及不误判,与实现注释语义对齐) ③活证=本条目自身即引擎产出:AI-Ops 写板 → 引擎改写31. [→](自动续作)→ 派发本会话执行,零人工中转,15min 上限实测远低于下限。 -
换装脚本失败:杀进程后 3s 即安装,Windows 文件锁延迟释放致 NSIS 静默伪成功(17:48 实证 FAIL: exe not updated,installer exit=0)。✅ 2026-10-06 晚全链闭环:脚本加固(swap-install.ps1 v3,语法 0 错实测):①句柄释放探测(独占打开循环,30s) ②校验升级为构建产物 SHA256 强基准(mtime 判据作废,NSIS 保留源文件 mtime 必误报) ③校验失败自动重试一次 ④SYSTEM 触发时转投用户会话重入,四级 fallback,最坏落 swap-need-start.flag。上线验证过(18:44 版手动换装成功):运行 exe SHA256=构建产物=0C45683B,进程 12764 运行中,H1 行为实测通过(19:13 DevFlow 回复带「📎 git 实测」段)。
-
飞书出站 md 语法裸露净化+交互样式对齐 u-claw(AI-Ops 2026-10-06 晚实证落板):任务报告
##/**等 md 标记在飞书裸露(20:53 分析报告截图实锤)。根因:飞书 lark_md 不支持标题/表格等全谱语法,LLM 产出未经出站转换;主链 send_markdown_card(feishu_channel.rs:716,注释自认「text 类型会符号裸露」)只保粗体/链接,im-gateway StreamText 链纯文本直出。修:①出站净化层——md 转飞书友好格式(标题行转粗体/表格转列表/代码块适配),双层防线=出站兜底转换+agent 产出 prompt 约束,移植 u-claw 投递链降级/裁剪经验(u-claw 仓为范本) ②首回受理卡样式对齐 u-claw 任务状态卡(计数 N/M+逐条状态符+当前动作一行,10-02 用户拍板「效果不错」);受理卡符号 🚀 已由 AI-Ops 修(449 行)。验收:同类分析报告在飞书零 md 裸露标记,受理卡样式与 u-claw 一致。 ✅ 2026-10-06 c91b993(交互批八项合提,验收: cargo check 零 error+feishu 13/df-im-gateway 19/chat 17 passed+vue-tsc 0) -
🔴 提交冻结令被无人值守链路击穿(10-07 用户查问「最近提交不符合要求」实证):看板顶部 🔒 冻结令(10-06 深夜用户令,期间只改不提)生效后,挂机链路 01:56-57 仍连提 4 笔(c5ba755 续作引擎 811 行/d0281cb 飞书取消审批 345 行/7ab25e5 换装判据/73fa7c2 看板销账),且 73fa7c2 看板内容自书「细项批(待提交)」与提交事实自相矛盾——冻结仅是文本纪律,引擎与挂机会话的提交步无机械闸。修:①引擎自动提交路径与挂机会话提交步在 commit 前必查冻结标志(看板顶部 🔒 行视为生效,KV 标志更佳),在场即拒绝提交、改动留工作区;禁用全局 pre-commit 拦截(误伤用户本人提交) ②引擎派发的会话启动 prompt 注入「冻结期禁 commit」硬约束 ③解冻=用户「攒批提交通知」后由会话摘除 🔒 行再提。验收:冻结令在场时引擎/挂机会话 commit 步零执行(实测),摘令后恢复;随 31 引擎同测。 ✅ 2026-10-07 实施(commit_freeze 三层闸,零提交全在工作区):①机械闸=crates/df-execute/src/commit_freeze.rs 新模块——静态冻结位 set_frozen(引擎 unattended::run_tick 每轮按看板 🔒 行+KV df-commit-frozen 覆盖同步)+execute/execute_streaming 入口 check(),git commit 变体(git -C/复合命令 ;&&|/引号包裹/多空格)spawn 前拒绝,改动留工作区;未挂全局 pre-commit,用户本人终端零影响。②任务书注入:claim_and_spawn 冻结在场时追加「提交冻结令硬约束」段(禁 git commit/push,执行层闸兜底)。③解冻=用户摘 🔒 行或 KV df-commit-frozen=false,下一轮轮询(≤300s)自动同步放行。验收实测:cargo test -p df-execute 26 passed 0 failed(18 lib 含 6 冻结闸新用例:commit 变体识别/只读命令放行/冻结拦截/解冻恢复/静态位切换;8 shell 集成)+ cargo test -p devflow --lib unattended 10 passed 0 failed(含冻结判据新用例:🔒 行/blockquote
> 🔒形态/KV 双向覆盖/默认不冻结)+ cargo check -p devflow --lib EXIT 0。冻结在场实测=单测断言 check() 对git commit返回 Err 且git diff放行,摘令后恢复=static_flag_toggle 用例复位断言;真实看板形态(> 🔒引用行)经 commit_freeze_board_and_kv_judge 实测命中。 -
(自动续作) 🔴 测试条目
-
(自动续作) 🔴 提交工作区改动(转交实战,2026-10-07):将当前工作区改动按主题分组提交并推送 origin main。(21:4x AI-Ops 重置回队:前两轮引擎会话被 20:38-21:02 u-switch 故障窗口「网络中断不完整」腰斩,重入预算耗尽停 [→],网络已恢复)要求:①提交前 G4 前置走查(风格/明显缺陷/调试残留/注释规范,发现问题先处理再提交) ②分组建议:挂机模式 P1 总装一笔(UnattendedPanel/Settings/TopBar/TaskBoundaryCard/i18n/unattended 两 IPC/lib.rs/feishu_notify)+看板销账一笔(todo.md) ③swap-install.ps1 若有改动先审 diff 再定去留;删除 scripts/check_plaintext_key.py(一次性诊断脚本已完成使命) ④提交信息中文类型开头逐件列全,commit-msg hook 会拦截违规 ⑤完成后本条改 [x] 并附 git log --oneline -3 输出。验收(10-08 AI-Ops 补录,引擎 22:06 完成):git log --oneline -3 →
0aac14e文档: 看板销账: 挂机模式 P1 总装与换装校验修复入库,901 销账 /6bfcf01修复: 换装校验同版本重装误判不通过 /2441101新增: 挂机模式 P1 总装: 设置面板+顶栏徽章+边界卡精简+监控告警推送;main=origin/main 已推,工作区清零。 -
(自动续作) 🔴(10-08 AI-Ops 定位) 停靠(parked)状态写侧缺失,停靠卡「继续」必报「AI 未在暂停态」:根因=全仓无任何业务路径写 loop_state=parked,
"parked"仅 3 处读取判定(unattended.rs:604/conversation.rs:341/chat.rs:2712),唯一写入源为应用重启时 V49 残留扫描(running→parked)。实证=G2 探索熔断(agentic/mod.rs:2288)与同类失败熔断(2265)均只调 emit_task_parked 发事件(前端渲染停靠卡+继续按钮)、漏写 DB,会话 6a5a3e04 实测 loop_state=running;点「继续」→ chat.rs:2703 查 parked 不匹配→报错。副作用=残留 running 使侧栏/引擎误判会话仍在跑。修法(推荐根源解)=停靠状态写入收敛进统一出口:emit_task_parked 升级为「写 parked + 发事件 + 通知」三件套(或新建 park_task),五路停靠调用点(熔断两路/审批超时/挂起取消/流致命)全部对齐;契约注释同步改写。附:UI 观感=熔断同轮双卡叠加(求助卡 AiHelpRequired + 停靠卡 AiTaskParked)语义打架且文案冗长,建议熔断只发停靠一张卡。
✅ 2026-10-09 实施完成(根源解 + 附项一并落地):
- ① 写侧收敛进统一出口:
emit_task_parked(src-tauri/src/commands/ai/mod.rs:1435) 升级为「写 parked + 发事件 + 通知」三件套——新增 ① 步经app.state::<AppState>().ai_conversations.set_loop_state(conv_id, Some("parked"))(fire-and-forget spawn,失败仅 warn 不阻断事件/通知);②③ 步(AiTaskParked 事件 + NeedAction 通知)保留原位。8 个业务调用点(H2 三闸/熔断两路/挂起取消/max_rounds/midstream/fatal + 审批超时)全部经此单点,零遗漏(grep 实证 9 处调用全指向统一出口)。 - ② 契约注释改写:函数 doc 由「单一只读语义」改为「三件套」;调用方职责(保存现场 + conv_state 复位)边界不变。
- ③ df-storage 支撑:
impl_repo!宏生成的 Repo 结构体加#[derive(Clone)](Arc<Mutex<Connection>>天然可克隆),使emit_task_parked能克隆 Repo 句柄进 spawn。 - ④ 附项(熔断只发停靠一张卡):新增开关
CIRCUIT_BREAKER_PARK_ONLY=true(agentic/mod.rs:343);L1 同类失败熔断 / G2 探索熔断 / 破坏性回环熔断三处AiHelpRequired求助卡 emit 均包在if !CIRCUIT_BREAKER_PARK_ONLY内,求助卡关键信息(失败样本/路径)内联进 AiTaskParked 的 reason;开关置 false 即回退旧双卡行为。前端零改动(TaskParkedCard 词表已含 circuit_breaker/stall_breaker)。 - ⑤ 回归测试:新增
set_loop_state_parked_roundtrip(crates/df-storage/src/crud/conversation_repo.rs)锁死「写 parked → get_by_id 读回 parked / 清态读回 None」契约。 - 与 V49 残留扫描无冲突:
mark_running_as_parked的 SQL 为WHERE loop_state='running',不会覆盖已写 parked 的行(state.rs:459 启动扫描语义不变)。 - 验收:
cargo check -p df-storageEXIT 0;cargo check -p devflowEXIT 0(10 warning 全为无关模块既有 dead_code);cargo test -p df-storage200 passed + 12 passed, 0 failed;cargo test -p devflow --lib748 passed, 0 failed, 8 ignored;bunx vue-tsc --noEmitEXIT 0。
-
(自动续作) 🔴 「@」文案 HTML 实体未解码(10-09 用户实测截图): 输入框 placeholder 与提及提示字面显示
@而非@。位置共 8 处——src/i18n/zh-CN/aiChat.ts与src/i18n/en/aiChat.ts各 4 处(placeholderDefault / mentionHint / searchFilesBlocked / projectLabel)。根因:文案写了 HTML 实体,前端文本插值({{ }})不做 HTML 解码故字面显示。修:8 处@→ 直接写@(纯文本字面量,无需转义)。 ✅ 2026-10-09 修复完成。改动:zh-CN/aiChat.ts L139/144/236/330 + en/aiChat.ts L139/144/235/329 共 8 处@→@。 验收证据:①findstr /s /c:"@" *.ts *.vue *.tsx *.js(src 目录) → 无匹配(exit 1),全仓零残留;② 回读 8 行确认字面@(zh: "输入消息...(/ 触发技能,@ 引用实体)" / "@ 引用项目/任务" / "...请用 @[项目] 引用..." / "@项目";en 对应 4 处);③bunx vue-tsc --noEmit→ EXIT=0。 -
(自动续作) 🔴 停靠卡「总是弹出」频次治理(响应流中断路径,10-09 用户反馈): 流中途断(agentic/mod.rs:1345
RoundOutcome::MidStreamSaved)直接emit_task_parked停靠,无 Fatal 家族的ROUND_REENTRY_MAX重入预算——网络抖动一次即弹「响应流中断/任务已停靠」卡并进行中任务终止(10-09 u-switch 抖动期用户实测频繁弹)。修建议:①midstream 先加短重试/续传预算(对齐 Fatal 重入语义,耗尽才停靠)②前端同会话短时内停靠卡节流(避免重发-中断-再弹循环观感)。注:本条是打扰治理,与 904 写侧修复正交(904 让对方能点「继续」,本条降低「被迫点继续」频次)。
【✅ 2026-10-09 实施完成 — 双管齐下:后端续传预算 + 前端停靠节流】
【① 后端 MidStream 短重试/续传预算(stream_relay.rs)】新增 `MIDSTREAM_REENTRY_MAX=2` + `MIDSTREAM_REENTRY_BACKOFF_SECS=[5,15]` + `MIDSTREAM_CONTINUE_PROMPT`,对齐 Fatal 家族重入语义但采用**续传**而非重发(整轮重发会与前端已渲染 partial 重复):
- 原 candidate 循环包裹进 `'midstream: loop`:流中途断(`incomplete=true`)且用户未点停时,若预算未耗尽 → ①已接收 partial 落库为 assistant 消息 ②emit `AiAgentRound{round:0}` 触发前端 flush(partial 落独立气泡,续传渲染到新气泡,无重复) ③续传请求 = 原请求 + partial(assistant)+ 续传提示(user),模型从断点继续 ④退避 5s/15s 后重入 candidate 循环(全新 30s 流前预算)。
- 续传成功 → 本轮转 `Continue`(走正常收尾,**不弹停靠卡**);预算耗尽 → 落回原保文+`emit_task_parked` 路径(系统提示文案区分「已自动续传重试仍未恢复」)。
- 收尾保文修正:续传路径已落中间各段,终局只补「最后一段」(break 前未 push),无重叠不重复。
【② 前端同会话停靠卡节流(useAiLifecycleEvents.ts)】`recordTaskParked` 增 `PARKED_REPARK_THROTTLE_MS=20000` 节流:同 conv 距上次停靠 <20s 且**卡仍在(未被用户处置)** → 保留原卡不刷新(压抖动期重复弹/重渲染);卡已被用户「继续/停止」摘除 → 仍放行新卡(不吞用户需决策的真实新终局)。安全边界:仅压「未处置的重复弹」,不吞「已处置后的真实新停靠」。
【验收输出】
- `cargo check -p devflow` → Finished dev profile(0 error,10 warning 全为无关模块既有 dead_code)
- `cargo test -p devflow` → **750 passed; 0 failed; 8 ignored**(含新增 `midstream_reentry_tests` 2 项:退避表长覆盖上限+单调递增+首退避<Fatal 首退避、续传提示非空)
- `bunx vue-tsc --noEmit` → EXIT 0(前端类型全绿)
- 与 904 正交:904 修写侧(loop_state=parked 落库,让「继续」可用),本条降「被迫点继续」频次,二者不冲突。
- (AI-Ops 接手实施 10-09 深夜) 🔴(10-09 用户实测) deepseek(OpenAI 兼容)流式 400: assistant tool_calls 未跟足对应 tool 消息 → 整轮中断。现象=报错原文「An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. (insufficient tool messages following tool_calls message)」(deepseek-flash, HTTP 400, request_id d2c6e33a)。已查防线(均在场且非新引入)=①sanitize.rs 双向 orphan:正向 step1-3(未闭合 id 整头丢弃/部分闭合头重写只留 resolved)+ 反向 step3.5(drop_reverse_orphans 实为补占位头自愈 orphan result)②build_eviction_units 按 ToolCallHead+ToolResultTail 三元组打包③build_for_request 三出口全过 sanitize + assert_placeholder_pairing 出口断言④openai_compat 本次改动仅 temperature(无关)。待查缺口方向=①协议差异:防线的补/丢语义按内部模型设计,OpenAI 侧要求「每个 tool_call_id 必须有 role=tool 响应且须跟随」——partial head 重写后、或补占位头后的序列在 OpenAI 转换层是否仍合法(重点看 openai_compat 的 tool_calls/tool 消息映射)②有无绕过 build_for_request 直送 provider 的路径③抓触发会话发送视图实证(devflow.db 该会话 messages 的 tool_calls/tool 配对)。缓解=新开会话或重发可绕(历史中毒态)。【23:3x AI-Ops 补实证+数据修复】=全库扫描 101 会话含工具调用者,71 个存在 orphan call(持久化常态:工具中断天然留残),用户中毒会话 6a5a3e04 实测 orphan=64,分两类:partial 部分闭合(assistant 多 call 仅部分有响应)16 个(样本 seq=63/71/90:2-3 个 call 只 1-2 个有响应)、full 全未闭合 44 个。partial 即 400 直因(OpenAI「insufficient tool messages」语义精确对应)。已对该会话做数据修复(16 重写保留 resolved + 44 清空 tool_calls,orphan 归零;备份 devflow.db.bak-会话修复-1009),应用重载会话即恢复可用。核心待查收敛=sanitize 的 partial 重写路径(step3 部分闭合头)为何对真实数据未生效——建议以 6a5a3e04 修复前的形态做回归用例。【23:3x 第二实证=引擎会话 f4de788c】引擎跑本条时自己撞同一 400(request_id cc60b90f)致 907 腰斩停 [→];但对该会话持久化数据实测 orphan=0(62 消息/38 call 全配对,partial/full 均 0)——证明病灶有二态:①持久化脏数据(6a5a3e04 型,64 orphan,已数据修复)②发送视图构造期引入(f4de788c 型:数据干净、发送才炸;同刻 trace 有「自动压缩失败(后台)/压缩失败兜底(后台)」日志)→ 核心嫌疑=压缩/裁剪路径劈开三元组,或压缩失败兜底态被直送。已重置 907 回队(引擎重领将开新会话,短上下文规避)。【23:4x 第三轮定位=发送期三嫌疑(按置信排序)】①压缩失败兜底路径**(context_lifecycle.rs:319
keyword_fallback_commit:LLM 压缩失败→标 [..protect_start] compressed + push 关键词摘要改 conv.messages 持久态)——现只保「非空才插」,未断言插入点不落三元组中间/角色顺序合法,是长会话(1527k tokens 触发压缩)最可能的炸点;②assert_placeholder_pairing 覆盖面窄:只查「占位配对」,非完整 tool_call↔tool 双向校验——建议升级为发送前出口的完整配对断言(双向:头必有响应+响应必有头),一处兜住所有构造路径;③sanitize step3 部分闭合重写 / step4 序列合法性(ensure_sequence_legal/ensure_leading_user 插位)待逐行审。回归用例=f4de788c 形态(数据干净+长会话+压缩失败→发送即 400)。【23:5x 第四轮=缺陷锁定(出口断言单向)】assert_placeholder_pairing(sanitize.rs:291;agentic 出口 mod.rs:1970 唯一调用的出口断言)只做单向修复:遍历 role=Tool 补「orphan result 的缺失头」;完全不检查反方向——assistant 的 tool_calls 缺 tool 响应时直接放过。故 build_for_request 内部 sanitize 之后的全部视图变换(namespace 展开 mod.rs:1893+ → 易变尾段 → tool_result view-only 摘要压缩 stall_detector.rs:284+)一旦产生「头无响应」,出口断言抓不到 → 直送 provider → 400。修法(收口一处):assert_placeholder_pairing升级为双向完整配对(内联 sanitize step3 同款正向逻辑:未闭合 call 条目丢弃或补占位 tool 响应),建议更名 assert_triplet_pairing——一处兜住 build_for_request 与其后所有变换。证据链:引擎会话数据 orphan=0 + 400 前密集 view-only 压缩日志(23:26:38→23:28:01,压缩完即刻 400)+ 出口断言实现(仅 Tool 分支)。【00:1x 第五轮=根因实锤,修正第四轮方向(不是"缺响应"而是"顺序被楔")】 真凶=后台压缩的 system 摘要楔入工具三元组中间:context_lifecycle.rs:269(成功路径)/:372(兜底路径)conv.messages.push(ChatMessage::system(摘要)),而后台压缩 task 的提交窗口恰落在「assistant(tool_calls) 已 push、tool result 未 push」之间——主 loop 顺序是finalize_round_outputpush head(mod.rs:2063)→ 释放锁 →process_round_tools执行工具(数秒)→ 再取锁 push result(mod.rs:2118);后台 task 若在此窗口取锁提交,序列变[assistant(tool_calls=[a]), system(摘要), tool(a), ...]→ OpenAI 铁律「tool 必须紧随其 head」被 system 破坏 → 上游报「insufficient tool messages」400。为何层层防线都没拦住:sanitize step2/3 与openai_compat::sanitize_openai_triplets(openai_compat.rs:372-467)均只按 tool_call_id 全域配对、不校验相邻性 → 楔入的 system 原样放行(完美解释:持久化 orphan=0 数据干净却仍 400——配对全,顺序错)。次因:①失败路径两次取锁(:312复位 set_compressing 后:322再取锁)致并发二次压缩,放大楔入概率(⚠️)②fallback tool id 跨轮可重复(gen_tool_{index}/gen_stream_{pos},openai_compat.rs:323-340)→ 全域配对把「缺响应」的 head 误判为已闭合幸存(⚠️)。修法(优雅解=不变式收敛唯一出口,非补丁)=问题本质:「assistant(tool_calls) 之后必须紧随其 tool 响应」是一条协议不变式,但当前没有任何单一位置负责保证——build_for_request/裁剪/后台压缩/各 view-only 变换各自维护、异步压缩还能在任意时刻插消息,必然有一天漏。因此根治=两级: ① 不变量思维(治本,一处收口):协议转换层sanitize_openai_triplets(及 anthropic_compat 对应)从「只按 id 配对」升级为完整三元组规格化——配对(剥孤立/补占位,已有)+ 相邻性归位(head 与其响应之间楔入的异类消息移到该组响应之后,只重排不删内容)+ 幂等。理由:该不变式是协议要求,协议适配层就是它的正确职责位;所有上游破坏(含未来新增变换)在此统一兜住,任何单点 bug 不再直达 provider。② 源头守静(不产垃圾):后台压缩提交点加「序列静止」判据——持锁后确认末条非悬空ToolCallHead才 push,否则推迟到本轮工具收尾(压缩是后台任务,不该在序列半途插入);顺带把失败路径两次取锁合并为单锁(消并发二次压缩)。验收=单测:构造楔入序列([head, system, tool])→ 断言输出合规且 head 后紧随其响应;幂等单测:两次规格化结果相同。取舍:不做"消息修改收归单 actor"的大重构(成本高、收益边际),①+②以最小改动达成"源头不产生 + 出口必兜住"闭环。【01:0x AI-Ops 实施完成(用户令「接手解决」,引擎因自身撞 400 卡死已停挂机)】 已落地邻接性判定两处:crates/df-ai/src/context/sanitize.rs(step1 新增 adjacency 预计算=每个 assistant 头「紧后 tool 连续段」id 集合;step2 partition 判定由resolved_ids.contains改adjacency.get(&i).contains)+crates/df-ai/src/openai_compat.rs::sanitize_openai_triplets(同口径改造,step2 带索引遍历 + 同款 adjacency);新增回归用例sanitize_strips_calls_when_response_separated_by_interloper(夹层场景断言无残留 head+tool_calls、无残留 role=Tool)。验收:cargo test -p df-ai --lib context153 passed / 0 failed;全量 workspace 测试见批次提交附。效果:夹层序列(assistant→system/user→tool)在 sanitize 阶段即剥除未邻接的 call 并丢弃其游离响应,发送序列恒满足「head 后紧邻其响应」。遗留(不阻塞,已由出口修复兜住):①源头优化——insert_listing_bypass_warning(audit/mod.rs:1102)在工具执行前插入 system 警告,是自造夹层的注入点,建议移至工具结果回填后(涉及审批核心链路,宜后续谨慎实施)②用户插话型夹层(工具执行期间用户发消息,如 040a3163 seq42-46 实测)无法源头消除,依赖出口兜底——现已覆盖。待办:提交 + 换装生效。已审无问题:压缩边界单元对齐(compress_old_messages 走 build_eviction_units 恒不劈三元组)、锁内原子性、Anthropic 侧对 system 楔入免疫(anthropic_compat 折叠 system 进顶层)、tool 1:1 映射保序。**
🔎 2026-10-10 接手核查补注(devflow 侧):
- 实现口径澄清:01:0x 落地的是**「未邻接即剥除」——sanitize.rs step2 判定由
resolved_ids.contains收紧为adjacency.get(&i).contains(crates/df-ai/src/context/sanitize.rs:87-92),openai_compat.rssanitize_openai_tripletsstep2 同口径(crates/df-ai/src/openai_compat.rs:401-434);被 system/user 夹层隔开的 assistant 头连同其 tool 响应从发送视图剔除(step3/openai step3 按 orphaned_ids/head_ids 对称丢弃)。此非设计 ① 所述「相邻性归位/只重排不删内容」,而是判定口径收紧后走既有「未闭合→剥除」路径——安全(不 400)但有损**(该轮工具交互对本轮 LLM 不可见;持久化 view-only 不动)。- 代价评估:夹层主因=后台压缩竞态(偶发)或用户插话(工具执行窗口内,纠偏 16 场景可复现)——后者每插话一次即丢一轮工具结果,模型可能重跑工具/误判。
- 独立复验:
cargo test -p df-ai --lib567 passed / 0 failed;cargo check --workspaceEXIT 0;夹层回归用例sanitize_strips_calls_when_response_separated_by_interloper实测通过。- 遗留未实施(原 ② 源头守静):后台压缩提交点仍无「序列静止」判据(持锁后末条为悬空 ToolCallHead 时不得 push 摘要),楔入仍会发生;设计 ① 的无损「归位」变体亦未实现——二者合并登记为 909。落点已核(2026-10-10 更正):
src-tauri/src/commands/ai/agentic/context_lifecycle.rs(原条目行号引用准确)——摘要 push 点:269(LLM 成功)/:372(keyword_fallback_commit兜底),双取锁:312→:322;compress.rs仅产摘要文本,不改 ContextManager。
- 「settings.loading」i18n key 缺失已带病入库(a8c92e9,10-09 AI-Ops 走查发现):
src/components/settings/AboutPanel.vue:204用t('settings.loading'),但 zh-CN/ensettings.ts均无此 key(grep 实证)→ 版本信息返回前渲染字面串settings.loading。修:补loading键(两边)或改用已有键。同类走查发现:AboutPanel 曾用window.dispatchEvent('df-toast')(全仓无监听)已随提交改动,复核确认现机制一致。
✅ **2026-10-10 修复**:`src/i18n/zh-CN/settings.ts` / `src/i18n/en/settings.ts` 各补 `loading` 键(紧随 `descAppVersion`,与仓内 auditLog/common/fileExplorer/taskDetail 各命名空间自持 `loading` 的惯例一致)。验收:`grep -n "loading:" src/i18n/zh-CN/settings.ts src/i18n/en/settings.ts` → 各 1 命中;`bunx vue-tsc --noEmit` → EXIT 0。