@synth-coder/memhub 0.1.0

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 (104) hide show
  1. package/.eslintrc.cjs +46 -0
  2. package/.github/workflows/ci.yml +74 -0
  3. package/.iflow/commands/opsx-apply.md +152 -0
  4. package/.iflow/commands/opsx-archive.md +157 -0
  5. package/.iflow/commands/opsx-explore.md +173 -0
  6. package/.iflow/commands/opsx-propose.md +106 -0
  7. package/.iflow/skills/openspec-apply-change/SKILL.md +156 -0
  8. package/.iflow/skills/openspec-archive-change/SKILL.md +114 -0
  9. package/.iflow/skills/openspec-explore/SKILL.md +288 -0
  10. package/.iflow/skills/openspec-propose/SKILL.md +110 -0
  11. package/.prettierrc +11 -0
  12. package/README.md +171 -0
  13. package/README.zh-CN.md +169 -0
  14. package/dist/src/contracts/index.d.ts +7 -0
  15. package/dist/src/contracts/index.d.ts.map +1 -0
  16. package/dist/src/contracts/index.js +10 -0
  17. package/dist/src/contracts/index.js.map +1 -0
  18. package/dist/src/contracts/mcp.d.ts +194 -0
  19. package/dist/src/contracts/mcp.d.ts.map +1 -0
  20. package/dist/src/contracts/mcp.js +112 -0
  21. package/dist/src/contracts/mcp.js.map +1 -0
  22. package/dist/src/contracts/schemas.d.ts +1153 -0
  23. package/dist/src/contracts/schemas.d.ts.map +1 -0
  24. package/dist/src/contracts/schemas.js +246 -0
  25. package/dist/src/contracts/schemas.js.map +1 -0
  26. package/dist/src/contracts/types.d.ts +328 -0
  27. package/dist/src/contracts/types.d.ts.map +1 -0
  28. package/dist/src/contracts/types.js +30 -0
  29. package/dist/src/contracts/types.js.map +1 -0
  30. package/dist/src/index.d.ts +8 -0
  31. package/dist/src/index.d.ts.map +1 -0
  32. package/dist/src/index.js +8 -0
  33. package/dist/src/index.js.map +1 -0
  34. package/dist/src/server/index.d.ts +5 -0
  35. package/dist/src/server/index.d.ts.map +1 -0
  36. package/dist/src/server/index.js +5 -0
  37. package/dist/src/server/index.js.map +1 -0
  38. package/dist/src/server/mcp-server.d.ts +80 -0
  39. package/dist/src/server/mcp-server.d.ts.map +1 -0
  40. package/dist/src/server/mcp-server.js +263 -0
  41. package/dist/src/server/mcp-server.js.map +1 -0
  42. package/dist/src/services/index.d.ts +5 -0
  43. package/dist/src/services/index.d.ts.map +1 -0
  44. package/dist/src/services/index.js +5 -0
  45. package/dist/src/services/index.js.map +1 -0
  46. package/dist/src/services/memory-service.d.ts +105 -0
  47. package/dist/src/services/memory-service.d.ts.map +1 -0
  48. package/dist/src/services/memory-service.js +447 -0
  49. package/dist/src/services/memory-service.js.map +1 -0
  50. package/dist/src/storage/frontmatter-parser.d.ts +69 -0
  51. package/dist/src/storage/frontmatter-parser.d.ts.map +1 -0
  52. package/dist/src/storage/frontmatter-parser.js +207 -0
  53. package/dist/src/storage/frontmatter-parser.js.map +1 -0
  54. package/dist/src/storage/index.d.ts +6 -0
  55. package/dist/src/storage/index.d.ts.map +1 -0
  56. package/dist/src/storage/index.js +6 -0
  57. package/dist/src/storage/index.js.map +1 -0
  58. package/dist/src/storage/markdown-storage.d.ts +76 -0
  59. package/dist/src/storage/markdown-storage.d.ts.map +1 -0
  60. package/dist/src/storage/markdown-storage.js +193 -0
  61. package/dist/src/storage/markdown-storage.js.map +1 -0
  62. package/dist/src/utils/index.d.ts +5 -0
  63. package/dist/src/utils/index.d.ts.map +1 -0
  64. package/dist/src/utils/index.js +5 -0
  65. package/dist/src/utils/index.js.map +1 -0
  66. package/dist/src/utils/slugify.d.ts +24 -0
  67. package/dist/src/utils/slugify.d.ts.map +1 -0
  68. package/dist/src/utils/slugify.js +56 -0
  69. package/dist/src/utils/slugify.js.map +1 -0
  70. package/docs/architecture.md +349 -0
  71. package/docs/contracts.md +119 -0
  72. package/docs/prompt-template.md +79 -0
  73. package/docs/proposal-close-gates.md +58 -0
  74. package/docs/tool-calling-policy.md +107 -0
  75. package/package.json +53 -0
  76. package/src/contracts/index.ts +12 -0
  77. package/src/contracts/mcp.ts +303 -0
  78. package/src/contracts/schemas.ts +311 -0
  79. package/src/contracts/types.ts +414 -0
  80. package/src/index.ts +8 -0
  81. package/src/server/index.ts +5 -0
  82. package/src/server/mcp-server.ts +352 -0
  83. package/src/services/index.ts +5 -0
  84. package/src/services/memory-service.ts +548 -0
  85. package/src/storage/frontmatter-parser.ts +243 -0
  86. package/src/storage/index.ts +6 -0
  87. package/src/storage/markdown-storage.ts +236 -0
  88. package/src/utils/index.ts +5 -0
  89. package/src/utils/slugify.ts +63 -0
  90. package/test/contracts/schemas.test.ts +313 -0
  91. package/test/contracts/types.test.ts +21 -0
  92. package/test/frontmatter-parser-more.test.ts +94 -0
  93. package/test/server/mcp-server-internals.test.ts +257 -0
  94. package/test/server/mcp-server.test.ts +97 -0
  95. package/test/services/memory-service-edge.test.ts +248 -0
  96. package/test/services/memory-service.test.ts +279 -0
  97. package/test/storage/frontmatter-parser.test.ts +223 -0
  98. package/test/storage/markdown-storage.test.ts +217 -0
  99. package/test/storage/storage-edge.test.ts +238 -0
  100. package/test/utils/slugify-edge.test.ts +94 -0
  101. package/test/utils/slugify.test.ts +68 -0
  102. package/tsconfig.json +26 -0
  103. package/tsconfig.test.json +8 -0
  104. package/vitest.config.ts +27 -0
@@ -0,0 +1,349 @@
1
+ # MemHub 架构设计文档
2
+
3
+ ## 概述
4
+
5
+ MemHub 是一个基于 Git 友好的记忆存储系统,使用 Markdown 格式存储记忆条目,通过 YAML Front Matter 存储元数据。它实现了 MCP (Model Context Protocol) Server,通过 stdio 进行通信。
6
+
7
+ ## 设计原则
8
+
9
+ 1. **Git 友好**: 所有数据以纯文本 Markdown 文件存储,天然支持版本控制
10
+ 2. **人类可读**: 记忆条目可以直接用文本编辑器打开阅读
11
+ 3. **简单优先**: 不使用数据库,避免复杂的迁移和锁定问题
12
+ 4. **契约先行**: 接口和类型定义先于实现
13
+ 5. **测试驱动**: 严格遵循 TDD (红-绿-重构)
14
+
15
+ ## 系统架构
16
+
17
+ ```
18
+ ┌─────────────────────────────────────────────────────────────┐
19
+ │ MCP Client │
20
+ │ (Claude Desktop, etc.) │
21
+ └──────────────────────┬──────────────────────────────────────┘
22
+ │ stdio
23
+
24
+ ┌─────────────────────────────────────────────────────────────┐
25
+ │ MemHub MCP Server │
26
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
27
+ │ │ MCP Router │ │ Services │ │ Storage Layer │ │
28
+ │ │ │ │ │ │ │ │
29
+ │ │ - list_tools │ │ - create │ │ - read memory │ │
30
+ │ │ - call_tool │ │ - read │ │ - write memory │ │
31
+ │ │ │ │ - update │ │ - search index │ │
32
+ │ │ │ │ - delete │ │ - list memories │ │
33
+ │ │ │ │ - search │ │ │ │
34
+ │ └──────────────┘ └──────────────┘ └──────────────────┘ │
35
+ └──────────────────────┬──────────────────────────────────────┘
36
+
37
+
38
+ ┌─────────────────────────────────────────────────────────────┐
39
+ │ Markdown Storage │
40
+ │ ┌─────────────────────────────────────────────────────┐ │
41
+ │ │ YYYY-MM-DD-title-slug.md │ │
42
+ │ │ ───────────────────────── │ │
43
+ │ │ --- │ │
44
+ │ │ id: uuid-v4 │ │
45
+ │ │ created_at: ISO8601 │ │
46
+ │ │ updated_at: ISO8601 │ │
47
+ │ │ tags: [tag1, tag2] │ │
48
+ │ │ category: string │ │
49
+ │ │ importance: 1-5 │ │
50
+ │ │ --- │ │
51
+ │ │ │ │
52
+ │ │ # Title │ │
53
+ │ │ │ │
54
+ │ │ Markdown content body... │ │
55
+ │ │ │ │
56
+ │ └─────────────────────────────────────────────────────┘ │
57
+ └─────────────────────────────────────────────────────────────┘
58
+ ```
59
+
60
+ ## 核心组件
61
+
62
+ ### 1. MCP Server (src/server/mcp-server.ts)
63
+
64
+ - 入口点,处理 stdio 通信
65
+ - 实现 MCP 协议的生命周期管理
66
+ - 路由工具调用到对应的服务
67
+
68
+ ### 2. Services (src/services/)
69
+
70
+ 业务逻辑层,包含:
71
+
72
+ - **MemoryService**: 记忆 CRUD 操作
73
+ - **SearchService**: 搜索和过滤
74
+ - **IndexService**: 索引管理(可选,用于性能)
75
+
76
+ ### 3. Storage Layer (src/storage/)
77
+
78
+ 数据持久化层:
79
+
80
+ - **MarkdownStorage**: Markdown 文件读写
81
+ - **FrontMatterParser**: YAML Front Matter 解析
82
+ - **FileSystem**: 文件系统抽象(便于测试)
83
+
84
+ ### 4. Contracts (src/contracts/)
85
+
86
+ 类型定义和 Zod 契约:
87
+
88
+ - **types.ts**: TypeScript 类型
89
+ - **schemas.ts**: Zod 验证模式
90
+ - **mcp.ts**: MCP 协议相关类型
91
+
92
+ ## 数据模型
93
+
94
+ ### Memory Entry (记忆条目)
95
+
96
+ ```typescript
97
+ interface Memory {
98
+ // Identity
99
+ id: string; // UUID v4
100
+
101
+ // Metadata (YAML Front Matter)
102
+ createdAt: string; // ISO 8601
103
+ updatedAt: string; // ISO 8601
104
+ tags: string[]; // 标签数组
105
+ category: string; // 分类
106
+ importance: number; // 1-5 重要性等级
107
+
108
+ // Content (Markdown Body)
109
+ title: string; // Markdown H1 标题
110
+ content: string; // Markdown 正文
111
+ }
112
+ ```
113
+
114
+ ### File Naming Convention
115
+
116
+ ```
117
+ {YYYY-MM-DD}-{title-slug}.md
118
+
119
+ Examples:
120
+ - 2024-03-15-project-kickoff.md
121
+ - 2024-03-20-meeting-notes.md
122
+ ```
123
+
124
+ ### Markdown Format
125
+
126
+ ```markdown
127
+ ---
128
+ id: '550e8400-e29b-41d4-a716-446655440000'
129
+ created_at: '2024-03-15T10:30:00Z'
130
+ updated_at: '2024-03-15T14:20:00Z'
131
+ tags:
132
+ - project
133
+ - planning
134
+ category: 'work'
135
+ importance: 4
136
+ ---
137
+
138
+ # Project Kickoff
139
+
140
+ Today we started the new project...
141
+
142
+ ## Key Decisions
143
+
144
+ - Decision 1
145
+ - Decision 2
146
+ ```
147
+
148
+ ## MCP Tools
149
+
150
+ ### 1. `memory_create`
151
+
152
+ 创建新记忆条目。
153
+
154
+ **Input:**
155
+
156
+ - title: string (required)
157
+ - content: string (required)
158
+ - tags?: string[]
159
+ - category?: string
160
+ - importance?: number (1-5, default: 3)
161
+
162
+ **Output:**
163
+
164
+ - id: string
165
+ - filePath: string
166
+
167
+ ### 2. `memory_read`
168
+
169
+ 读取记忆条目。
170
+
171
+ **Input:**
172
+
173
+ - id: string (required)
174
+
175
+ **Output:**
176
+
177
+ - Memory object
178
+
179
+ ### 3. `memory_update`
180
+
181
+ 更新记忆条目。
182
+
183
+ **Input:**
184
+
185
+ - id: string (required)
186
+ - title?: string
187
+ - content?: string
188
+ - tags?: string[]
189
+ - category?: string
190
+ - importance?: number
191
+
192
+ **Output:**
193
+
194
+ - updated Memory object
195
+
196
+ ### 4. `memory_delete`
197
+
198
+ 删除记忆条目。
199
+
200
+ **Input:**
201
+
202
+ - id: string (required)
203
+
204
+ **Output:**
205
+
206
+ - success: boolean
207
+
208
+ ### 5. `memory_list`
209
+
210
+ 列出记忆条目(支持过滤和分页)。
211
+
212
+ **Input:**
213
+
214
+ - category?: string
215
+ - tags?: string[]
216
+ - fromDate?: string (ISO 8601)
217
+ - toDate?: string (ISO 8601)
218
+ - limit?: number (default: 20, max: 100)
219
+ - offset?: number (default: 0)
220
+
221
+ **Output:**
222
+
223
+ - memories: Memory[]
224
+ - total: number
225
+ - hasMore: boolean
226
+
227
+ ### 6. `memory_search`
228
+
229
+ 全文搜索记忆。
230
+
231
+ **Input:**
232
+
233
+ - query: string (required)
234
+ - limit?: number (default: 10)
235
+
236
+ **Output:**
237
+
238
+ - results: SearchResult[]
239
+ - memory: Memory
240
+ - score: number
241
+ - matches: string[]
242
+
243
+ ### 7. `memory_get_categories`
244
+
245
+ 获取所有分类。
246
+
247
+ **Output:**
248
+
249
+ - categories: string[]
250
+
251
+ ### 8. `memory_get_tags`
252
+
253
+ 获取所有标签。
254
+
255
+ **Output:**
256
+
257
+ - tags: string[]
258
+
259
+ ## 错误处理
260
+
261
+ 所有错误使用标准 MCP 错误格式:
262
+
263
+ ```typescript
264
+ interface McpError {
265
+ code: number; // MCP error code
266
+ message: string; // Human readable message
267
+ data?: unknown; // Additional context
268
+ }
269
+ ```
270
+
271
+ 错误码定义:
272
+
273
+ - `INVALID_PARAMS`: 参数验证失败
274
+ - `NOT_FOUND`: 记忆条目不存在
275
+ - `STORAGE_ERROR`: 存储操作失败
276
+ - `INTERNAL_ERROR`: 内部错误
277
+
278
+ ## 配置
279
+
280
+ 通过环境变量配置:
281
+
282
+ ```bash
283
+ MEMHUB_STORAGE_PATH=/path/to/memories # 存储目录,默认: ./memories
284
+ MEMHUB_LOG_LEVEL=info # 日志级别: debug, info, warn, error
285
+ ```
286
+
287
+ ## 技术栈
288
+
289
+ - **Runtime**: Node.js 18+
290
+ - **Language**: TypeScript 5.3+
291
+ - **Protocol**: MCP (Model Context Protocol)
292
+ - **Transport**: stdio
293
+ - **Validation**: Zod
294
+ - **Testing**: Vitest (覆盖率 >= 80%)
295
+ - **Linting**: ESLint + Prettier
296
+
297
+ ## 目录结构
298
+
299
+ ```
300
+ memhub/
301
+ ├── docs/
302
+ │ ├── architecture.md # 本文档
303
+ │ └── contracts.md # 契约文档
304
+ ├── src/
305
+ │ ├── contracts/ # 类型和契约
306
+ │ │ ├── types.ts
307
+ │ │ ├── schemas.ts
308
+ │ │ └── mcp.ts
309
+ │ ├── server/ # MCP Server
310
+ │ │ └── mcp-server.ts
311
+ │ ├── services/ # 业务逻辑
312
+ │ │ ├── memory-service.ts
313
+ │ │ └── search-service.ts
314
+ │ ├── storage/ # 存储层
315
+ │ │ ├── markdown-storage.ts
316
+ │ │ └── frontmatter-parser.ts
317
+ │ └── utils/ # 工具函数
318
+ │ └── file-system.ts
319
+ ├── test/ # 测试
320
+ │ ├── unit/
321
+ │ ├── integration/
322
+ │ └── fixtures/
323
+ ├── .github/
324
+ │ └── workflows/
325
+ │ └── ci.yml # CI 配置
326
+ ├── package.json
327
+ ├── tsconfig.json
328
+ ├── vitest.config.ts
329
+ ├── .eslintrc.cjs
330
+ ├── .prettierrc
331
+ └── README.md
332
+ ```
333
+
334
+ ## 开发流程
335
+
336
+ 1. **设计**: 先写架构文档和契约
337
+ 2. **契约**: 定义 TypeScript 类型和 Zod Schema
338
+ 3. **测试**: 编写红色测试(先失败)
339
+ 4. **实现**: 编写最小实现使测试通过(绿色)
340
+ 5. **重构**: 优化代码结构
341
+ 6. **重复**: 循环 3-5 步
342
+
343
+ ## 质量门禁
344
+
345
+ - ✅ ESLint 无错误
346
+ - ✅ Prettier 格式化检查通过
347
+ - ✅ TypeScript 严格类型检查通过
348
+ - ✅ 单元测试全部通过
349
+ - ✅ 代码覆盖率 >= 80%
@@ -0,0 +1,119 @@
1
+ # MemHub 契约文档(vNext)
2
+
3
+ 当前对外 MCP 工具仅保留两项:
4
+
5
+ 1. `memory_load`(首轮)
6
+ 2. `memory_update`(末轮)
7
+
8
+ 目标是形成稳定闭环:**先读 STM,再回写 STM**。
9
+
10
+ ---
11
+
12
+ ## 1) memory_load
13
+
14
+ 用于用户输入后第一轮主动加载短期记忆。
15
+
16
+ ### 输入
17
+
18
+ ```ts
19
+ interface MemoryLoadInput {
20
+ id?: string; // 指定单条记忆
21
+ sessionId?: string; // 会话 UUID
22
+ date?: string; // YYYY-MM-DD
23
+ query?: string; // 文本检索
24
+ category?: string;
25
+ tags?: string[];
26
+ limit?: number; // 默认 20
27
+ scope?: 'stm' | 'all'; // 默认 stm
28
+ }
29
+ ```
30
+
31
+ ### 输出
32
+
33
+ ```ts
34
+ interface MemoryLoadOutput {
35
+ items: Memory[];
36
+ total: number;
37
+ }
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 2) memory_update
43
+
44
+ 用于本轮结束前主动回写记忆。
45
+
46
+ ### 输入
47
+
48
+ ```ts
49
+ type EntryType = 'decision' | 'preference' | 'knowledge' | 'todo' | 'state_change';
50
+
51
+ interface MemoryUpdateInput {
52
+ id?: string; // 有 id 则更新;无 id 则追加
53
+ sessionId?: string; // 无则服务端自动生成并返回
54
+ mode?: 'append' | 'upsert'; // 默认 append
55
+ entryType?: EntryType;
56
+ title?: string;
57
+ content: string; // 必填
58
+ tags?: string[];
59
+ category?: string;
60
+ importance?: number; // 1-5
61
+ }
62
+ ```
63
+
64
+ ### 输出
65
+
66
+ ```ts
67
+ interface MemoryUpdateOutput {
68
+ id: string;
69
+ sessionId: string;
70
+ filePath: string;
71
+ created: boolean;
72
+ updated: boolean;
73
+ memory: Memory;
74
+ }
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Memory 数据模型
80
+
81
+ ```ts
82
+ interface Memory {
83
+ id: string;
84
+ createdAt: string;
85
+ updatedAt: string;
86
+ sessionId?: string;
87
+ entryType?: EntryType;
88
+ tags: string[];
89
+ category: string;
90
+ importance: number;
91
+ title: string;
92
+ content: string;
93
+ }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## 存储路径契约(并发安全)
99
+
100
+ 为避免多个 CLI 同日写入冲突,采用分层目录:
101
+
102
+ ```text
103
+ {storageRoot}/YYYY-MM-DD/{session_uuid}/{timestamp}-{slug}.md
104
+ ```
105
+
106
+ 例如:
107
+
108
+ ```text
109
+ memories/2026-03-03/550e8400-e29b-41d4-a716-446655440111/2026-03-03T16-40-12-123Z-task-summary.md
110
+ ```
111
+
112
+ ---
113
+
114
+ ## 调用策略契约(强建议)
115
+
116
+ - 用户输入后第一轮:调用 `memory_load`
117
+ - 最终输出前最后一轮:调用 `memory_update`
118
+
119
+ 详细策略见:`docs/tool-calling-policy.md`
@@ -0,0 +1,79 @@
1
+ # Prompt Template for Coding Agents (MemHub STM Loop)
2
+
3
+ Use this template in Codex / Claude Code / OpenCode system prompt or task preamble.
4
+
5
+ ---
6
+
7
+ ## System Rule: STM Closed Loop
8
+
9
+ You are connected to MemHub MCP.
10
+
11
+ ### Mandatory tool-calling behavior
12
+
13
+ 1. **First round after receiving user prompt**: call `memory_load`.
14
+ 2. **Final round before sending final answer**: call `memory_update`.
15
+
16
+ Do not skip these two calls unless tool is unavailable.
17
+
18
+ ---
19
+
20
+ ## Tool usage policy
21
+
22
+ ### On first round (`memory_load`)
23
+
24
+ Call with the most specific context available:
25
+
26
+ ```json
27
+ {
28
+ "sessionId": "<session-uuid-if-known>",
29
+ "scope": "stm",
30
+ "limit": 20
31
+ }
32
+ ```
33
+
34
+ If task is date-scoped, add `date: "YYYY-MM-DD"`.
35
+ If task is keyword-driven, add `query`.
36
+
37
+ ### On final round (`memory_update`)
38
+
39
+ Write only high-value context likely reused in next 3 turns:
40
+
41
+ - decisions
42
+ - preference changes
43
+ - constraints
44
+ - task state changes
45
+ - reusable conclusions
46
+
47
+ Example:
48
+
49
+ ```json
50
+ {
51
+ "sessionId": "<session-uuid-if-known>",
52
+ "mode": "append",
53
+ "entryType": "decision",
54
+ "title": "Storage architecture decision",
55
+ "content": "Use date/session_uuid nested markdown storage to avoid multi-CLI collision.",
56
+ "tags": ["architecture", "storage", "stm"],
57
+ "category": "engineering",
58
+ "importance": 4
59
+ }
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Minimal execution checklist
65
+
66
+ - [ ] First tool call is `memory_load`
67
+ - [ ] Final tool call is `memory_update`
68
+ - [ ] `memory_update` content is concise and reusable
69
+ - [ ] No sensitive secrets in memory payload
70
+
71
+ ---
72
+
73
+ ## Failure fallback
74
+
75
+ If tool call fails:
76
+
77
+ 1. continue task execution
78
+ 2. mention memory tool failure briefly in internal reasoning/logs
79
+ 3. still provide final user answer
@@ -0,0 +1,58 @@
1
+ # Proposal: Close Remaining Quality Gates (Phase 2)
2
+
3
+ ## Context
4
+ Current implementation already has broad functionality and passing test suites, but quality gates are still blocked by:
5
+
6
+ 1. ESLint configuration/type-aware parsing issues on test files
7
+ 2. TypeScript typecheck errors in server and storage/service imports
8
+ 3. Coverage gate failure on function coverage (<80%)
9
+ 4. Project path inconsistency (`workspace/workspace/memhub`)
10
+
11
+ ## Root Causes
12
+ - ESLint `parserOptions.project` only pointed to `tsconfig.json`, while test files are not included there.
13
+ - Some implementation details introduced strict-mode lint/type mismatches (`any` usage, fallthrough, readonly/no-unused issues).
14
+ - Existing server tests focus on constants/contracts but not internal execution paths, leaving many functions uncovered.
15
+ - Project was scaffolded under a nested directory.
16
+
17
+ ## Plan of Record
18
+
19
+ ### Step 1 — Fix static quality gates
20
+ - Update ESLint type-aware project references to include test TS config.
21
+ - Update `tsconfig.test.json` include set.
22
+ - Fix strict lint/type issues in server/service/storage/utils modules.
23
+
24
+ ### Step 2 — Raise function coverage to >=80%
25
+ - Add focused tests for MCP server runtime paths:
26
+ - JSON parsing failure path
27
+ - invalid request path
28
+ - method dispatch (`initialize`, `tools/list`, `tools/call`, unknown method)
29
+ - error handling (`ServiceError`, validation-like error, generic error)
30
+ - response/error serialization
31
+ - log filtering behavior
32
+ - Preserve existing passing behavior and avoid over-mocking core service logic.
33
+
34
+ ### Step 3 — Validate full gate
35
+ Run and require pass for:
36
+ - `npm run lint`
37
+ - `npm run typecheck`
38
+ - `npm run test`
39
+ - `npm run test:coverage` (global lines/functions/branches/statements >= 80)
40
+
41
+ ### Step 4 — Normalize repository location
42
+ - Move project to `C:\Users\cloud_user\.openclaw\workspace\memhub` (if missing).
43
+ - Verify scripts still run from new root.
44
+
45
+ ## Acceptance Criteria
46
+ - No lint errors
47
+ - No typecheck errors
48
+ - All tests pass
49
+ - Coverage thresholds all >= 80%
50
+ - Repository available at normalized path
51
+
52
+ ## Risks and Mitigations
53
+ - **Risk:** Private method tests become brittle.
54
+ - **Mitigation:** Test externally visible behavior and error contracts where possible; keep internals tests focused and minimal.
55
+ - **Risk:** Path migration may break references.
56
+ - **Mitigation:** Move whole directory atomically and rerun full gate.
57
+ - **Risk:** Coverage improvements skew test value.
58
+ - **Mitigation:** Prefer behavior-driven tests over shallow line-hitting.
@@ -0,0 +1,107 @@
1
+ # Tool Calling Policy (STM-first)
2
+
3
+ > 目标:让模型在每轮任务中稳定形成「先加载短期记忆,再产出,再回写记忆」的闭环。
4
+
5
+ ## 一、调用时序(强约束)
6
+
7
+ 1. **首轮调用 `memory_load`**(在响应用户前)
8
+ - 用于加载当前会话/任务相关短期记忆(STM)
9
+ - 若无命中,继续任务,不阻塞
10
+
11
+ 2. **末轮调用 `memory_update`**(在本轮输出结束前)
12
+ - 将本轮新增的关键上下文写回
13
+ - 重点写入:决策、约束变更、待办变化、关键结论
14
+
15
+ ---
16
+
17
+ ## 二、STM 判据(3 轮复用原则)
18
+
19
+ 若信息在未来 **3 轮** 内很可能被再次引用,则纳入 STM:
20
+
21
+ - 当前任务目标/范围
22
+ - 新确认的约束条件
23
+ - 待办项与状态变化(pending / done)
24
+ - 临时变量、参数、文件路径、报错栈
25
+ - 用户明确修正/改口(需求切换)
26
+
27
+ 不满足则不强行写入,避免噪音。
28
+
29
+ ---
30
+
31
+ ## 三、建议工具定义(简化版)
32
+
33
+ ## `memory_load`
34
+ **作用**:统一“看记忆”,用于当前轮开头加载上下文。
35
+
36
+ **建议入参**:
37
+ - `session_id`(可选,推荐)
38
+ - `date`(可选,默认今天)
39
+ - `limit`(可选,默认 20)
40
+ - `tags`(可选)
41
+ - `category`(可选)
42
+ - `query`(可选)
43
+ - `scope`(可选:`stm|all`,默认 `stm`)
44
+
45
+ **建议返回**:
46
+ - `items[]`(记忆条目)
47
+ - `summary`(可选摘要)
48
+ - `pending[]` / `done[]`(若可提取)
49
+
50
+ ---
51
+
52
+ ## `memory_update`
53
+ **作用**:统一“写记忆”,用于当前轮末尾回写。
54
+
55
+ **建议入参**:
56
+ - `session_id`(可选;无则自动生成并返回)
57
+ - `date`(可选,默认今天)
58
+ - `mode`:`append|upsert`(默认 `append`)
59
+ - `entry_type`:`decision|preference|knowledge|todo|state_change`
60
+ - `title`
61
+ - `content`
62
+ - `tags[]`
63
+ - `category`
64
+ - `importance`(1-5)
65
+
66
+ **建议返回**:
67
+ - `id`
68
+ - `session_id`
69
+ - `file_path`
70
+ - `created|updated`
71
+
72
+ ---
73
+
74
+ ## 四、并发与目录规范
75
+
76
+ 为支持多个 CLI 同时写入,建议目录如下:
77
+
78
+ ```text
79
+ memories/
80
+ YYYY-MM-DD/
81
+ <session_uuid>/
82
+ 2026-03-03T16-41-23.123Z-<slug>.md
83
+ ```
84
+
85
+ 说明:
86
+ - 同一天按 `session_uuid` 分桶,避免并发冲突
87
+ - 每条记录仍保留 YAML + Markdown 正文
88
+ - `session_uuid` 可来自调用方;缺省由服务端生成
89
+
90
+ ---
91
+
92
+ ## 五、触发更新条件
93
+
94
+ 在以下事件发生时,优先触发 `memory_update`:
95
+
96
+ - 用户显式改需求(如“换个方案”)
97
+ - 任务状态切换(分析 → 实现 / 实现 → 验证)
98
+ - 新信息与既有 STM 冲突
99
+ - 本轮产出形成可复用结论
100
+
101
+ ---
102
+
103
+ ## 六、设计原则
104
+
105
+ - **STM 保留细节,不做过度抽象**
106
+ - **LTM 另层抽取,不与 STM 混存**
107
+ - **先 load,后 update,形成闭环**