memory-eternal 0.10.0 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "memory-eternal",
4
- "version": "0.9.23",
5
- "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
4
+ "version": "0.10.3",
5
+ "description": "记忆核心(Memory Eternal):对话结束后自动沉淀知识卡到本地记忆库(~/.dsh/memory-vault),支持检索 / 召回 / 审核中心。",
6
6
  "author": {
7
7
  "name": "EternalNight996",
8
8
  "url": "https://github.com/EternalNight996"
@@ -18,17 +18,3 @@
18
18
  }
19
19
  ]
20
20
  }
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memory-eternal",
3
- "version": "0.9.23",
4
- "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
3
+ "version": "0.10.3",
4
+ "description": "记忆核心(Memory Eternal):对话结束后自动沉淀知识卡到本地记忆库(~/.dsh/memory-vault),支持检索 / 召回 / 审核中心。",
5
5
  "author": {
6
6
  "name": "EternalNight996",
7
7
  "url": "https://github.com/EternalNight996"
@@ -13,17 +13,3 @@
13
13
  "mcpServers": "./.mcp.json",
14
14
  "hooks": "./hooks/hooks.codex.json"
15
15
  }
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memory-eternal",
3
- "version": "0.9.23",
4
- "description": "璁板繂鏍稿績锛圡emory Eternal锛夛細鐭ヨ瘑鍗¤嚜鍔ㄦ矇娣€/鍙洖锛岀粺涓€ ~/.dsh/memory-vault锛屼細璇濈粨鏉熻嚜鍔ㄥ叆搴撹繘寰呭鏍搞€?,
3
+ "version": "0.10.3",
4
+ "description": "记忆核心(Memory Eternal):对话结束后自动沉淀知识卡到本地记忆库(~/.dsh/memory-vault),支持检索 / 召回 / 审核中心。",
5
5
  "author": {
6
6
  "name": "EternalNight996",
7
7
  "url": "https://github.com/EternalNight996"
@@ -12,17 +12,3 @@
12
12
  "mcpServers": "./.mcp.json",
13
13
  "hooks": "./hooks/hooks.cursor.json"
14
14
  }
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
package/.mcp.json CHANGED
@@ -1,9 +1,9 @@
1
- {
2
- "mcpServers": {
3
- "memory": {
4
- "command": "node",
5
- "args": ["${CLAUDE_PLUGIN_ROOT}/bin/dsh-memory.mjs", "mcp"],
6
- "env": {}
7
- }
8
- }
9
- }
1
+ {
2
+ "mcpServers": {
3
+ "memory": {
4
+ "command": "node",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/bin/dsh-memory.mjs", "mcp"],
6
+ "env": {}
7
+ }
8
+ }
9
+ }
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 EternalNight996
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 EternalNight996
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md CHANGED
@@ -69,7 +69,7 @@ After **restarting the host**, three things are live immediately:
69
69
 
70
70
  **UI language**: The whole UI is bilingual (English / 中文) and follows **DSH Settings → Language** in real time — Cards, Graph, Audit Center, card templates, config panel all included; the standalone web page follows the browser language.
71
71
 
72
- **Edit config**: Vault left rail "Memory Config" (or DSH Settings → Memory) → DSH memory config / cost control / auto-audit config / self-hosting — just hit "Save Config". `autoWebMode` / `watchdogAutoSpawn` changes require a DSH restart.
72
+ **Edit config**: Vault left rail "Memory Config" (or DSH Settings → Memory) → DSH memory config / cost control / auto-audit config / self-hosting — just hit "Save Config". `autoWebMode` / `watchdogAutoSpawn` changes require a DSH restart — and note an **already running watchdog is never stopped by a config change**: use `dsh-memory stop` / `dsh-memory restart` (see Self-hosting).
73
73
 
74
74
  ### 🟨 Claude Code
75
75
 
@@ -110,6 +110,14 @@ dsh-memory mcp # MCP stdio (mount to any MCP client)
110
110
  dsh-memory serve [--port 7999] # run web in foreground
111
111
  dsh-memory open # ensure web alive + open browser
112
112
  dsh-memory watchdog [--port 7799] # watchdog keep-alive (standalone process)
113
+ dsh-memory status [--json] # resident watchdog: pid / port / version / alive
114
+ dsh-memory stop [--port 7799] # stop the resident watchdog (+ the web it spawned)
115
+ dsh-memory restart [--port 7799] # stop + respawn (apply a new version)
116
+ dsh-memory audit list [--status pending|rejected|approved|deleted|all] [--limit N] [--json]
117
+ # list cards; the total is never rewritten by --limit (which caps output only)
118
+ # all = audit queue (pending + rejected), excluding approved / deleted
119
+ dsh-memory audit approve <card path...> # human bulk approve
120
+ dsh-memory audit reject <card path...> --reason "..." # human bulk reject
113
121
  ```
114
122
 
115
123
  When not running on DSH, the `dsh-memory` command comes from `npm i -g`.
@@ -126,13 +134,16 @@ Three concepts, don't mix them:
126
134
 
127
135
  **Change these**: Vault left rail "Memory Config" (or DSH Settings → Memory) → edit the table and save; `autoWebMode` / `watchdogAutoSpawn` need a DSH restart.
128
136
 
137
+ > ⚠️ **Same port is never auto-replaced (#19)**: the watchdog is a **standalone process we deliberately never kill** (several sessions share one). So turning `watchdogAutoSpawn` off does **not** stop the running one, and changing `webCheckIntervalMs` / `webMaxRestart` has no effect on it.
138
+ > Stop or upgrade it explicitly with `dsh-memory stop [--port N]` / `dsh-memory restart [--port N]` (`stop` also stops the **web it spawned**, so no orphan keeps holding the port); `dsh-memory status` shows the resident pid, port, start time and whether its **version lags the installed package**.
139
+
129
140
  **MCP is a protocol, not a resident service**: the agent spawns it per session and exits when done — no "auto-start on boot" concept.
130
141
 
131
142
  ### Three deployment intensities
132
143
 
133
144
  | Scenario | Config | Memory |
134
145
  |---|---|---|
135
- | Personal dev (default) | `autoWebMode=init` + `watchdogAutoSpawn=off` | web 47 MB |
146
+ | Personal dev (recommended) | `autoWebMode=init` + **manually** turn `watchdogAutoSpawn` off (its default is **on**) | web 47 MB |
136
147
  | Resident 7×24 | `watchdogAutoSpawn=on` | web + watchdog 47+47 MB |
137
148
  | True boot auto-start (no DSH) | Windows Task Scheduler runs `dsh-memory watchdog --port 7799 --interval 5000 --max-restart 10` | same |
138
149
 
@@ -187,7 +198,7 @@ Resolution order: `MEMORY_VAULT_DIR` env → the `path` of the `vaultProfiles` e
187
198
  | Setting | Default | In plain words |
188
199
  |---|---|---|
189
200
  | Keep-alive `autoWebMode` | init | `init`=open web once at DSH start; `interval`=periodically check & restart if dead; `manual`=fully manual |
190
- | Watchdog `watchdogAutoSpawn` | on | a **standalone process** keeps web alive (+47 MB). Personal use can turn off |
201
+ | Watchdog `watchdogAutoSpawn` | on | a **standalone process** keeps web alive (+47 MB). Personal use can turn off — but an existing instance is **not** stopped automatically, run `dsh-memory stop` (#19) |
191
202
  | Auto-mount MCP `autoMcpSetup` | off | **lets Claude Code / Codex / Cursor use your memory**. On = auto-configures them; Off = never touches your config, run `dsh-memory setup` manually |
192
203
 
193
204
  > 💰 **To save money**: turn `Distill cards` off, lower `Distill output cap`, raise `Recall min score`.
@@ -198,7 +209,7 @@ Top of the config page: **🟢 A Light / 💰 B Budget / ⭐ C Premium** — cli
198
209
 
199
210
  | Plan | Scenario | Keep-alive | Watchdog | Distill | Distill cap | Recall min | Memory | LLM cost |
200
211
  |---|---|---|---|---|---|---|---|---|
201
- | 🟢 **A Light** | Personal dev (default) | init | off | on | 900 | 2 | ~47 MB | normal |
212
+ | 🟢 **A Light** | Personal dev (recommended) | init | off | on | 2000 | 2 | ~47 MB | normal |
202
213
  | 💰 **B Budget** | Tight budget / many Agents | init | off | **off** | 500 | 3 | ~47 MB | **~0** |
203
214
  | ⭐ **C Premium** | Long projects / teams | interval | **on** | on | 1200 | 1 | ~94 MB | high |
204
215
 
@@ -307,10 +318,13 @@ Diagnostics:
307
318
  ## 📋 Changelog
308
319
 
309
320
  > **Withdrawn versions**: **v0.9.16 – v0.9.22 are all withdrawn** (problem-period releases: git tags deleted, npm entries deprecated — use **v0.9.23**). **v0.9.14 is deprecated** (its client-rendering changes hurt the feel and were reverted; its server-side algorithm work shipped in **v0.9.15**, whose rendering is identical to v0.9.13). **v0.9.0 – v0.9.5 are all deprecated on npm, and the release tags for v0.9.1 / v0.9.2 / v0.9.3 / v0.9.4 have been removed from git** (v0.9.5 is merely superseded, so its tag stays) — v0.9.1/v0.9.2 ship the blank-memory-page defect, v0.9.0 false-alarms its capture warnings, v0.9.3 does not support DSH v0.1.7-rc.2 (the plugin stops mounting entirely: the settings service changed and the client-side `settingsScope` is gone), v0.9.4 crashes under the official desktop build (schemastery 3.18.4 volatile live references) with `cfg.vaultDir.trim is not a function`, and **v0.9.5's full-screen overlay covers the desktop shell's window controls (its top-right "×" sits on the window Close button — one click quits the whole shell)**. Use **v0.9.6+** (`npm i memory-eternal@latest`).
310
- > **DSH compatibility**: `>=0.1.5-alpha.2 <0.2.0`. **v0.9.4 adds support for DSH v0.1.7-rc.2**, which replaced the settings service with a forms-only API and removed `@deepseek-ai/dsh-client-runtime` / `settingsScope`; **v0.9.5 adds support for schemastery ≥3.18.4 volatile live references** (the shape the official desktop profile uses, while the web profile still ships 3.18.1 — both work); **v0.9.6 keeps full-screen overlays clear of the desktop shell's window controls**. The 0.1.5 line still uses the legacy `settings.register` path; both paths are kept.
321
+ > **DSH compatibility**: `>=0.1.5-alpha.2 <0.3.0-0` (**widened in v0.10.1**: the old `<0.2.0` upper bound excludes DSH `0.2.0-rc.x` under plain semver — DSH's plugin guard uses `includePrerelease: true`, so installs still worked, but the declaration did not match reality. The range now covers the whole 0.1/0.2 line, and `<0.3.0-0` still blocks 0.3.0 and its prereleases. **Verified running on the official desktop build DSH 0.2.0-rc.2**: mounting, memory page, auto-capture, review centre and import/export all work). **v0.9.4 adds support for DSH v0.1.7-rc.2**, which replaced the settings service with a forms-only API and removed `@deepseek-ai/dsh-client-runtime` / `settingsScope`; **v0.9.5 adds support for schemastery ≥3.18.4 volatile live references** (the shape the official desktop profile uses, while the web profile still ships 3.18.1 — both work); **v0.9.6 keeps full-screen overlays clear of the desktop shell's window controls**. The 0.1.5 line still uses the legacy `settings.register` path; both paths are kept.
311
322
 
312
323
  | Version | Date | Highlights |
313
324
  |---|---|---|
325
+ | **v0.10.3** | 2026-10-06 | **Fixed the counting semantics of `audit list` (#20).** ① The total is now **decoupled from `--limit`**: the reported count is the **matching total** (via `countCards`) while `--limit` caps output only, and truncation is stated explicitly (`显示前 M 张 … 还有 X 张未显示`). ② **No more silent truncation by default** (omit `--limit`, or `--limit 0`, to list everything). ③ `--json` now exposes `total` / `returned` / `count` (a backward-compatible alias of total; in 0.10.2 it wrongly equalled returned) / `limit` (null = all) / `hasMore`. ④ The meaning of `--status all` is documented in the usage text and README: the audit queue (pending + rejected), **excluding** dequeued approved and recycle-bin deleted; `approved` remains queryable explicitly. ⑤ **Same defect fixed in the MCP `memory_audit_list` tool**: it also silently capped at 20 and reported the truncated length as the pending count; it now reports the matching total plus how many are hidden, cap 100 → 500. |
326
+ | **v0.10.2** | 2026-10-06 | **Five long-standing issues fixed at once (#15 / #16 / #17 / #18 / #19).** ① **Per-project vaults finally work in the host (#15-1)**: the host matched `vaultProfiles[].match.workspace` against the process cwd (the directory dsh was launched from) — it now uses the **session's own workspace** from `session.header.cwd` (both capture and `memory_recall`), while CLI/MCP/hooks keep their existing cwd behaviour. ② **Distillation stops burning doomed candidates (#15-2)**: providers declaring `supportsReasoningEffort:false` no longer receive a `reasoningEffort` field (unknown = supported), and they move behind supporting candidates instead of being dropped. ③ **Truncated output is no longer misreported as a parse failure (#18)**: a dedicated `MAX_TOKENS` code (with the actual cap in the message), one automatic retry with a doubled cap, failure reporting that **always keeps the first candidate's error as the primary cause** plus a per-code summary of the rest, default `captureMaxTokens` 900 → **2000**, and a `distill-failed` tag on fallback raw cards. ④ **Standalone-web config saves are no longer lost silently (#16)**: drain errors are no longer swallowed (stderr + capture log, throttled), and the shared `memory-eternal-config.json` is now written **atomically (tmp + rename)** — the old non-atomic write could be read mid-truncation by the standalone web / MCP, fail JSON.parse and silently fall back to defaults, the pending file is **kept** with `dropped:true` + `lastError` after retries are exhausted, and the state shows up in `/diagnostics` and `/config`. ⑤ **Audit CLI (#17)**: `dsh-memory audit list/approve/reject` (multiple paths, `--json` for jq) reuses the same `setCardStatus` guard and `audit_log`; MCP gains only a **read-only** `memory_audit_list`. ⑥ **Watchdog lifecycle (#19)**: new `dsh-memory status/stop/restart`, `pkgVersion` recorded in the lock (status warns when the resident instance is outdated), truthful `spawned` vs `delegated to existing pid` host logs, a clear notice when `watchdogAutoSpawn` is off but an instance is still running, `dsh-memory stop` also stops the **web server the watchdog spawned** (on Windows `process.kill(pid,'SIGTERM')` terminates unconditionally, so the watchdog's own exit handler never runs — the old behaviour left an orphan web holding the port; the web pid is recorded in the lock and confirmed against the process command line before killing, avoiding pid-reuse mistakes), plus README fixes for the contradictory default and the "restart turns it off" promise. |
327
+ | **v0.10.1** | 2026-10-02 | **Fixes "export works, import brings in 0 cards".** Root cause: "Export JSON" wrote a **bare array**, while `/import` only read `payload.cards` — a bare array was silently treated as an empty backup (`ok:true` / `imported:0` / `skipped:0`), so the UI only ever said "Import complete: 0". ① `/import` now accepts both a **bare array** (backups from v0.10.0 and earlier) and an **envelope object** `{format, formatVersion, exportedAt, count, cards}`; an unrecognized shape returns **400 with a readable reason**, an empty file returns a `warning`. ② Export now writes the envelope (older builds only read `payload.cards`, so the envelope stays compatible with them) and keeps each card's `status` / `store`. ③ The import dedup baseline is now a **pre-import snapshot** (new `dedupAgainst` option on `writeCard`) — otherwise near-identical cards inside one backup dedup against each other and swallow part of the batch (a backup is the source of truth). ④ The import response adds `total` / `skipped` / `quarantined` / `failed[]` (with a per-card reason), and the toast reads "Import complete: N / of M · pending review K · skipped D"; a run that imports nothing is shown as a failure. ⑤ New `tests/import-roundtrip.test.mjs` (6 checks). ⑥ **A broken install now speaks plainly (issue #14)**: a copy installed from the plugin marketplace can be missing its `web/` assets, and the sidebar then showed a raw `{"ok":false,"error":"ENOENT …"}` page. Now a missing `index.html` with `app.js` still present is covered by a **built-in shell** that boots the UI anyway (self-healing), while a missing `app.js` returns a JS snippet that paints the diagnosis into `#root` plus a page stating which file is gone, its absolute path, the package version and how to reinstall. Both cases land in the auto-capture log (`app.js` → `fail`, health turns red; `index.html` only → `warn`), and the host self-checks the same way at startup (shared predicates and wording in the new `lib/web-assets.js`, with 6 checks in `tests/web-assets.test.mjs`). ⑦ `appendCaptureLog` no longer fails silently when the `DSH_HOME` directory does not exist. ⑧ **DSH compatibility widened to `>=0.1.5-alpha.2 <0.3.0-0`**: the old `<0.2.0` upper bound excludes DSH `0.2.0-rc.x` under plain semver (DSH's guard uses `includePrerelease:true`, so installs still worked, but the declaration did not match reality) — the range now covers the whole 0.1/0.2 line while `<0.3.0-0` still blocks 0.3.0 and its prereleases; `dsh.compatibility` gains `"0.2.0-rc.2": "compatible"` (verified on the official desktop build 0.2.0-rc.2). ⑨ **Fixed three third-party plugin manifests that were invalid JSON**: the closing quote of `description` in `.claude-plugin` / `.codex-plugin` / `.cursor-plugin` had been swallowed by a double-encoding accident (last touched in v0.9.23); DSH never reads those files, so nothing surfaced, but installing through Claude Code / Codex / Cursor **always failed to parse**. They are now valid UTF-8 JSON with `version` bumped to 0.10.1, plus a new **shipped-files health guard** `tests/manifests.test.mjs` (3 checks: every shipped JSON parses / the three manifests' `name`+`version` match package.json / no encoding-accident mojibake in shipped text). Measured on a real **661-card bare-array backup (3.9 MB): 0 cards before the fix → 661 after** (654 into the main store + 7 into quarantine). `npm test` now runs **187 checks** |
314
328
  | **v0.9.23** | 2026-09-30 | **No more save flicker.** After a successful save the client immediately re-fetches `/config`, but the host volatile echo lags, so inputs visibly reverted to the old values and then jumped back. The client now keeps a **local overlay** for fields that were saved but not yet echoed (`src/client/config-merge.js`, pure function + 4 checks), dropping each key once the host echoes it, and following the host value afterwards; resetting the form clears the overlay. `npm test` now runs **139 checks** |
315
329
 
316
330
  <details>
package/README.md CHANGED
@@ -68,7 +68,7 @@ node -e "console.log(require('memory-eternal/package.json').version)"
68
68
 
69
69
  **界面语言**:全套 UI 中英双语,跟随 **DSH 设置 → 语言** 实时切换(含知识卡 / 知识图谱 / 审核中心 / 新建卡模板);浏览器直接访问 web 时跟随浏览器语言。
70
70
 
71
- **改配置**:记忆库左栏「记忆配置」(或 DSH 设置 → 记忆)→ DSH 记忆配置 / 成本控制 / 自动审核配置 / 服务自管理,点「保存配置」即写入。`autoWebMode`/`watchdogAutoSpawn` 的改动需重启 DSH 生效。
71
+ **改配置**:记忆库左栏「记忆配置」(或 DSH 设置 → 记忆)→ DSH 记忆配置 / 成本控制 / 自动审核配置 / 服务自管理,点「保存配置」即写入。`autoWebMode`/`watchdogAutoSpawn` 的改动需重启 DSH 生效;注意**已常驻的 watchdog 不会被配置改动自动停掉**,要停止或换新版请执行 `dsh-memory stop` / `dsh-memory restart`(见「服务自管理」)。
72
72
 
73
73
  ### 🟨 Claude Code
74
74
 
@@ -121,6 +121,14 @@ dsh-memory mcp # MCP stdio(挂任意 MCP 客户端)
121
121
  dsh-memory serve [--port 7999] # 前台跑 web
122
122
  dsh-memory open # ensure web 存活 + 开浏览器
123
123
  dsh-memory watchdog [--port 7799] # 看门狗保活 web(独立进程)
124
+ dsh-memory status [--json] # 看常驻 watchdog:pid / 端口 / 版本 / 是否存活
125
+ dsh-memory stop [--port 7799] # 停止常驻 watchdog(配置改动不会自动停;连它拉起的 web 一起停)
126
+ dsh-memory restart [--port 7799] # 停止并重起 watchdog(升级后换新版)
127
+ dsh-memory audit list [--status pending|rejected|approved|deleted|all] [--limit N] [--json]
128
+ # 列出卡片;总数不受 --limit 影响,--limit 只限制显示条数(默认全部)
129
+ # all = 审核队列(pending + rejected),不含 approved / deleted
130
+ dsh-memory audit approve <卡片路径...> # 人工批量批准
131
+ dsh-memory audit reject <卡片路径...> --reason "..." # 人工批量驳回
124
132
  ```
125
133
 
126
134
  单独装(不发 DSH)时 `dsh-memory` 命令来自 `npm i -g`。
@@ -137,13 +145,18 @@ dsh-memory watchdog [--port 7799] # 看门狗保活 web(独立进程)
137
145
 
138
146
  **改这些**:记忆库左栏「记忆配置」(或 DSH 设置 → 记忆)→ 表格里改,点「保存配置」;`autoWebMode`/`watchdogAutoSpawn` 需重启 DSH 生效。
139
147
 
148
+ > ⚠️ **同端口不会自动替换(#19)**:看门狗是**独立进程且故意不杀**(多会话共用一个),所以
149
+ > 关闭 `watchdogAutoSpawn` **不会**停掉已经在跑的那个,改 `webCheckIntervalMs`/`webMaxRestart` 也不会生效。
150
+ > 要停止 / 换新版请显式执行 `dsh-memory stop [--port N]` 与 `dsh-memory restart [--port N]`(`stop` 会**连它拉起的 web 一起停**,不留占端口的孤儿);
151
+ > `dsh-memory status` 会显示常驻实例的 pid、端口、启动时间与**版本是否落后于本机安装的包**。
152
+
140
153
  **MCP 是协议不是常驻服务**:agent 开会话才 spawn,用完即退,没有「开机自启」一说。
141
154
 
142
155
  ### 三种部署强度
143
156
 
144
157
  | 场景 | 配置 | 内存 |
145
158
  |---|---|---|
146
- | 个人开发(默认) | `autoWebMode=init` + `watchdogAutoSpawn=off` | web 47 MB |
159
+ | 个人开发(推荐) | `autoWebMode=init` + **手动**把 `watchdogAutoSpawn` 关掉(默认是**开**,见下方配置表) | web 47 MB |
147
160
  | 常驻 7×24 | `watchdogAutoSpawn=on` | web + watchdog 47+47 MB |
148
161
  | 真正开机自启(无 DSH) | Windows 计划任务跑 `dsh-memory watchdog --port 7799 --interval 5000 --max-restart 10` | 同上 |
149
162
 
@@ -198,7 +211,7 @@ dsh-memory watchdog [--port 7799] # 看门狗保活 web(独立进程)
198
211
  | 配置项 | 默认 | 大白话说明 |
199
212
  |---|---|---|
200
213
  | 保活模式 `autoWebMode` | init | `init`=DSH 启动时开一次 web;`interval`=定时检查挂了自动重启;`manual`=全靠手动 |
201
- | 看门狗 `watchdogAutoSpawn` | 开 | 后台一个**独立进程**保证 web 不死(+47 MB 内存)。个人用可关 |
214
+ | 看门狗 `watchdogAutoSpawn` | 开 | 后台一个**独立进程**保证 web 不死(+47 MB 内存)。个人用可关——但关闭后**既有实例不会自动停**,需 `dsh-memory stop`(#19) |
202
215
  | 自动挂载 MCP `autoMcpSetup` | 关 | **让 Claude Code / Codex / Cursor 也能用你的记忆库**。开=自动配好它们;关=不碰你电脑配置,手动跑 `dsh-memory setup` |
203
216
 
204
217
  > 💰 **想省钱**:把「蒸馏知识卡」关掉、调低「蒸馏输出上限」、调高「召回相关性阈值」。
@@ -209,7 +222,7 @@ dsh-memory watchdog [--port 7799] # 看门狗保活 web(独立进程)
209
222
 
210
223
  | 方案 | 场景 | 保活 | 看门狗 | 蒸馏 | 蒸馏上限 | 召回阈值 | 内存 | LLM 成本 |
211
224
  |---|---|---|---|---|---|---|---|---|
212
- | 🟢 **A 轻量省心** | 个人开发(默认)| init | 关 | 开 | 900 | 2 | ~47 MB | 正常 |
225
+ | 🟢 **A 轻量省心** | 个人开发(推荐)| init | 关 | 开 | 2000 | 2 | ~47 MB | 正常 |
213
226
  | 💰 **B 极致省钱** | 预算敏感/多 Agent | init | 关 | **关** | 500 | 3 | ~47 MB | **近 0** |
214
227
  | ⭐ **C 高质量** | 长项目/团队 | interval | **开** | 开 | 1200 | 1 | ~94 MB | 高 |
215
228
 
@@ -338,11 +351,16 @@ curl http://127.0.0.1:7999/memory-eternal/api/web-info # 独立 web 是否活
338
351
 
339
352
  ## 📋 更新日志
340
353
 
354
+ > **发布规则(2026-09-30 起)**:正式版一律**三端同步发布** —— `npm publish` + **GitHub Release** + **Gitee Release**,并保证 `vX.Y.Z` tag 在三端一致。桌面版 profile 依赖 `github:EternalNight996/memory-eternal`、`dsh web` 走 npm 版本号,少任何一端都会出现「npm 上是新版、桌面版还是旧的」。统一入口:`npm run release:dry`(预演)→ `npm run release`(正式)。详见 [PUBLISH.md](./PUBLISH.md)。
355
+ >
341
356
  > **版本撤回说明**:**v0.9.16 – v0.9.22 已全部撤回**(问题期间版本:git tag 已删除、npm 已标记 deprecated,请使用 **v0.9.23**)。**v0.9.14 已 deprecated**(客户端渲染改动降低手感,已回退;其服务器侧算法优化并入 **v0.9.15**,渲染与 v0.9.13 完全一致)。**v0.9.0 – v0.9.5 均已在 npm 标记 deprecated;v0.9.1 / v0.9.2 / v0.9.3 / v0.9.4 的 release tag 已从 git 移除**(v0.9.5 只是被取代、tag 保留)—— v0.9.1/v0.9.2 带记忆页白屏缺陷,v0.9.0 沉淀告警误报刷屏,v0.9.3 不支持 DSH v0.1.7-rc.2(升级后插件整体挂不上:设置服务换血 + 客户端 `settingsScope` 消失),v0.9.4 在官方桌面版(schemastery 3.18.4 的 volatile 活引用)下抛 `cfg.vaultDir.trim is not a function`、插件整体挂不上,**v0.9.5 的全屏浮层会盖住桌面版的窗口控制面板(右上角「×」压在窗口「关闭」上,点一下会退出整个桌面壳)**。请一律使用 **v0.9.6+**(`npm i memory-eternal@latest`)。
342
- > **DSH 兼容性**:`>=0.1.5-alpha.2 <0.2.0`。**v0.9.4 起适配 DSH v0.1.7-rc.2**(该版本把设置服务换成纯表单 API,并移除了 `@deepseek-ai/dsh-client-runtime` 与 `settingsScope`);**v0.9.5 起兼容 schemastery ≥3.18.4 的 volatile 活引用**(官方桌面版 profile 即此形态,web profile 仍是 3.18.1,两者都支持);**v0.9.6 起全屏浮层自动让开桌面壳的窗口标题栏**(不再压住最小化/最大化/关闭)。0.1.5 系列仍走旧的 `settings.register` 路径,两条路径都保留。
357
+ > **DSH 兼容性**:`>=0.1.5-alpha.2 <0.3.0-0`(**v0.10.1 起放宽**:旧的上界 `<0.2.0` 在 semver 上会把 DSH `0.2.0-rc.x` 排除在外 —— DSH 的插件守卫用 `includePrerelease:true` 判定,实际仍能装上,但声明与事实不一致;现在明确覆盖整个 0.1/0.2 线,且 `<0.3.0-0` 仍然挡住 0.3.0 及其预发布。**已在官方桌面版 DSH 0.2.0-rc.2 上实测运行**:插件挂载、记忆页、自动沉淀、审核中心、导入导出均正常)。**v0.9.4 起适配 DSH v0.1.7-rc.2**(该版本把设置服务换成纯表单 API,并移除了 `@deepseek-ai/dsh-client-runtime` 与 `settingsScope`);**v0.9.5 起兼容 schemastery ≥3.18.4 的 volatile 活引用**(官方桌面版 profile 即此形态,web profile 仍是 3.18.1,两者都支持);**v0.9.6 起全屏浮层自动让开桌面壳的窗口标题栏**(不再压住最小化/最大化/关闭)。0.1.5 系列仍走旧的 `settings.register` 路径,两条路径都保留。
343
358
 
344
359
  | 版本 | 日期 | 关键改动 |
345
360
  |---|---|---|
361
+ | **v0.10.3** | 2026-10-06 | **修复 `audit list` 的计数语义(#20)**。① 总数与 `--limit` **解耦**:`共 N 张` 取**匹配总数**(`countCards`),`--limit` 只限制显示条数,截断时明确写出 `显示前 M 张 … 还有 X 张未显示`。② **默认不再静默截断**(不给 `--limit`、或 `--limit 0` = 全部显示)。③ `--json` 拆分为 `total`(匹配总数)/ `returned`(本次返回)/ `count`(= total 的兼容别名;0.10.2 里它误等于 returned)/ `limit`(null = 全部)/ `hasMore`。④ `--status all` 的语义写进用法与 README:= 审核队列(pending + rejected),**不含**已出队的 approved 与回收中心的 deleted;`approved` 可显式查询。⑤ **同源修复 MCP 的 `memory_audit_list`**:它同样存在「默认 20 静默截断 + 把截断条数报成待处理数」,现改为报匹配总数 + 未显示提示,上限 100 → 500。 |
362
+ | **v0.10.2** | 2026-10-06 | **五个存量 issue 集中修复(#15 / #16 / #17 / #18 / #19)**。① **按项目选库在宿主侧终于生效(#15-1)**:宿主过去拿进程 cwd 去匹配 `vaultProfiles[].match.workspace`,而那是「启动 dsh 的目录」——现在从 `session.header.cwd` 取**会话自己的工作区**(capture 与 memory_recall 两条路径都传),CLI/MCP/hooks 行为不变。② **蒸馏不再选错 provider(#15-2)**:声明 `supportsReasoningEffort:false` 的候选不再被传 `reasoningEffort`(能力未知一律按支持处理),并把它们排到支持者之后但**不删除**,避免兜底全无。③ **输出截断不再伪装成解析失败(#18)**:新增独立错误码 `MAX_TOKENS`(含实际上限值),撞上限自动以双倍上限重试同一候选;兜底上报改为**始终以第一候选为主因** + 其余错误按码汇总(不再被最后一个候选覆盖);默认 `captureMaxTokens` 900 → **2000**;失败兜底的原文卡加 `distill-failed` 标签便于过滤。④ **独立 Web 端保存配置不再静默丢失(#16)**:drain 报错不再被 `catch {}` 吞掉(进 stderr + 自动沉淀日志,5 分钟去重节流),共享配置 `memory-eternal-config.json` 改为 **tmp + rename 原子写**(原先非原子写会在截断窗口内被独立 web / MCP 读到半截内容 → JSON.parse 失败 → 设置静默回落成默认值),重试耗尽后**保留 pending 文件**并标注 `dropped:true` + `lastError`(不再删除用户改动),失败状态进 `/diagnostics` 与 `/config` 响应。⑤ **审核中心有了 CLI(#17)**:`dsh-memory audit list/approve/reject`(多路径批量、`--json` 便于 jq 筛选、复用同一套 `setCardStatus` 守卫与 `audit_log`);MCP 侧只新增**只读**的 `memory_audit_list`,不暴露 approve/reject。⑥ **看门狗有了生命周期(#19)**:新增 `dsh-memory status/stop/restart`,锁文件写入 `pkgVersion`(status 会提示「常驻实例是旧版」),宿主日志按抢锁结果如实打印 `spawned` / `delegated to existing pid`(不再每次都谎报 spawned),关闭 `watchdogAutoSpawn` 时明确提示既有实例仍在跑;并且 `dsh-memory stop` 会**连同该 watchdog 拉起的 web 一起停**(Windows 上 `process.kill(pid,'SIGTERM')` 是无条件终止,watchdog 的退出处理器根本不会执行 —— 旧写法会在 stop 后留下一个占着端口的孤儿 web;web 子进程 pid 现在记在锁里,杀之前还会用进程命令行确认确实是 `web.js`,防 pid 复用误杀);README 修正「默认值自相矛盾」与「重启即可关闭」的错误承诺。 |
363
+ | **v0.10.1** | 2026-10-02 | **修复「导出 OK、导入 0 张」**。根因:客户端「导出JSON」写出的是**裸数组**,而 `/import` 只读 `payload.cards` —— 裸数组被静默当成空备份(`ok:true` / `imported:0` / `skipped:0`),UI 只显示「导入完成:0」,看不出是格式不匹配。① `/import` 现在同时接受**裸数组**(v0.10.0 及以前的备份)与**信封对象** `{format, formatVersion, exportedAt, count, cards}`;形状不认识 → **400 + 人话原因**,空文件 → `warning`,坏 JSON → 原有的解析失败提示;② 导出改为**带信封**(老版本只认 `payload.cards`,信封对老版本也互通)并保留每张卡的 `status` / `store`;③ 导入去重基线改为**导入前快照**(`writeCard` 新增 `dedupAgainst`)—— 否则同一份备份里互相近似的卡会在写入过程中互相判重、被自己人吞掉一批(备份是真相源);④ 导入应答补 `total` / `skipped` / `quarantined` / `failed[]`(含每条未导入原因),提示语改为「导入完成:N 张 / 文件共 M 张 · 待审核 K · 跳过 D」,一张都没进来时按**失败样式**提示;⑤ 新增 `tests/import-roundtrip.test.mjs`(6 项:裸数组 / 信封 / 导出→导入全量往返 / 重复导入如实报重复 / 坏形状 / 审核守卫不可绕过)。⑥ **装坏了也要说人话(issue #14)**:从插件市场装出来的副本可能缺 `web/` 静态资源,那时侧边栏「记忆」只会弹一页 `{"ok":false,"error":"ENOENT …"}` —— 现在缺 `index.html` 但 `app.js` 还在就用**内置外壳**把界面拉起来(自救),缺 `app.js` 则回一段把诊断画进 `#root` 的 JS + 一页含「缺哪个文件 / 绝对路径 / 包版本 / 怎么重装」的说明;两种缺失都写进自动沉淀日志(`app.js` → `fail` 健康态亮红、只缺 `index.html` → `warn`),宿主启动时也自检一次(判据与措辞由新增的 `lib/web-assets.js` 统一,附 `tests/web-assets.test.mjs` 6 项)。⑦ 顺带修 `appendCaptureLog` 在 `DSH_HOME` 目录不存在时静默失败(诊断信息连一条都留不下)。⑧ **DSH 兼容范围放宽到 `>=0.1.5-alpha.2 <0.3.0-0`**:旧上界 `<0.2.0` 按 semver 会把 DSH `0.2.0-rc.x` 排除在外(DSH 守卫用 `includePrerelease:true`,实际装得上,但声明与事实不符)——现在覆盖整个 0.1/0.2 线,`<0.3.0-0` 仍挡住 0.3.0 及其预发布;`dsh.compatibility` 同步补 `"0.2.0-rc.2": "compatible"`(本机在官方桌面版 0.2.0-rc.2 上实测运行)。⑨ **修三个第三方插件清单长期非法 JSON**:`.claude-plugin` / `.codex-plugin` / `.cursor-plugin` 的 `description` 收尾引号被双重编码吃掉(最后改动停在 v0.9.23),DSH 不走这三个文件所以一直没暴露,但 Claude Code / Codex / Cursor 侧安装**必然解析失败**;现已重写为合法 UTF-8 JSON、`version` 跟到 0.10.1,并新增**随包体检守卫** `tests/manifests.test.mjs`(3 项:随包 JSON 全部可解析 / 三清单 `name`+`version` 与 package.json 一致 / 随包文本无编码事故乱码)。实测用户 **661 张真实备份(裸数组、3.9MB):修复前导入 0 张 → 修复后 661 张**(654 进主库 + 7 进隔离区)。`npm test` 共 **187 项** |
346
364
  | **v0.10.0** | 2026-09-30 | **两套存储:未审核内容物理隔离**。① `cards`(主库)只存 `approved`,新增 `quarantine`(隔离区,含 `quarantined_at` / `quarantine_reason`)存 `pending`/`rejected`/`deleted`;② 召回/检索/图谱/去重/导出等读路径**不再需要状态条件**(查主库即安全),根治 v0.9 审计出的三处绕过审核漏洞(去重池把新知识写进待审卡、`readCard` 直读未审核正文、`/card` 无状态校验);③ 审核流转改为**跨表搬家**(事务内完成,id 由新增的 `card_sequence` 单一发号器分配,`card_updates` 随卡改绑);④ 首次启动**自动迁移**存量非 approved 卡(不删内容,幂等);⑤ 新增 `checkMainStoreInvariant()` 不变量体检与 `tests/two-store.test.mjs`(15 条);⑥ 入料噪声闸门:剥离 DSH 运行时注入(环境快照 / team 广播 / teammate 原文 / 工具说明),挡住碎片卡与糊标题;⑦ 修 `settings-compat` 在 Windows 上的原生崩溃(`fs.watch` 父目录 → 改监听文件) |
347
365
  | **v0.9.23** | 2026-09-30 | **保存不再闪烁**。保存成功后客户端会立刻重拉 `/config`,而宿主 volatile 回流是滞后的 → 输入框会「先退回原配置、再跳回修改后的值」。现在客户端把「已保存但宿主未回显」的字段做**本地叠加**(新增 `src/client/config-merge.js` 纯函数 + 4 项单测),宿主回显一致后自动摘除,之后仍跟随宿主权威值;重置表单会清空叠加层。`npm test` 共 **139 项** |
348
366