issue #124: 情感态 energy 昼夜节律 nudge(读时施加) #129

Merged
Yushu merged 2 commits from feat/124-circadian-energy-nudge into main 2026-08-13 08:27:37 +00:00
Member

Closes #124

实现

  • 新增 read_delay.py 内的 circadian_energy_adjustment(issue #123 占位版本)——本片发现它与 ADR-0017/ADR-0005 的"新 gate 不单独读墙钟,只读 energy"边界冲突:字面上没让 read_delay_window 读钟,但技术上绕开了 ADR-0017"拒绝了"节点否决的形状。经 Forgejo issue 评论核实评估会话裁决,撤掉本地实现,改为读时统一施加。
  • 新函数 affective_state.circadian_energy_nudge(纯函数,昼夜区间判定)+ affective_state.get_effective_fast_state(全仓唯一读口:读原始存储值、叠加 nudge、clamp、不落库)。
  • 四个消费点全部改走 get_effective_fast_state:门控默认取值(gate_pipeline.py)、已读延迟窗(entry_reactive.py)、打字节奏与 mood_congruence 召回评分(runtime_loop.py)。
  • 新增 3 个 config 字段:arise_circadian_energy_nudge_{start_hour,end_hour,amount},复用 issue #123 的 config 分类先例。
  • read_delay.py 撤回原有 circadian_energy_adjustmentdatetime import,模块归属边界收紧为"全程不读墙钟",新增 AST 守卫测试锁定。

两轴 review 发现与修正(5 项,全部确认)

  1. [HIGH] /why_query 是第5个未接线消费点,仍直接读 storage 原始值,展示坐标与真实召回排序脱节——entry_admin.py 改走 get_effective_fast_state,新增排序翻转回归测试。
  2. [MEDIUM standards] 3 个新昼夜节律参数只被 RuntimeLoop 一个方法读,按 issue #105 既有标准应收进 RuntimeLoopConfig——重构 runtime_loop.py/loop_factory.py/runtime_loop_helpers.py
  3. [LOW standards / MEDIUM spec](同一处缺口的两个角度)AST 归属边界守卫只挡了 datetime 模块,漏了 time.time() 等价读钟方式——扩展守卫覆盖 datetime+time
  4. [MEDIUM spec] get_effective_fast_state 文档声称"决策快照全覆盖"过度宽泛,忽略 Callback 送回路径(ADR-0029 定死的真无门控路径)的合法例外——收窄措辞。

文档

  • docs/adr/0005-affective-state.md 新增更新节,记录 #123 违规诊断、方案形状、语义变化、四个消费点、AST 守卫、config 复用。
  • docs/adr/0017-reactive-timing-and-coverage.md 新增简短更新节,指向 ADR-0005 详情。
  • docs 分支按规矩不推送,仅本地提交)

测试

  • 变异测试确认并补齐 4 处真实覆盖缺口:打字节奏/mood_congruence/门控默认取值/已读延迟窗的接线证明测试。
  • 两轴 review 后新增 /why_query 生效值消费的排序翻转回归测试。
  • 全量测试 1737 passed;ruff 全绿;ty check 对本片改动文件扫描出的 18 条诊断经核实为既有的 _event() 测试辅助函数返回类型宽松(-> object)导致的噪音,与本片改动无关(同款诊断在 issue #123 的 ty check 中已被判定为既有噪音)。

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

Closes #124 ## 实现 - 新增 `read_delay.py` 内的 `circadian_energy_adjustment`(issue #123 占位版本)——本片发现它与 ADR-0017/ADR-0005 的"新 gate 不单独读墙钟,只读 energy"边界冲突:字面上没让 `read_delay_window` 读钟,但技术上绕开了 ADR-0017"拒绝了"节点否决的形状。经 Forgejo issue 评论核实评估会话裁决,撤掉本地实现,改为读时统一施加。 - 新函数 `affective_state.circadian_energy_nudge`(纯函数,昼夜区间判定)+ `affective_state.get_effective_fast_state`(全仓唯一读口:读原始存储值、叠加 nudge、clamp、不落库)。 - 四个消费点全部改走 `get_effective_fast_state`:门控默认取值(`gate_pipeline.py`)、已读延迟窗(`entry_reactive.py`)、打字节奏与 mood_congruence 召回评分(`runtime_loop.py`)。 - 新增 3 个 config 字段:`arise_circadian_energy_nudge_{start_hour,end_hour,amount}`,复用 issue #123 的 config 分类先例。 - `read_delay.py` 撤回原有 `circadian_energy_adjustment` 及 `datetime` import,模块归属边界收紧为"全程不读墙钟",新增 AST 守卫测试锁定。 ## 两轴 review 发现与修正(5 项,全部确认) 1. **[HIGH]** `/why_query` 是第5个未接线消费点,仍直接读 storage 原始值,展示坐标与真实召回排序脱节——`entry_admin.py` 改走 `get_effective_fast_state`,新增排序翻转回归测试。 2. **[MEDIUM standards]** 3 个新昼夜节律参数只被 `RuntimeLoop` 一个方法读,按 issue #105 既有标准应收进 `RuntimeLoopConfig`——重构 `runtime_loop.py`/`loop_factory.py`/`runtime_loop_helpers.py`。 3. **[LOW standards / MEDIUM spec]**(同一处缺口的两个角度)AST 归属边界守卫只挡了 `datetime` 模块,漏了 `time.time()` 等价读钟方式——扩展守卫覆盖 `datetime`+`time`。 4. **[MEDIUM spec]** `get_effective_fast_state` 文档声称"决策快照全覆盖"过度宽泛,忽略 Callback 送回路径(ADR-0029 定死的真无门控路径)的合法例外——收窄措辞。 ## 文档 - `docs/adr/0005-affective-state.md` 新增更新节,记录 #123 违规诊断、方案形状、语义变化、四个消费点、AST 守卫、config 复用。 - `docs/adr/0017-reactive-timing-and-coverage.md` 新增简短更新节,指向 ADR-0005 详情。 - (`docs` 分支按规矩不推送,仅本地提交) ## 测试 - 变异测试确认并补齐 4 处真实覆盖缺口:打字节奏/mood_congruence/门控默认取值/已读延迟窗的接线证明测试。 - 两轴 review 后新增 `/why_query` 生效值消费的排序翻转回归测试。 - 全量测试 1737 passed;ruff 全绿;`ty check` 对本片改动文件扫描出的 18 条诊断经核实为既有的 `_event()` 测试辅助函数返回类型宽松(`-> object`)导致的噪音,与本片改动无关(同款诊断在 issue #123 的 ty check 中已被判定为既有噪音)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ADR-0005/ADR-0017 拍板:energy 方程新增昼夜节律 nudge 项,深夜时段给 energy
一个额外向下的值;"新 gate(已读延迟窗)不单独读墙钟,只读 energy"这条边界
不能只靠代码审查。

issue #123 里的 circadian_energy_adjustment 是这条边界的一次未遂违反——字面
上没让 read_delay_window 读钟,但调用方只喂给已读延迟窗自己用,门控/打字
节奏/mood_congruence 三处完全看不到,技术上绕开了 ADR-0017「拒绝了」节点名
否决的"新 gate 与 energy 并列各自读时钟"那个形状。评估侧裁决方案 (b)(读时
施加,AC 给的二选一之一):撤掉那个局部版本,改成 affective_state.py 新增
的 circadian_energy_nudge(原逻辑原样搬家)+ get_effective_fast_state(快
情感态的唯一"生效读口":存储值 + 昼夜节律读时修正,只叠加到 energy 轴,
valence/dominance 原样保留——同 issue #94 的 _apply_interaction_polarity
"快层只写一个轴"先例,只是从写时挪到读时,彻底不新增 update_fast_state 调用
源)。

四个消费点全部改走这个新 helper:gate_pipeline.py(affective_state 缺省时
的默认读取分支,Drive Tick/即刻追问因此也受益)、runtime_loop.py 两处(打字
节奏、mood_congruence 召回打分)、entry_reactive.py(已读延迟窗)。

归属边界补了 AST 扫描守卫(read_delay.py 不 import datetime、不出现任何
X.now()/X.utcnow() 形态的调用),以及四个消费点各自的接线回归测试(变异
测试逐一验证过:删掉任何一处的新读法,测试都会红)。
issue #124 两轴 review 5 项发现,全部确认并修正:

1. [HIGH] /why_query 是 get_effective_fast_state 的第5个未接线消费点,仍
   直接读 storage 原始值——展示的默认坐标与真实召回排序脱节。entry_admin.py
   改走 get_effective_fast_state,新增排序翻转回归测试锁定。

2. [MEDIUM standards] 3 个新昼夜节律参数只被 RuntimeLoop 一个方法读,按
   issue #105 既有标准应收进 RuntimeLoopConfig 而非留作独立构造参数。
   重构 runtime_loop.py/loop_factory.py/runtime_loop_helpers.py 三处。

3. [LOW standards / MEDIUM spec] AST 归属边界守卫只挡了 datetime 模块,
   漏了 time.time() 等价读钟方式。扩展 test_read_delay.py 的守卫覆盖
   datetime+time 两个模块。

4. [MEDIUM spec] get_effective_fast_state 文档声称"决策快照全覆盖"过度
   宽泛,忽略了 Callback 送回路径(ADR-0029 定死的真无门控路径)的合法
   例外。收窄措辞,明确该函数只对"经过门控"的路径生效。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Yushu merged commit 6fada5644d into main 2026-08-13 08:27:37 +00:00
Yushu deleted branch feat/124-circadian-energy-nudge 2026-08-13 08:27:38 +00:00
Sign in to join this conversation.
No description provided.