modusensus / modusensus/dsh-mneme

[Bug] memory_get 输出 schema 漏声明 scope 来源列:命中任何被标注的行必然报 invalid output(0.8.1)

Closed
#184 1 comment 0 reactions 1 assignee Claimed by @modusensus View on GitHub
bug
Dominant language
JavaScript
Stars
100
Forks
11
Avg merge
1h 17m
Merged PRs (30d)
124

Description

## 环境

- dsh-mneme **0.8.1**(`npm view @modusensus/dsh-mneme version` → `0.8.1`,无已修复版本)
- 宿主:dsh Web profile(`~/.dsh/profiles/web`),Windows + node v24.14.1
- 记忆库规模:13243 行,其中 **6 行**带 scope 标注

## 现象

`memory_get` 对**任意被 scope 标注过的记忆 id** 返回:

```
tool "memory_get" returned invalid output: "value.memory.agent_scope_source" is not a declared property (additionalProperties: false); "value.memory.workspace_scope_source" is not a declared property (additionalProperties: false)
```

未被标注的 id 正常返回,所以外部表现为「个别 id 必失败、多数 id 正常」,容易被当成偶发问题。

## 复现

1. 在开启 scope 自动标注(`scopeEnabled`)的会话里写一条记忆 → 该行落 `agent_scope_source='auto'` / `workspace_scope_source='auto'`;
2. `memory_get(id=<该行 id>)` → 上报表错;
3. 对照:`memory_search` / `memory_list` 对同一行正常,`memory_update` / `memory_forget` / `memory_archive` 也正常。

本机实测(同一 DB):

| 调用 | 该行标注 | 结果 |
| --- | --- | --- |
| `memory_get 9cf1081a-…` | 无 | 正常返回 |
| `memory_get 5f954bb7-…` | `auto` | 报错 |
| `memory_get 07ae6f40-…` | `auto` | 报错 |
| 写入新记忆后立刻 `memory_get` 自己 | `auto` | 报错 |

即:**在开启标注的会话里,每写一条新记忆就多一条 `memory_get` 读不回来的行。**

SQL 口径:

```sql
SELECT COUNT(*) FROM memories
WHERE agent_scope_source IS NOT NULL OR workspace_scope_source IS NOT NULL; -- 6 / 13243
```

## 根因(代码证据)

三处拼起来即构成缺陷,且**只**在 `memory_get` 上成立:

1. **返回体会带这两个键** —— `lib/service.js:1489-1495`,`toApiList()` 条件展开:

```js
...(m.agent_scope_source !== undefined ? { agent_scope_source: m.agent_scope_source } : {}),
...(m.workspace_scope_source !== undefined ? { workspace_scope_source: m.workspace_scope_source } : {}),
...(m.scope_decided_at !== undefined ? { scope_decided_at: m.scope_decided_at } : {}),
```

2. **`memory_get` 的 output schema 没声明它们** —— `lib/tools.js:275-300`(`memory` 对象 properties 只到 `agent_scope` / `workspace_scope`),而 `additionalProperties: false`(`lib/tools.js:282`)→ 校验直接拒绝。共缺 3 个键:`agent_scope_source`、`workspace_scope_source`、`scope_decided_at`。

3. **为什么只命中少数行** —— `lib/store.js:400-402` 把列 `NULL` 映射为 `undefined`,条件展开后不带键;只有被标注过的行才带键。

同族工具为什么不炸:`memory_search` / `memory_list` 共用 `MEMORY_ITEM_SCHEMA`(`lib/tools.js:18-41`,其 **33-35 行已声明这三个键**);`memory_update` / `memory_forget` / `memory_archive` 返回的是手挑的小对象。`src/tools.js:269-305` 与 lib 同步缺失(lib 由 `scripts/sync-lib.js` 从 src 生成)。

推测引入点:这条路径来自 #171(per-dim 来源列)—— 加列时只更新了共享的 `MEMORY_ITEM_SCHEMA`,漏掉了 `memory_get` 的内联 schema。`test/tools.test.js` 里也没有「DTO 键集 ⊆ 各工具 output schema 声明键集」这类断言,所以 CI 没拦住。

## 影响

- 功能面:`memory_get` 对被标注行完全不可用(当前 6/13243,但会随会话持续增长)。
- 数据面:无损坏、无写入失败,仅读取被输出 schema 校验拦下。

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.