冷启动渐进解锁三件套:gate连续缩放+三因子召回闸+冷启动自我介绍 #118

Merged
Yushu merged 2 commits from feat/112-cold-start-unlock-trio into main 2026-08-12 01:56:13 +00:00
Member

Closes #112

做了什么

  • 沉默预算连续缩放gating.progressive_unlock_scale 让沉默预算 capacity/refill_rate 随渐进解锁档位(unlock_level)连续单调收紧,level=0 时取 arise_progressive_unlock_gate_scale_floor(默认 0.3),level→1 趋于不收紧。与既有离散 apply_cold_start_floor(事件触发保底 ≥1)同时生效、互不冲突。
  • 三因子召回补闸:新增 RECALL_UNLOCK_THRESHOLD=0.25,接入三个入口——RuntimeLoop._recall_events(同时覆盖 _full_frozen_snapshot/_run_event_driven_turn)与 search_memory 工具的 schema 可见性(同 note_pending_intent 既有先例,不在 handler 内部二次防御)。此前这一级被实现期当成恒解锁,progressive_unlock.py 自己的 docstring 都写着"(已解锁)"。
  • 冷启动声明性文本render_cold_start_notice() 挂进 _full_frozen_snapshot,纯陈述不下指令(同 render_time_since_last_interaction 既有形状)。Drive Tick 的 assemble_light_context 显式不带这段文本——ADR-0007 原文把"可做轻量自我介绍"绑在"被@"语义上,Drive Tick 从不是被@触发。
  • 决策快照:新增 recall_gated_by_unlock 字段,区分"未解锁没跑"与"跑了没匹配"两种"没有记忆",/why 据此给出不同解释。

一处偏离 AC 字面要求(已与用户 grill,写进 ADR)

AC 原文还要求门控阈值基值(gate_threshold_base)也随 unlock_level 缩放。实现期发现这个消费者集合为空——事件触发的级一打分恒为无穷大,缩放对它零效果;tier-2 环境信号的显式打分已经受 ADR-0014"晚解锁"专职把关(is_relationship_network_unlocked,档位 0.4),再叠一层缩放会撞上该 ADR"拒绝了"节明确回绝过的"与既有门控双重裁决打架"——实测在档位刚过 0.4 时缩放系数仅约 0.58,足以让 tier-2 唯一的显著性满分场景(无熟悉度加成)永远打不过阈值。按 YAGNI 未落地,详见 ADR-0007/0011/0014 更新节(docs 分支,本地提交未推送,见下)。

测试

  • 全量测试 1578 passed,ruff 干净。
  • 对所有新守卫(召回闸、schema 可见性、冷启动文本、缩放单调性、5 处调用点接线)做过变异测试验证——特别是发现并补上了 is_cold_startentry_reactive.py 的接线此前完全没有 e2e 覆盖(make_loop 默认值会掩盖接线错误),已在 test_progressive_unlock_e2e.py 补上。
  • 经两轴 review(Standards + Spec,sonnet)+ 对抗性复核,3 处发现均已修复:过期 docstring(config.py)、/why 措辞在 [0.15, 0.25) 区间不成立、参数名与既有离散 floor 撞名。

Test plan

  • uv run pytest 全量通过
  • uv run ruff check 干净
  • 变异测试验证召回闸/schema可见性/冷启动文本三处新守卫
  • 两轴 review + 对抗性复核,发现均已修复
  • ADR-0007/0011/0014/0031 更新节已在 docs 分支本地提交(不推送)
Closes #112 ## 做了什么 - **沉默预算连续缩放**:`gating.progressive_unlock_scale` 让沉默预算 capacity/refill_rate 随渐进解锁档位(`unlock_level`)连续单调收紧,`level=0` 时取 `arise_progressive_unlock_gate_scale_floor`(默认 0.3),`level→1` 趋于不收紧。与既有离散 `apply_cold_start_floor`(事件触发保底 ≥1)同时生效、互不冲突。 - **三因子召回补闸**:新增 `RECALL_UNLOCK_THRESHOLD=0.25`,接入三个入口——`RuntimeLoop._recall_events`(同时覆盖 `_full_frozen_snapshot`/`_run_event_driven_turn`)与 `search_memory` 工具的 schema 可见性(同 `note_pending_intent` 既有先例,不在 handler 内部二次防御)。此前这一级被实现期当成恒解锁,`progressive_unlock.py` 自己的 docstring 都写着"(已解锁)"。 - **冷启动声明性文本**:`render_cold_start_notice()` 挂进 `_full_frozen_snapshot`,纯陈述不下指令(同 `render_time_since_last_interaction` 既有形状)。Drive Tick 的 `assemble_light_context` **显式不带**这段文本——ADR-0007 原文把"可做轻量自我介绍"绑在"被@"语义上,Drive Tick 从不是被@触发。 - **决策快照**:新增 `recall_gated_by_unlock` 字段,区分"未解锁没跑"与"跑了没匹配"两种"没有记忆",`/why` 据此给出不同解释。 ## 一处偏离 AC 字面要求(已与用户 grill,写进 ADR) AC 原文还要求门控阈值基值(`gate_threshold_base`)也随 `unlock_level` 缩放。实现期发现这个消费者集合为空——事件触发的级一打分恒为无穷大,缩放对它零效果;tier-2 环境信号的显式打分已经受 ADR-0014"晚解锁"专职把关(`is_relationship_network_unlocked`,档位 0.4),再叠一层缩放会撞上该 ADR"拒绝了"节明确回绝过的"与既有门控双重裁决打架"——实测在档位刚过 0.4 时缩放系数仅约 0.58,足以让 tier-2 唯一的显著性满分场景(无熟悉度加成)永远打不过阈值。按 YAGNI 未落地,详见 ADR-0007/0011/0014 更新节(`docs` 分支,本地提交未推送,见下)。 ## 测试 - 全量测试 1578 passed,ruff 干净。 - 对所有新守卫(召回闸、schema 可见性、冷启动文本、缩放单调性、5 处调用点接线)做过变异测试验证——特别是发现并补上了 `is_cold_start` 在 `entry_reactive.py` 的接线此前完全没有 e2e 覆盖(`make_loop` 默认值会掩盖接线错误),已在 `test_progressive_unlock_e2e.py` 补上。 - 经两轴 review(Standards + Spec,sonnet)+ 对抗性复核,3 处发现均已修复:过期 docstring(`config.py`)、`/why` 措辞在 `[0.15, 0.25)` 区间不成立、参数名与既有离散 floor 撞名。 ## Test plan - [x] `uv run pytest` 全量通过 - [x] `uv run ruff check` 干净 - [x] 变异测试验证召回闸/schema可见性/冷启动文本三处新守卫 - [x] 两轴 review + 对抗性复核,发现均已修复 - [x] ADR-0007/0011/0014/0031 更新节已在 `docs` 分支本地提交(不推送)
沉默预算容量/回填速率随渐进解锁档位连续缩放;三因子召回补一道解锁闸
(三个入口:全量冻结快照/事件驱动轮次/search_memory 工具可见性);
冷启动声明性文本挂进全量冻结快照,Drive Tick 轻上下文显式排除。

实现期 grill 后推翻了 AC 原文里"门控阈值基值也随档位缩放"这一项——
消费者集合为空(事件触发无穷大分数免疫、tier-2 已有自己的解锁门槛),
按 YAGNI 未落地,理由见 ADR-0011/0014 更新节。
config.py 的 arise_progressive_unlock_gate_scale_floor docstring 仍写着
"门控阈值基值除以这个数",是被推翻方案的残留文本,与实际实现(只缩放预算
容量/回填速率)矛盾;explain.py 的召回闸解释文案借用"冷启动期"这个有精确
定义的术语,在 [0.15, 0.25) 区间会说一句不成立的话;gating.py/gate_pipeline.py
的 cold_start_scale_floor 参数名与既有的离散冷启动下限 budget_cold_start_floor
撞名,模糊了模块文档反复强调的"离散 floor vs 连续 scale 是两个维度"这条区分,
改名 unlock_scale_floor。
Yushu merged commit d9c6ea7c60 into main 2026-08-12 01:56:13 +00:00
Yushu deleted branch feat/112-cold-start-unlock-trio 2026-08-12 01:56:14 +00:00
Sign in to join this conversation.
No description provided.