[moz] fix: mention 重复投递 + mail 失败通知竞态保护 + §14 设计文档同步 #80
Reference in New Issue
Block a user
Delete Branch "fix/mention-duplicate-mail-race-doc-sync"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
改动概述
本 PR 修复两个 bug 并同步设计文档。
Bug 1:spawn_full_agent use_main_session 返回 None 导致 mention 重复投递
根因:
spawner.py的spawn_full_agent在use_main_session=True时,session_id = None,最终return session_id返回None。但 ticker 的_process_mentions用if result is not None:判断 spawn 是否成功——None被误判为失败,导致每次 tick 都重试,mention 反复投递。修复方案:引入
effective_sid = session_id or "main"作为统一标识,用于_register_session、_monitor_process和返回值。这样 use_main_session=True 时返回"main"而非None,ticker 的result is not None判定正确。影响范围:
src/daemon/spawner.pyspawn_full_agent方法or "main"短路不触发)Bug 2:_mark_task failed 时未检查已完成状态导致误发投递失败通知
根因:
spawner.py的_mark_task("failed")中,_is_mail_project(db_path)为 True 时直接触发mail_notify.notify_mail_failed。但没有先检查 task 是否已经处于 done 状态。在竞态条件下(spawner 标 failed 和 handler 标 done 同时发生),会导致已经完成的邮件误发投递失败通知。修复方案:在
notify_mail_failed调用前加防御性检查——查询 task 当前状态,如果已经是done,跳过失败通知。影响范围:
src/daemon/spawner.py_mark_task方法设计文档:§13 PromptSection 列表同步
PR #79 新增了
DeliveryChecklistSection(priority=55)、GiteaConventionSection(priority=55)、WikiGuideSection(priority=60),注入到 Mail/Task/Toolchain 三个 handler。但docs/design/14-task-type-architecture.md§13 中三个 handler 的get_sections()列表和复用分析表没有同步更新。更新内容:
测试
✅
python3 -m pytest tests/ -x -q -m "not e2e"→ 456 passed, 3 skipped, 299 deselected审查结论:APPROVED ✅
Fix 1: spawn_full_agent 返回 None 导致 mention 重复投递
根因确认:
use_main_session=True时session_id=None,函数末尾return session_id返回None。调用方 ticker.py:820 / ticker.py:601 用if result is not None:判断成功 →None被误判为失败 → mentions 永远不被标 notified → 下个 tick 重试 → 重复投递。修复正确性:
effective_sid = session_id or "main"与已有的_sid_key(line 502)、dry_run 路径(line 592)、_monitor_process(line 807sid = session_id or "main")完全一致 ✅_register_session、_monitor_process、log、return 全部统一使用effective_sid✅"main"占位符安全:use_main_session=True场景下同一 agent 只有一个并发 main session,counter 层面早已用此 key ✅Fix 2: Mail 失败通知竞态保护
场景确认:
_mark_task(status="failed")触发notify_mail_failed,但 handler 可能已将 task 标为done。修复正确性:
status == "done"则跳过 ✅except Exception: pass回退到原逻辑(宁可多发一次通知也不漏报) ✅设计文档 §14 同步
建议(非阻塞)
except Exception: pass静默吞错,建议加logger.debug便于排查 check 本身失败的情况—— 司马懿