群内插句嘴实现:能量窗口 + 群管鉴权(issue #159) #168

Merged
Yushu merged 1 commit from feat/159-group-slow-interrupt into main 2026-08-19 09:07:15 +00:00
Member

Closes #159

What

正式给 issue #37 AC7 交付的 slow_interrupt_energy_boostgating.py)接上消费方:群内非 @ 消息的"插句嘴"能力,per-chat opt-in、能量窗口触发(ADR-0032)。

  • 新增独立的"群管理员"host 回调 IsGroupAdmin/ArisePorts.is_group_admin,语义严格限定"平台原生群管理员/群主判断"——不复用 ports.is_admin
  • 新增 per-chat opt-in 存储开关(SlowInterruptStoragePort)+ /setslowinterrupt 命令(经 _group_admin_gate 校验,host 未接线时如实说明不支持)
  • IngressPort.is_bot_of 同步早期判定 + _handle_group_slow_interrupt(新 @event_postprocessor 分派点):tier-1(活跃度信号喂情感态 EMA)恒开、不受 opt-in 限制;tier-2(读内容判断是否接话)需要 opt-in + 能量窗口两道闸都过
  • RuntimeLoop.run_group_slow_interrupt:不经 run(),天然不写 Delta(AC5"未接话内容不写入任何 RecallEvent/长期存储"由此自动满足)
  • TriggerPath 新增 group_slow_interruptdecision_snapshot.py/cost.py/explain.py/gate_pipeline.py 完成 blast radius 更新

Review 修复

两轴 review(Standards + Spec)+ 对抗式 Verify 确认 4 处问题并已修复:

  • run_group_slow_interrupt 未解析 message.media_refs 就组装上下文,带图片/贴纸的非 @ 消息触发插句嘴评估时会在 assemble_context 对空 media_contentKeyError,被外层 except Exception 静默吞掉——已接入 _resolve_media_content,并补充回归测试(先反向验证测试能捕获该 bug,再确认修复后通过)
  • _spawn_slow_interrupt_window_record 的 fire-and-forget 任务缺少异常兜底——已仿 _learn_stickers 先例包一层 try/except + logger.exception
  • cost.py/gate_pipeline.py 的触发路径计数文档未同步新增的第六条路径——已更新
  • :新增的 4 个 PersistentStorage 方法此前只经内存版 SentLog 测过——已补 test_slow_interrupt_storage.py(memory/persistent 参数化覆盖)

Test plan

  • uv run pytest -q:1993 passed
  • uv run ruff check src/ tests/:全通过
  • uv run lint-imports:2 kept, 0 broken
  • ty check:47 diagnostics(与 main 基线一致,无新增)
  • mutation testing:_handle_group_slow_interrupt 的 opt-in/窗口/is_bot/私聊/续期共 5 处守卫逐一变异验证测试能捕获
Closes #159 ## What 正式给 issue #37 AC7 交付的 `slow_interrupt_energy_boost`(`gating.py`)接上消费方:群内非 @ 消息的"插句嘴"能力,per-chat opt-in、能量窗口触发(ADR-0032)。 - 新增独立的"群管理员"host 回调 `IsGroupAdmin`/`ArisePorts.is_group_admin`,语义严格限定"平台原生群管理员/群主判断"——不复用 `ports.is_admin` - 新增 per-chat opt-in 存储开关(`SlowInterruptStoragePort`)+ `/setslowinterrupt` 命令(经 `_group_admin_gate` 校验,host 未接线时如实说明不支持) - `IngressPort.is_bot_of` 同步早期判定 + `_handle_group_slow_interrupt`(新 `@event_postprocessor` 分派点):tier-1(活跃度信号喂情感态 EMA)恒开、不受 opt-in 限制;tier-2(读内容判断是否接话)需要 opt-in + 能量窗口两道闸都过 - `RuntimeLoop.run_group_slow_interrupt`:不经 `run()`,天然不写 Delta(AC5"未接话内容不写入任何 RecallEvent/长期存储"由此自动满足) - `TriggerPath` 新增 `group_slow_interrupt`,`decision_snapshot.py`/`cost.py`/`explain.py`/`gate_pipeline.py` 完成 blast radius 更新 ## Review 修复 两轴 review(Standards + Spec)+ 对抗式 Verify 确认 4 处问题并已修复: - **高**:`run_group_slow_interrupt` 未解析 `message.media_refs` 就组装上下文,带图片/贴纸的非 @ 消息触发插句嘴评估时会在 `assemble_context` 对空 `media_content` 取 `KeyError`,被外层 `except Exception` 静默吞掉——已接入 `_resolve_media_content`,并补充回归测试(先反向验证测试能捕获该 bug,再确认修复后通过) - **中**:`_spawn_slow_interrupt_window_record` 的 fire-and-forget 任务缺少异常兜底——已仿 `_learn_stickers` 先例包一层 `try/except + logger.exception` - **低**:`cost.py`/`gate_pipeline.py` 的触发路径计数文档未同步新增的第六条路径——已更新 - **低**:新增的 4 个 `PersistentStorage` 方法此前只经内存版 `SentLog` 测过——已补 `test_slow_interrupt_storage.py`(memory/persistent 参数化覆盖) ## Test plan - [x] `uv run pytest -q`:1993 passed - [x] `uv run ruff check src/ tests/`:全通过 - [x] `uv run lint-imports`:2 kept, 0 broken - [x] `ty check`:47 diagnostics(与 main 基线一致,无新增) - [x] mutation testing:`_handle_group_slow_interrupt` 的 opt-in/窗口/is_bot/私聊/续期共 5 处守卫逐一变异验证测试能捕获
正式给 slow_interrupt_energy_boost 接上消费方:群内非 @ 消息的插句嘴能力,
per-chat opt-in、能量窗口触发。新增独立的群管理员 host 回调(不复用
ports.is_admin)、per-chat opt-in 存储开关 + /setslowinterrupt 命令、
tier-1 活跃度信号(恒开)与 tier-2 插句嘴评估(opt-in+窗口双闸)分离的
@event_postprocessor 分派点,未接话内容不写入任何 RecallEvent/长期存储。
Yushu merged commit 6c5c6b0f4f into main 2026-08-19 09:07:15 +00:00
Yushu deleted branch feat/159-group-slow-interrupt 2026-08-19 09:07:16 +00:00
Sign in to join this conversation.
No description provided.