已读延迟窗本体+scope_ceiling三档+文档同步 #123

Closed
opened 2026-08-13 01:33:43 +00:00 by KumaAgent · 1 comment
Member

Parent

#103 第四批清单:31 条实现类落差 + 9 条待拍板(条目 15、2、20、27)

What to build

ADR-0017 拍板的"已读延迟窗"是一个独立新 gate:Outbox 防抖批次就绪后、Runtime Loop 组装上下文前独立计时,delay = clamp(f(energy), 0, scope_ceiling[scope]),纯内部计时对外零信号。origin/main 上它是一个 14 行的 return None 空壳(docstring 自称"Phase 4 真人感层的范围",但这个推迟从没写进任何设计文档、也没有票承接,Phase 4 收尾时掉了)。冷启动期 scope_ceiling 要收得更紧这条子轴也完全没接线。

真正的改动面不在函数体,在 flush/cancel 的归属结构——这是本片最容易被低估的地方。

Acceptance criteria

一、已读延迟窗本体

  • read_delay_window 签名扩展,接入 energy/scope/is_cold_start 三个新输入,delay = clamp(f(energy), 0, scope_ceiling[scope])
  • 架构位置独立于防抖:不直接拉长 Outbox 防抖窗口,防抖照旧快速合并连续消息;新 gate 在防抖批次就绪后、Runtime Loop 组装上下文前独立计时
  • 纯内部计时,对外零信号:不建能力分支,delay 就是唯一效果,不叠加任何信号发送
  • 倒计时不因期间新到消息重置:新消息只并入同一累积批次,供窗口结束后两级门控级二统一判定,不延长等待
  • chat scope(私聊/群聊)只影响静态系数/上限(scope_ceiling[private|group]),不进 energy 计算
  • 结构性风险必须处理(比"函数体+两三个 config"大一档):Debouncer.flush() 是取批次即从缓冲区清空,_handle_reactive_message_pending_flushes[chat_id]previous_flush.cancel()——两者叠加意味着"flush 后 sleep"期间到达的新消息会 cancel 掉正在等待的任务、已取出的整批消息直接丢失、新消息另起缓冲区,与"新消息只并入同一累积批次、不延长等待"这条决策正相反。必须重排 flush/cancel 的归属结构
  • Debouncer.discard_message(服务 ADR-0004 撤回联动)当前 docstring 自称"flush 后是 no-op"——引入真实等待后,撤回联动对窗口内消息会静默失效,须在片内显式决定接不接
  • tests/test_read_delay.py 整份重写(现有唯一用例断言的是"零延迟直通",与新行为矛盾)

原文(docs/adr/0017-reactive-timing-and-coverage.md「决策 → 已读延迟窗」节):

架构位置 = 另堆一个独立新 gate,不直接拉长现有 Outbox 防抖窗口:防抖照旧快速合并连续消息(不因本机制变慢),新 gate 在防抖批次就绪后、Runtime Loop 组装上下文前独立计时。……倒计时不因期间新到消息重置:新消息只并入同一累积批次(供窗口结束后"选择性回应"处理),不延长等待。

二、scope_ceiling 三档(含冷启动档)

  • scope_ceiling 私聊/群聊/冷启动三档静态值,冷启动档取更紧值;is_cold_start 已在 progressive_unlock.py 备好,只是消费方是空的
  • unlock level 目前在同一次 _debounced_flush 里被算了多次(_evaluate_unified_gate 内部一次、spontaneous_goal_unlocked 现算一次),read_delay 要用就得把它上提到 read_delay 之前,否则会出现第三次重复的 DB 读——建议顺手收敛成一次并传下去

原文(docs/adr/0017「决策 → 已读延迟窗」节最后一条子弹):

冷启动期收紧:渐进解锁未启阶段,scope_ceiling 取更紧静态值(见"选择性回应"的 floor 联动)。

原文(同 ADR「备注(实现期跟进,不属本决策)」节——推迟的是数值不是机制):

scope_ceiling(私聊/群聊/冷启动三档)具体数值……均按 ADR-0011 阈值三层分类推迟到真实 QQ 场景数据标定。

  • 引文陷阱:floor=1 已被 ADR-0029 扩到共享沉默预算本身(不再是"选择性回应"专属),但 scope_ceiling 从未被扩,AC/实现引文请引 ADR-0017 原文,不要照抄 ADR-0007 里"选择性回应 floor=1"那句去重建一个已退场的机制

三、文档同步(零独立改动面,作为逐字验收清单)

  • CONTEXT.md「已读延迟窗」条、design.md mermaid gate 节点、design.md「真人感层」条三处已用现在时描述本机制,实现落地后逐字核对成立即可,无需改字
  • design.md"上线路线"第 4 阶段枚举当前不含已读延迟窗(虽然 read_delay.py 自称属于该阶段),补一行

原文(CONTEXT.md「已读延迟窗(Read Delay Window)」条):

Outbox 防抖批次就绪后、Runtime Loop 开始组装上下文前的独立等待阶段,时长 = f(energy)(深夜按昼夜节律 nudge energy 本身,不单独引入墙钟输入,保 energy 唯一调节器不开口子);按 chat scope(私聊/群聊)设不同静态上限封顶……纯内部计时,对外零信号……窗口倒计时不因期间新到消息重置……冷启动期(渐进解锁未启阶段)scope_ceiling 取更紧静态值。

Blocked by

  • #112 — 冷启动渐进解锁三件套(需要它建立的 unlock level 穿线与 is_cold_start 传递路径,本片的冷启动档直接复用)
## Parent #103 第四批清单:31 条实现类落差 + 9 条待拍板(条目 15、2、20、27) ## What to build ADR-0017 拍板的"已读延迟窗"是一个独立新 gate:Outbox 防抖批次就绪后、Runtime Loop 组装上下文前独立计时,`delay = clamp(f(energy), 0, scope_ceiling[scope])`,纯内部计时对外零信号。origin/main 上它是一个 14 行的 `return None` 空壳(docstring 自称"Phase 4 真人感层的范围",但这个推迟从没写进任何设计文档、也没有票承接,Phase 4 收尾时掉了)。冷启动期 `scope_ceiling` 要收得更紧这条子轴也完全没接线。 真正的改动面不在函数体,在 flush/cancel 的归属结构——这是本片最容易被低估的地方。 ## Acceptance criteria **一、已读延迟窗本体** - [ ] `read_delay_window` 签名扩展,接入 `energy`/`scope`/`is_cold_start` 三个新输入,`delay = clamp(f(energy), 0, scope_ceiling[scope])` - [ ] **架构位置独立于防抖**:不直接拉长 Outbox 防抖窗口,防抖照旧快速合并连续消息;新 gate 在防抖批次就绪后、Runtime Loop 组装上下文前独立计时 - [ ] **纯内部计时,对外零信号**:不建能力分支,delay 就是唯一效果,不叠加任何信号发送 - [ ] **倒计时不因期间新到消息重置**:新消息只并入同一累积批次,供窗口结束后两级门控级二统一判定,不延长等待 - [ ] `chat scope`(私聊/群聊)只影响静态系数/上限(`scope_ceiling[private|group]`),**不进 energy 计算** - [ ] **结构性风险必须处理**(比"函数体+两三个 config"大一档):`Debouncer.flush()` 是取批次即从缓冲区清空,`_handle_reactive_message` 对 `_pending_flushes[chat_id]` 会 `previous_flush.cancel()`——两者叠加意味着"flush 后 sleep"期间到达的新消息会 cancel 掉正在等待的任务、已取出的整批消息直接丢失、新消息另起缓冲区,与"新消息只并入同一累积批次、不延长等待"这条决策正相反。必须重排 flush/cancel 的归属结构 - [ ] `Debouncer.discard_message`(服务 ADR-0004 撤回联动)当前 docstring 自称"flush 后是 no-op"——引入真实等待后,撤回联动对窗口内消息会静默失效,须在片内显式决定接不接 - [ ] `tests/test_read_delay.py` 整份重写(现有唯一用例断言的是"零延迟直通",与新行为矛盾) 原文(docs/adr/0017-reactive-timing-and-coverage.md「决策 → 已读延迟窗」节): > **架构位置 = 另堆一个独立新 gate**,不直接拉长现有 Outbox 防抖窗口:防抖照旧快速合并连续消息(不因本机制变慢),新 gate 在防抖批次就绪后、Runtime Loop 组装上下文前独立计时。……**倒计时不因期间新到消息重置**:新消息只并入同一累积批次(供窗口结束后"选择性回应"处理),不延长等待。 **二、scope_ceiling 三档(含冷启动档)** - [ ] `scope_ceiling` 私聊/群聊/冷启动三档静态值,冷启动档取更紧值;`is_cold_start` 已在 `progressive_unlock.py` 备好,只是消费方是空的 - [ ] unlock level 目前在同一次 `_debounced_flush` 里被算了多次(`_evaluate_unified_gate` 内部一次、`spontaneous_goal_unlocked` 现算一次),read_delay 要用就得把它上提到 read_delay 之前,否则会出现第三次重复的 DB 读——建议顺手收敛成一次并传下去 原文(docs/adr/0017「决策 → 已读延迟窗」节最后一条子弹): > **冷启动期收紧**:渐进解锁未启阶段,`scope_ceiling` 取更紧静态值(见"选择性回应"的 `floor` 联动)。 原文(同 ADR「备注(实现期跟进,不属本决策)」节——推迟的是数值不是机制): > `scope_ceiling`(私聊/群聊/冷启动三档)**具体数值**……均按 ADR-0011 阈值三层分类推迟到真实 QQ 场景数据标定。 - [ ] 引文陷阱:`floor=1` 已被 ADR-0029 扩到共享沉默预算本身(不再是"选择性回应"专属),但 `scope_ceiling` 从未被扩,AC/实现引文请引 ADR-0017 原文,不要照抄 ADR-0007 里"选择性回应 floor=1"那句去重建一个已退场的机制 **三、文档同步(零独立改动面,作为逐字验收清单)** - [ ] CONTEXT.md「已读延迟窗」条、design.md mermaid `gate` 节点、design.md「真人感层」条三处已用现在时描述本机制,实现落地后逐字核对成立即可,无需改字 - [ ] design.md"上线路线"第 4 阶段枚举当前不含已读延迟窗(虽然 `read_delay.py` 自称属于该阶段),补一行 原文(CONTEXT.md「已读延迟窗(Read Delay Window)」条): > Outbox 防抖批次就绪后、Runtime Loop 开始组装上下文前的独立等待阶段,时长 = f(energy)(深夜按昼夜节律 nudge energy 本身,不单独引入墙钟输入,保 energy 唯一调节器不开口子);按 chat scope(私聊/群聊)设不同静态上限封顶……纯内部计时,对外零信号……窗口倒计时不因期间新到消息重置……冷启动期(渐进解锁未启阶段)scope_ceiling 取更紧静态值。 ## Blocked by - #112 — 冷启动渐进解锁三件套(需要它建立的 unlock level 穿线与 `is_cold_start` 传递路径,本片的冷启动档直接复用)
Yushu closed this issue 2026-08-13 04:54:11 +00:00
Author
Member

2026-08-14(评估侧):本票落地的 circadian_energy_adjustment(read_delay.py)被 #124 撤掉替换——它读墙钟只服务本票的已读延迟窗自己,是 ADR-0017「拒绝了」节点名否决的形状(新 gate 与 energy 并列各自读时钟)。真正共享、供全部 4 个 energy 消费方使用的版本见 #124,决议与代码走向见该票评论。

2026-08-14(评估侧):本票落地的 `circadian_energy_adjustment`(read_delay.py)被 #124 撤掉替换——它读墙钟只服务本票的已读延迟窗自己,是 ADR-0017「拒绝了」节点名否决的形状(新 gate 与 energy 并列各自读时钟)。真正共享、供全部 4 个 energy 消费方使用的版本见 #124,决议与代码走向见该票评论。
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#123
No description provided.