已读延迟窗本体+scope_ceiling三档+文档同步 #128
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/123-read-delay-window"
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 #123
实现
ADR-0017"已读延迟窗"落地:Outbox 防抖批次就绪后、Runtime Loop 组装上下文前独立计时,
delay = clamp(f(energy), 0, scope_ceiling[scope])。read_delay.py:circadian_energy_adjustment/compute_read_delay_seconds纯函数 +read_delay_window薄 IO 壳(asyncio.sleep)。scope_ceiling三档静态值(私聊/群聊/冷启动,冷启动档统一取最紧值,优先于私聊/群聊判断)。真正的改动面按 AC 点名不在函数体,在 flush/cancel 的归属结构:
Debouncer.flush()从"防抖窗口结束立刻做"改为推迟到已读延迟窗结束之后才做。原因:flush()立刻清空缓冲区 +_handle_reactive_message对_pending_flushes[chat_id]会cancel(),两者叠加意味着"flush 后 sleep"期间到达的新消息会 cancel 掉正在等待的任务、已取出的整批消息直接丢失、新消息另起缓冲区——与"新消息只并入同一累积批次、不延长等待"这条决策正相反。改法:新增模块级标记_read_delay_in_progress,已读延迟窗进行中的 chat,新消息只add_message并入缓冲区,不 cancel、不重排。副作用(预期内):Debouncer.discard_message(撤回联动)的有效窗口随之自然从"防抖阶段"扩大到"防抖 + 已读延迟"两个阶段。unlock_level/AffectiveState在同一次_debounced_flush里收敛成各自一次读取(_evaluate_unified_gate新增unlock_level覆盖参数,复用既有affective_state覆盖参数),避免同一次 flush 三处各读一次 Sent Log/画像/情感态。过程中发现并修了一个真实的正确性回归:_debounced_flush为已读延迟窗新增的情感态读取,如果不通过覆盖参数传给门控,会变成门控"第二次读",一旦期间情感态被 tier-1 传染/衰减改动,门控判定用的就不是已读延迟窗算energy时看到的那份,决策快照也会记错——被 issue #79 就已存在的test_the_snapshot_carries_the_affective_state_the_gate_judged_on精确抓住。两轴 review 发现与修正
两轴 review(sonnet)跑出 3 条发现,adversarial verify 后 2 条确认、1 条证伪:
test_gate_pipeline_unlock_level.py手搓的_FakePorts只有storage一个字段,与_evaluate_unified_gate期望的ArisePorts(字段齐全的具体 dataclass,非 Protocol)类型不兼容——ty/basedpyright均报invalid-argument-type,会在 CI 类型检查任务上红。改用仓库已有的configure_arisefixture +get_ports()拿一个真正合法的ArisePorts,call-countingSentLog通过其sent_log注入点接线,运行时行为不变。test_read_delay_wiring_e2e.py两条结构性回归测试靠固定asyncio.sleep(0.1)猜"任务应该已经进入已读延迟窗"——这正是本仓dispatch_helpers.py明文警告过、且test_silence_window_wiring.py已经真实撞过一次的满负载偶发失败模式。改为直接轮询本片新增的_read_delay_in_progress标记本身(超时兜底),确定性等待,不猜时长。read_delay_window签名"没有按 AC 字面接住energy/scope/is_cold_start三个输入"——核实后这个拆分理由已经逐字写在compute_read_delay_seconds的 docstring 里("scope/is_cold_start由调用方算好传入,三档选择不是本函数职责"),发现声称"完全不出现"与代码矛盾,不成立。文档
CONTEXT.md/design.md 真人感层条/mermaid
gate节点核对后确认已用现在时准确描述本机制,无需改字;design.md"上线路线"第 4 阶段枚举补了"已读延迟窗"一行;ADR-0017 补更新节记录 flush/cancel 归属结构重排的完整来龙去脉;ADR-0011 阈值表确认三个新增静态 config 字段的分类归属。测试
ruff check/ty check均通过。unlock_level覆盖参数、affective_state透传、compute_read_delay_secondsclamp、circadian_energy_adjustment边界共 6 处新守卫(分别 mutate 后确认对应测试变红,还原后 md5 校验一致)。test_read_delay_wiring_e2e.py的确定性轮询修正后连续跑 5 次稳定通过。