fix: 话题响应策略修复 + bypass 判定收敛共享#256
Conversation
历史教训(话题 omt_197a3379c4cf1bb7):session 创建者在多人话题 里发图,bot 自作多情冲上去回。多人讨论里 bot 无法可靠判断"这条 是给我还是给别人"——所以干脆要求显式 @bot 才回。 - 抽出 thread-participants 模块,统一拉历史 + 判断"是否有非 session 创建者的人类参与者",失败时保守返回 true - 单 bot 模式:图片/文档/文字 三条 bypass 路径全部加多人话题 前置过滤 - 多 bot 模式:thread creator bypass 同样加多人话题过滤 - 单人话题保留原 Qwen 文字判断 + 图片/文档直放 - 新增 thread-participants 单测 + event-handler 多人话题场景测试 - 新增 docs/design/thread-bypass-policy.md 记录策略 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
被黎叔在话题 omt_197a5d56cc92dbe9 抓现行:发「不用新分支,但是
文档需要更新」没响应。日志显示 Qwen 判 {respond: false} —— 因
为 Qwen prompt 里只塞了消息文本本身,没上下文,看到一句像"安排
开发干活"的话就误判成"不是跟 bot 说话"。
反思:话题本就是 user vs bot 的对话载体,单人话题里 session 创
建者发的消息基本就是冲 bot 来的。多人话题已经在前一版强制 @
了,单人话题再用 Qwen 二次判断纯属画蛇添足——既增加延迟,又
引入误判。直接放行。
- 单 bot 模式:单人话题图片/文档/文字 全部直接 allow,砍掉
checkThreadRelevance 调用
- 多 bot 模式:thread creator bypass 在单人话题直接 bypass=true
- 移除 thread-relevance import;event-handler.test 移除 Qwen
mock,单测用例从 'semantic_check' 收敛到 'allow' / 'block'
- 更新 design doc:单人/多人差异表 + 历史演进 v4 注明取消 Qwen
的原因
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
黎叔提醒的边界:单人话题虽然总放行,但一旦动态加入第三人, 就要立即切换到多人保守模式。 实现层面早就是对的——threadHasOtherHumanParticipant 每次都 现拉 fetchRecentMessages,没缓存。但语义没有被显式断言, 所以补一个 stateful mock 测试 + 在 design doc 里加"动态切换" 小节固化下来。 - thread-participants.test.ts 新增 transitions from solo to multi-user as third party joins - design doc「多人话题的定义」下加「动态切换」小节,说明 每条消息都实时拉 + 第三人插话的处理流程 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
event-handler.ts 里单 bot 和多 bot 模式各有一套 thread bypass 逻辑(session 创建者校验 + 多人话题保守),代码近乎完全重复。之前 deb97d4 加多人话题保守 时改了多 bot 分支,差点漏改单 bot;后续每加一条规则都得改两份,迟早飘。 把 bypass 判定抽到 thread-participants.ts 的 evaluateThreadBypass(),event-handler 里两个分支只剩 "判 @mention 状态 + 调共享函数"。返回带 reason 的结果对象 (no_session / not_creator / multi_user / solo),日志保持各分支独立。 - 新增 8 条 evaluateThreadBypass 单测覆盖所有 reason 分支 + agentId 透传 - 补 chat-history-fork.test.ts 和 event-handler.test.ts 里 security mock 漏导出的 isOwner(event-handler.ts 现在模块级常量直接引用 isOwner) - 更新 docs/design/thread-bypass-policy.md,标注共享判定与 v5 演进 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @flagflag's task in 3m 37s —— View job Code Review: 话题响应策略修复 + bypass 判定收敛
✅ Approved — 高质量重构,未发现需要阻塞的问题这个 PR 把单 bot / 多 bot 两条分支的 bypass 判定收敛到 做得好的地方
一处非阻塞的小提醒(doc/impl 语义差,confidence ~70,不强制改) 设计文档 测试:本环境的 bash 受限无法直接跑 整体评价:逻辑正确、可读性好、测试与文档到位,符合仓库测试政策(feat+test、bugfix+回归)。👍 |
冲突解决思路: - 保留 main 的 resolveMentionGate 白名单架构(每条放行条件返回命名 reason) - 内部 bypass 段改用本分支抽出的 evaluateThreadBypass 共享判定 - 多 bot:通过返回 'thread_bypass'(不再有 _exclusive 后缀) - 单 bot:通过返回 'thread_session_owner' - 多人话题保守拦截 + 移除 Qwen 二次判断的语义全部保留 同步更新: - mention-gate.test.ts:去掉过时的 Qwen mock 和 _exclusive 期望 - restart-history.test.ts:补 isOwner mock(main 新增的 security 依赖) - 删除未使用的 formatThreadContext 辅助函数 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Claude finished @flagflag's task in 1m 34s —— View job Code Review: 话题响应策略修复 + bypass 判定收敛(synchronize 复审)
✅ Approved — 合并后的集成依然干净,未发现阻塞问题本次 synchronize 主要是合并了 main 的 核对要点
一处遗留的非阻塞提醒(doc/impl 语义差,confidence ~70,沿用上次评审,未阻塞) 设计文档 Fix this →(分支 测试:本环境 bash 受限无法直接跑 vitest/typecheck。依据 PR 描述:thread-participants 11/11、event-handler 62/62、typecheck 干净、全量 1411/1412(剩 1 个为 整体评价:合并后逻辑闭合、判定收敛彻底、测试与设计文档到位,符合仓库测试政策。👍 |
reviewer 指出 doc/impl 语义差:文档写"曾经有过"+"话题一旦多人化就一直保持保守", 但实现是 fetchRecentMessages 默认 limit=10,只看最近 N 条窗口。 把决策表里的措辞改成"最近 N 条窗口(默认 N=10)",并把工程取舍和已知边界 (沉寂多轮再单人续聊会被重判 solo)写明,与代码现状对齐。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Addressed — |
|
Claude finished @flagflag's task in 1m 13s —— View job Code Review: 话题响应策略修复 + bypass 判定收敛(doc 修正复审)
✅ Approved — 上次的 doc/impl 语义差已修复,无新增问题本次 synchronize 是针对上两轮评审里那条非阻塞提醒的定向修复( 已解决:doc/impl 语义差(前两轮 confidence ~70)
复核要点(均无回归)
测试:本环境 bash 受限无法直接跑 vitest/typecheck。依据 PR 描述:thread-participants 11/11、event-handler 62/62、typecheck 干净、全量 1411/1412(剩 1 个为 整体评价:判定收敛彻底、依赖注入到位、文档与实现已对齐、测试覆盖充分。先前唯一的非阻塞提醒已闭环,无遗留项。👍 |
变更概述
修复了话题(thread)内消息触发 bot 响应的几个 bug,并把单 bot / 多 bot 两个模式的 bypass 判定收敛到共享函数。
omt_197a3379c4cf1bb7——session 创建者发图给第三人看,bot 自作多情冲上去回复;多人讨论 bot 没法可靠判断"消息是给谁的",干脆要求显式 @evaluateThreadBypass()让单 bot 和多 bot 模式共享同一份判定逻辑。event-handler 里两个分支只剩"判 @mention 状态 + 调共享函数",再不会出现一边改一边漏的策略漂移测试计划
🤖 Generated with Claude Code