relations补回指消解——ADR-0016遗漏的第四个写入目标(issue #146) #148

Merged
Yushu merged 1 commit from feat/146-relations-anaphora-resolution into main 2026-08-17 08:41:02 +00:00
Member

Closes #146

做了什么

relations 补回指消解(resolved_subject),补齐 ADR-0016 遗漏的第四个写入目标——facts/events/relations 三类写入目标现已全部覆盖(knowledge 按 ADR-0016 决策节明确不加,措辞多是群共享概念、回指模糊影响面小)。

  • _EXTRACT_MEMORIES_TOOLrelations 候选:user_a_id/user_b_id 类型放宽为 ["string", "null"](同 facts 的 scope_id 先例),新增 resolved_subject_a/resolved_subject_b 两个独立出口(issue #144 拍板:"两个独立 resolved_subject,不是一个"——关系边有两个主体位,不能照搬 facts/events 单一字段的形状),required 去掉两个结构化字段,只留 ["label", "sensitive"]
  • _resolve_subject 泛化成接受 field 关键字参数(缺省值不变),facts/events 现有调用点零改动,relations 侧分别用 field="resolved_subject_a"/"resolved_subject_b" 复用同一条校验。
  • _parse_relation:两个主体位各自 fallback-only 仲裁(结构化值合法时不读对应 resolved_subject_*,不覆盖已给出的判断),任一侧最终未解析则整条候选丢弃(比照画像更新的失败处理,不比照事件记忆的部分填——关系边需要两个具体端点才构成一条可查询的边)。user_a_id == user_b_id 的防御性检查放在合并后的最终 id 上,覆盖"一侧结构化点名、另一侧代词消解到同一人"这种只有合并后才会暴露的重复。
  • 顺手补齐 _build_promptinstruction 字符串里此前完全缺失的 relations= 抽取指导文本(相邻缺口)。

文档

发现 ADR-0016 应该已有一个 issue #144 的决策更新节(issue #146 工单正文逐字引用了它),但当前 docs 分支上找不到——怀疑是已知的"docs 分支本地提交丢失"问题丢掉的两个提交之一。据工单正文的逐字引用回填了这个决策节点,紧接着补了 issue #146 的落地记录,合并成一个更新节;同时订正了 CONTEXT.md/design.md 里 issue #137 遗留的"relations 同样不在本轮范围"过时表述。

验证

  • 新增测试:test_delta_compressor.py::TestResolvedSubjectRelationsFallback(两侧都结构化/一侧结构化一侧消解/一侧消解不了丢弃/两侧都消解不了丢弃/合并后 A==B 防御性丢弃,共 7 条,两侧对称覆盖)、test_delta_compression_cycle.py::TestRelationResolvedSubjectFlowsThroughToStorage(端到端落库,resolved_subject_a/_b 两侧对称各一条)。
  • "合并后 A==B 丢弃"是防空转设计:用"先合并再比较"的正确实现才会通过、"先比较原始字段再合并"的错误实现会误判成端点不同而放行——已用 mutation 实测验证过区分度。
  • 变异测试 4/4:A 侧/B 侧回指消解分别禁用、仲裁反转(覆盖而非 fallback)、身份检查改回比较原始字段——均被对应测试捕获。
  • 全量测试 1887 passed,ruff 通过,ty 与既有基线一致(47 条,均非本片改动文件)。
  • 两轴 review(Standards + Spec,sonnet,含对抗式 Verify):5 条发现,4 条 CONFIRMED 并已修复(新测试类漏标 @pytest.mark.asynciouser_b_id 侧"不被覆盖"测试与 resolved_subject_a 端到端落库测试均缺对称覆盖,已补齐;user_a_id/user_b_id 的 schema description 相比 facts.scope_id 模板漏了"对方自述"例子与代词举例,已补齐),1 条 REFUTED("A/B 两侧 fallback 逻辑重复应收进共用 helper"——核实后确认这是 _resolve_subject 文档字符串本身描述、认可的"两个独立主体位各自 fallback"设计,不构成违反)。

不做的事(按 AC)

不记录决策快照//why 因回指模糊丢弃了几条 relations 候选(ADR-0016 已把这类观测性需求留给实现期按需加,本票不强制);relations 以外任何字段/机制不动。

Closes #146 ## 做了什么 给 `relations` 补回指消解(`resolved_subject`),补齐 ADR-0016 遗漏的第四个写入目标——facts/events/relations 三类写入目标现已全部覆盖(`knowledge` 按 ADR-0016 决策节明确不加,措辞多是群共享概念、回指模糊影响面小)。 - `_EXTRACT_MEMORIES_TOOL` 的 `relations` 候选:`user_a_id`/`user_b_id` 类型放宽为 `["string", "null"]`(同 facts 的 `scope_id` 先例),新增 `resolved_subject_a`/`resolved_subject_b` 两个独立出口(issue #144 拍板:"两个独立 `resolved_subject`,不是一个"——关系边有两个主体位,不能照搬 facts/events 单一字段的形状),`required` 去掉两个结构化字段,只留 `["label", "sensitive"]`。 - `_resolve_subject` 泛化成接受 `field` 关键字参数(缺省值不变),facts/events 现有调用点零改动,relations 侧分别用 `field="resolved_subject_a"`/`"resolved_subject_b"` 复用同一条校验。 - `_parse_relation`:两个主体位各自 fallback-only 仲裁(结构化值合法时不读对应 `resolved_subject_*`,不覆盖已给出的判断),任一侧最终未解析则整条候选丢弃(比照画像更新的失败处理,不比照事件记忆的部分填——关系边需要两个具体端点才构成一条可查询的边)。`user_a_id == user_b_id` 的防御性检查放在**合并后的最终 id** 上,覆盖"一侧结构化点名、另一侧代词消解到同一人"这种只有合并后才会暴露的重复。 - 顺手补齐 `_build_prompt` 的 `instruction` 字符串里此前完全缺失的 `relations=` 抽取指导文本(相邻缺口)。 ## 文档 发现 ADR-0016 应该已有一个 issue #144 的决策更新节(issue #146 工单正文逐字引用了它),但当前 `docs` 分支上找不到——怀疑是已知的"docs 分支本地提交丢失"问题丢掉的两个提交之一。据工单正文的逐字引用回填了这个决策节点,紧接着补了 issue #146 的落地记录,合并成一个更新节;同时订正了 `CONTEXT.md`/`design.md` 里 issue #137 遗留的"relations 同样不在本轮范围"过时表述。 ## 验证 - 新增测试:`test_delta_compressor.py::TestResolvedSubjectRelationsFallback`(两侧都结构化/一侧结构化一侧消解/一侧消解不了丢弃/两侧都消解不了丢弃/合并后 A==B 防御性丢弃,共 7 条,两侧对称覆盖)、`test_delta_compression_cycle.py::TestRelationResolvedSubjectFlowsThroughToStorage`(端到端落库,`resolved_subject_a`/`_b` 两侧对称各一条)。 - "合并后 A==B 丢弃"是防空转设计:用"先合并再比较"的正确实现才会通过、"先比较原始字段再合并"的错误实现会误判成端点不同而放行——已用 mutation 实测验证过区分度。 - 变异测试 4/4:A 侧/B 侧回指消解分别禁用、仲裁反转(覆盖而非 fallback)、身份检查改回比较原始字段——均被对应测试捕获。 - 全量测试 1887 passed,ruff 通过,ty 与既有基线一致(47 条,均非本片改动文件)。 - 两轴 review(Standards + Spec,sonnet,含对抗式 Verify):5 条发现,4 条 CONFIRMED 并已修复(新测试类漏标 `@pytest.mark.asyncio`;`user_b_id` 侧"不被覆盖"测试与 `resolved_subject_a` 端到端落库测试均缺对称覆盖,已补齐;`user_a_id`/`user_b_id` 的 schema description 相比 `facts.scope_id` 模板漏了"对方自述"例子与代词举例,已补齐),1 条 REFUTED("A/B 两侧 fallback 逻辑重复应收进共用 helper"——核实后确认这是 `_resolve_subject` 文档字符串本身描述、认可的"两个独立主体位各自 fallback"设计,不构成违反)。 ## 不做的事(按 AC) 不记录决策快照/`/why` 因回指模糊丢弃了几条 relations 候选(ADR-0016 已把这类观测性需求留给实现期按需加,本票不强制);`relations` 以外任何字段/机制不动。
_EXTRACT_MEMORIES_TOOL的relations候选加resolved_subject_a/_b两个独立
出口(user_a_id/user_b_id各配一个fallback,issue #144拍板:"两个独立
resolved_subject,不是一个"),_resolve_subject泛化成接受字段名参数,
facts/events现有调用点零改动。_parse_relation两侧各自fallback-only
仲裁,任一侧未解析整条丢弃;user_a_id==user_b_id防御性检查放在合并后
的最终id上,覆盖"一侧结构化点名、另一侧代词消解到同一人"这种合并后才
暴露的重复。顺手补齐_build_prompt里此前完全缺失的relations=抽取指导。

两轴review发现4条并已修复:新测试类漏了@pytest.mark.asyncio装饰器;
user_b_id侧、resolved_subject_a端到端落库两处测试覆盖不对称(补齐);
user_a_id/user_b_id的schema description相比facts.scope_id模板漏了
"对方自述"例子与代词举例(补齐)。
Yushu merged commit 1799d1e383 into main 2026-08-17 08:41:02 +00:00
Yushu deleted branch feat/146-relations-anaphora-resolution 2026-08-17 08:41:03 +00:00
Sign in to join this conversation.
No description provided.