关系网注入分档恢复 + lookup_relation按需工具 + 独立封顶 #119

Merged
Yushu merged 2 commits from feat/114-relationship-injection-tiers-and-cap into main 2026-08-12 03:23:37 +00:00
Member

Closes #114

做了什么

一、恢复注入分档

  • 摘除 _full_frozen_snapshot/_run_event_driven_turn 两处每轮自动查询隐式同群/同事件共现——2026-07-13 那次"修复漏实现"更新把 ADR-0008 原定的"按需"档误做成了"每轮自动",诊断出 _run_event_driven_turn 那个调用点当时就已经是空转(sender_ids 至多 1 个 id)。
  • gather_implicit_relations 已无生产调用方,直接删除;render_relationship_snapshotimplicit_pairs 参数与 implicit_lines 渲染段同步删除。
  • 新建 core 原生工具 lookup_relation(user_a_id, user_b_id):恢复"同群按需"这一档,不经工具港、计入 run_limit、恒可见(不受能力位/渐进解锁门控)。知情-gate(is_relationship_edge_visible)同样接入——主动工具调用不能绕过被动注入已经守住的敏感数据闸,命中但不可见时退回隐式判断而非报错/泄漏。
  • 显式边 + 同事件共现保持自动,gather_relationship_edges 拉取逻辑本身一行未改。

二、独立封顶

  • 新增静态 config arise_max_relationship_lines_per_turn(默认 10),只接在 render_relationship_snapshot——在知情-gate 过滤之后截断显式边渲染行数。

两轴 review 抓到的一处真实 bug(已修复)

最初实现里 gather_relationship_edges 也独立截断了一次(同一个 limit),但它不知道 current_chat_id,没有能力过滤可见性——两层截断复合后,一条对当前 chat 不可见的边可能在 gather 层就抢占了截断名额,导致最终渲染的可见边数少于上限,即便系统里还有更多真正可见的边。这正是"独立封顶"这条 AC 本身警告过要避免的不确定性("封顶多少条取决于恰好有多少条不可见"),只是发生在 gather 层而不是最初以为的 render 层。

修复:截断只在 render_relationship_snapshot 一处进行(唯一知道可见性的地方),gather_relationship_edges 只负责拉取+去重。新增端到端测试 test_invisible_edges_do_not_steal_the_cap_from_visible_ones 复现并钉住这个场景——只有跑完整 gather→render 流水线才能抓到,单独测任一函数都测不出。

其余 3 处修复:_handle_lookup_relation docstring 误称与自动路径"共用存储读取"(实际是不同存储方法);两处弱断言 != "同事" 改成精确 ==user_a_id/user_b_id 的类型校验从静默 str() 强转改成 isinstance 显式拒绝非字符串,同 _sanitized_query_arg/_handle_update_profile 既有模式。

测试

  • 全量测试 1588 passed,ruff 干净。
  • 对新增守卫(知情-gate 过滤、自查/空参/非字符串类型校验、封顶截断顺序、复合截断场景)均做过变异测试验证。
  • 经两轴 review(Standards + Spec,sonnet)+ 对抗性复核,4 处发现全部修复。

Test plan

  • uv run pytest 全量通过
  • uv run ruff check 干净
  • 变异测试验证所有新守卫(含修复后的复合截断场景)
  • 两轴 review + 对抗性复核,发现均已修复
  • ADR-0008 更新节已在 docs 分支本地提交(不推送)
Closes #114 ## 做了什么 **一、恢复注入分档** - 摘除 `_full_frozen_snapshot`/`_run_event_driven_turn` 两处每轮自动查询隐式同群/同事件共现——2026-07-13 那次"修复漏实现"更新把 ADR-0008 原定的"按需"档误做成了"每轮自动",诊断出 `_run_event_driven_turn` 那个调用点当时就已经是空转(`sender_ids` 至多 1 个 id)。 - `gather_implicit_relations` 已无生产调用方,直接删除;`render_relationship_snapshot` 的 `implicit_pairs` 参数与 `implicit_lines` 渲染段同步删除。 - 新建 core 原生工具 `lookup_relation(user_a_id, user_b_id)`:恢复"同群按需"这一档,不经工具港、计入 `run_limit`、恒可见(不受能力位/渐进解锁门控)。知情-gate(`is_relationship_edge_visible`)同样接入——主动工具调用不能绕过被动注入已经守住的敏感数据闸,命中但不可见时退回隐式判断而非报错/泄漏。 - 显式边 + 同事件共现保持自动,`gather_relationship_edges` 拉取逻辑本身一行未改。 **二、独立封顶** - 新增静态 config `arise_max_relationship_lines_per_turn`(默认 10),只接在 `render_relationship_snapshot`——**在知情-gate 过滤之后**截断显式边渲染行数。 ## 两轴 review 抓到的一处真实 bug(已修复) 最初实现里 `gather_relationship_edges` 也独立截断了一次(同一个 limit),但它不知道 `current_chat_id`,没有能力过滤可见性——两层截断复合后,一条对当前 chat 不可见的边可能在 gather 层就抢占了截断名额,导致最终渲染的可见边数少于上限,即便系统里还有更多真正可见的边。这正是"独立封顶"这条 AC 本身警告过要避免的不确定性("封顶多少条取决于恰好有多少条不可见"),只是发生在 gather 层而不是最初以为的 render 层。 修复:截断只在 `render_relationship_snapshot` 一处进行(唯一知道可见性的地方),`gather_relationship_edges` 只负责拉取+去重。新增端到端测试 `test_invisible_edges_do_not_steal_the_cap_from_visible_ones` 复现并钉住这个场景——只有跑完整 gather→render 流水线才能抓到,单独测任一函数都测不出。 其余 3 处修复:`_handle_lookup_relation` docstring 误称与自动路径"共用存储读取"(实际是不同存储方法);两处弱断言 `!= "同事"` 改成精确 `==`;`user_a_id`/`user_b_id` 的类型校验从静默 `str()` 强转改成 `isinstance` 显式拒绝非字符串,同 `_sanitized_query_arg`/`_handle_update_profile` 既有模式。 ## 测试 - 全量测试 1588 passed,ruff 干净。 - 对新增守卫(知情-gate 过滤、自查/空参/非字符串类型校验、封顶截断顺序、复合截断场景)均做过变异测试验证。 - 经两轴 review(Standards + Spec,sonnet)+ 对抗性复核,4 处发现全部修复。 ## Test plan - [x] `uv run pytest` 全量通过 - [x] `uv run ruff check` 干净 - [x] 变异测试验证所有新守卫(含修复后的复合截断场景) - [x] 两轴 review + 对抗性复核,发现均已修复 - [x] ADR-0008 更新节已在 `docs` 分支本地提交(不推送)
摘除_full_frozen_snapshot/_run_event_driven_turn两处每轮自动查询隐式
同群/同事件共现(2026-07-13那次实现反馈误把ADR-0008原定的"按需"档做成
了自动,见ADR-0008更新节);新建core原生工具lookup_relation复用同一套
lookup_relation/get_known_chat_ids存储读取,恒可见、计入run_limit、套
知情-gate;gather_relationship_edges/render_relationship_snapshot显式边
拉取与渲染接上arise_max_relationship_lines_per_turn上限,封顶在知情-gate
过滤之后生效。
最严重的一处:gather_relationship_edges 与 render_relationship_snapshot
此前各自独立截断到同一个 limit,前者不知道 current_chat_id、没有能力
过滤可见性,两层复合会让不可见边抢占截断名额——这正是"独立封顶"这条 AC
本身警告过要避免的不确定性,只是发生在 gather 层而非 render 层。改为
只在 render_relationship_snapshot 一处截断(唯一知道可见性的地方),
gather_relationship_edges 只负责拉取+去重。新增端到端测试复现并钉住这个
composed-truncation场景。

其余三处:_handle_lookup_relation docstring 误称与自动路径"共用存储读取"
(实际是不同方法);两处弱断言 `!= "同事"` 改成精确 `==`;user_a_id/
user_b_id 的类型校验从静默 str() 强转改成 isinstance 显式拒绝非字符串,
同 _sanitized_query_arg/_handle_update_profile 既有模式。
Yushu merged commit e2a709aa3a into main 2026-08-12 03:23:37 +00:00
Yushu deleted branch feat/114-relationship-injection-tiers-and-cap 2026-08-12 03:23:38 +00:00
Sign in to join this conversation.
No description provided.