真 bug 合集:向量库探活误报 + edit 降级漏能力位 + 群聊沉默窗口不撤销 + 文案 #98
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/93-real-bug-batch"
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?
Closes #93
五处独立小修。其中 AC 第 4 条的前提经查证不成立、改动已撤回,另有一处 AC 点名的接线位置被换掉(有实测复现支撑),两处都在下面说明。
1. 向量库探活把 property 当函数调用 →
/diagnose恒误报 ✅ping_vector_store写成await self._qdrant().get_collections(),而_qdrant是@property。全文件 11 处self._qdrant只有这一处多了括号。_probe宽捕Exception只回类名,于是真实部署上向量库永远 down、理由还是个具误导性的TypeError。没被发现的原因是
PersistentStorage.ping_vector_store从未被执行过——唯一相关测试用的是自定义假 storage。新增tests/test_diagnostics_storage.py,两套实现共用同一份契约断言。变异验证:把括号加回去,persistent 参数立刻红。2.
_handle_edit的降级路径不查capabilities.self_recall✅降级 = 撤回旧消息 + 重发新内容,所以它也要
self_recall。_handle_self_recall有这道 fail-closed 闸(issue #20 修的就是这个),edit 那扇门原样漏了出来。而edit=False & self_recall=False是CapabilitySet的缺省组合、edit 工具对模型恒可见——不声明能力位的平台上这就是默认行为。同时修测试替身:
fake_egress.recall()此前不查能力位就记账,所以就算有人写了这条组合的用例也不会红。(规格轴逐条核对了runtime_loop.py全部 10 处self._egress.*,确认edit降级是最后一个洞。)3. 沉默窗口在群聊里不撤销 → 恰好在抢话 ✅(接线位置与 AC 不同)
_silence_window.interrupt()唯一调用点在_handle_reactive_message里,而那个 handler 注册在on_message(rule=to_me())——群聊第三方发言不撤销待发消息,恰恰是这个机制要治的那件事。私聊因to_me()恒真而碰巧正确。AC 点名
@event_postprocessor,实现用的是@event_preprocessor,因为 postprocessor 位置有一条实测可复现的竞态:它跑在_handle_reactive_message已经create_task(_debounced_flush(...))之后,只要那个 flush 抢先注册好asyncio.Event,interrupt 就会撤掉本轮自己的回复。复现:
ARISE_DEBOUNCE_WINDOW_SECONDS=0跑test_gating_e2e.py+test_walking_skeleton.py→@event_postprocessor@event_preprocessor生产默认的去抖窗口只是让它需要事件循环卡住才触发,不是让它消失——实际表现就是全量测试在高负载批次里偶发红(我在实现期真撞到过两批)。已固化成回归测试
test_the_interrupt_does_not_cancel_the_send_it_triggered;变异验证:改回 postprocessor 时它立刻红、同文件另两条仍绿。preprocessor 的额外风险(抛异常时 NoneBot
return False丢弃整条事件,所有插件都收不到)由两轴 review 指出,已就地用 try/except +logger.exception兜住——本特性失灵最多少撤销一次待发,不该把整个 bot 变哑。新增
tests/test_silence_window_wiring.py:走真实handle_event、不装任何 matcher,断言的是真实wait()的返回值而不是"interrupt 被调过",并带一条"别的 chat 不受影响"的反向对照。4.
[tool.pytest]节名——AC 前提不成立,改动已撤回 ❌ticket 说"pytest 只读
[tool.pytest.ini_options],于是整节配置静默失效"。在本仓钉的 pytest 9.1.1 上不成立:[tool.pytest]是 pytest 9 的原生 TOML 形式、也是官方推荐写法,ini_options才是向后兼容的字符串形式,两者不能并存(_pytest/config/findpaths.py里同时出现直接报错)。实测原始状态(
[tool.pytest])下:config.inipath已指向 pyproject.toml、config.getini("asyncio_mode")已是auto、--strict-markers已经在拦没注册的 marker。这一节一直是生效的,没有任何配置在静默失效。顺带自省:我原来当作"改名生效"的两条证据(头部出现
configfile:行 + strict-marker 探针变红)都是改名之后才测的,改名之前同样成立——等于没证明任何变化。是两轴 review 逼我回头补测才发现的。改动已撤回,查证结果写进了注释,免得下一个人再"修"一次。
5.
ports.py未配置时的错误文案 ✅原文案列的"前处理/后处理/persona/llm_client/权限"既不是字段名、也早已漏了后来加的那几项。改成指向
ArisePorts的字段定义——不再维护一份会过期的清单。范围外但同源的一处
gating.py里"真实群聊非 @ 流量目前完全不经过反应式入口"那条注记,随本改动部分过期,一并注明:非 @ 消息现在会经过这个钩子,但它只调interrupt(),不产生任何门控评估/LLM 调用/记账,所以那条"新增消息接收面/成本面"的顾虑仍未被触及。验证
uv run pytest -n auto连跑 4 次(含两次高负载批次,91s / 149s)1444 passed。ruff check全过。