@modusensus/dsh-mneme 0.7.3 → 0.7.5

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.
Files changed (145) hide show
  1. package/.github/workflows/test.yml +32 -0
  2. package/CHANGELOG.md +89 -0
  3. package/CONTRIBUTING.md +245 -0
  4. package/README.md +159 -419
  5. package/SECURITY.md +674 -0
  6. package/docs/devlog/2026-08-14-dsh-mneme-dev-log.md +247 -0
  7. package/docs/devlog/2026-08-15-dsh-mneme-audit-stress-dev-log.md +145 -0
  8. package/docs/devlog/2026-08-15-dsh-mneme-pipeline-dev-log.md +56 -0
  9. package/docs/devlog/2026-08-15-dsh-mneme-reflection-dev-log.md +77 -0
  10. package/docs/devlog/2026-08-15-dsh-mneme-review-fixes-dev-log.md +64 -0
  11. package/docs/devlog/2026-08-15-dsh-mneme-semantic-dev-log.md +90 -0
  12. package/dsh-mneme/CHANGELOG.md +358 -0
  13. package/dsh-mneme/LICENSE +21 -0
  14. package/dsh-mneme/README.md +493 -0
  15. package/dsh-mneme/docs/AGENT_MEMORY_RESEARCH.md +183 -0
  16. package/dsh-mneme/docs/ENTITIES.md +245 -0
  17. package/dsh-mneme/docs/LOCAL_MODEL.md +141 -0
  18. package/dsh-mneme/docs/MIGRATION.md +127 -0
  19. package/dsh-mneme/docs/SEMANTIC.md +256 -0
  20. package/dsh-mneme/docs/SLEEP.md +163 -0
  21. package/{src → dsh-mneme/lib}/api.js +15 -0
  22. package/{lib → dsh-mneme/lib}/client.js +192 -3
  23. package/{lib → dsh-mneme/lib}/config.js +7 -0
  24. package/{lib → dsh-mneme/lib}/inject.js +20 -3
  25. package/{lib → dsh-mneme/lib}/mirror.js +3 -1
  26. package/{lib → dsh-mneme/lib}/quality-filter.js +3 -1
  27. package/{src → dsh-mneme/lib}/service.js +9 -5
  28. package/{lib → dsh-mneme/lib}/store.js +35 -1
  29. package/{lib → dsh-mneme/lib}/summarize.js +2 -2
  30. package/{src → dsh-mneme/lib}/tools.js +3 -3
  31. package/dsh-mneme/package-lock.json +1936 -0
  32. package/dsh-mneme/package.json +83 -0
  33. package/{lib → dsh-mneme/src}/api.js +15 -0
  34. package/{src → dsh-mneme/src}/config.js +7 -0
  35. package/{src → dsh-mneme/src}/inject.js +20 -3
  36. package/{src → dsh-mneme/src}/mirror.js +3 -1
  37. package/{src → dsh-mneme/src}/quality-filter.js +3 -1
  38. package/{lib → dsh-mneme/src}/service.js +9 -5
  39. package/{src → dsh-mneme/src}/store.js +35 -1
  40. package/{src → dsh-mneme/src}/summarize.js +2 -2
  41. package/{lib → dsh-mneme/src}/tools.js +3 -3
  42. package/{test → dsh-mneme/test}/config.test.js +7 -0
  43. package/{test → dsh-mneme/test}/inject.test.js +57 -0
  44. package/dsh-mneme/test/layered-types-stats.test.js +144 -0
  45. package/package.json +18 -43
  46. package//346/250/252/345/271/205.png +0 -0
  47. /package/{cordis.patch.yml → dsh-mneme/cordis.patch.yml} +0 -0
  48. /package/{lib → dsh-mneme/lib}/commands.js +0 -0
  49. /package/{lib → dsh-mneme/lib}/dream/clustering.js +0 -0
  50. /package/{lib → dsh-mneme/lib}/dream/decisions.js +0 -0
  51. /package/{lib → dsh-mneme/lib}/dream/sleep.js +0 -0
  52. /package/{lib → dsh-mneme/lib}/dream/tag-extractor.js +0 -0
  53. /package/{lib → dsh-mneme/lib}/dream.js +0 -0
  54. /package/{lib → dsh-mneme/lib}/embedding.js +0 -0
  55. /package/{lib → dsh-mneme/lib}/entities/extractor.js +0 -0
  56. /package/{lib → dsh-mneme/lib}/heat.js +0 -0
  57. /package/{lib → dsh-mneme/lib}/hot-memory.js +0 -0
  58. /package/{lib → dsh-mneme/lib}/index.js +0 -0
  59. /package/{lib → dsh-mneme/lib}/local-embedder.js +0 -0
  60. /package/{lib → dsh-mneme/lib}/parser/tag.js +0 -0
  61. /package/{lib → dsh-mneme/lib}/parser/wiki-link.js +0 -0
  62. /package/{lib → dsh-mneme/lib}/reranker.js +0 -0
  63. /package/{lib → dsh-mneme/lib}/search/adaptive.js +0 -0
  64. /package/{lib → dsh-mneme/lib}/search/bm25.js +0 -0
  65. /package/{lib → dsh-mneme/lib}/search/tag-boost.js +0 -0
  66. /package/{lib → dsh-mneme/lib}/settings.js +0 -0
  67. /package/{lib → dsh-mneme/lib}/vector-index.js +0 -0
  68. /package/{scripts → dsh-mneme/scripts}/benchmark-embed.js +0 -0
  69. /package/{scripts → dsh-mneme/scripts}/benchmark-recall.js +0 -0
  70. /package/{scripts → dsh-mneme/scripts}/benchmark-rerank.js +0 -0
  71. /package/{scripts → dsh-mneme/scripts}/e2e-dsh.js +0 -0
  72. /package/{scripts → dsh-mneme/scripts}/stress-dsh.js +0 -0
  73. /package/{scripts → dsh-mneme/scripts}/sync-lib.js +0 -0
  74. /package/{src → dsh-mneme/src}/commands.js +0 -0
  75. /package/{src → dsh-mneme/src}/dream/clustering.js +0 -0
  76. /package/{src → dsh-mneme/src}/dream/decisions.js +0 -0
  77. /package/{src → dsh-mneme/src}/dream/sleep.js +0 -0
  78. /package/{src → dsh-mneme/src}/dream/tag-extractor.js +0 -0
  79. /package/{src → dsh-mneme/src}/dream.js +0 -0
  80. /package/{src → dsh-mneme/src}/embedding.js +0 -0
  81. /package/{src → dsh-mneme/src}/entities/extractor.js +0 -0
  82. /package/{src → dsh-mneme/src}/heat.js +0 -0
  83. /package/{src → dsh-mneme/src}/hot-memory.js +0 -0
  84. /package/{src → dsh-mneme/src}/index.js +0 -0
  85. /package/{src → dsh-mneme/src}/local-embedder.js +0 -0
  86. /package/{src → dsh-mneme/src}/parser/tag.js +0 -0
  87. /package/{src → dsh-mneme/src}/parser/wiki-link.js +0 -0
  88. /package/{src → dsh-mneme/src}/reranker.js +0 -0
  89. /package/{src → dsh-mneme/src}/search/adaptive.js +0 -0
  90. /package/{src → dsh-mneme/src}/search/bm25.js +0 -0
  91. /package/{src → dsh-mneme/src}/search/tag-boost.js +0 -0
  92. /package/{src → dsh-mneme/src}/settings.js +0 -0
  93. /package/{src → dsh-mneme/src}/vector-index.js +0 -0
  94. /package/{test → dsh-mneme/test}/api.test.js +0 -0
  95. /package/{test → dsh-mneme/test}/audit.test.js +0 -0
  96. /package/{test → dsh-mneme/test}/benchmark.test.js +0 -0
  97. /package/{test → dsh-mneme/test}/boundary-v0625.test.js +0 -0
  98. /package/{test → dsh-mneme/test}/client.test.js +0 -0
  99. /package/{test → dsh-mneme/test}/clustering.test.js +0 -0
  100. /package/{test → dsh-mneme/test}/commands.test.js +0 -0
  101. /package/{test → dsh-mneme/test}/conflict-freeze.test.js +0 -0
  102. /package/{test → dsh-mneme/test}/directory.test.js +0 -0
  103. /package/{test → dsh-mneme/test}/dream.test.js +0 -0
  104. /package/{test → dsh-mneme/test}/entities.test.js +0 -0
  105. /package/{test → dsh-mneme/test}/epistemic.test.js +0 -0
  106. /package/{test → dsh-mneme/test}/fnew-0112.test.js +0 -0
  107. /package/{test → dsh-mneme/test}/fnew-03.test.js +0 -0
  108. /package/{test → dsh-mneme/test}/graph-api.test.js +0 -0
  109. /package/{test → dsh-mneme/test}/heat.test.js +0 -0
  110. /package/{test → dsh-mneme/test}/helpers/dream-mock.js +0 -0
  111. /package/{test → dsh-mneme/test}/hot-memory.test.js +0 -0
  112. /package/{test → dsh-mneme/test}/llm-audit.test.js +0 -0
  113. /package/{test → dsh-mneme/test}/local-embedder.test.js +0 -0
  114. /package/{test → dsh-mneme/test}/mirror-dirty.test.js +0 -0
  115. /package/{test → dsh-mneme/test}/mirror-edit-digest.test.js +0 -0
  116. /package/{test → dsh-mneme/test}/mirror-generation.test.js +0 -0
  117. /package/{test → dsh-mneme/test}/mirror.test.js +0 -0
  118. /package/{test → dsh-mneme/test}/normalize-decisions.test.js +0 -0
  119. /package/{test → dsh-mneme/test}/peer-blockers.test.js +0 -0
  120. /package/{test → dsh-mneme/test}/policy-epoch.test.js +0 -0
  121. /package/{test → dsh-mneme/test}/provenance.test.js +0 -0
  122. /package/{test → dsh-mneme/test}/quality-filter.test.js +0 -0
  123. /package/{test → dsh-mneme/test}/reasoning-effort.test.js +0 -0
  124. /package/{test → dsh-mneme/test}/recall-evals.test.js +0 -0
  125. /package/{test → dsh-mneme/test}/recall-layer.test.js +0 -0
  126. /package/{test → dsh-mneme/test}/recall-runs.test.js +0 -0
  127. /package/{test → dsh-mneme/test}/receipt-chain.test.js +0 -0
  128. /package/{test → dsh-mneme/test}/reflection.test.js +0 -0
  129. /package/{test → dsh-mneme/test}/reranker.test.js +0 -0
  130. /package/{test → dsh-mneme/test}/search-fusion.test.js +0 -0
  131. /package/{test → dsh-mneme/test}/semantic.test.js +0 -0
  132. /package/{test → dsh-mneme/test}/service-search.test.js +0 -0
  133. /package/{test → dsh-mneme/test}/service.test.js +0 -0
  134. /package/{test → dsh-mneme/test}/settings.test.js +0 -0
  135. /package/{test → dsh-mneme/test}/sleep-heat.test.js +0 -0
  136. /package/{test → dsh-mneme/test}/sleep.test.js +0 -0
  137. /package/{test → dsh-mneme/test}/store.test.js +0 -0
  138. /package/{test → dsh-mneme/test}/stress.test.js +0 -0
  139. /package/{test → dsh-mneme/test}/summarize.test.js +0 -0
  140. /package/{test → dsh-mneme/test}/tag-boost.test.js +0 -0
  141. /package/{test → dsh-mneme/test}/tag.test.js +0 -0
  142. /package/{test → dsh-mneme/test}/tools.test.js +0 -0
  143. /package/{test → dsh-mneme/test}/updated-at-semantics.test.js +0 -0
  144. /package/{test → dsh-mneme/test}/vector-index.test.js +0 -0
  145. /package/{test → dsh-mneme/test}/wiki-link.test.js +0 -0
@@ -0,0 +1,32 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ node-version: [24]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: ${{ matrix.node-version }}
21
+ - name: Install dependencies
22
+ working-directory: dsh-mneme
23
+ run: npm ci
24
+ - name: Run tests
25
+ working-directory: dsh-mneme
26
+ run: npm run test:coverage
27
+ - name: Upload coverage to Codecov
28
+ uses: codecov/codecov-action@v4
29
+ with:
30
+ token: ${{ secrets.CODECOV_TOKEN }}
31
+ files: dsh-mneme/coverage/lcov.info
32
+ fail_ci_if_error: false
package/CHANGELOG.md ADDED
@@ -0,0 +1,89 @@
1
+ # Changelog
2
+
3
+ All notable changes to dsh-mneme are documented here.
4
+
5
+ ## [Unreleased]
6
+
7
+ - **诚实审计修复(v0.2.7,F-03)**
8
+ - autoDream 决策无变更且 summary 为空时,不再误报 ok:true——新增 `noop` 状态(ok:false,baseline 不刷新),避免空跑循环
9
+ - 有变更但 summary 缺失 → `degraded`(ok:true 但如实标记 summary 缺失)
10
+ - parseReceipt 支持 ok/noop/degraded/reconcile/failed
11
+ - 测试 259 → **263**
12
+
13
+ - **社区贡献 · 嵌入式面板 UI 改进(PR #2,@Liuxin4950)**
14
+ - 记忆面板与设置面板的嵌入模式(settings.section 插槽)不再复用弹窗面板样式(去掉 boxShadow / background / borderRadius / padding),改为全宽平铺渲染,消除 DSH 设置页内多余的悬浮卡片与阴影
15
+ - 弹窗(portal)模式保持原有面板样式不变;新增回归测试锁定 embedded 分支不携带 modal chrome
16
+
17
+ - **安全审计修复(v0.2.5)**
18
+ - 并发安全:CAS 冲突守卫——过期快照不再覆盖并发写入(防丢更新)
19
+ - 事务化决策应用:merge/archive 原子提交,receipt 反映已提交子步骤,部分提交 = reconcile(绝不虚报 ok)
20
+ - 压测硬断言:lost-update 与多步原子性失败即非零退出(`npm run stress`)
21
+ - 运行时人工编辑三方合并(three-way),不再静默覆盖
22
+ - 新增 `memory_archive` 工具(第 7 个模型工具)+ `memory_list include_archived`,归档可恢复
23
+ - reranker 改为 opt-in:`rerankEnabled=false`、`rerankProvider=none` 默认(裸装不加载 onnxruntime)
24
+ - npm `files` 纳入 scripts/test,tarball 内可直接跑压测
25
+ - 测试 236 → **258**(+22)
26
+
27
+ - **安全加固(v0.2.4)**:API 鉴权 `apiToken`(写操作与密钥端点要求 Bearer 校验)+ `apiKey` 掩码回传 + timing-safe token 比对
28
+
29
+ - **审查修复补丁(v0.2.3)**
30
+ - failure 记录增加 `before` JSON 快照(title/content/importance 变更可追溯,不只 content)
31
+ - vector-index `rebuildIndex` guard 改为检查 `embedSingle`(修复 embed/embedSingle 不一致导致的静默跳过)
32
+
33
+ - **流水线补全(v0.2.2)**
34
+ - reflection 修复:failure 记录检查 title/importance 变化(不只 content);支持 query 上下文(memory_update 加 `reason` 参数);update 校验失败不污染 claimed;`failure_memories` 清理(`deleteOldFailures` + 启动自动清理 90 天前)
35
+ - 专项测试补全:`vector-index.test.js`(modelHash 漂移/重建/增量)+ `service-search.test.js`(hybrid/auto/rerank 端到端)
36
+ - api.js `/search` 的 mode 参数文档化
37
+ - 测试 212 → **233**
38
+
39
+ - **反思更新(v0.2.1)**:`update` 决策 + 失败追踪
40
+ - autoDream 新增 `update` 决策类型:修正单条记忆的过时/错误内容(单 id、必须实际变化、非 summary、24h 保护、每次 ≤2)
41
+ - 审计记录 update 的 `_before` 快照;update 后向量索引同步
42
+ - `failure_memories` 表:记录用户纠正(user_correction)+ 查询/统计接口
43
+ - 配置:`reflectionUpdateEnabled` / `reflectionFailureTracking` / `reflectionUpdateMaxPerRun` / `reflectionUpdateMinAgeHours`
44
+
45
+ - **Semantic 升级(v0.2.0-semantic)**:完全离线语义记忆引擎
46
+ - 本地 Embedding:`embedProvider: local`(ONNX bge-small-zh-v1.5,transformers.js/onnxruntime)或 `ollama`;原 `openai` 外部 API 保留为默认,向后兼容
47
+ - 向量索引层:`vector_meta` 模型指纹追踪 + 索引统计(`/api/dsh-mneme/semantic`)
48
+ - Rerank 精排:`rerankEnabled`(bge-reranker-base cross-encoder),召回后精排 Top-K,失败自动跳过
49
+ - 混合搜索:`memory_search` 新增 `mode: hybrid`(向量优先 + 关键词补位);`auto` 保持关键词优先 + 向量补位
50
+ - autoDream 语义增强:K-Means 聚类预分组(k-means++)、`[潜在冲突]` 向量相似度标记、整理后向量索引重建
51
+ - 模型下载:断点续传 + 缓存(transformers.js 内置);`.npmrc` 跳过 onnxruntime CUDA 下载避免安装失败
52
+ - 文档:`docs/SEMANTIC.md` / `docs/LOCAL_MODEL.md` / `docs/MIGRATION.md` + 基准脚本 `benchmark-embed` / `benchmark-rerank`
53
+ - autoDream 裁决审计:每次运行写入 `dream_runs`(输入快照 sha256 digest + 完整输入快照 + LLM 决策清单 + 逐 id 去向 + receipt `dsh-mneme:run:<id>:<status>:<hash>:<count>:<applied>`),可离线回放、定位静默错误
54
+ - 幂等决策应用:merge / conflict 重复应用无累积副作用(来源注释不重复追加),防并发/重放下的重复合并
55
+ - 三轴线压测 `npm run stress`:长会话检索(Recall@k、陈旧残留率)/ 冲突裁决(可重放仲裁集)/ 多 Agent 并发(丢更新、重复合并、事务/崩溃恢复)
56
+
57
+ ## [0.1.6] - 2026-08-14
58
+
59
+ - Vector (semantic) search via OpenAI-compatible embeddings endpoint, with automatic fallback to LIKE keyword search on failure
60
+ - Web GUI memory panel: browse by type, full-text + semantic search
61
+
62
+ ## [0.1.5] - 2026-08-14
63
+
64
+ - autoDream consolidation refinements: conflict resolution with source tracking, fail-safe decision validation
65
+
66
+ ## [0.1.4] - 2026-08-14
67
+
68
+ - User settings: profile + behavior rules injected every turn
69
+ - Custom slash commands (register, route to agent)
70
+
71
+ ## [0.1.3] - 2026-08-14
72
+
73
+ - autoDream background consolidation: dedup / merge / archive / conflict resolution
74
+
75
+ ## [0.1.2] - 2026-08-14
76
+
77
+ - Session summarization: auto-distill preferences / decisions / lessons at session end
78
+ - Web panel improvements
79
+
80
+ ## [0.1.1] - 2026-08-13
81
+
82
+ - Memory tools: memory_save / memory_search / memory_list / memory_update / memory_delete / memory_forget
83
+ - Markdown mirror sync (human-editable, manual edits take priority)
84
+
85
+ ## [0.1.0] - 2026-08-13
86
+
87
+ - Initial release: cross-session memory for DeepSeek Harness
88
+ - SQLite store (node:sqlite, zero native deps) + human-editable Markdown mirror
89
+ - Auto-injection of relevant memories at session start
@@ -0,0 +1,245 @@
1
+ # Contributing
2
+
3
+ > **English** | [中文](#贡献指南)
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - **Node.js 24+** (CI runs on Node 24)
10
+ - **npm** (the repo uses npm; CI installs with `npm ci`)
11
+ - **git** (on Windows, watch LF/CRLF: the repo is LF-normalized and git converts automatically)
12
+
13
+ ---
14
+
15
+ ## Repository Layout
16
+
17
+ The repository root is the publishing manifest; the actual plugin code lives in the `dsh-mneme/` subdirectory:
18
+
19
+ ```
20
+ dsh-mneme-1/
21
+ ├── package.json # npm publishing manifest (main → dsh-mneme/lib/index.js)
22
+ ├── README.md / CHANGELOG.md / SECURITY.md
23
+ └── dsh-mneme/ # the plugin itself
24
+ ├── src/ # source (ESM) — all feature work happens here
25
+ ├── lib/ # build output; DSH actually loads lib/index.js
26
+ ├── scripts/ # sync-lib.js, e2e-dsh.js, stress-dsh.js, benchmark-*
27
+ ├── test/ # node:test test suite
28
+ ├── docs/ # SEMANTIC / SLEEP / ENTITIES / MIGRATION deep-dives
29
+ ├── package.json # plugin metadata and scripts
30
+ └── cordis.patch.yml # DSH injection patch
31
+ ```
32
+
33
+ **Key convention: `src/` is the single source of truth; `lib/` is build output.**
34
+
35
+ - Write code only in `src/`, then run `npm run sync` to mirror changes into `lib/`.
36
+ - **Never edit `lib/` by hand** — the next sync overwrites it. The only exception is `lib/client.js` (the Web-panel bundle, authored independently; sync never touches it).
37
+ - `npm pack` / `npm publish` run sync automatically via the `prepack` hook, so a published tarball always ships a fresh `lib/`.
38
+
39
+ ---
40
+
41
+ ## Local Development
42
+
43
+ ```bash
44
+ # 1. Install dependencies (inside dsh-mneme/)
45
+ cd dsh-mneme
46
+ npm ci
47
+
48
+ # 2. After editing files under src/, mirror to lib/
49
+ npm run sync
50
+
51
+ # 3. Run the tests
52
+ npm test # node --test test/*.test.js
53
+ npm run test:coverage # c8 coverage
54
+ ```
55
+
56
+ Common scripts (all run under `dsh-mneme/`):
57
+
58
+ | Command | Description |
59
+ |---------|-------------|
60
+ | `npm test` | Full unit/integration suite |
61
+ | `npm run test:coverage` | Tests + c8 coverage (used by CI) |
62
+ | `npm run e2e` | End-to-end smoke test (scripts/e2e-dsh.js) |
63
+ | `npm run stress` | Three-axis stress test (scripts/stress-dsh.js) |
64
+ | `npm run sync` | src/ → lib/ mirror |
65
+
66
+ ---
67
+
68
+ ## Testing Conventions
69
+
70
+ - Tests use Node's built-in **`node:test` + `node:assert/strict`**; no third-party test framework.
71
+ - New features require corresponding tests; **changing core logic (e.g. model routing, decision validation) must update the affected test assertions** so the suite stays green before committing.
72
+ - Test files live in `test/`, named `*.test.js`; shared mocks go in `test/helpers/` (e.g. `dream-mock.js`).
73
+ - Known environment dependency: a few cases in `reranker.test.js` need `@huggingface/transformers` (locally this one case fails without the package; it is unrelated to repo logic and CI installs it and passes).
74
+
75
+ ---
76
+
77
+ ## Code Style & Engineering Conventions
78
+
79
+ - **ESM**: the repo is `"type": "module"`; everything uses `import`/`export`.
80
+ - **Comments in Chinese**, biased toward "why" — core logic, config options, and fail-safe branches must explain their intent.
81
+ - **Fail-safe is a hard rule**: local failures in any background LLM path (autoDream / sleep / autoTag / summarization) must skip or degrade, **never** block the main flow (write, recall, injection).
82
+ - **Config is defined centrally with schemastery in `src/config.js`** (`z.object` + `.default(...)`); new options must keep docs and default-value semantics in sync.
83
+ - **Audit honesty**: a run's status (ok / noop / degraded / reconcile / failed) must reflect what actually committed — never a fake ok.
84
+
85
+ ---
86
+
87
+ ## Commits & Branches
88
+
89
+ - Commit messages follow **Conventional Commits**:
90
+
91
+ ```
92
+ fix(dream): reject cross-type merge as a whole batch (Issue #26)
93
+ feat(tag): add tag-weighted recall
94
+ docs: expand the SEMANTIC doc
95
+ release: v0.6.9 ...
96
+ ```
97
+
98
+ - Run `npm test` before committing and confirm green (note any environment-only known exceptions in the commit message).
99
+ - **Small fixes**: can push straight to `main` (this is the project's workflow).
100
+ - **Larger features / breaking changes**: open an Issue first to state the motivation and design, then submit a PR — the PR triggers CI (Node 24 + full suite + Codecov).
101
+ - Release operations (version bumps, tags, Releases, npm publish) are performed by maintainers — see the next section.
102
+
103
+ ---
104
+
105
+ ## Release Process (Maintainers)
106
+
107
+ Versioning follows semantic versioning (`MAJOR.MINOR.PATCH`). Full flow:
108
+
109
+ 1. **Update CHANGELOG**: add a version entry (`## [X.Y.Z] - date`, split into 「修复 / 新增 / 测试」) at the top of `dsh-mneme/CHANGELOG.md`; update the root `CHANGELOG.md` if it tracks the same.
110
+ 2. **Bump version**: change `version` in `dsh-mneme/package.json` and `package-lock.json`; the root `package.json` is synced automatically by the `prepublishOnly` hook — no manual edit.
111
+ 3. **Full test pass**: `npm test` must be green.
112
+ 4. **Commit and push**: commit → `git push origin main` → `git tag vX.Y.Z` → `git push origin vX.Y.Z`.
113
+ 5. **Create a GitHub Release**: title `vX.Y.Z`, body referencing the matching CHANGELOG entry (review before publishing).
114
+ 6. **Publish to npm**: run `npm publish` from the **repository root** (`prepublishOnly` copies the version from `dsh-mneme/package.json` into the root `package.json`; `prepack` syncs `lib/`).
115
+
116
+ ---
117
+
118
+ ## Miscellaneous
119
+
120
+ - Security issues go through [SECURITY.md](SECURITY.md) or a GitHub Security Advisory — never paste sensitive info into a public Issue.
121
+ - Be respectful and constructive; PRs touching data integrity, security, or behavior must include reproduction steps and regression evidence.
122
+
123
+ ---
124
+
125
+ # 贡献指南
126
+
127
+ > **中文** | [English](#contributing)
128
+
129
+ ---
130
+
131
+ ## 环境要求
132
+
133
+ - **Node.js 24+**(CI 在 node 24 上运行)
134
+ - **npm**(仓库使用 npm,CI 用 `npm ci`)
135
+ - **git**(Windows 下注意 LF/CRLF:仓库以 LF 为准,git 会自动转换)
136
+
137
+ ---
138
+
139
+ ## 代码库布局
140
+
141
+ 仓库根目录是发布清单,实际插件代码在 `dsh-mneme/` 子目录:
142
+
143
+ ```
144
+ dsh-mneme-1/
145
+ ├── package.json # npm 包发布清单(main 指向 dsh-mneme/lib/index.js)
146
+ ├── README.md / CHANGELOG.md / SECURITY.md
147
+ └── dsh-mneme/ # 插件本体
148
+ ├── src/ # 源码(ESM),所有功能都在这里开发
149
+ ├── lib/ # 构建产物,DSH 实际加载的是 lib/index.js
150
+ ├── scripts/ # sync-lib.js、e2e-dsh.js、stress-dsh.js、benchmark-*
151
+ ├── test/ # node:test 测试
152
+ ├── docs/ # SEMANTIC / SLEEP / ENTITIES / MIGRATION 等专题文档
153
+ ├── package.json # 插件包元数据与 scripts
154
+ └── cordis.patch.yml # DSH 注入补丁
155
+ ```
156
+
157
+ **关键约定:`src/` 是唯一的事实来源,`lib/` 是构建产物。**
158
+
159
+ - 所有代码改动只写 `src/`,改完必须运行 `npm run sync` 同步到 `lib/`。
160
+ - **不要手工编辑 `lib/`**——下次 sync 会覆盖你的改动。唯一的例外是 `lib/client.js`(Web 面板打包产物,独立创作,sync 不会触碰它)。
161
+ - `npm pack` / `npm publish` 会通过 `prepack` 钩子自动执行 sync,所以发布产物永远是新鲜的 `lib/`。
162
+
163
+ ---
164
+
165
+ ## 本地开发
166
+
167
+ ```bash
168
+ # 1. 安装依赖(在 dsh-mneme/ 目录内)
169
+ cd dsh-mneme
170
+ npm ci
171
+
172
+ # 2. 修改 src/ 下的文件后,同步到 lib/
173
+ npm run sync
174
+
175
+ # 3. 跑测试
176
+ npm test # node --test test/*.test.js
177
+ npm run test:coverage # c8 覆盖率
178
+ ```
179
+
180
+ 常用脚本(均在 `dsh-mneme/` 下):
181
+
182
+ | 命令 | 说明 |
183
+ |------|------|
184
+ | `npm test` | 全量单元/集成测试 |
185
+ | `npm run test:coverage` | 测试 + c8 覆盖率(CI 使用) |
186
+ | `npm run e2e` | 端到端冒烟(scripts/e2e-dsh.js) |
187
+ | `npm run stress` | 三轴线压测(scripts/stress-dsh.js) |
188
+ | `npm run sync` | src/ → lib/ 同步 |
189
+
190
+ ---
191
+
192
+ ## 测试约定
193
+
194
+ - 测试框架为 Node 内置 **`node:test` + `node:assert/strict`**,不引入第三方测试库。
195
+ - 新增功能必须有对应测试;**修改核心逻辑(如模型路由、决策校验)时必须同步更新受影响用例的断言**,保证全量测试通过后提交。
196
+ - 测试文件放在 `test/`,命名 `*.test.js`;共享 mock 放 `test/helpers/`(如 `dream-mock.js`)。
197
+ - 已知环境依赖:`reranker.test.js` 的个别用例需要 `@huggingface/transformers`(本地未安装该包时这 1 例会失败,与本仓库逻辑无关,CI 会正常安装并通过)。
198
+
199
+ ---
200
+
201
+ ## 代码风格与工程约定
202
+
203
+ - **ESM**:仓库 `"type": "module"`,全部使用 `import`/`export`。
204
+ - **注释用中文**,且偏向"解释为什么"——核心逻辑、配置项、fail-safe 分支都要求写清意图。
205
+ - **fail-safe 是硬性约定**:所有后台 LLM 链路(autoDream / sleep / autoTag / 摘要)中的局部失败只能跳过或降级,**绝不能**阻断主流程(写入、检索、注入)。
206
+ - **配置项统一用 schemastery 定义在 `src/config.js`**(`z.object` + `.default(...)`),新增配置记得同步文档与默认值语义。
207
+ - **审计诚实性**:任何 run 的状态(ok / noop / degraded / reconcile / failed)必须反映真实提交结果,绝不虚报。
208
+
209
+ ---
210
+
211
+ ## 提交与分支
212
+
213
+ - 提交信息遵循 **Conventional Commits**:
214
+
215
+ ```
216
+ fix(dream): 修复跨类型 merge 整单拒绝(Issue #26)
217
+ feat(tag): 新增标签加权召回
218
+ docs: 补充 SEMANTIC 文档
219
+ release: v0.6.9 ...
220
+ ```
221
+
222
+ - 提交前跑一遍 `npm test` 确认全绿(环境相关的已知例外需在提交说明里注明)。
223
+ - **小改动 / 修复**:可直推 `main`(本项目采用此工作流)。
224
+ - **较大功能 / 破坏性改动**:建议先开 Issue 说明动机与方案,再通过 PR 提交,PR 会触发 CI 校验(node 24 + 全量测试 + Codecov)。
225
+ - 发布相关操作(改版本号、打 tag、发 Release、npm publish)由维护者执行,详见下节。
226
+
227
+ ---
228
+
229
+ ## 发布流程(维护者)
230
+
231
+ 版本号遵循语义化版本(`MAJOR.MINOR.PATCH`)。完整流程:
232
+
233
+ 1. **更新 CHANGELOG**:在 `dsh-mneme/CHANGELOG.md` 顶部新增版本条目(`## [X.Y.Z] - 日期`,分「修复 / 新增 / 测试」小节),根目录 `CHANGELOG.md` 如涉及同步更新。
234
+ 2. **更新版本号**:改 `dsh-mneme/package.json` 的 `version` 与 `package-lock.json`;根目录 `package.json` 由 `prepublishOnly` 钩子自动同步,无需手改。
235
+ 3. **全量测试**:`npm test` 确认通过。
236
+ 4. **提交并推送**:commit → `git push origin main` → `git tag vX.Y.Z` → `git push origin vX.Y.Z`。
237
+ 5. **创建 GitHub Release**:标题为 `vX.Y.Z`,正文引用 CHANGELOG 对应条目(发布前需人工过目)。
238
+ 6. **发布 npm**:在**仓库根目录**执行 `npm publish`(`prepublishOnly` 会自动把 `dsh-mneme/package.json` 的版本号写入根 `package.json`,`prepack` 自动 sync `lib/`)。
239
+
240
+ ---
241
+
242
+ ## 其他
243
+
244
+ - 安全问题请走 [SECURITY.md](SECURITY.md) 或 GitHub Security Advisory,不要在公开 Issue 贴敏感信息。
245
+ - 保持礼貌与建设性;涉及数据损坏 / 安全 / 破坏性改动的 PR 需附复现步骤与回归证据。