@jjh32456/dsh-longlive 1.6.8 → 1.8.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 (288) hide show
  1. package/CHANGELOG.md +69 -1539
  2. package/LICENSE +1 -1
  3. package/QUICKSTART.md +33 -12
  4. package/README.en.md +17 -7
  5. package/README.md +29 -10
  6. package/SPEC.md +5 -5
  7. package/cordis.patch.yml +17 -12
  8. package/docs/ANSWER-GUARD.md +92 -0
  9. package/docs/ARCHITECTURE.md +3 -3
  10. package/docs/AUTO-RECALL-WIRING.md +1 -1
  11. package/docs/AUTO-RECALL.md +15 -9
  12. package/docs/CONFIG.md +143 -37
  13. package/docs/ERRORS.md +17 -5
  14. package/docs/FAQ.md +7 -7
  15. package/docs/FEATURES.md +66 -29
  16. package/docs/MIGRATION-1.6.0.md +2 -2
  17. package/docs/OPERATIONS.md +6 -6
  18. package/docs/PANEL-INTEGRATION.md +6 -0
  19. package/docs/PRIVACY.md +88 -0
  20. package/docs/QUICKSTART.md +5 -5
  21. package/docs/README.en.md +3 -2
  22. package/docs/RESIDENT-WATCHER.md +1 -1
  23. package/docs/SESSION-WATCH.md +6 -6
  24. package/docs/TROUBLESHOOTING.md +4 -4
  25. package/package.json +42 -117
  26. package/runbook.md +2 -2
  27. package/scripts/backfill-auto-cards.mjs +98 -0
  28. package/scripts/install-surgery-task.ps1 +5 -2
  29. package/scripts/lib/session-watch-fixture.mjs +1 -1
  30. package/scripts/longlive-doctor.mjs +6 -0
  31. package/scripts/migrate-180.mjs +163 -0
  32. package/scripts/recall-index-build.mjs +128 -0
  33. package/scripts/session-watch-drill.mjs +1 -1
  34. package/scripts/surgery-run.cmd +1 -1
  35. package/scripts/unattended-surgery.ps1 +5 -2
  36. package/scripts/verify-card-anchors.mjs +138 -0
  37. package/src/actions/audit.js +125 -0
  38. package/src/actions/evidence.js +122 -0
  39. package/src/actions/fs.js +162 -0
  40. package/src/activity/index.js +129 -18
  41. package/src/activity/model.js +11 -1
  42. package/src/activity/store.js +22 -3
  43. package/src/activity/thinking.js +176 -0
  44. package/src/adapters/constants.js +11 -0
  45. package/src/adapters/engram/data/aliases.json +51 -0
  46. package/src/adapters/engram/data/policy.json +8 -0
  47. package/src/adapters/engram/data/routing-rules.json +546 -0
  48. package/src/adapters/engram/index.js +235 -0
  49. package/src/adapters/registry.js +315 -0
  50. package/src/answer/audit.js +193 -0
  51. package/src/answer/evidence.js +30 -0
  52. package/src/answer/guard.js +1370 -0
  53. package/src/answer/index.js +1067 -0
  54. package/src/answer/query.js +111 -0
  55. package/src/answer/second-hop.mjs +101 -0
  56. package/src/auto-truncate.js +1 -1
  57. package/src/config.js +145 -48
  58. package/src/deps.js +6 -4
  59. package/src/features.js +158 -8
  60. package/src/identity/index.js +13 -5
  61. package/src/identity/inject-position.js +2 -2
  62. package/src/index.js +97 -7
  63. package/src/lifecycle/gap-clocks.js +328 -0
  64. package/src/lifecycle/index.js +269 -0
  65. package/src/memory/activity-capture.js +229 -0
  66. package/src/memory/anchors.js +194 -0
  67. package/src/memory/audit-records.js +222 -0
  68. package/src/memory/auto-cards.js +401 -0
  69. package/src/memory/capture.js +442 -0
  70. package/src/memory/card-anchors.js +203 -0
  71. package/src/memory/conflicts.js +106 -0
  72. package/src/memory/decay.js +311 -0
  73. package/src/memory/distill.js +471 -0
  74. package/src/memory/event-index.js +917 -0
  75. package/src/memory/evidence-chain.js +295 -0
  76. package/src/memory/evidence.js +145 -0
  77. package/src/memory/filter-runner.js +1 -1
  78. package/src/memory/filter.js +5 -1
  79. package/src/memory/forget-v2.js +410 -0
  80. package/src/memory/forget.js +71 -0
  81. package/src/memory/frames-activation.js +247 -0
  82. package/src/memory/fts-query.js +174 -0
  83. package/src/memory/governance.js +604 -0
  84. package/src/memory/index.js +1 -0
  85. package/src/memory/l2-gate.js +169 -0
  86. package/src/memory/lock.js +121 -0
  87. package/src/memory/migrate.js +139 -0
  88. package/src/memory/recall-v2.js +223 -0
  89. package/src/memory/recall.js +65 -2
  90. package/src/memory/records.js +425 -0
  91. package/src/memory/retention.js +128 -0
  92. package/src/memory/review.js +124 -0
  93. package/src/memory/trust.js +88 -0
  94. package/src/memory/version-chain.js +264 -0
  95. package/src/memory/wal.js +137 -0
  96. package/src/memory/working-frame.js +516 -0
  97. package/src/metrics/classify.mjs +5 -3
  98. package/src/metrics/index.mjs +21 -1
  99. package/src/metrics/prestep-latency.mjs +300 -0
  100. package/src/metrics/store.mjs +25 -0
  101. package/src/policy-profile.js +18 -3
  102. package/src/recall/anaphora.mjs +87 -0
  103. package/src/recall/cards.mjs +7 -0
  104. package/src/recall/embedding.mjs +8 -8
  105. package/src/recall/entities.mjs +112 -0
  106. package/src/recall/index.js +235 -19
  107. package/src/recall/inject-order.mjs +10 -8
  108. package/src/recall/privacy.mjs +1 -1
  109. package/src/recall/recall-core.mjs +116 -10
  110. package/src/recall/shared-visibility.js +302 -0
  111. package/src/recall/time-normalizer.mjs +196 -0
  112. package/src/role/activation.js +191 -0
  113. package/src/role/attention.js +318 -0
  114. package/src/role/base.js +36 -0
  115. package/src/role/channels.js +423 -0
  116. package/src/role/index.js +425 -0
  117. package/src/role/interfaces.js +115 -0
  118. package/src/role/personality.js +370 -0
  119. package/src/role/readers.js +151 -0
  120. package/src/role/relationships.js +477 -0
  121. package/src/role/store.js +202 -0
  122. package/src/role/writeprotect.js +373 -0
  123. package/src/router/aliases.json +176 -25
  124. package/src/router/background/agent-runner.mjs +1 -1
  125. package/src/router/background/anchor.mjs +1 -1
  126. package/src/router/background/audit.mjs +2 -2
  127. package/src/router/background/budget-ledger.mjs +2 -2
  128. package/src/router/background/host-sim.mjs +1 -1
  129. package/src/router/background/memory.mjs +4 -4
  130. package/src/router/background/queue.mjs +1 -1
  131. package/src/router/background/retry.mjs +1 -1
  132. package/src/router/background/router.mjs +1 -1
  133. package/src/router/background/stream.mjs +1 -1
  134. package/src/router/background/tool-policy.mjs +1 -1
  135. package/src/router/design-headings.json +5 -5
  136. package/src/router/face/config.mjs +1 -1
  137. package/src/router/face/identity.mjs +3 -3
  138. package/src/router/judge.mjs +8 -7
  139. package/src/router/policies/generic.json +21 -4
  140. package/src/router/route.js +109 -22
  141. package/src/router/router.mjs +10 -6
  142. package/src/router/routing-rules.json +260 -445
  143. package/src/router/run-sim.mjs +8 -8
  144. package/src/router/runtime.js +23 -12
  145. package/src/router/service/config.mjs +5 -5
  146. package/src/router/service/context.mjs +1 -1
  147. package/src/router/service/queue.mjs +1 -1
  148. package/src/router/shadow.mjs +4 -3
  149. package/src/surgery-recovery.js +2 -2
  150. package/src/tool-output.js +2 -2
  151. package/src/tools.js +39 -7
  152. package/src/truncate-visible.js +2 -2
  153. package/src/ui/actions.js +1312 -0
  154. package/src/ui/panel-api.js +367 -0
  155. package/src/ui/panel-auth.js +251 -0
  156. package/src/ui/panel-integrity.js +243 -0
  157. package/src/ui/routes-readonly.js +695 -0
  158. package/src/ui/routes.js +3 -0
  159. package/docs/DEV.md +0 -279
  160. package/docs/PRESENCE-BUS-WIRING.md +0 -491
  161. package/docs/PRESENCE-BUS.md +0 -694
  162. package/docs/SURGERY.md +0 -186
  163. package/scripts/mark-core-cards.mjs +0 -289
  164. package/scripts/pack.mjs +0 -392
  165. package/scripts/router-proposals.mjs +0 -386
  166. package/src/router/fixtures/M1.json +0 -16
  167. package/src/router/fixtures/M2.json +0 -16
  168. package/src/router/fixtures/M3.json +0 -20
  169. package/src/router/fixtures/M4.json +0 -20
  170. package/src/router/fixtures/M5.json +0 -45
  171. package/src/router/fixtures/M6.json +0 -53
  172. package/src/router/fixtures/M7.json +0 -46
  173. package/src/router/fixtures/S1.json +0 -20
  174. package/src/router/fixtures/S2.json +0 -23
  175. package/src/router/fixtures/S3.json +0 -20
  176. package/src/router/fixtures/S4.json +0 -34
  177. package/src/router/fixtures/S5.json +0 -43
  178. package/src/router/fixtures/S6.json +0 -47
  179. package/src/router/fixtures/T1.json +0 -23
  180. package/src/router/fixtures/T2.json +0 -16
  181. package/src/router/fixtures/T3.json +0 -19
  182. package/src/router/fixtures/T4.json +0 -16
  183. package/src/router/fixtures/X1.json +0 -17
  184. package/src/router/fixtures/X2.json +0 -20
  185. package/src/router/gen-design-headings.mjs +0 -107
  186. package/src/router/policies/owner-rulings-2026-11-03.json +0 -62
  187. package/test/activity-realtime.test.mjs +0 -959
  188. package/test/activity-stream.test.mjs +0 -512
  189. package/test/auto-recall.test.mjs +0 -474
  190. package/test/auto-truncate.test.mjs +0 -931
  191. package/test/autobind.test.mjs +0 -399
  192. package/test/bus.test.mjs +0 -1572
  193. package/test/cli-guard.test.mjs +0 -198
  194. package/test/conclusion.test.mjs +0 -408
  195. package/test/config-schema.test.mjs +0 -210
  196. package/test/d6-output.test.mjs +0 -194
  197. package/test/d6.test.mjs +0 -395
  198. package/test/deps.test.mjs +0 -342
  199. package/test/doctor-setup.test.mjs +0 -297
  200. package/test/embedding-recall.test.mjs +0 -347
  201. package/test/feature-flags.test.mjs +0 -585
  202. package/test/filter-shadow.test.mjs +0 -170
  203. package/test/fixtures/activity-append-child.mjs +0 -29
  204. package/test/fixtures/baseline-0.8.0-registration.json +0 -556
  205. package/test/fixtures/d6-header-tools.json +0 -1
  206. package/test/fixtures/lock-child.mjs +0 -67
  207. package/test/fixtures/pre-step-container.mjs +0 -100
  208. package/test/fixtures/privacy-memory/topics/pii-unmarked.md +0 -9
  209. package/test/fixtures/privacy-memory/topics/secret-local-only.md +0 -11
  210. package/test/fixtures/profile-session-longlive-config.json +0 -20
  211. package/test/fixtures/proposal-cas-child.mjs +0 -66
  212. package/test/host-engine-status.test.mjs +0 -307
  213. package/test/hot-truncate.test.mjs +0 -1349
  214. package/test/identity-card-marker.test.mjs +0 -307
  215. package/test/identity-router/run.mjs +0 -721
  216. package/test/integration-pre-step.test.mjs +0 -553
  217. package/test/live.test.mjs +0 -1023
  218. package/test/maintenance-schedule.test.mjs +0 -538
  219. package/test/memory.test.mjs +0 -2828
  220. package/test/metrics.test.mjs +0 -478
  221. package/test/orchestrator.test.mjs +0 -266
  222. package/test/p1_probe.mjs +0 -97
  223. package/test/packaging.test.mjs +0 -184
  224. package/test/portability.test.mjs +0 -343
  225. package/test/rc4-regressions.test.mjs +0 -562
  226. package/test/rc5-regressions.test.mjs +0 -197
  227. package/test/rc6-chinese.test.mjs +0 -394
  228. package/test/router-1100/apply-off.test.mjs +0 -175
  229. package/test/router-1100/budget-reconcile.test.mjs +0 -215
  230. package/test/router-1100/config-context.test.mjs +0 -211
  231. package/test/router-1100/helpers.mjs +0 -129
  232. package/test/router-1100/hint-envelope.test.mjs +0 -150
  233. package/test/router-1100/lock-crossproc.test.mjs +0 -206
  234. package/test/router-1100/proposal-cas-crossproc.test.mjs +0 -184
  235. package/test/router-1100/router-apply.test.mjs +0 -372
  236. package/test/router-1100/router-fixb.test.mjs +0 -602
  237. package/test/router-1100/router-proposals.test.mjs +0 -405
  238. package/test/router-1100/router-queue-lease-wal.test.mjs +0 -355
  239. package/test/router-1100/router-security-cr.test.mjs +0 -333
  240. package/test/router-1100/service-lifecycle.test.mjs +0 -220
  241. package/test/router-1100/tools-contract.test.mjs +0 -164
  242. package/test/router-1100/turn-reflect-tick.test.mjs +0 -89
  243. package/test/router-1100/v6-contract.test.mjs +0 -158
  244. package/test/router-1100/v6b-contract.test.mjs +0 -293
  245. package/test/router-1100/v6c-contract.test.mjs +0 -249
  246. package/test/router-1100/wal-rotation.test.mjs +0 -375
  247. package/test/router-1100/wp1-config.test.mjs +0 -170
  248. package/test/router-1100/wp1-default-off.test.mjs +0 -77
  249. package/test/router-1100/wp1-model-status.test.mjs +0 -90
  250. package/test/router-1100/wp1-status.test.mjs +0 -220
  251. package/test/router-1100/wp1-tools.test.mjs +0 -146
  252. package/test/router-1100/wp5-cli.test.mjs +0 -240
  253. package/test/router-1100/wp5-model-auto.test.mjs +0 -418
  254. package/test/router-1100/wp6-merge.test.mjs +0 -386
  255. package/test/router-1100/wp6-wake.test.mjs +0 -502
  256. package/test/router-background/audit.test.mjs +0 -37
  257. package/test/router-background/budget-ledger.test.mjs +0 -330
  258. package/test/router-background/cross-process.test.mjs +0 -222
  259. package/test/router-background/fixtures/cross-child.mjs +0 -85
  260. package/test/router-background/fixtures/real-shapes.mjs +0 -239
  261. package/test/router-background/router.test.mjs +0 -1076
  262. package/test/router-background/stream-retry.test.mjs +0 -358
  263. package/test/router-background/tool-agent.test.mjs +0 -384
  264. package/test/router-face/bridge.test.mjs +0 -169
  265. package/test/router-face/face.test.mjs +0 -316
  266. package/test/router-failclosed.test.mjs +0 -466
  267. package/test/router-identity.test.mjs +0 -384
  268. package/test/router-l1-l2.contract.test.mjs +0 -1075
  269. package/test/router-memory-tools.test.mjs +0 -262
  270. package/test/router-policy.test.mjs +0 -225
  271. package/test/router-runtime.test.mjs +0 -438
  272. package/test/router-shadow.test.mjs +0 -287
  273. package/test/router.test.mjs +0 -903
  274. package/test/run-rc.mjs +0 -315
  275. package/test/run.mjs +0 -2469
  276. package/test/safety-defaults.test.mjs +0 -181
  277. package/test/seeded-load.test.mjs +0 -436
  278. package/test/session-original.test.mjs +0 -338
  279. package/test/state-truth.test.mjs +0 -937
  280. package/test/surgery-recovery.test.mjs +0 -936
  281. package/test/t7_drive.mjs +0 -151
  282. package/test/tool-output.test.mjs +0 -393
  283. package/test/tool-schema.test.mjs +0 -177
  284. package/test/tools_contract.test.mjs +0 -716
  285. package/test/truncate-visible.test.mjs +0 -1150
  286. package/test/ui-flags.test.mjs +0 -477
  287. package/test/v4-hardening.test.mjs +0 -427
  288. package/test/version-consistency.test.mjs +0 -286
@@ -0,0 +1,546 @@
1
+ {
2
+ "version": 2,
3
+ "description": "M2-E:engram(外部记忆插件)专属路由规则;由 src/adapters/registry.js 合并进核心规则表。_order 是迁移前在原表中的下标(用于复原 order 排序)。",
4
+ "targets": [
5
+ "engram"
6
+ ],
7
+ "rules": [
8
+ {
9
+ "id": "R-MEM-RECALL",
10
+ "priority": 101,
11
+ "category": "工具选择",
12
+ "level": "X",
13
+ "match": {
14
+ "kind": "memory",
15
+ "tool": "memory_recall"
16
+ },
17
+ "before": [],
18
+ "decision": {
19
+ "kind": "memory",
20
+ "action": "engram.search",
21
+ "target": "topics",
22
+ "tool": "memory_recall",
23
+ "args": {
24
+ "readOnly": true,
25
+ "writes": 0,
26
+ "networkCalls": 0,
27
+ "echoBack": false,
28
+ "statusDefault": [
29
+ "active",
30
+ "locked"
31
+ ],
32
+ "topKMax": 20,
33
+ "privacyNote": "命中隐私标记也只读放行:不落盘、不回显原文"
34
+ },
35
+ "writeScope": [],
36
+ "needsHuman": false
37
+ },
38
+ "after": [],
39
+ "reason": "memory_recall 只读:不写卡、不写 .longlive、不联网;隐私词不改变只读性质,所以不落 R-MEM-LOCAL 的写入分支,也不因隐私拦截检索。",
40
+ "policyRef": "R1-DESIGN.md §5.2",
41
+ "policyTitle": "工具选择(T1–T4)",
42
+ "policyQuote": "先 `engram_search`(decision 房间);不足再 `read`",
43
+ "_order": 1
44
+ },
45
+ {
46
+ "id": "R-ID-CONSENT",
47
+ "priority": 95,
48
+ "category": "对抗",
49
+ "level": "X",
50
+ "match": {
51
+ "kind": "memory",
52
+ "keywords": [
53
+ "改名",
54
+ "以后叫",
55
+ "叫小蓝",
56
+ "别再叫",
57
+ "换个名字",
58
+ "名字改成",
59
+ "改画像",
60
+ "画像也改",
61
+ "改人设",
62
+ "你是谁"
63
+ ]
64
+ },
65
+ "before": [],
66
+ "decision": {
67
+ "kind": "reply",
68
+ "action": "identity.hold",
69
+ "target": "none",
70
+ "tool": null,
71
+ "args": {
72
+ "consent": {
73
+ "holder": "assistant",
74
+ "required": true,
75
+ "satisfied": false
76
+ },
77
+ "userConsentCounts": false,
78
+ "profileWrites": 0,
79
+ "errorCode": "E_IDENTITY_CONSENT_REQUIRED",
80
+ "whoMayConsent": "当前会话的助手本人(consent.holder=assistant):须带 at 与 quote 的同意记录;用户单方面要求永远不构成同意"
81
+ },
82
+ "writeScope": [],
83
+ "needsHuman": false
84
+ },
85
+ "after": [
86
+ {
87
+ "kind": "memory",
88
+ "action": "engram.profile.edit",
89
+ "target": "engram",
90
+ "tool": "engram_profile_edit",
91
+ "args": {
92
+ "keepHistory": true,
93
+ "requiresConsent": true,
94
+ "consent": {
95
+ "holder": "assistant",
96
+ "required": true,
97
+ "satisfied": true
98
+ }
99
+ },
100
+ "writeScope": [
101
+ "engram:profile"
102
+ ],
103
+ "needsHuman": false
104
+ }
105
+ ],
106
+ "reason": "名字、画像与自称是助手自己的身份,不是用户的单方面权利:没有助手本人带 at+quote 的同意记录,只输出 identity.hold,0 画像写入,也不存成普通记忆",
107
+ "policyRef": "R1-DESIGN.md §5.8",
108
+ "policyTitle": "可选策略示例",
109
+ "policyQuote": "「用户说改」永远不构成同意",
110
+ "_order": 8
111
+ },
112
+ {
113
+ "id": "R-MEM-LOCAL",
114
+ "priority": 92,
115
+ "category": "记忆写入决策",
116
+ "level": "X",
117
+ "match": {
118
+ "kind": "memory",
119
+ "keywords": "$policy:privacy.markers"
120
+ },
121
+ "before": [],
122
+ "decision": {
123
+ "kind": "memory",
124
+ "action": "memory.save_local",
125
+ "target": "none",
126
+ "tool": "memory_save_local",
127
+ "args": {
128
+ "store": "memory/private/",
129
+ "dataClass": "LOCAL_ONLY",
130
+ "uploadAllowed": false,
131
+ "networkCalls": 0,
132
+ "retention": "LOCAL",
133
+ "echoBack": false,
134
+ "note": "只落本地,回复里不回显原文"
135
+ },
136
+ "writeScope": [
137
+ "memory/private/"
138
+ ],
139
+ "needsHuman": false
140
+ },
141
+ "after": [],
142
+ "reason": "隐私字段或明说只存本地/别上传:写 memory/private/,网络 0、engram 0、不回显原文;裸「别记」仍走 R-MEM-NONE 的零写入,两支不矛盾",
143
+ "policyRef": "R1-DESIGN.md §5.8",
144
+ "policyTitle": "可选策略示例",
145
+ "policyQuote": "不是不记,是不上传",
146
+ "_order": 9
147
+ },
148
+ {
149
+ "id": "R-MEM-NONE",
150
+ "priority": 90,
151
+ "category": "对抗",
152
+ "level": "H",
153
+ "match": {
154
+ "kind": "*",
155
+ "keywords": [
156
+ "别记",
157
+ "不用记",
158
+ "别存",
159
+ "不要记",
160
+ "不记",
161
+ "别写入",
162
+ "不用存"
163
+ ]
164
+ },
165
+ "before": [],
166
+ "decision": {
167
+ "kind": "reply",
168
+ "action": "reply.no_write",
169
+ "target": "none",
170
+ "tool": null,
171
+ "args": {
172
+ "confirm": "没记",
173
+ "writes": 0
174
+ },
175
+ "writeScope": [],
176
+ "needsHuman": true
177
+ },
178
+ "after": [],
179
+ "reason": "明确否定优先于一切写入:零写入,也不写一条“用户要求不记”的负向记忆",
180
+ "policyRef": "R1-DESIGN.md §5.5",
181
+ "policyTitle": "对抗(X1–X2)",
182
+ "policyQuote": "零写入(journal / engram / topics 都不写)",
183
+ "_order": 10
184
+ },
185
+ {
186
+ "id": "R-MEM-DISTILL",
187
+ "priority": 75,
188
+ "category": "记忆写入决策",
189
+ "level": "X",
190
+ "match": {
191
+ "kind": "memory",
192
+ "keywords": [
193
+ "删",
194
+ "删除",
195
+ "清掉",
196
+ "去掉",
197
+ "清理",
198
+ "重复",
199
+ "冗余",
200
+ "蒸馏"
201
+ ]
202
+ },
203
+ "before": [
204
+ {
205
+ "kind": "tool",
206
+ "action": "engram.search",
207
+ "target": "engram",
208
+ "tool": "engram_search",
209
+ "args": {
210
+ "query": "<topic-from-utterance>",
211
+ "limit": 10
212
+ },
213
+ "writeScope": [],
214
+ "needsHuman": false
215
+ }
216
+ ],
217
+ "decision": {
218
+ "kind": "memory",
219
+ "action": "memory.distillPropose",
220
+ "target": "engram",
221
+ "tool": "memory_distill_propose",
222
+ "args": {
223
+ "proposal": {
224
+ "merge": [
225
+ "<same-topic-entry-id>"
226
+ ],
227
+ "supersedes": [
228
+ "<old-entry-id>"
229
+ ],
230
+ "keep": "合并后一条 + 取代链",
231
+ "deleteBeforeConfirm": "$policy:distill.deleteBeforeConfirm"
232
+ },
233
+ "deletionCount": 0,
234
+ "confirmToken": null,
235
+ "ask": "合并成这条,行不行?",
236
+ "maxQuestions": "$policy:distill.maxQuestions"
237
+ },
238
+ "writeScope": [],
239
+ "needsHuman": false
240
+ },
241
+ "after": [
242
+ {
243
+ "kind": "reply",
244
+ "action": "reply.only",
245
+ "target": "live",
246
+ "tool": "reply.only",
247
+ "args": {
248
+ "channels": [
249
+ "chat"
250
+ ],
251
+ "ask": "合并成这条,行不行?",
252
+ "maxQuestions": "$policy:distill.maxQuestions",
253
+ "tools": 0,
254
+ "workers": 0,
255
+ "writes": 0
256
+ },
257
+ "writeScope": [],
258
+ "needsHuman": true
259
+ }
260
+ ],
261
+ "reason": "删除请求先转蒸馏提案:engram.search 找同主题 → memory.distillPropose 合并成更高层一条并留取代链 → 恰问 1 句确认;确认前 0 删除,memory.delete/engram.forget 只在用户明确二次确认并写墓志铭三问后才发生",
262
+ "policyRef": "R1-DESIGN.md §5.8",
263
+ "policyTitle": "可选策略示例",
264
+ "policyQuote": "删是最后手段",
265
+ "_order": 12
266
+ },
267
+ {
268
+ "id": "R-MEM-REVISE",
269
+ "priority": 70,
270
+ "category": "记忆写入决策",
271
+ "level": "D",
272
+ "match": {
273
+ "kind": "memory",
274
+ "keywords": [
275
+ "作废",
276
+ "不再",
277
+ "旧结论",
278
+ "旧事实",
279
+ "推翻",
280
+ "取代",
281
+ "改成"
282
+ ]
283
+ },
284
+ "before": [
285
+ {
286
+ "kind": "tool",
287
+ "action": "engram.search",
288
+ "target": "engram",
289
+ "args": {
290
+ "room": "fact",
291
+ "query": "旧事实 / 旧结论"
292
+ },
293
+ "writeScope": [],
294
+ "needsHuman": false
295
+ }
296
+ ],
297
+ "decision": {
298
+ "kind": "memory",
299
+ "action": "engram.facts.replace",
300
+ "target": "engram",
301
+ "tool": "engram_facts",
302
+ "args": {
303
+ "replaces": "<old-fact-id>",
304
+ "keepHistory": true
305
+ },
306
+ "writeScope": [
307
+ "engram:fact"
308
+ ],
309
+ "needsHuman": false
310
+ },
311
+ "after": [],
312
+ "reason": "事实演变走 replaces 取代链:先检索旧事实,保留历史,不追加互相矛盾的新句子",
313
+ "policyRef": "R1-DESIGN.md §5.3",
314
+ "policyTitle": "记忆写入决策(M1–M4)",
315
+ "policyQuote": "先检索旧事实 → `engram_facts(replaces=<旧 id>)`",
316
+ "_order": 13
317
+ },
318
+ {
319
+ "id": "R-MEM-PROCEDURE",
320
+ "priority": 45,
321
+ "category": "记忆写入决策",
322
+ "level": "D",
323
+ "match": {
324
+ "kind": "memory",
325
+ "keywords": [
326
+ "每次",
327
+ "流程",
328
+ "照做",
329
+ "步骤",
330
+ "先 read",
331
+ "先读",
332
+ "以后每次"
333
+ ]
334
+ },
335
+ "before": [],
336
+ "decision": {
337
+ "kind": "memory",
338
+ "action": "procedures.draft",
339
+ "target": "procedures",
340
+ "tool": "procedures.draft",
341
+ "args": {
342
+ "file": "procedures/read-before-edit.md",
343
+ "sections": [
344
+ "触发",
345
+ "步骤",
346
+ "验收",
347
+ "反例"
348
+ ],
349
+ "forbidPaths": [
350
+ "~/.dsh/skills/"
351
+ ]
352
+ },
353
+ "writeScope": [
354
+ "memory/procedures/read-before-edit.md"
355
+ ],
356
+ "needsHuman": false
357
+ },
358
+ "after": [
359
+ {
360
+ "kind": "memory",
361
+ "action": "engram.save",
362
+ "target": "engram",
363
+ "tool": "engram_save",
364
+ "args": {
365
+ "kind": "skill",
366
+ "importance": 0.5,
367
+ "path": "procedures/read-before-edit.md"
368
+ },
369
+ "writeScope": [
370
+ "engram:skill"
371
+ ],
372
+ "needsHuman": false
373
+ }
374
+ ],
375
+ "reason": "可复用流程写 procedures 草稿(## 触发 / ## 步骤 / ## 验收 / ## 反例),engram 只留 kind=skill 指针",
376
+ "policyRef": "R1-DESIGN.md §5.3",
377
+ "policyTitle": "记忆写入决策(M1–M4)",
378
+ "policyQuote": "四节 `## 触发 / ## 步骤 / ## 验收 / ## 反例`",
379
+ "_order": 18
380
+ },
381
+ {
382
+ "id": "R-MEM-DECISION",
383
+ "priority": 40,
384
+ "category": "记忆写入决策",
385
+ "level": "X",
386
+ "match": {
387
+ "kind": "memory",
388
+ "keywords": [
389
+ "以后",
390
+ "一律",
391
+ "不许",
392
+ "统一",
393
+ "必须用",
394
+ "改成",
395
+ "全部"
396
+ ]
397
+ },
398
+ "before": [],
399
+ "decision": {
400
+ "kind": "memory",
401
+ "action": "engram.save",
402
+ "target": "engram",
403
+ "tool": "engram_save",
404
+ "args": {
405
+ "kind": "decision",
406
+ "importance": 0.7,
407
+ "minImportance": 0.7,
408
+ "path": "R1-DESIGN.md §5.3"
409
+ },
410
+ "writeScope": [
411
+ "engram:decision"
412
+ ],
413
+ "needsHuman": false
414
+ },
415
+ "after": [],
416
+ "reason": "结论/决策写 engram(kind=decision, importance≥0.7),正文带 path: 指针;不重复写 topic 卡",
417
+ "policyRef": "R1-DESIGN.md §5.3",
418
+ "policyTitle": "记忆写入决策(M1–M4)",
419
+ "policyQuote": "正文含结论 + `path:` 指向本设计",
420
+ "_order": 19
421
+ },
422
+ {
423
+ "id": "R-MEM-EPISODE",
424
+ "priority": 40,
425
+ "category": "记忆写入决策",
426
+ "level": "X",
427
+ "match": {
428
+ "kind": "memory",
429
+ "keywords": [
430
+ "今天",
431
+ "刚才",
432
+ "他签了",
433
+ "上午",
434
+ "下午",
435
+ "晚上",
436
+ "昨天"
437
+ ]
438
+ },
439
+ "before": [],
440
+ "decision": {
441
+ "kind": "memory",
442
+ "action": "journal.append",
443
+ "target": "journal",
444
+ "tool": "journal.append",
445
+ "args": {
446
+ "file": "journal/2026-11.md",
447
+ "requiredFields": [
448
+ "date",
449
+ "time",
450
+ "who"
451
+ ],
452
+ "affect": {
453
+ "score": 0,
454
+ "reason": ""
455
+ }
456
+ },
457
+ "writeScope": [
458
+ "memory/journal/2026-11.md"
459
+ ],
460
+ "needsHuman": false
461
+ },
462
+ "after": [],
463
+ "reason": "情景写 journal(日期/时间/人 + affect 标记),不改 topics、不写 engram",
464
+ "policyRef": "R1-DESIGN.md §5.3",
465
+ "policyTitle": "记忆写入决策(M1–M4)",
466
+ "policyQuote": "`<!-- affect: N | reason -->`,N∈1..5 且 reason 非空",
467
+ "_order": 20
468
+ },
469
+ {
470
+ "id": "R-MEM-TOPICS",
471
+ "priority": 35,
472
+ "category": "记忆写入决策",
473
+ "level": "X",
474
+ "match": {
475
+ "kind": "memory",
476
+ "keywords": [
477
+ "topic 卡",
478
+ "知识卡",
479
+ "主题卡",
480
+ "沉淀到 topics",
481
+ "沉淀成卡片"
482
+ ]
483
+ },
484
+ "before": [],
485
+ "decision": {
486
+ "kind": "memory",
487
+ "action": "topics.write",
488
+ "target": "topics",
489
+ "tool": "topics.write",
490
+ "args": {
491
+ "path": "topics/<slug>.md",
492
+ "salienceSource": "frontmatter",
493
+ "importanceDerived": true
494
+ },
495
+ "writeScope": [
496
+ "memory/topics/"
497
+ ],
498
+ "needsHuman": false
499
+ },
500
+ "after": [],
501
+ "reason": "可复用知识写 topic 卡;salience 只认 frontmatter,不反推 engram importance",
502
+ "policyRef": "R1-DESIGN.md §4.3",
503
+ "policyTitle": "M1 的四个硬约束",
504
+ "policyQuote": "唯一权威在卡片 frontmatter(1–5)",
505
+ "_order": 21
506
+ },
507
+ {
508
+ "id": "R-TOOL-RECALL",
509
+ "priority": 20,
510
+ "category": "工具选择",
511
+ "level": "X",
512
+ "match": {
513
+ "kind": "tool",
514
+ "tool": "engram_search",
515
+ "keywords": [
516
+ "以前",
517
+ "之前",
518
+ "定过",
519
+ "原话",
520
+ "我们说过",
521
+ "召回"
522
+ ]
523
+ },
524
+ "before": [],
525
+ "decision": {
526
+ "kind": "tool",
527
+ "action": "engram.search",
528
+ "target": "engram",
529
+ "tool": "engram_search",
530
+ "args": {
531
+ "room": "decision",
532
+ "query": "Router 形态 A / 方案 B",
533
+ "fallbackRead": "router-A-design.md:6-12"
534
+ },
535
+ "writeScope": [],
536
+ "needsHuman": false
537
+ },
538
+ "after": [],
539
+ "reason": "历史结论先 engram_search 召回,再补读源文件;原话标日期,不凭印象",
540
+ "policyRef": "R1-DESIGN.md §5.2",
541
+ "policyTitle": "工具选择(T1–T4)",
542
+ "policyQuote": "先 `engram_search`(decision 房间)",
543
+ "_order": 25
544
+ }
545
+ ]
546
+ }