Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@

## 📰 最近更新

**v0.14.0-beta.3 — 情绪页白屏修好了,档位被冻结覆盖也说得明白了**(2026-11-12,预发布)
**v0.14.0 — 图像与情绪都成了记忆,召回也不再被窗口截断**(2026-11-12)

点开「情感」页整块面板变空白的回归修掉了。根因是一行 `formatRelativeTime(it.lastSeen)` 漏传 `t`,函数内部要拿它取文案,缺参就抛错;这行跑在 render 里,React 整棵树卸载,日志里什么都不留——所以看起来像「点了没反应」。`v0.14.0-beta.1` 与 `beta.2` 都带这个回归,只有库里存在带 `lastSeen` 的情绪边时才触发,因此不是每个人都会遇到。
另修一处「面板说的和实际做的不一致」:档位选 `off` 或 `shadow`、同时开着**矛盾冻结**时,判成矛盾的对会照旧停车进待审队列,档位选哪一档都不减少——而这条互斥关系此前只写在设置项提示语里,下拉旁边看不到。现在档位下方直接标一行「⚠ 冻结正在覆盖本档位」。判据与后端同源,不改默认值、不改语义;要停止新增仍须自己关掉矛盾冻结。
两件攒了很久的事落地。图像记忆不再停在「图变成一句文字躺在转录里」:新增 `image_sources` 溯源表,让蒸馏摘要能回指它来自哪张图,粒度是窗口级——无法证明「这张图只为第 3 条记忆贡献」,按行猜等于编造归因(`imageMemoryEnabled`,默认关)。情绪同理:单次场合(occasion)的情绪此前只写在库里、模型看不见,现在补上注入出口(`affectiveInjectEnabled`,默认关)。两个开关都默认关闭,关闭态的输出与改动前逐字节一致。
召回侧修掉两处**静默缺失**:词法索引的语料此前固定 500 行、注入候选池固定 200 行,掉出窗口的记忆不报错、不变慢,只是「有这条却搜不到」——实测 8 个查询里,500 行窗口与全量语料的 top10 只有 1–4 条重合;注入池合格 8421 条,8210 条永远进不了窗。现在语料改为全量取数 + 增量索引(重建成本随变化行数走,不再随语料规模走),候选池改为全量排序键 + 只对入选条目回表。另:后台 LLM 调用统一补上 `sessionId`,走 OpenCode 这类严格网关不再 400(#668)。

> 逐条见 [CHANGELOG](dsh-mneme/CHANGELOG.md) · 完整版本历史见 [Releases](https://github.com/slow-stack/mneme/releases)

Expand Down Expand Up @@ -289,6 +289,7 @@ dsh-mneme-serve # 默认 ~/.dsh/memory + 127.0.0.1:8790
| **v0.9** | M.O.(Modus Operandi)beta:项目级工作流本体 + 候选分层与升格判据 + 面板清单/图同屏;设置面板按「新手之外」重划折叠线(#427);安全审计与供应链加固(声明式路由鉴权、OSV 阻断、发布签名);**v0.9.1 补上写侧**:执行窗口、运行账、归属候选、观察旁挂与脱节检出、步骤 `assert`/`optional`、沉淀链草稿挖掘、人格定义页(按 agent 多卡);**v0.9.2 让看不见的失败显形**:功能开关第三态「待重启」、作用域级可逆闸门(#471)、巩固 `max_tokens` 超上限自动降级(#478);**v0.9.3 接通自动沉淀**:按会话头 `cwd` 反查项目桶、挂 `turn/end`、冷却 10 分钟、单次预算 4 秒,只产提议不产草稿(#489),并修作用域反查自 v0.8.0 起静默降级(#487)、`/nudge` 写盘口漏拦 `PATCH`/`DELETE`、多帧 zstd 反证断言绑 Node 整块解语义(#490);**v0.9.4 补上三条链的最后一环**:agent 主动整理接口有了工具(`memory_organize`,`organizeEnabled` 默认关,关时模型根本看不到它)、画像可以从记忆提取**草稿**(`profileExtractEnabled` 默认关,只出草稿、采用是用户再点一次,手写的原文不被模型改写)、人格 `default` 卡不再无条件进「没建卡」的身份(#497,`personaStrictAddressing` 默认关),面板那段「注入生效文本」改成由后端单源渲染,另补蒸馏转录围栏与解析失败护栏(#494);**v0.9.5 让记忆递得出去也收得回来**:分享包 `mneme.share/v1`(只含活跃行、scope 与 home 前缀不进包、密钥/PII 整条不进、报告先于下载、3 MiB 水位、一条不合格整包拒、干跑为默认、按 `share_external_id` 幂等、整包退出走物删),「本机巩固不改写别人导入的原文」由单一谓词守在汇流口与九个行池,记忆溯源读出口 `GET /memory/provenance`(@z2Ace0107,409 与 503 两种「没有」分开),并修同标题重复入库(#505)、模式扫描窗口饿死(#515)、五处 prompt 未围栏(#501/#493)与 dream 合并护栏整类误拦(#521),面板加设置页分组目录(#518) | ✅ 已发布(v0.9.5) |
| **v0.10** | 归因与闸门:蒸馏归因补上「运行」身份(`distill_runs` 窗口级 + `memory_mints` 行级,历史行不猜)、溯源补上反方向 `?sessionId=`、会话级无痕闸门(`sessionGateEnabled`,判据只认宿主委派标记 + 有界记账)、防谄媚补到写入面(蒸馏与总览的立场 / 叙述纪律)、`differentiate` 改落账本不改正文(#533)、sleep 冲突相位输入侧预算与续排(#529)、面板「最近巩固」区分 organize 回执(#495)、面板首次有移动端与 481–519px 中间带断点(#542) | ✅ 已发布(v0.10.0) |
| **v0.13** | 情绪终于有地方可放:「这一次很焦虑」与「你是个焦虑的人」在存储上不再一样——`affective_context` 关系类型带情绪词与归因;sleep 新增情感相位,按三个独立会话才升成稳定倾向,不足就降级不丢弃,降级与丢弃全部记账;同场合的边按会话合并而不是每轮重写。同版:日记本、M.O. 下架、面板几处修复 | ✅ 已发布(v0.13.0) |
| **v0.14** | 图像与情绪都成了记忆:图像描述有了溯源表(`image_sources`,摘要能回指来自哪张图),单次场合的情绪补上注入出口(`affectiveInjectEnabled`);召回侧修掉两处静默截断——词法语料 500 行、注入候选池 200 行,改成全量与增量;后台 LLM 调用统一补 `sessionId`,严格网关不再 400(#668) | ✅ 已发布(v0.14.0) |
| **v0.12** | pin 显式化(`pinned_memories` 表 + `memory_pin`(取消钉选传 `unpin: true`),钉住的行在注入里优先占位,不再靠类型推断;`pinnedInjectBudget` 默认 0 = pin 池关闭)+ pin 池不再被向量路 `poolSize` 封顶挤出 + 「Agent 眼中的你」自动事实(`profileFactsEnabled` 默认关)+ 向量解析缓存跟工作集自适应(命中率 0% → 100%,单轮检索快 5.6 倍,存储换 `Float32Array`)+ 修 #579 地志工具错误路径与「读不到答成没匹配」+ 修 #590 严格寻址把「一张卡都没建」判成「没有这张卡」 | ✅ 已发布(v0.12.0) |

> 完整逐小版本说明见 [CHANGELOG](dsh-mneme/CHANGELOG.md)。
Expand Down Expand Up @@ -336,10 +337,10 @@ dsh-mneme 的机制设计与下列公开研究相互印证(以下引用均逐

## 📰 Recent updates

**v0.14.0-beta.3 — the affective panel no longer goes blank, and an overridden tier now says so** (2026-11-12, pre-release)
**v0.14.0 — images and emotion both become memory, and recall stops hitting a window** (2026-11-12)

The regression that blanked the whole affective panel is fixed. One call to `formatRelativeTime(it.lastSeen)` was missing its `t` argument; the function reaches for that to look up a label, so it threw — and because the line runs inside render, React unmounted the entire tree and left nothing in the log. That is why it looked like "I clicked it and nothing happened". Both `v0.14.0-beta.1` and `beta.2` shipped this; it only triggers when the library holds an affective edge with `lastSeen`, so not every user hits it.
This release also fixes one case where the panel disagreed with behaviour: with the tier set to `off` or `shadow` and **conflict freeze** on, contradicting pairs still park in the pending queue no matter which tier is chosen — and that mutual exclusion was only documented in a settings hint, invisible from the dropdown itself. The tier row now shows "⚠ conflict freeze is overriding this tier". The condition is the same one the backend uses, defaults and semantics are untouched, and stopping new arrivals still requires turning conflict freeze off.
Two long-running threads land. Image memory no longer stops at "the picture became a sentence in the transcript": a new `image_sources` table lets a distilled summary point back to the picture it came from, at window granularity — you cannot prove "this image contributed only to memory #3", and guessing per row would be inventing attribution (`imageMemoryEnabled`, off by default). Same for emotion: one-off occasions were being written to the store but never reached the model, and now they have an injection path (`affectiveInjectEnabled`, off by default). Both flags default to off, and with them off the output is byte-for-byte what it was.
Recall loses two **silent** truncations: the lexical corpus was capped at 500 rows and the injection candidate pool at 200, and memories falling outside the window never errored, never got slower — they simply could not be found. Measured: across 8 queries the 500-row window shared only 1–4 of its top 10 with the full corpus, and of 8421 injection-eligible rows, 8210 could never enter the window. The corpus is now taken in full with an incremental index (rebuild cost follows changed rows, not corpus size), and the candidate pool takes full sort keys and hydrates only the rows it selects. Also: every background LLM call now carries a `sessionId`, so strict gateways such as OpenCode stop answering 400 (#668).

> Full list in [CHANGELOG](dsh-mneme/CHANGELOG.md) · version history in [Releases](https://github.com/slow-stack/mneme/releases)

Expand Down Expand Up @@ -596,6 +597,7 @@ Community projects that wire mneme into more platforms — not part of this repo
| **v0.9** | M.O. (Modus Operandi) beta: project-level workflows + candidate tiering & promotion criteria + panel list-and-graph view; settings panel re-folded at "beyond the newcomer" (#427); security & supply-chain hardening (declarative route auth, OSV gate, signed releases); **v0.9.1 adds the write side**: execution windows, run ledger, attribution candidates, observation sidecar with drift detection, step `assert`/`optional`, draft mining from session logs, persona page (per-agent cards); **v0.9.2 makes silent failures visible**: feature-flag third state "pending restart", scope-level reversible gate (#471), automatic max_tokens downgrade for consolidation (#478); **v0.9.3 wires up auto-distillation**: resolves the project bucket from the session header's `cwd`, hooks `turn/end`, 10-minute cooldown, 4-second budget, proposals only and never drafts (#489), and fixes the scope reverse-lookup that had been silently degrading since v0.8.0 (#487), the `/nudge` write gate missing `PATCH`/`DELETE`, and a multi-frame zstd counter-assertion bound to Node's whole-buffer decode semantics (#490); **v0.9.4 supplies the missing last link on three chains**: the agent-driven organizing interface finally gets a tool (`memory_organize`, behind `organizeEnabled`, off by default — off means the model cannot even see it), the profile can be drafted from memory (`profileExtractEnabled`, off by default; a draft only — applying it is another user action, and hand-written text is never rewritten by the model), and the persona `default` card is no longer handed to identities that simply have no card (#497, `personaStrictAddressing`, off by default); the panel's "injected text" card is now rendered by a single backend source, plus the distillation transcript fence and parse-failure guard (#494); **v0.9.5 makes memory shareable and recallable**: the `mneme.share/v1` pack (active rows only, no scopes or home prefixes, secret/PII rows dropped whole, report before file, 3 MiB watermark, one bad row rejects the whole pack, dry-run by default, idempotent on `share_external_id`, withdrawal deletes rather than archives), a single predicate guarding "local consolidation never rewrites someone else's imported text" at the dedupe choke point and nine row pools, the provenance read endpoint `GET /memory/provenance` (@z2Ace0107, with 409 and 503 kept as two different answers), plus fixes for duplicate same-title writes (#505), a starved pattern-scan window (#515), five unfenced consolidation prompts (#501/#493) and a merge guard skipping whole categories (#521), and a sticky settings section index (#518) | ✅ Released (v0.9.5) |
| **v0.10** | Attribution and gates: distillation provenance gains a **run** identity (`distill_runs` per window plus `memory_mints` per row; historical rows left NULL rather than guessed), provenance gains the reverse direction `?sessionId=`, a per-session incognito gate (`sessionGateEnabled`, keyed on the host's own delegation markers with a bounded ledger), anti-sycophancy rules reaching the write side (stance and narration discipline in distillation and overview), `differentiate` moving to a ledger instead of rewriting text (#533), an input budget and catch-up for the sleep conflict phase (#529), the "last consolidation" card no longer showing organize receipts (#495), and the panel's first mobile and 481–519px breakpoints (#542) | ✅ Released (v0.10.0) |
| **v0.13** | Emotion finally has a place to live: "anxious this time" and "an anxious person" no longer look identical in storage. A new `affective_context` relation carries the emotion word and its attribution; a new sleep phase promotes an emotion to a stable trait only after three independent sessions, downgrading rather than discarding when it falls short, with every downgrade and drop accounted for. Edges for the same occasion merge by session instead of being rewritten each run. Same release: the diary, M.O. removed from the panel, several panel fixes | ✅ Released (v0.13.0) |
| **v0.14** | Images and emotion both become memory: image descriptions get a provenance table (`image_sources`, so a summary can point back to the picture it came from), and one-off occasions get an injection path (`affectiveInjectEnabled`); recall loses two silent truncations — a 500-row lexical corpus and a 200-row injection pool — now full-width with incremental indexing; and every background LLM call carries a `sessionId`, so strict gateways stop answering 400 (#668) | ✅ Released (v0.14.0) |
| **v0.12** | Explicit pinning (a `pinned_memories` table behind `memory_pin` — release with `unpin: true` — so pinned rows take their place in the injected block instead of relying on their type; `pinnedInjectBudget` defaults to 0, which leaves the pin pool off) + pinned rows no longer squeezed out by the vector path's `poolSize` cap + automatic facts for "you as the agent sees it" (`profileFactsEnabled`, off by default) + an embedding-resolution cache that follows the working set (hit rate 0% → 100%, single-round retrieval 5.6x faster, storage on `Float32Array`) + #579 chorography tool error paths and "cannot read" no longer answered as "no match" + #590 strict addressing no longer reading "no card was ever created" as "no card for this identity" | ✅ Released (v0.12.0) |

> Full per-minor-version changelog in [CHANGELOG](dsh-mneme/CHANGELOG.md).
Expand Down
16 changes: 8 additions & 8 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ We actively maintain the latest minor version. Security fixes are backported to

| Version | Supported | Status |
|---|---|---|
| 0.13.x | ✅ Yes | Active development |
| 0.12.x | ⚠️ Best-effort | Critical fixes only |
| < 0.12.0 | ❌ No | Please upgrade to 0.13.x |
| 0.14.x | ✅ Yes | Active development |
| 0.13.x | ⚠️ Best-effort | Critical fixes only |
| < 0.13.0 | ❌ No | Please upgrade to 0.14.x |

**End-of-life notice**: 0.12.x is in best-effort maintenance (critical fixes only). Its end-of-life date will be announced in advance; after that date no security fixes will be provided for 0.12.x. Security support for 0.11.x and below has ended — please upgrade to 0.13.x.
**End-of-life notice**: 0.13.x is in best-effort maintenance (critical fixes only). Its end-of-life date will be announced in advance; after that date no security fixes will be provided for 0.13.x. Security support for 0.12.x and below has ended — please upgrade to 0.14.x.

---

Expand Down Expand Up @@ -408,11 +408,11 @@ This project is licensed under the **MIT License**. See [LICENSE](https://github

| 版本 | 支持状态 | 说明 |
|---|---|---|
| 0.13.x | ✅ 支持 | 活跃开发中 |
| 0.12.x | ⚠️ 尽力维护 | 仅关键修复 |
| < 0.12.0 | ❌ 不支持 | 请升级至 0.13.x |
| 0.14.x | ✅ 支持 | 活跃开发中 |
| 0.13.x | ⚠️ 尽力维护 | 仅关键修复 |
| < 0.13.0 | ❌ 不支持 | 请升级至 0.14.x |

**停止维护通知**:0.12.x 处于尽力维护阶段(仅关键修复)。停止维护的具体日期将提前公布;该日期之后将不再提供 0.12.x 的安全修复。0.11.x 及更早版本的安全支持已终止——请升级至 0.13.x。
**停止维护通知**:0.13.x 处于尽力维护阶段(仅关键修复)。停止维护的具体日期将提前公布;该日期之后将不再提供 0.13.x 的安全修复。0.12.x 及更早版本的安全支持已终止——请升级至 0.14.x。

---

Expand Down
2 changes: 2 additions & 0 deletions dsh-mneme/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

## [0.14.0] - 2026-11-12

- **注入的规则池只看得到前 200 条记忆:候选池此前固定 `store.list({ limit: 200 })`,合格行 8400+ 条里 8200 条永远进不了窗(#619)**。这个窗口按 `importance DESC` 取,于是注入位实际上由「谁更重要」决定一个固定的前 200 名,而真正的排序规则(summary 优先档 → preference → importance×quality×heat×scope)只在这 200 条**内部**生效。实测本机库 9067 条活跃记忆里,按注入闸门(`injectType` / 非 narrative / importance ≥ 3)合格的有 8421 条,其中 8210 条永远进不了候选窗;窗口内 200 条的 importance 分布是**全部 5**——也就是说 summary 优先档这条规则,在最需要它的场景里根本没机会触发。
- **窗口改成只限制回表条数,不再决定谁能参与排序**。`store.listInjectPool()` 取全部活跃行的排序键(12 列:`id / type / source / importance / quality_score / last_accessed_at / created_at / updated_at / agent_scope / workspace_scope / archived / forgotten`),过滤与排序都在 JS 侧做,最后只对入选的 `max(200, poolSize)` 条回表补正文。回表深度与改动前一致(200),所以 backfill(槽位没填满时往下补)的行为不变。
- **不走 `store.list({ limit: null })`**:list 的投影由 PRAGMA 派生、搬全部列(含 content),9k 行实测 340-400ms;这里 12 列实测 200ms,正文只对 200 条用 `listByIdsForInject` 点查回来(6.8ms)。加起来仍低于改动前那条 `LIMIT 200` 查询的 ~76ms + 后续排序,但账要算清:**这不是变快,是把「看不见的记忆」换成了「多扫一遍排序键」**,换来召回覆盖面。
Expand Down
1 change: 1 addition & 0 deletions dsh-mneme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ v0.3.0 起新增**记忆基因**层:从记忆里抽取**命名实体**、**带
| 版本 | 头条 |
|------|------|
| **v0.13.0**(2026-11-10) | 情绪终于有地方可放:`affective_context` 带情绪词与归因,三个独立会话才升成稳定倾向,不足就降级不丢弃 |
| **v0.14.0**(2026-11-12) | 图像描述有了溯源表(摘要能回指哪张图),单次场合的情绪补上注入出口;召回侧两处静默截断(词法语料 500 行、注入池 200 行)改成全量 + 增量;后台 LLM 调用统一补 `sessionId` |
| **v0.12.0**(2026-11-07) | pin 从「按类型猜」变成你亲手钉的事实;向量缓存从恒 0% 命中改为跟工作集自适应(1.8–2.4s → 370–424ms) |
| **v0.11.0**(2026-11-05) | 记忆读得懂仓库:文件树与 import 图编译成模块划分与地志页 |
| **v0.10.1**(2026-11-03) | 打开记忆详情不再崩掉整个宿主 |
Expand Down
Loading
Loading