pmem-ai 0.6.2 → 0.7.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 (85) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +68 -4
  3. package/dist/commands/ask.d.ts.map +1 -1
  4. package/dist/commands/ask.js +5 -1
  5. package/dist/commands/ask.js.map +1 -1
  6. package/dist/commands/distill.d.ts.map +1 -1
  7. package/dist/commands/distill.js +15 -6
  8. package/dist/commands/distill.js.map +1 -1
  9. package/dist/commands/doctor.d.ts.map +1 -1
  10. package/dist/commands/doctor.js +21 -8
  11. package/dist/commands/doctor.js.map +1 -1
  12. package/dist/commands/graph.d.ts +3 -0
  13. package/dist/commands/graph.d.ts.map +1 -1
  14. package/dist/commands/graph.js +73 -25
  15. package/dist/commands/graph.js.map +1 -1
  16. package/dist/commands/init.d.ts +13 -0
  17. package/dist/commands/init.d.ts.map +1 -1
  18. package/dist/commands/init.js +142 -32
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/integration.d.ts.map +1 -1
  21. package/dist/commands/integration.js +170 -15
  22. package/dist/commands/integration.js.map +1 -1
  23. package/dist/commands/new.d.ts.map +1 -1
  24. package/dist/commands/new.js +15 -14
  25. package/dist/commands/new.js.map +1 -1
  26. package/dist/commands/rebuild.d.ts.map +1 -1
  27. package/dist/commands/rebuild.js +84 -15
  28. package/dist/commands/rebuild.js.map +1 -1
  29. package/dist/commands/recall.d.ts.map +1 -1
  30. package/dist/commands/recall.js +11 -5
  31. package/dist/commands/recall.js.map +1 -1
  32. package/dist/commands/rename.d.ts.map +1 -1
  33. package/dist/commands/rename.js +98 -19
  34. package/dist/commands/rename.js.map +1 -1
  35. package/dist/commands/status.d.ts.map +1 -1
  36. package/dist/commands/status.js +31 -6
  37. package/dist/commands/status.js.map +1 -1
  38. package/dist/commands/update.d.ts +2 -0
  39. package/dist/commands/update.d.ts.map +1 -1
  40. package/dist/commands/update.js +117 -1
  41. package/dist/commands/update.js.map +1 -1
  42. package/dist/commands/verify.d.ts.map +1 -1
  43. package/dist/commands/verify.js +5 -3
  44. package/dist/commands/verify.js.map +1 -1
  45. package/dist/core/db.d.ts +8 -0
  46. package/dist/core/db.d.ts.map +1 -1
  47. package/dist/core/db.js +47 -0
  48. package/dist/core/db.js.map +1 -1
  49. package/dist/core/discover/detect.d.ts +12 -0
  50. package/dist/core/discover/detect.d.ts.map +1 -0
  51. package/dist/core/discover/detect.js +68 -0
  52. package/dist/core/discover/detect.js.map +1 -0
  53. package/dist/core/discover/index.d.ts +12 -0
  54. package/dist/core/discover/index.d.ts.map +1 -0
  55. package/dist/core/discover/index.js +645 -0
  56. package/dist/core/discover/index.js.map +1 -0
  57. package/dist/core/discover/patterns.d.ts +29 -0
  58. package/dist/core/discover/patterns.d.ts.map +1 -0
  59. package/dist/core/discover/patterns.js +322 -0
  60. package/dist/core/discover/patterns.js.map +1 -0
  61. package/dist/core/fs.d.ts +7 -0
  62. package/dist/core/fs.d.ts.map +1 -1
  63. package/dist/core/fs.js +57 -1
  64. package/dist/core/fs.js.map +1 -1
  65. package/dist/core/manifest.d.ts +23 -1
  66. package/dist/core/manifest.d.ts.map +1 -1
  67. package/dist/core/manifest.js +72 -0
  68. package/dist/core/manifest.js.map +1 -1
  69. package/dist/index.js +31 -2
  70. package/dist/index.js.map +1 -1
  71. package/dist/types.d.ts +108 -1
  72. package/dist/types.d.ts.map +1 -1
  73. package/docs/handover-v0.6.4.md +285 -0
  74. package/docs/project-roadmap.md +129 -4
  75. package/docs/release-checklist-v0.7.0.md +60 -0
  76. package/docs/session-start-create-design-eval.md +203 -0
  77. package/docs/usage.md +38 -0
  78. package/docs/v0.6.4 pre-design.md +526 -0
  79. package/docs/v0.7.0 pre-design.md +405 -0
  80. package/package.json +7 -3
  81. package/skills/pmem/SKILL.md +86 -6
  82. package/skills/pmem/references/first-init.md +21 -0
  83. package/skills/pmem/references/memory-cards.md +44 -1
  84. package/skills/pmem/references/session-workflow.md +3 -3
  85. package/skills/pmem/references/universal-domains.md +66 -0
@@ -0,0 +1,405 @@
1
+ # v0.7.0 前置设计决策
2
+
3
+ 本文档记录 pmem v0.7.0 开工前的产品与技术决策。v0.7.0 的核心定位:
4
+
5
+ > **Universal Agent Memory**
6
+ >
7
+ > v0.6 track 已于 v0.6.4 封版。v0.6 的核心循环(Markdown 卡片 → SQLite 索引 → recall/ask/update/verify)在代码层面
8
+ > 已被验证是领域无关的——阻碍非软件项目的是出厂配置和少量硬编码列表,不是架构。
9
+ >
10
+ > v0.7.0 不引入 embedding、MCP/REST、Graph UI、telemetry、远程多用户服务。
11
+ > v0.7.0 只做一件事:**把 pmem 从"软件项目专用"扩展为"任意 agent 项目的本地记忆运行时"**。
12
+ >
13
+ > v0.7.0 要回答的唯一问题:
14
+ > **一个写小说的 agent、做研究的 agent、写剧本的 agent,能否用和 coding agent 完全相同的 `pmem recall` / `pmem ask` / `pmem update` 工作流,在自有 domain 术语下管理项目记忆?**
15
+
16
+ ---
17
+
18
+ ## 一、背景:v0.6 通用化调研
19
+
20
+ ### 1.1 已完成的调研
21
+
22
+ v0.6.4 开发期间,通过代码层全景扫描 + 真实小说项目 E2E,获得了完整的通用化阻力地图:
23
+
24
+ | 调研产物 | 内容 | 状态 |
25
+ |----------|------|------|
26
+ | 类型系统硬编码全景 | 6 个真阻塞点 + 14 个 friction 点 | Wave 1 已完成 |
27
+ | 变更检测 + discover 通用化评估 | 7 个 blocker + provider 模型潜力 | Wave 1 已完成 |
28
+ | init/integration/skills 通用化扩展点 | 8 个 const 模板 + 5 种 manifest 探测 | Wave 1 已完成 |
29
+ | 真实小说项目 friction 报告 | 14 条 friction,2 BLOCKER + 6 FRICTION + 3 COSMETIC | Wave 2 已完成 |
30
+ | v0.6 现状报告 | 8 项 P1/P2 未闭环 + roadmap 缺口 | Wave 1 已完成 |
31
+
32
+ ### 1.2 关键结论
33
+
34
+ **核心循环已通用**。以下组件对自定义卡片类型完全透明:
35
+
36
+ - `rebuild.ts` 的 `parseCard()`——`type` 字段不做校验(`as unknown as CardFrontmatter` 强制转型)
37
+ - SQLite schema——`cards.type TEXT` 无 CHECK 约束
38
+ - `ask.ts` 的 alias/tag/graph_expansion/keyword_fallback——不依赖 type
39
+ - `consistency.ts` 的 `checkStaleMemory()`——基于 `source_files` 路径比较,不区分文件类型
40
+ - `update --suggest` 的聚合/分级/历史分类——读 `dirty_flags` 表,type-agnostic
41
+
42
+ **阻碍来自 ~20 行硬编码**。真正绑死"软件项目"语义的代码点是出厂配置值,不是架构约束。
43
+
44
+ ---
45
+
46
+ ## 二、v0.7.0 产品目标
47
+
48
+ ### 2.1 一句话目标
49
+
50
+ > **任意 agent 项目(软件 / 小说 / 研究 / 剧本 / 课程 / ...)都能用 pmem 管理项目记忆,术语和配置跟随项目 domain,不写代码。**
51
+
52
+ ### 2.2 用户对象
53
+
54
+ | 用户 | 当前状态 | v0.7.0 目标 |
55
+ |------|---------|------------|
56
+ | Coding agent(现有) | 工作正常 | 零回归 |
57
+ | 写作 agent | `pmem new character` 被拒绝;`recall` 的 `active_modules` 永远是 `[]` | 全工作流可用 |
58
+ | 研究 agent | 无 `source` / `citation` 卡片类型;`discover` 对文献扫描无用 | 可自定义类型 |
59
+ | 新 domain 的 agent | init 模板只有 software 预设;manifest 不可自描述 domain | `init --domain` 加载预设 |
60
+
61
+ ### 2.3 成功标准
62
+
63
+ 1. `pmem init my-project --domain novel` 创建小说项目骨架:`characters/`、`chapters/`、`world/`、`arc/` 四个目录 + 对应卡片类型。
64
+ 2. `pmem new character "张三"` 不再报 "Invalid card type",接受 manifest 声明的任意类型。
65
+ 3. `pmem recall --format json` 的输出中**同时包含** `active_modules`(兼容旧 agent)和 `active_foundation`(新字段)。两者内容为项目声明的"基础卡片类型"。在 software domain 中两者内容一致(都是 `module` 类型卡);在 novel domain 中为 `character`/`chapter` 等。未来版本考虑弃用 `active_modules`。
66
+ 4. `pmem ask "张三"` 在小说项目中仍通过 alias 找到 `character.zhangsan`(不退化)。
67
+ 5. `pmem status` 的目录级模糊匹配不再对小说项目产生高误报(`chapters/` 下改一章不应触发所有 `source_files` 含 `chapters/*` 的卡)。
68
+ 6. 现有 v0.6.x 项目(软件项目)无需任何迁移即可在 v0.7.0 下正常工作。`card_types` / `domain` / `foundational_types` / `type_dirs` 全为**可选字段**,缺省时行为与 v0.6.4 完全一致。
69
+ 7. manifest schema 新增字段全部为**可选**,缺省时行为与 v0.6.4 完全一致。不存在"新增字段数量上限"约束——新增字段的唯一硬性要求是:**必须有 v0.6.4 缺省回退,旧项目不迁移即可用**。`schema_version` 不升主版本号(仍 `0.3`)。
70
+
71
+ ### 2.4 范围排除(不做)
72
+
73
+ 以下方向继续不进入 v0.7.0:
74
+
75
+ | 排除项 | 原因 |
76
+ |--------|------|
77
+ | embedding / semantic search | 引入模型依赖和隐私变量,应在独立版本评估 |
78
+ | `pmem serve` / MCP / REST | 服务化扩大协议面;v0.7.0 专注 CLI 通用化 |
79
+ | Graph UI | 独立产品决策 |
80
+ | telemetry | 隐私策略未定 |
81
+ | 远程同步 / 多用户 | 与本地 CLI runtime 定位不一致 |
82
+ | discover provider 重写 | v0.7.0 只默认禁用 discover(非软件项目),provider 接口化推迟到 v0.7.1+ |
83
+ | `auto_update.*` 字段真正接通 | 推迟(v0.6 期间一直是死配置,不阻塞通用化) |
84
+ | `card_globs` 被 rebuild 消费 | 推迟(rebuild 目前用 `'.pmem/**/*.md'` 硬编码,已实际比 card_globs 更宽松) |
85
+ | init --type-preset wizard(交互式) | v0.7.0 只做非交互的 `--domain` flag + 预设加载;交互式向导推迟 |
86
+
87
+ ---
88
+
89
+ ## 三、类型系统阻力地图
90
+
91
+ 以下是从代码层全景扫描(Wave 1)和真实小说 E2E(Wave 2)中提取的完整阻力清单。
92
+
93
+ ### 3.1 硬编码阻塞点(6 个,v0.7.0 必须修复)
94
+
95
+ | # | 文件 | 代码 | 严重程度 |
96
+ |---|------|------|----------|
97
+ | 1 | `src/commands/new.ts:6` | `VALID_TYPES = ['decision','module','task','feature','risk','trace']` | **BLOCKING** |
98
+ | 2 | `src/commands/new.ts:8-15` | `TYPE_DIR_MAP` 硬编码 type→目录映射 | **BLOCKING** |
99
+ | 3 | `src/core/manifest.ts:113` | `id_pattern` 正则白名单 10 种 type 前缀 | **BLOCKING** |
100
+ | 4 | `src/commands/distill.ts:198,202` | `WHERE ... AND c.type IN ('module','decision','task','feature')` | **BLOCKING** |
101
+ | 5 | `src/commands/distill.ts:267-281` | `for (const dir of ['modules','features','decisions','tasks'])` | **BLOCKING** |
102
+ | 6 | `src/types.ts:3-16` | `NodeType` 联合类型(TypeScript 编译期,运行时已擦除) | friction |
103
+
104
+ **修正方案(v0.7.0 MVP)**:
105
+
106
+ 1. `new.ts`: `VALID_TYPES` 从 manifest 读 `schema.card_types`;`TYPE_DIR_MAP` 从 manifest 读 `schema.type_dirs`
107
+ 2. `manifest.ts`: `id_pattern` 改为 `'^({types})\\.[a-z0-9._-]+$'`,运行时用 manifest 声明的类型列表渲染
108
+ 3. `distill.ts`: `IN (...)` 和 `for (...)` 从 manifest 读 `distill.merge_target_types`
109
+ 4. `types.ts`: `NodeType` 从联合类型改为 `string`(保留向后兼容的 type alias)
110
+
111
+ ### 3.2 Friction 点(10 个,v0.7.0 理想修复,可分阶段)
112
+
113
+ | # | 文件 | 问题 | 修复成本 |
114
+ |---|------|------|----------|
115
+ | 7 | `src/commands/recall.ts:95` | `c.type === 'module'` 过滤 | S(读 manifest `recall.foundational_types`) |
116
+ | 8 | `src/commands/ask.ts:272` | evidence 只挑 `decision/trace` | S(读 manifest `ask.evidence_types`) |
117
+ | 9 | `src/commands/graph.ts:208` | trace 只认 `decision/trace` | S(读 manifest `trace.evidence_types`) |
118
+ | 10 | `src/commands/status.ts:222` | `skipDirs` 硬编码 `node_modules/.git/.pmem/dist/build/.claude` | S(读 manifest `change_detection.skip_dirs`) |
119
+ | 11 | `src/commands/status.ts:242-246` | mtime 扫描硬编码 `src/lib/app/tests` | M(读 manifest `change_detection.mtime_scan_dirs`) |
120
+ | 12 | `src/commands/rebuild.ts:312` | `task → next_step_of` 启发式 | S(读 manifest `edges.derived_rules`) |
121
+ | 13 | `src/commands/migrate.ts:205` | fallback type 写死 `module` | S(读 manifest `card_policy.default_card_type`) |
122
+ | 14 | `src/commands/distill.ts:152` | 兜底 type 写死 `trace` | S(同上) |
123
+ | 15 | `src/commands/init.ts:509-513` | 初始目录列表硬编码 | M(按 domain 预设加载) |
124
+ | 16 | `src/core/manifest.ts:103-105` | `ignore_patterns` 默认值 `node_modules/dist/build` | S(拆 `software_ignore` + `generic_ignore`) |
125
+
126
+ ### 3.3 真正通用的组件(无需修改)
127
+
128
+ - `rebuild.ts` 的 `parseCard()` / upsert
129
+ - SQLite schema(所有 TEXT 列无 CHECK)
130
+ - `ask.ts` 检索流
131
+ - `consistency.ts` 的 `checkStaleMemory()`
132
+ - `update --suggest` 聚合/分级逻辑
133
+ - `verify.ts`(policy 按 type key 查表,新 type 自动获得默认值)
134
+
135
+ ---
136
+
137
+ ## 四、v0.7.0 详细设计
138
+
139
+ ### 4.1 Manifest schema 新增字段(可选,缺省回退 v0.6.4 行为)
140
+
141
+ ```yaml
142
+ # .pmem/manifest.yml 新增字段(全部可选)
143
+
144
+ project:
145
+ name: my-novel
146
+ domain: novel # 新增:项目 domain(novel|software|research|screenplay|course|...)
147
+ language: zh-CN
148
+
149
+ schema: # 新增顶层 key
150
+ card_types: # 项目允许的卡片类型
151
+ - character
152
+ - chapter
153
+ - world
154
+ - arc
155
+ - decision
156
+ - trace
157
+ type_dirs: # type → .pmem/ 子目录映射
158
+ # 内置 preset 中的 type 必须显式列出(避免 ${type}s 歧义,
159
+ # 如 world 不能默认成 worlds)。
160
+ # 自定义 type(不在任何 preset 中)缺省为 ${type}s。
161
+ character: characters
162
+ chapter: chapters
163
+ world: world
164
+ arc: arc
165
+ decision: decisions
166
+ trace: traces
167
+ foundational_types: # recall 中视为"基础卡片"的类型(替代硬编码 module)
168
+ - character
169
+ - chapter
170
+ evidence_types: # ask/trace 中视为 evidence 的类型
171
+ - decision
172
+ - trace
173
+ default_type: trace # 兜底卡片类型(替代硬编码 trace)
174
+
175
+ card_policy:
176
+ id_pattern: '^({types})\.[a-z0-9._-]+$' # {types} 由 card_types 渲染
177
+ max_tokens:
178
+ character: 1200
179
+ chapter: 2000
180
+ world: 1500
181
+ arc: 1000
182
+ decision: 1000
183
+ trace: 1000
184
+ default_max_tokens: 1000 # 新增:未在 max_tokens 中列出的 type 的兜底值
185
+
186
+ change_detection: # 新增顶层 key(拆分自 auto_update)
187
+ mtime_scan_dirs: # no-git 降级时的扫描目录
188
+ - chapters
189
+ - characters
190
+ - world
191
+ skip_dirs: # 从 status/mark-dirty 中排除的目录
192
+ - .git
193
+ - .pmem
194
+ - drafts
195
+
196
+ discover:
197
+ enabled: false # 新增:非软件项目默认 false
198
+
199
+ distill:
200
+ merge_target_types: # 新增:trace 可合并到的稳定卡片类型
201
+ - character
202
+ - chapter
203
+ - world
204
+ - arc
205
+ - decision
206
+ ```
207
+
208
+ **缺省行为**:
209
+
210
+ 当 `schema.card_types` 未定义时,回退到 v0.6.4 `id_pattern` 实际白名单:
211
+ `['project','module','feature','task','decision','trace','risk','assumption','resource','integration']`
212
+ (来源:`src/core/manifest.ts:113`。注意 `integration` 在 id_pattern 但不在 `NodeType`;`constraint`/`person`/`file`/`doc` 在 `NodeType` 但不在 id_pattern——回退以 id_pattern 为准,因为它是运行时真正生效的 gate)。
213
+ 当 `schema.type_dirs` 未定义时:内置 preset 中的 type 使用 preset 显式列出的目录;自定义 type(不在任何 preset 中的)回退到 `${type}s` 规则。
214
+ 当 `schema.foundational_types` 未定义时,回退到 `['module']`(保持 v0.6.4 行为)。
215
+ 当 `discover.enabled` 未定义时,软件项目默认 `true`,非软件项目默认 `false`。
216
+
217
+ ### 4.2 Domain 预设
218
+
219
+ v0.7.0 内置 3 个 domain 预设,通过 `pmem init --domain <name>` 加载:
220
+
221
+ | Domain | card_types | foundational_types | type_dirs | discover |
222
+ |--------|-----------|-------------------|-----------|----------|
223
+ | `software`(默认) | project/module/feature/task/decision/risk/trace/person | module | 同 v0.6.4 | enabled |
224
+ | `novel` | character/chapter/world/arc/decision/trace | character/chapter | characters/chapters/world/arc/decisions/traces | disabled |
225
+ | `research` | source/claim/note/experiment/decision/trace | source/claim | sources/claims/notes/experiments/decisions/traces | disabled |
226
+
227
+ `--domain` 缺省时等同于 `--domain software`(向后兼容 v0.6.x)。
228
+
229
+ 用户可以通过 manifest 手动增删 `card_types`、覆盖任意字段,domain 预设只是 init 时的起点。
230
+
231
+ ### 4.3 init 通用化方案
232
+
233
+ **CLI 变更**:
234
+
235
+ ```bash
236
+ pmem init my-novel --domain novel --guided \
237
+ --description "武侠小说" --stage "草稿" --next "完成第一章"
238
+ ```
239
+
240
+ **init 流程变更**:
241
+
242
+ 1. `--domain <name>` 加载内置预设(`src/commands/init.ts` 新增 `DOMAIN_PRESETS` 常量)
243
+ 2. 按 `type_dirs` 创建目录(替代当前的 8 个 const 目录)
244
+ 3. 写入 manifest 时填入 `schema.card_types` / `schema.type_dirs` / `schema.foundational_types` 等
245
+ 4. `source_of_truth.card_globs` 从 `type_dirs` 自动生成
246
+ 5. candidates 扫描按 `card_types` 生成候选项
247
+
248
+ **不改**:`--guided` 的交互流程、`--answers` 文件路径、`AGENTS.md` 生成逻辑。
249
+
250
+ ### 4.4 integration/skills 通用化方案
251
+
252
+ **integration**:
253
+
254
+ `pmem integration install` 的文件生成**不区分 domain**。CLA.md / AGENTS.md / slash command 文件 / git-hooks 的内容是通用 agent 工作流指令,已包含 `pmem recall --budget 2000` / `pmem ask` / `pmem update` / `pmem verify`,这些命令在所有 domain 下行为一致。
255
+
256
+ 唯一需要调整的是 CLAUDE.md 模板中的示例术语("module" → "基础卡片"),改为 domain-neutral 表述。
257
+
258
+ **skills**:
259
+
260
+ `skills/` 目录下的 4 个 SKILL.md(recall/ask/update/distill)的内容已领域无关。`skills/code-task.md` 的命名改为 `skills/task.md`,内容改为通用任务描述模板。
261
+
262
+ ### 4.5 迁移策略
263
+
264
+ **零迁移**。v0.6.x 项目在 v0.7.0 下:
265
+
266
+ 1. `schema.*` 字段全部缺省 → 回退 v0.6.4 硬编码值
267
+ 2. `pmem new module "..."` 仍工作(`module` 在 software 预设中)
268
+ 3. `pmem recall` 的 `active_modules` 字段保留,同时新增 `active_foundation`(两者内容一致)
269
+ 4. `pmem verify` 的 `id_pattern` 正则不变
270
+ 5. `schema_version` 不升
271
+
272
+ **Resolved config(运行时计算,不回写)**:
273
+ PMEM 加载 manifest 时计算一个 resolved config 对象:
274
+ - 若 `schema.card_types` 已定义 → 使用其值
275
+ - 若未定义 → resolved config 取 v0.6.4 `id_pattern` 白名单回退值
276
+ - resolved config 是**内存中的计算结果**,不写回 manifest 文件
277
+ - 旧项目 manifest 在磁盘上保持原样——v0.7.0 不会在 `pmem rebuild` / `pmem status` / 任何读操作时自动向 manifest 注入 `schema.*` 字段
278
+ - 唯一的 manifest 写入路径是 `pmem init`(新项目)和用户手动编辑
279
+
280
+ **v0.7.0 新项目**:
281
+ - `init --domain novel` 写入 `schema.card_types` 等字段
282
+ - manifest 中这些字段的存在是 v0.7.0 项目与 v0.6.x 项目的唯一区别
283
+
284
+ **升级路径**:
285
+ - v0.6.x 用户想使用自定义类型,手动编辑 manifest 加 `schema.card_types` + `schema.type_dirs` + 放宽 `id_pattern`(加 `{types}` 占位符),然后 `pmem rebuild`
286
+ - 不需要 `pmem migrate` 命令
287
+
288
+ ---
289
+
290
+ ## 五、实现分阶段
291
+
292
+ ### Phase 1: Core unblock(P0,必须)
293
+
294
+ | # | 改动 | 文件 | 工作量 |
295
+ |---|------|------|--------|
296
+ | 1 | `NodeType` 放宽为 `string` | `src/types.ts` | S |
297
+ | 2 | `pmem new` 从 manifest 读 `card_types` + `type_dirs` | `src/commands/new.ts` | S |
298
+ | 3 | `id_pattern` 改为 `{types}` 占位符 | `src/core/manifest.ts` | S |
299
+ | 4 | `distill` 从 manifest 读 `merge_target_types` | `src/commands/distill.ts` | S |
300
+ | 5 | manifest 默认值填入 `card_types` / `type_dirs` / `foundational_types` 等新字段(缺省回退 v0.6.4 行为) | `src/core/manifest.ts` | M |
301
+ | 6 | node:test 覆盖:自定义 type 的 new/rebuild/ask/verify 全链路 | `src/core/*.test.ts` | M |
302
+
303
+ **Phase 1 DoD**:`pmem new character "张三"` 在 `manifest.schema.card_types` 含 `character` 时成功。
304
+
305
+ ### Phase 2: Domain presets(P0)
306
+
307
+ | # | 改动 | 文件 | 工作量 |
308
+ |---|------|------|--------|
309
+ | 7 | `init --domain` flag + `DOMAIN_PRESETS` 常量(software/novel/research) | `src/commands/init.ts` | M |
310
+ | 8 | init 目录按 `type_dirs` 创建 | `src/commands/init.ts` | S |
311
+ | 9 | `card_globs` 从 `type_dirs` 自动生成 | `src/commands/init.ts` | S |
312
+
313
+ **Phase 2 DoD**:`pmem init my-novel --domain novel --guided` 创建 `characters/` / `chapters/` / `world/` / `arc/` 四个目录,manifest 含 `card_types: [character, chapter, world, arc, ...]`。
314
+
315
+ ### Phase 3: Friction polish(P1,理想)
316
+
317
+ | # | 改动 | 文件 | 工作量 |
318
+ |---|------|------|--------|
319
+ | 10 | `recall` JSON 同时输出 `active_modules`(兼容)和 `active_foundation`(新字段),两者内容从 manifest `foundational_types` 读取 | `src/commands/recall.ts` | S |
320
+ | 11 | `status` 的 `skipDirs` / `mtime_scan_dirs` 从 manifest 读 | `src/commands/status.ts` | M |
321
+ | 12 | `ask` / `graph` / `migrate` / `rebuild` 的 type-specific 启发式改为读 manifest | 4 个文件 | S×4 |
322
+ | 13 | `auto_update.ignore_patterns` 拆 `software_ignore` + `generic_ignore` | `src/core/manifest.ts` | S |
323
+ | 14 | `skills/code-task.md` → `skills/task.md` + 通用内容 | `skills/` | S |
324
+
325
+ **Phase 3 DoD**:小说项目 `recall --format json` 同时输出 `active_modules`(兼容,内容与 `active_foundation` 一致)和 `active_foundation`(含 `character`/`chapter` 类型的卡)。
326
+
327
+ ### Phase 4: discover default-disable(P2)
328
+
329
+ | # | 改动 | 文件 | 工作量 |
330
+ |---|------|------|--------|
331
+ | 15 | `discover` 命令读 `manifest.discover.enabled`,false 时直接返回 "disabled in this project" | `src/commands/discover.ts` | S |
332
+ | 16 | 非 software domain 的 manifest 默认 `discover.enabled: false` | `src/commands/init.ts` | S |
333
+
334
+ ---
335
+
336
+ ## 六、测试计划
337
+
338
+ ### 单元测试(新增 + 不改旧)
339
+
340
+ | 场景 | 覆盖 |
341
+ |------|------|
342
+ | `pmem new character "张三"` 在 novel domain 成功 | 新增 |
343
+ | `pmem new character "张三"` 在 software domain 仍拒绝(保持旧行为) | 新增 |
344
+ | `pmem rebuild` 索引 character/world/arc 卡片 | 新增 |
345
+ | `pmem ask "张三"` 通过 alias 找到 character.zhangsan | 新增 |
346
+ | `pmem recall` 在 novel domain 返回 `active_foundation`(非 `active_modules`) | 新增 |
347
+ | `id_pattern` 的 `{types}` 占位符渲染正确 | 新增 |
348
+ | 旧 software project 全部 node:test 不退步 | 回归 |
349
+
350
+ ### E2E
351
+
352
+ | 场景 | 覆盖 |
353
+ |------|------|
354
+ | `init --domain novel` + `new character` + `rebuild` + `ask` + `recall` + `verify` 全链路 | 新增脚本 `scripts/e2e-v07-novel.sh` |
355
+ | `init --domain research` + 自定义 source/claim 卡片 | 新增脚本 `scripts/e2e-v07-research.sh` |
356
+ | 旧 software project `init --guided` → 完整 v0.6 workflow 不退步 | 复用 `scripts/e2e-real-workflow.sh` |
357
+ | `init --domain novel` 后 `discover` 输出 "disabled" | 新增 |
358
+ | status 在 novel 项目不误报(改 ch01 只触发 exact match 的卡) | 新增 |
359
+
360
+ ### 回归
361
+
362
+ | 套件 | 要求 |
363
+ |------|------|
364
+ | `npm test`(node:test) | 137 现有 + 新增 ≥ 10 → 全部通过 |
365
+ | 12 个 v0.6 E2E 脚本 | 全绿(旧 software project 不退步) |
366
+ | `npm run build` | 0 error |
367
+
368
+ ---
369
+
370
+ ## 七、schema 兼容性
371
+
372
+ - `manifest.pmem.schema_version` 保持 `'0.3'`(不升主版本号)
373
+ - 所有新增字段在 manifest 中为**可选**
374
+ - `card_policy.id_pattern` 的新格式 `'^({types})\.[a-z0-9._-]+$'` 在 `{types}` 未渲染时等价于旧正则(回退到 v0.6.4 硬编码列表)
375
+ - 不新增 `pmem migrate` 步骤——v0.6.x `.pmem/` 目录直接被 v0.7.0 读取
376
+ - `pmem.db` 表结构不变
377
+
378
+ ---
379
+
380
+ ## 八、风险与缓解
381
+
382
+ | 风险 | 缓解 |
383
+ |------|------|
384
+ | `NodeType` 放宽为 `string` 后 TypeScript 不再检查拼写错误 | 在 `manifest.ts` 的 `loadManifest` / `validateManifest` 中增加运行时 card_type 白名单校验(仅当 manifest 声明了 `card_types` 时) |
385
+ | distill 的 `merge_target_types` 配置错误(用户声明了不存在的类型) | distill 在 merge 时检查目标卡是否存在,不存在则跳过 + warning |
386
+ | `id_pattern` 的 `{types}` 占位符中类型名含正则特殊字符(如 `c++`) | `escapeRegExp` 处理 |
387
+ | 太多 domain 预设导致维护负担 | v0.7.0 只内置 3 个(software/novel/research);后续 domain 由社区提供 manifest 示例 |
388
+ | `active_modules` → `active_foundation` 字段名变更破坏 agent JSON 解析 | `recall --format json` 同时输出 `active_modules`(兼容别名)和 `active_foundation`(新字段),给 agent 迁移窗口期 |
389
+
390
+ ---
391
+
392
+ ## 九、审批记录
393
+
394
+ | 角色 | 决定 | 日期 |
395
+ |------|------|------|
396
+ | 提交人 | Claude Opus 4.8 | 2026-06-02 |
397
+ | CTO | 待审批 | |
398
+
399
+ ### 设计来源
400
+
401
+ - 类型系统阻力地图:Wave 1 子任务报告(4 个 sub-agent 并行代码扫描)
402
+ - 小说项目 friction 报告:Wave 2 实测(temp/novel-test/)
403
+ - init/integration/skills 通用化扩展点:Wave 1 子任务报告
404
+ - v0.6 现状报告:Wave 1 子任务报告
405
+ - v0.6.4 pre-design §九(v0.7.0 边界)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmem-ai",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Project Memory for AI Agents: a local CLI runtime for project context, recall, and memory updates",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -8,9 +8,10 @@
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",
11
+ "pretest": "npm run build",
11
12
  "dev": "ts-node src/index.ts",
12
13
  "start": "node dist/index.js",
13
- "test": "node --require ts-node/register --test src/core/*.test.ts",
14
+ "test": "node --require ts-node/register --test src/core/*.test.ts src/commands/*.test.ts",
14
15
  "test:e2e:install": "bash scripts/e2e-install-smoke.sh",
15
16
  "test:e2e:workflow": "bash scripts/e2e-real-workflow.sh",
16
17
  "test:e2e:non-git": "bash scripts/e2e-non-git-fallback.sh",
@@ -20,7 +21,10 @@
20
21
  "test:e2e:v06-empty": "bash scripts/e2e-v06-empty-guidance.sh",
21
22
  "test:e2e:v06-nongit": "bash scripts/e2e-v06-non-git-ux.sh",
22
23
  "test:e2e:v06-skills": "bash scripts/e2e-v06-skills.sh",
23
- "test:e2e:v061-suggest": "bash scripts/e2e-v061-suggest.sh"
24
+ "test:e2e:v061-suggest": "bash scripts/e2e-v061-suggest.sh",
25
+ "test:e2e:v063-discover": "bash scripts/e2e-v063-discover.sh",
26
+ "test:e2e:v07-novel": "bash scripts/e2e-v07-novel.sh",
27
+ "test:e2e:v07-research": "bash scripts/e2e-v07-research.sh"
24
28
  },
25
29
  "keywords": [
26
30
  "agent",
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: pmem
3
- description: Project memory for AI agents — recall context, ask questions, detect changes, update memory, verify consistency across sessions.
3
+ description: Universal project memory for AI agents — initialize software, novel, or research memory; recall context; ask questions; detect changes; update cards; verify consistency across sessions.
4
4
  allowed-tools: Bash(pmem:*)
5
5
  ---
6
6
 
7
7
  # Project Memory with pmem
8
8
 
9
- `pmem` gives coding agents persistent project memory across sessions. It stores memory as Markdown cards under `.pmem/` and builds SQLite indexes for fast recall.
9
+ `pmem` gives agents persistent project memory across sessions. It stores memory as Markdown cards under `.pmem/` and builds SQLite indexes for fast recall. v0.7.0 is domain-neutral: the same workflow works for software projects, novels, research work, and custom card schemas.
10
10
 
11
11
  ## Quick start
12
12
 
@@ -15,12 +15,18 @@ allowed-tools: Bash(pmem:*)
15
15
  pmem init my-project --guided --description "A backend service" --stage "Alpha" --next "Set up CI/CD"
16
16
  pmem rebuild
17
17
 
18
+ # Or initialize a domain preset
19
+ pmem init my-novel --domain novel
20
+ pmem init lit-review --domain research
21
+
18
22
  # Restore context (do this at session start)
19
- pmem session start -a "Claude"
23
+ pmem session start -a "<agent-name>"
20
24
  pmem recall --format compact --budget 2000
21
25
 
22
26
  # Find relevant memory
23
27
  pmem ask "auth module" --format compact
28
+ pmem ask "main character motivation" --format compact
29
+ pmem ask "source claim evidence" --format compact
24
30
  ```
25
31
 
26
32
  ## Core Workflow
@@ -30,7 +36,7 @@ Every session follows this loop:
30
36
  ```
31
37
  session start → recall (restore context) → ask (find specific memory)
32
38
 
33
- edit code
39
+ edit project files
34
40
 
35
41
  status (detect changes) → mark-dirty --auto (flag affected cards)
36
42
 
@@ -44,9 +50,17 @@ session end → verify (check consistency)
44
50
  ### Init & Setup
45
51
 
46
52
  ```bash
53
+ # Default software preset
54
+ pmem init my-project
55
+
47
56
  # Interactive guided setup (asks 3 questions)
48
57
  pmem init my-project --guided
49
58
 
59
+ # Domain presets (v0.7.0)
60
+ pmem init my-project --domain software
61
+ pmem init my-novel --domain novel
62
+ pmem init my-research --domain research
63
+
50
64
  # Non-interactive (for scripts and agents)
51
65
  pmem init my-project --guided \
52
66
  --description "Project description" \
@@ -62,6 +76,36 @@ pmem rebuild --full # full rebuild, clear all tables
62
76
  pmem rebuild --card module.core # rebuild single card
63
77
  ```
64
78
 
79
+ ### Domain Presets & Custom Schemas (v0.7.0)
80
+
81
+ Use presets when the project is not a conventional software codebase:
82
+
83
+ | Preset | Foundational cards | Default discover |
84
+ |--------|--------------------|------------------|
85
+ | `software` | `module` | enabled |
86
+ | `novel` | `character`, `chapter` | disabled |
87
+ | `research` | `source`, `claim` | disabled |
88
+
89
+ The project manifest can define:
90
+
91
+ ```yaml
92
+ schema:
93
+ card_types: [character, chapter, world, arc, decision, trace]
94
+ type_dirs:
95
+ character: characters
96
+ chapter: chapters
97
+ foundational_types: [character, chapter]
98
+ evidence_types: [decision, trace]
99
+ creatable_types: [character, chapter, world, arc, decision, trace]
100
+ default_type: trace
101
+ discover:
102
+ enabled: false
103
+ ```
104
+
105
+ For `pmem recall --format json`, read `active_foundation`. `active_modules` remains as a backward-compatible alias with the same contents.
106
+
107
+ Legacy v0.6.x projects do not need migration. When `schema` is absent, pmem falls back to the old software defaults without rewriting the manifest.
108
+
65
109
  ### Context Recovery
66
110
 
67
111
  ```bash
@@ -77,6 +121,39 @@ pmem related module.core --depth 2
77
121
  pmem trace decision.sqlite_runtime
78
122
  ```
79
123
 
124
+ ### Relationship Discovery (v0.6.3+)
125
+
126
+ ```bash
127
+ # Auto-discover software project relationships across 6 languages
128
+ pmem discover --dry-run --format json # preview without writing
129
+ pmem discover --format json # discover and write inferred edges
130
+
131
+ # Filter by language
132
+ pmem discover --lang nodejs,python
133
+
134
+ # Use custom pattern file
135
+ pmem discover --pattern-file .pmem/discover-patterns.json
136
+
137
+ # Review and manage inferred edges
138
+ pmem related <id> --format json --source inferred
139
+ pmem update --confirm --accept-edges 1,2,3
140
+ pmem update --confirm --reject-edges 4,5
141
+ ```
142
+
143
+ The discover command scans:
144
+ - **Source file imports** (6 languages: Node.js, Python, Rust, Go, C/C++, Java) - confidence 0.7
145
+ - **Package manager dependencies** (package.json, Cargo.toml, go.mod, etc.) - confidence 0.7-0.85
146
+
147
+ **False-positive guard**: language builtins (Node.js `fs`/`path`/`crypto`, Python `os`/`sys`/`json`, Go `fmt`/`net`, Java `java.*`/`javax.*`/`jakarta.*`/Spring, C/C++ standard headers) and `@types/*` are silently dropped before any output. They never become edges or ambiguous entries.
148
+
149
+ **Ambiguous output is signal-first**: each `ambiguous` entry has a `severity` of either:
150
+ - `actionable` — local project file that has no card. Run `pmem new module "Title"` to create one, or `pmem update --confirm --reject-edges <id>` if no card is needed.
151
+ - `informational` — external package / framework / builtin with no card. No action needed.
152
+
153
+ The compact output lists actionable items first, then collapses informational ones to a count. Parse `summary.actionable` from JSON to drive your review loop.
154
+
155
+ For `novel` and `research` presets, `discover.enabled` defaults to `false`. Running `pmem discover` exits 0 with a disabled message and does not scan files.
156
+
80
157
  ### Change Detection & Memory Update
81
158
 
82
159
  ```bash
@@ -90,7 +167,7 @@ pmem mark-dirty -r "Refactored auth module"
90
167
 
91
168
  # Get memory update suggestions
92
169
  pmem update --suggest --format json
93
- # NOTE: v0.6.2+ exits 0 regardless; check JSON summary.has_actionable for suggestions
170
+ # NOTE: v0.6.2+ exits 0 regardless; check JSON summary.has_actionable or summary.blocking
94
171
 
95
172
  # Confirm and write changes
96
173
  pmem update --confirm -s "Updated auth module" -n "Add token refresh"
@@ -119,7 +196,7 @@ pmem migrate --to 0.3 --backup
119
196
  ### Sessions
120
197
 
121
198
  ```bash
122
- pmem session start -a "Claude"
199
+ pmem session start -a "<agent-name>"
123
200
  pmem session end -s "Completed auth refactor"
124
201
  ```
125
202
 
@@ -132,6 +209,7 @@ pmem integration install claude-code
132
209
  # Install agent skills globally
133
210
  pmem install --skills --claude # → ~/.claude/skills/pmem/
134
211
  pmem install --skills --codex # → ~/.codex/skills/pmem/
212
+ pmem install --skills --gemini # → ~/.gemini/skills/pmem/
135
213
  pmem install --skills --all # → all detected agents
136
214
 
137
215
  # Verify integration status
@@ -193,4 +271,6 @@ pmem verify
193
271
  * **First-time project setup** — [references/first-init.md](references/first-init.md)
194
272
  * **Session workflow in detail** — [references/session-workflow.md](references/session-workflow.md)
195
273
  * **Creating memory cards** — [references/memory-cards.md](references/memory-cards.md)
274
+ * **Universal domains and schemas** — [references/universal-domains.md](references/universal-domains.md)
275
+ * **Discovering project relationships** — run `pmem discover --dry-run --format json` to see inferred edges, then use `pmem update --confirm --accept-edges` to promote them
196
276
  * **Troubleshooting** — [references/troubleshooting.md](references/troubleshooting.md)
@@ -12,6 +12,7 @@ pmem --version
12
12
  ```bash
13
13
  pmem install --skills --claude # for Claude Code
14
14
  pmem install --skills --codex # for Codex
15
+ pmem install --skills --gemini # for Gemini
15
16
  pmem install --skills --all # for all detected agents
16
17
  ```
17
18
 
@@ -28,6 +29,16 @@ pmem init your-project --guided \
28
29
  pmem rebuild
29
30
  ```
30
31
 
32
+ Domain presets (v0.7.0):
33
+
34
+ ```bash
35
+ pmem init your-project --domain software # default; modules/features/tasks
36
+ pmem init your-novel --domain novel # characters/chapters/world/arc
37
+ pmem init your-research --domain research # sources/claims/notes/experiments
38
+ ```
39
+
40
+ Use `software` for codebases, `novel` for writing projects, and `research` for literature reviews or evidence-driven notes. Novel and research projects disable `pmem discover` by default to avoid code-scanner noise.
41
+
31
42
  Or with a JSON answers file:
32
43
 
33
44
  ```bash
@@ -77,6 +88,16 @@ echo "export const app = { name: 'my-app' };" > src/index.ts
77
88
  pmem rebuild
78
89
  ```
79
90
 
91
+ For non-software projects, use the preset card types:
92
+
93
+ ```bash
94
+ pmem new character "Main Protagonist"
95
+ pmem new chapter "Opening Scene"
96
+ pmem new source "Smith 2024 Survey"
97
+ pmem new claim "Memory Improves Agent Continuity"
98
+ pmem rebuild
99
+ ```
100
+
80
101
  ## Step 5: Verify setup
81
102
 
82
103
  ```bash