Skip to content

[feature] distill_records 只有写入路径:给「这条记忆是哪次蒸馏带进来的」一个读出口 #421

Closed

Description

@modusensus

要解决的问题

PR #417 按 #399 的约定把蒸馏窗口的原始记录落进了 distill_records,并把 memory → (session_id, seq_start, seq_end) 的归因写进 memory_provenance。但那次只做了写:没有任何读路径 —— 面板不显示、API 没有端点、service 没有查询方法。结果是这批数据只进不出:它占了库、进了回收面,却没人能看见。

具体场景:一条记忆的来源可疑(内容与原文对不上,或需要确认它到底是从哪几句里蒸出来的),现在唯一的办法是直接开 sqlite 手写 JOIN。而 #399 里「我们测不出自己丢了多少」这个目标,恰恰要靠读出口才成立。

期望的方案

给一个最小读出口,两个方向:

  1. 按记忆看窗口:给定 memory_id,返回它在 memory_provenance 里的区间 [(session_id, seq_start, seq_end)],再按区间取出 distill_records 的原文行。
  2. 按会话看窗口:给定 session_id,列出该会话所有已留存的窗口(按 seq 升序)。

形态上倾向先走 GET /api/dsh-mneme/memory/provenance?memoryId=(面板与外部 API 同一份实现);面板侧挂在哪里由维护者定。distillRecords.enabled=false 时回 409 distill-records-disabled,依附既有开关、不新增开关。(2026-10-29 更正:本句原文是「按既有习惯返回空或 404」。#509 里 z2Ace0107 指出 404 不成立——本端点设计成永远不出 404(缺 id 是 400、未知 id 是 200 + 空 windows,读端点不替调用方判断记忆是否存在),而状态码是唯一被代理/监控/重试逻辑读取的通道,把「功能关了」写成 404 等于让它读成「这条记忆不存在」。仓里同型先例是 src/api.js:525-526:409 disabled(用户没开)与 503 unavailable(装配缺失)必须是两个可区分的答案,src/index.js:589-591 把这句话写死在注释里。判断归我,原文措辞留在这里以免读者以为规格一直是这样。)上面两条是形态建议,不是实现要求。

考虑过的替代方案

实现口径确认 / Implementation gates

  • 新行为开关 opt-in 默认关(本提案依附既有 distillRecords.enabled,不新增开关)
  • 无 schema 变更(只读既有两张表,无需迁移)
  • 接受带回归测试的验收线

披露 / Disclosure

  • 本提案由 AI 辅助整理(人工审核后提交)

Activity

  1. modusensus commented on Oct 20, 2026

    @modusensus
    MemberAuthor

    现状(2026-10-21 对照 main 实测)

    读方法已经有了,但没有 HTTP 出口——差最后一段接线。

    所以现在「这条记忆是哪次蒸馏带进来的」在库里有答案、在代码里能查,但外部(面板、standalone API、脚本)拿不到。

    还缺什么

    1. 在 api.js 与 api-standalone.js 各加一条只读路由(建议 GET /api/dsh-mneme/memory/provenance?id=<id>),响应至少含 distill_run_id / run_type / created_at / trigger_source;
    2. 面板侧「记忆详情」加一行来源(可折叠,不占主视觉);
    3. 加一条契约用例:对一条 dream 写入的记忆断言 distill_run_id 非空,对一条 memory_save 写入的断言为 null(而不是报错)。

    接手建议

    这是纯出口的活:service.js 不用改,只加路由 + 面板一行。没有设计分歧,可以直接提 PR。

  2. z2Ace0107 commented on Oct 23, 2026

    @z2Ace0107
    Contributor

    想接这条。计划分两步,先做后端:

    1. src/api.js 与 src/api-standalone.js 各加一条只读路由 GET .../memory/provenance?id=<id>,响应含 distill_run_id / run_type / created_at / trigger_source。service.js 不用改——provenanceFor 已经在 :2600;
    2. 补契约用例:对一条 dream 写入的记忆断言 distill_run_id 非空,对 memory_save 写入的断言为 null(而不是报错)。

    distillRecords.enabled=false 时按既有习惯返回空,不新增开关。

    面板「记忆详情」那一行我想先不动——lib/client.js 是单写者资源,我不想和面板线撞车。如果你希望一起做,我可以在 PR 里留好位置,等你安排面板侧写入者时再补。

    我同时认了 #461 和 #383,按由易到难串行做(#461 → #383 → #421),两周内都交 PR。

  3. modusensus commented on Oct 29, 2026

    @modusensus
    MemberAuthor

    方向 1 已由 #509 落地并合入 main(6a05618):GET /api/dsh-mneme/memory/provenance?memoryId=,两张皮共用同一份 src/provenance-http.js,状态码阶梯 401 → 400 缺 id → 409 distill-records-disabled → 503 provenance-unavailable → 200,依附既有 distillRecords.enabled、不新增开关,判据与写侧 src/summarize.js:988 逐字同源并有静态锁。实现与其中最主要的判断(409 而非 404)由 @z2Ace0107 在 #509 完成。

    本条正文那句「按既有习惯返回空或 404」已按 #509 的论证原地更正为 409,原措辞留在括号里,读者能看到规格是怎么走到这一步的。

    方向 2(按 session_id 列那一会话的窗口)拆到 #524 —— issue 当时写明那是形态建议不是实现要求,所以本条按「方向 1 已交付」关闭,不把没做的格子算成已兑现。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions