文件: internal/swarm/manager.go L533-535(delete(m.results, tmID))vs L719-735(GetTeammateResult,#1814 修复)与 L797-799(emit 注释)
问题描述
ShutdownTeammate 无条件 delete(m.results, tmID)。但 #1814 修复专门让 stored-result 在 teammate 移除后仍可取(GetTeammateResult 把 stored-result 检查移到存在性门禁之前,注释明说"先 shutdown 后取结果"是最常见顺序);emit teammate_shutdown case 注释 "Keep the last result available even after shutdown" 与该 delete 直接矛盾。#2121 guard(teammateGoverned)使 shutdown 后无任何路径再写回——delete 是终态性数据丢失。两个 issue 修复互相打架(#1633 修 quota 泄漏时顺带删掉了 #1814 刻意保留的数据)。
触发场景
leader 按 #1814 描述的顺序:teammate 完成任务(结果已入 m.results)→ ShutdownTeammate 释放配额槽 → GetTeammateResult → 返回 ("", false),最终产出永久丢失。
修复建议
ShutdownTeammate 保留 m.results[tmID](与 emit 注释一致);results 条目由 team 生命周期(DeleteTeam/GetTeamResults)或容量上限统一回收。
严重程度: medium(明确现实序列的数据丢失)
来源: cron-1 深度审查,初审 sa-133 + 独立复核 sa-134 双重确认 2>&1 | tail -1 && gh issue create --title "[code-review] swarm SendToTeammate/GetTeamResults use team pointer after releasing m.mu: TOCTOU vs DeleteTeam/ShutdownTeammate silently drops messages" --body "文件: internal/swarm/manager.go L609-621(SendToTeammate)、L740-747(GetTeamResults)
问题描述
m.mu 下取 team 指针后解锁再操作。与 DeleteTeam/ShutdownTeammate 并发时:消息可投进已被 cancel 的 teammate Inbox,runner 已退出不消费,SendToTeammate 返回 nil 静默成功。对比 ShutdownTeammate 自身(L520-524 在 tm.mu 下同步 cancel+移除)与 #2121 对 SpawnTeammate 的同类修复,修复模式已存在而 Send 路径未用。
触发场景
leader 并发 SendToTeammate(team, tm, msg) 与 DeleteTeam(team):Send 在 L616 解锁后被调度让出;DeleteTeam 完成移除+cancel;Send 恢复后消息投递成功返回 nil,实际无人消费。
修复建议
投递操作纳入 team 生命周期临界区(team.mu 下校验 teammate 存活 + 投递原子化),或对已 cancel 的 teammate inbox 投递返回错误。
严重程度: medium(并发窗口窄,但后果为静默消息丢失 + 假送达)
来源: cron-1 深度审查,初审 sa-133 + 独立复核 sa-134 双重确认(候选 3 metadata alias 经复核否定未立案)"
文件: internal/swarm/manager.go L533-535(delete(m.results, tmID))vs L719-735(GetTeammateResult,#1814 修复)与 L797-799(emit 注释)
问题描述
ShutdownTeammate 无条件
delete(m.results, tmID)。但 #1814 修复专门让 stored-result 在 teammate 移除后仍可取(GetTeammateResult 把 stored-result 检查移到存在性门禁之前,注释明说"先 shutdown 后取结果"是最常见顺序);emit teammate_shutdown case 注释 "Keep the last result available even after shutdown" 与该 delete 直接矛盾。#2121 guard(teammateGoverned)使 shutdown 后无任何路径再写回——delete 是终态性数据丢失。两个 issue 修复互相打架(#1633 修 quota 泄漏时顺带删掉了 #1814 刻意保留的数据)。触发场景
leader 按 #1814 描述的顺序:teammate 完成任务(结果已入 m.results)→ ShutdownTeammate 释放配额槽 → GetTeammateResult → 返回 ("", false),最终产出永久丢失。
修复建议
ShutdownTeammate 保留 m.results[tmID](与 emit 注释一致);results 条目由 team 生命周期(DeleteTeam/GetTeamResults)或容量上限统一回收。
严重程度: medium(明确现实序列的数据丢失)
来源: cron-1 深度审查,初审 sa-133 + 独立复核 sa-134 双重确认 2>&1 | tail -1 && gh issue create --title "[code-review] swarm SendToTeammate/GetTeamResults use team pointer after releasing m.mu: TOCTOU vs DeleteTeam/ShutdownTeammate silently drops messages" --body "文件: internal/swarm/manager.go L609-621(SendToTeammate)、L740-747(GetTeamResults)
问题描述
m.mu 下取 team 指针后解锁再操作。与 DeleteTeam/ShutdownTeammate 并发时:消息可投进已被 cancel 的 teammate Inbox,runner 已退出不消费,SendToTeammate 返回 nil 静默成功。对比 ShutdownTeammate 自身(L520-524 在 tm.mu 下同步 cancel+移除)与 #2121 对 SpawnTeammate 的同类修复,修复模式已存在而 Send 路径未用。
触发场景
leader 并发 SendToTeammate(team, tm, msg) 与 DeleteTeam(team):Send 在 L616 解锁后被调度让出;DeleteTeam 完成移除+cancel;Send 恢复后消息投递成功返回 nil,实际无人消费。
修复建议
投递操作纳入 team 生命周期临界区(team.mu 下校验 teammate 存活 + 投递原子化),或对已 cancel 的 teammate inbox 投递返回错误。
严重程度: medium(并发窗口窄,但后果为静默消息丢失 + 假送达)
来源: cron-1 深度审查,初审 sa-133 + 独立复核 sa-134 双重确认(候选 3 metadata alias 经复核否定未立案)"