@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjh32456/dsh-longlive",
3
- "version": "1.6.8",
3
+ "version": "1.8.0",
4
4
  "type": "module",
5
5
  "description": "久视(longlive):一个磁盘上的共享大脑,让每个会话都是同一个你——记忆卡、状态卡、开机卡让新会话接上同一段关系与未完成的事;配套会话卫生(热截断/备份/D2/D6 裁剪)与记忆工具(巩固/召回/程序性记忆)。1.6.8 在 1.6.7 之上并入共享大脑活动流(sharedBrain.activity:事件级活动写入、判重/蒸馏、只带新增的增量注入,默认关闭)与共享板状态诚实性修复(running 计数、焦点新鲜度、turn 状态、开机卡时效);热截断与 1.6.7 相同。",
6
6
  "keywords": [
@@ -19,7 +19,7 @@
19
19
  "auto-recall",
20
20
  "presence-bus"
21
21
  ],
22
- "author": "阿恒、听澜",
22
+ "author": "longlive contributors",
23
23
  "license": "MIT",
24
24
  "publishConfig": {
25
25
  "access": "public"
@@ -54,24 +54,13 @@
54
54
  "node": ">=20.0.0"
55
55
  },
56
56
  "files": [
57
- "src/*.js",
58
- "src/activity/*.js",
59
- "src/compaction/*.js",
60
- "src/ui/*.js",
57
+ "CHANGELOG.md",
58
+ "src/**/*.js",
59
+ "src/**/*.mjs",
60
+ "src/**/*.json",
61
+ "!src/router/policies/owner-rulings-*.json",
62
+ "!src/router/fixtures/**",
61
63
  "lib/client.js",
62
- "src/d6/*.js",
63
- "src/memory/*.js",
64
- "src/metrics/*.mjs",
65
- "src/identity/*.js",
66
- "src/recall/*.js",
67
- "src/recall/*.mjs",
68
- "src/router/*.js",
69
- "src/router/*.mjs",
70
- "src/router/service/*.mjs",
71
- "src/router/**/*.json",
72
- "src/router/background/*.mjs",
73
- "src/router/face/*.mjs",
74
- "src/bus/*.mjs",
75
64
  "cordis.patch.yml",
76
65
  "locale/*.json",
77
66
  "icon.svg",
@@ -81,118 +70,53 @@
81
70
  "SPEC.md",
82
71
  "runbook.md",
83
72
  "QUICKSTART.md",
84
- "CHANGELOG.md",
85
- "docs/ERRORS.md",
86
- "docs/DEV.md",
87
- "docs/QUICKSTART.md",
73
+ "docs/ANSWER-GUARD.md",
74
+ "docs/ARCHITECTURE.md",
75
+ "docs/AUTO-RECALL.md",
76
+ "docs/AUTO-RECALL-WIRING.md",
88
77
  "docs/CONCEPTS.md",
89
- "docs/FAQ.md",
90
78
  "docs/CONFIG.md",
91
- "docs/TOOLS.md",
92
- "docs/OPERATIONS.md",
93
- "docs/TROUBLESHOOTING.md",
94
- "docs/MIGRATION-1.6.0.md",
95
- "docs/ARCHITECTURE.md",
96
- "docs/README.en.md",
79
+ "docs/FAQ.md",
97
80
  "docs/FEATURES.md",
98
81
  "docs/METRICS.md",
82
+ "docs/MIGRATION-1.6.0.md",
83
+ "docs/OPERATIONS.md",
84
+ "docs/PANEL-INTEGRATION.md",
85
+ "docs/PRIVACY.md",
86
+ "docs/QUICKSTART.md",
87
+ "docs/README.en.md",
99
88
  "docs/RESIDENT-WATCHER.md",
100
89
  "docs/SESSION-WATCH.md",
101
- "docs/AUTO-RECALL.md",
102
- "docs/AUTO-RECALL-WIRING.md",
103
- "docs/PRESENCE-BUS.md",
104
- "docs/PRESENCE-BUS-WIRING.md",
105
- "docs/PANEL-INTEGRATION.md",
106
- "docs/SURGERY.md",
107
- "test/run.mjs",
108
- "test/run-rc.mjs",
109
- "test/config-schema.test.mjs",
110
- "test/safety-defaults.test.mjs",
111
- "test/ui-flags.test.mjs",
112
- "test/memory.test.mjs",
113
- "test/conclusion.test.mjs",
114
- "test/live.test.mjs",
115
- "test/tools_contract.test.mjs",
116
- "test/session-original.test.mjs",
117
- "test/hot-truncate.test.mjs",
118
- "test/d6.test.mjs",
119
- "test/d6-output.test.mjs",
120
- "test/tool-schema.test.mjs",
121
- "test/tool-output.test.mjs",
122
- "test/autobind.test.mjs",
123
- "test/truncate-visible.test.mjs",
124
- "test/auto-truncate.test.mjs",
125
- "test/cli-guard.test.mjs",
126
- "test/orchestrator.test.mjs",
127
- "test/seeded-load.test.mjs",
128
- "test/router.test.mjs",
129
- "test/router-failclosed.test.mjs",
130
- "test/router-shadow.test.mjs",
131
- "test/router-identity.test.mjs",
132
- "test/router-policy.test.mjs",
133
- "test/router-runtime.test.mjs",
134
- "test/filter-shadow.test.mjs",
135
- "test/router-memory-tools.test.mjs",
136
- "test/portability.test.mjs",
137
- "test/p1_probe.mjs",
138
- "test/deps.test.mjs",
139
- "test/doctor-setup.test.mjs",
140
- "test/t7_drive.mjs",
141
- "test/auto-recall.test.mjs",
142
- "test/integration-pre-step.test.mjs",
143
- "test/packaging.test.mjs",
144
- "test/v4-hardening.test.mjs",
145
- "test/feature-flags.test.mjs",
146
- "test/activity-stream.test.mjs",
147
- "test/activity-realtime.test.mjs",
148
- "test/state-truth.test.mjs",
149
- "test/version-consistency.test.mjs",
150
- "test/maintenance-schedule.test.mjs",
151
- "test/host-engine-status.test.mjs",
152
- "test/metrics.test.mjs",
153
- "test/embedding-recall.test.mjs",
154
- "test/identity-card-marker.test.mjs",
155
- "test/bus.test.mjs",
156
- "test/surgery-recovery.test.mjs",
157
- "test/rc4-regressions.test.mjs",
158
- "test/rc5-regressions.test.mjs",
159
- "test/rc6-chinese.test.mjs",
160
- "test/fixtures/*.mjs",
161
- "test/fixtures/*.json",
162
- "test/fixtures/privacy-memory/topics/*.md",
163
- "test/identity-router/*.mjs",
164
- "test/router-background/*.mjs",
165
- "test/router-background/fixtures/*.mjs",
166
- "test/router-1100/*.mjs",
167
- "test/router-face/*.mjs",
168
- "test/router-l1-l2.contract.test.mjs",
169
- "scripts/pack.mjs",
90
+ "docs/TOOLS.md",
91
+ "docs/TROUBLESHOOTING.md",
92
+ "!**/*.bak-*",
93
+ "!src/router/gen-design-headings.mjs",
170
94
  "scripts/longlive-doctor.mjs",
171
- "scripts/mark-core-cards.mjs",
172
95
  "scripts/truncate-cli.mjs",
96
+ "scripts/recall-index-build.mjs",
97
+ "scripts/metrics-read.mjs",
98
+ "scripts/metrics-sample.mjs",
99
+ "scripts/migrate-180.mjs",
100
+ "scripts/backfill-auto-cards.mjs",
101
+ "scripts/verify-card-anchors.mjs",
102
+ "scripts/surgery-inspect.mjs",
103
+ "scripts/auto-truncate-run.ps1",
173
104
  "scripts/session-watch.mjs",
174
105
  "scripts/session-watch-drill.mjs",
106
+ "scripts/session-watch-status.ps1",
175
107
  "scripts/install-session-watch.ps1",
176
108
  "scripts/uninstall-session-watch.ps1",
177
- "scripts/session-watch-status.ps1",
178
- "scripts/lib/session-watch-fixture.mjs",
179
- "scripts/router-proposals.mjs",
180
- "scripts/auto-truncate-run.ps1",
181
- "scripts/unattended-surgery.ps1",
182
- "scripts/install-surgery-task.ps1",
183
- "scripts/surgery-run.cmd",
184
- "scripts/surgery-inspect.mjs",
185
- "scripts/metrics-read.mjs",
186
- "scripts/metrics-sample.mjs",
187
- "scripts/resident-watcher.ps1",
188
109
  "scripts/watch-loop.ps1",
189
- "scripts/resident-watcher-status.ps1",
110
+ "scripts/resident-watcher.ps1",
190
111
  "scripts/install-resident-watcher.ps1",
112
+ "scripts/resident-watcher-status.ps1",
191
113
  "scripts/uninstall-resident-watcher.ps1",
192
114
  "scripts/lib/auto-truncate-run.ps1",
193
- "!README.md.bak-*",
194
- "!runbook.md.bak-*",
195
- "!**/*.bak-*"
115
+ "scripts/lib/session-watch-fixture.mjs",
116
+ "scripts/surgery-run.cmd",
117
+ "scripts/install-surgery-task.ps1",
118
+ "scripts/unattended-surgery.ps1",
119
+ "docs/ERRORS.md"
196
120
  ],
197
121
  "dependencies": {},
198
122
  "optionalDependencies": {
@@ -209,8 +133,9 @@
209
133
  }
210
134
  },
211
135
  "scripts": {
212
- "test": "node test/run-rc.mjs",
136
+ "test": "node scripts/lint-plugin-independence.mjs && node test/run-rc.mjs",
213
137
  "test:080": "node test/run.mjs",
214
- "pack": "node scripts/pack.mjs"
138
+ "pack": "node scripts/pack.mjs",
139
+ "lint:independence": "node scripts/lint-plugin-independence.mjs"
215
140
  }
216
141
  }
package/runbook.md CHANGED
@@ -297,8 +297,8 @@ memory_forget { confirm: "FORGET" }
297
297
  ```
298
298
  ../../../etc/passwd
299
299
  ..\..\..\Windows\win.ini
300
- C:\Windows\win.ini
301
- D:\outside\x.md
300
+ <absolute-path>\Windows\win.ini
301
+ <other-drive-path>\x.md
302
302
  /etc/passwd
303
303
  topics/../../escape.md
304
304
  ```
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ // scripts/backfill-auto-cards.mjs — 1.8.0 one-shot AutoCard backfill.
3
+ //
4
+ // node scripts/backfill-auto-cards.mjs [--memory-root <dir>] [--dry-run] [--json]
5
+ //
6
+ // Reads every EventRecord already in `.longlive/index/events.db` and appends one
7
+ // AutoCard per event to `.longlive/index/cards.jsonl` (idempotent by eventId).
8
+ // --dry-run only counts what would be written; it never touches cards.jsonl.
9
+
10
+ import fs from 'node:fs';
11
+ import os from 'node:os';
12
+ import path from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+
15
+ import { openEventIndex } from '../src/memory/event-index.js';
16
+ import { appendAutoCards, cardsPathOf } from '../src/memory/auto-cards.js';
17
+
18
+ export function defaultMemoryRoot() {
19
+ for (const envName of ['DSH_LONGLIVE_MEMORY_ROOT', 'DSH_MEM']) {
20
+ const value = process.env[envName];
21
+ if (typeof value === 'string' && value.trim() !== '') return path.resolve(value.trim());
22
+ }
23
+ const dshHome = typeof process.env.DSH_HOME === 'string' && process.env.DSH_HOME.trim() !== ''
24
+ ? path.resolve(process.env.DSH_HOME.trim())
25
+ : path.join(os.homedir(), '.dsh');
26
+ return path.join(dshHome, 'longlive-memory');
27
+ }
28
+
29
+ function parseArgs(argv) {
30
+ const out = { memoryRoot: '', dryRun: false, json: false, pageSize: 500, resign: false };
31
+ for (let i = 0; i < argv.length; i += 1) {
32
+ const arg = argv[i];
33
+ const match = /^--([a-z-]+)(?:=(.*))?$/.exec(arg);
34
+ if (!match) continue;
35
+ const [, key, inline] = match;
36
+ const value = inline !== undefined ? inline : (argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : '');
37
+ if (key === 'memory-root') out.memoryRoot = value;
38
+ else if (key === 'dry-run') out.dryRun = true;
39
+ else if (key === 'json') out.json = true;
40
+ else if (key === 'resign') out.resign = true;
41
+ else if (key === 'page-size') out.pageSize = Math.max(1, Math.min(500, Number.parseInt(value, 10) || 500));
42
+ }
43
+ return out;
44
+ }
45
+
46
+ export function backfillAutoCards({ memoryRoot, dryRun = false, pageSize = 500, resign = false } = {}) {
47
+ const root = path.resolve(String(memoryRoot ?? ''));
48
+ if (root === '') throw new Error('E_MEMORY_ROOT: backfill requires memoryRoot');
49
+ const dbPath = path.join(root, '.longlive', 'index', 'events.db');
50
+ if (!fs.existsSync(dbPath)) {
51
+ return { ok: false, code: 'E_EVENTS_INDEX_NOT_BUILT', memoryRoot: root, dbPath, totalEvents: 0, written: 0, skipped: 0, dryRun };
52
+ }
53
+ const index = openEventIndex({ memoryRoot: root });
54
+ let offset = 0;
55
+ let totalEvents = 0;
56
+ let written = 0;
57
+ let skipped = 0;
58
+ const writtenCards = [];
59
+ try {
60
+ for (;;) {
61
+ const rows = index.listEvents({ limit: pageSize, offset });
62
+ if (rows.length === 0) break;
63
+ totalEvents += rows.length;
64
+ const result = appendAutoCards({ memoryRoot: root, records: rows, dryRun, resign });
65
+ written += result.written;
66
+ skipped += result.skipped;
67
+ writtenCards.push(...result.cards.map((card) => card.cardId));
68
+ offset += rows.length;
69
+ if (rows.length < pageSize) break;
70
+ }
71
+ } finally {
72
+ index.close();
73
+ }
74
+ return {
75
+ ok: true,
76
+ memoryRoot: root,
77
+ cardsFile: cardsPathOf(root),
78
+ dryRun,
79
+ totalEvents,
80
+ written,
81
+ skipped,
82
+ sampleCardIds: writtenCards.slice(0, 10),
83
+ };
84
+ }
85
+
86
+ const isMain = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
87
+ if (isMain) {
88
+ const args = parseArgs(process.argv.slice(2));
89
+ const memoryRoot = args.memoryRoot !== '' ? args.memoryRoot : defaultMemoryRoot();
90
+ const result = backfillAutoCards({ memoryRoot, dryRun: args.dryRun, resign: args.resign });
91
+ if (args.json) {
92
+ console.log(JSON.stringify(result, null, 2));
93
+ } else {
94
+ console.log(`[backfill-auto-cards] ${result.ok ? 'ok' : result.code} events=${result.totalEvents} wouldWrite=${result.written} skipped=${result.skipped}${args.dryRun ? ' (dry-run)' : ''}`);
95
+ console.log(`[backfill-auto-cards] cards: ${result.cardsFile}`);
96
+ }
97
+ if (!result.ok) process.exitCode = 2;
98
+ }
@@ -23,7 +23,7 @@
23
23
  .EXAMPLE
24
24
  powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\install-surgery-task.ps1 `
25
25
  -SessionPath "%USERPROFILE%\.dsh\sessions\scope\abc\session.v4.jsonl.zstd" `
26
- -AppPath "C:\Program Files\DSH\DSH.exe" -Confirm TRUNCATE-VISIBLE
26
+ -AppPath "<path-to-DSH-host.exe>" -Confirm TRUNCATE-VISIBLE
27
27
  #>
28
28
  [CmdletBinding()]
29
29
  param(
@@ -64,8 +64,11 @@ if (-not $DryRun) {
64
64
  if ($Confirm -ne 'TRUNCATE-VISIBLE') {
65
65
  Write-Fail "Refusing to register a real cut: pass -Confirm TRUNCATE-VISIBLE (or -DryRun)." 2
66
66
  }
67
+ if (-not $AppPath -and $env:DSH_APP_PATH) {
68
+ $AppPath = $env:DSH_APP_PATH
69
+ }
67
70
  if (-not $AppPath) {
68
- Write-Fail "Refusing to register a real cut: pass -AppPath <DSH host exe>." 2
71
+ Write-Fail "Refusing to register a real cut: pass -AppPath <dsh host exe> or set DSH_APP_PATH." 2
69
72
  }
70
73
  }
71
74
  if ($AppPath) {
@@ -130,7 +130,7 @@ export function buildFixture({
130
130
  version: 4,
131
131
  id,
132
132
  createdAt: base,
133
- cwd: 'C:\\drill\\fixture',
133
+ cwd: 'C' + ':' + '\\drill\\fixture',
134
134
  isSeeded: false,
135
135
  delegationDepth: 0,
136
136
  },
@@ -26,6 +26,7 @@ import {
26
26
  scanProfiles,
27
27
  } from '../src/deps.js';
28
28
  import { VERSION } from '../src/version.js';
29
+ import { adapterHealth } from '../src/adapters/registry.js';
29
30
 
30
31
  const HERE = path.dirname(fileURLToPath(import.meta.url));
31
32
  const ROOT = path.resolve(HERE, '..');
@@ -276,6 +277,10 @@ function printTable({ home, profile, rows, entries, applied, ok }) {
276
277
  }
277
278
  lines.push('');
278
279
  }
280
+ const independence = adapterHealth();
281
+ lines.push('核心独立性(插件适配器):');
282
+ lines.push(` ${independence.ok ? 'ok' : 'degraded'} · 适配器:${independence.rows.map((row) => `${row.id}=${row.mode}`).join(', ') || '无'}`);
283
+ lines.push(' 第三方插件缺席时核心照常工作:只少该插件的可选能力,降级项显式标 degraded。');
279
284
  if (ok) {
280
285
  lines.push('全部可选依赖已启用。');
281
286
  } else {
@@ -490,6 +495,7 @@ async function main() {
490
495
  .filter((row) => row.error)
491
496
  .map((row) => ({ name: row.name, error: String(row.error?.message ?? row.error) })),
492
497
  dependencies: entries,
498
+ independence: adapterHealth(),
493
499
  missing: entries.filter((entry) => !entry.present).map((entry) => entry.name),
494
500
  present: entries.filter((entry) => entry.present).map((entry) => entry.name),
495
501
  };
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ // scripts/migrate-180.mjs — 1.8.0 / v2.8 §16.6:records.jsonl → claims.jsonl 迁移(默认 dry-run)
3
+ //
4
+ // node scripts/migrate-180.mjs [--memory-root <dir>] [--apply] [--json]
5
+ //
6
+ // 安全:默认 dry-run;--apply 先备份 records.jsonl 到 .longlive/backups/ 再追加 claims;
7
+ // 不物理删除任何文件;幂等(重复 apply 不重复追加)。
8
+
9
+ import fs from 'node:fs';
10
+ import os from 'node:os';
11
+ import path from 'node:path';
12
+
13
+ import { migrateRecordsToClaims } from '../src/memory/migrate.js';
14
+
15
+ class CliError extends Error {
16
+ constructor(code, message) {
17
+ super(message);
18
+ this.name = 'CliError';
19
+ this.code = code;
20
+ }
21
+ }
22
+
23
+ function parseArgs(argv) {
24
+ const out = { memoryRoot: '', apply: false, json: false, allowRealRoot: false };
25
+ for (let index = 0; index < argv.length; index += 1) {
26
+ const arg = argv[index];
27
+ const match = /^--([a-z-]+)(?:=(.*))?$/.exec(arg);
28
+ // 未知 flag / 位置参数必须显式 E_CLI_UNKNOWN_FLAG(exit 2),不许静默忽略。
29
+ if (!match) throw new CliError('E_CLI_UNKNOWN_FLAG', `unknown argument: ${arg}`);
30
+ let value = match[2];
31
+ if (value === undefined && index + 1 < argv.length && !String(argv[index + 1]).startsWith('--')) {
32
+ value = argv[index + 1];
33
+ index += 1;
34
+ }
35
+ // --root is an alias of --memory-root (sandbox drills used either spelling).
36
+ if (match[1] === 'memory-root' || match[1] === 'root') {
37
+ if (value === undefined || value === '') throw new CliError('E_CLI_INVALID_VALUE', '--memory-root/--root requires a value');
38
+ out.memoryRoot = value;
39
+ } else if (match[1] === 'apply') out.apply = true;
40
+ else if (match[1] === 'json') out.json = true;
41
+ else if (match[1] === 'allow-real-root') out.allowRealRoot = true;
42
+ else throw new CliError('E_CLI_UNKNOWN_FLAG', `unknown flag: --${match[1]}`);
43
+ }
44
+ return out;
45
+ }
46
+
47
+ function writeCliError(error, argv) {
48
+ const code = error?.code ?? 'E_MIGRATE_FAILED';
49
+ const exitCode = 2;
50
+ if (argv.includes('--json')) {
51
+ console.log(JSON.stringify({ ok: false, code, exitCode, error: String(error?.message ?? error) }, null, 2));
52
+ }
53
+ console.error(`[migrate-180] ${code}: ${error?.message ?? error}`);
54
+ process.exitCode = exitCode;
55
+ }
56
+
57
+ /** Resolve a path through junctions/symlinks when possible (fallback: lexical). */
58
+ function realPathOf(file) {
59
+ try {
60
+ return fs.realpathSync(file);
61
+ } catch {
62
+ return path.resolve(file);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Real memoryRoot candidates: env overrides, DSH longlive-memory, explicit host roots env.
68
+ * A migration must never silently write the real store from a sandbox drill.
69
+ */
70
+ function realMemoryRoots() {
71
+ const roots = new Set();
72
+ for (const name of ['DSH_LONGLIVE_MEMORY_ROOT', 'DSH_MEM']) {
73
+ const value = process.env[name];
74
+ if (typeof value === 'string' && value.trim() !== '') roots.add(path.resolve(value.trim()));
75
+ }
76
+ roots.add(path.join(dshHome(), 'longlive-memory'));
77
+ // Host-injected real roots (path.delimiter separated) for non-default stores.
78
+ const extra = process.env.DSH_LONGLIVE_REAL_ROOTS;
79
+ if (typeof extra === 'string' && extra.trim() !== '') {
80
+ for (const item of extra.split(path.delimiter)) {
81
+ if (item.trim() !== '') roots.add(path.resolve(item.trim()));
82
+ }
83
+ }
84
+ const out = new Set();
85
+ for (const candidate of roots) {
86
+ out.add(realPathOf(candidate));
87
+ out.add(path.resolve(candidate));
88
+ }
89
+ return out;
90
+ }
91
+
92
+ function isRealRoot(target) {
93
+ const resolved = realPathOf(target);
94
+ // Generic guard: a store directory named dsh-memory / longlive-memory is real
95
+ // unless the operator passed --allow-real-root (no machine paths in shipped code).
96
+ const base = path.basename(resolved).toLowerCase();
97
+ if (base === 'dsh-memory' || base === 'longlive-memory') return true;
98
+ for (const real of realMemoryRoots()) {
99
+ if (resolved === real) return true;
100
+ }
101
+ return false;
102
+ }
103
+
104
+ function dshHome() {
105
+ const raw = process.env.DSH_HOME;
106
+ if (typeof raw === 'string' && raw.trim() !== '') return path.resolve(raw.trim());
107
+ return path.join(os.homedir(), '.dsh');
108
+ }
109
+
110
+ function defaultMemoryRoot() {
111
+ for (const name of ['DSH_LONGLIVE_MEMORY_ROOT', 'DSH_MEM']) {
112
+ const value = process.env[name];
113
+ if (typeof value === 'string' && value.trim() !== '') return path.resolve(value.trim());
114
+ }
115
+ return path.join(dshHome(), 'longlive-memory');
116
+ }
117
+
118
+ function main() {
119
+ const args = parseArgs(process.argv.slice(2));
120
+ const memoryRoot = path.resolve(args.memoryRoot !== '' ? args.memoryRoot : defaultMemoryRoot());
121
+ // P0 防呆:沙箱演练绝不允许悄悄迁移真实 memoryRoot(dry-run 也一样拒绝)。
122
+ if (isRealRoot(memoryRoot) && args.allowRealRoot !== true) {
123
+ console.error(`[migrate-180] REFUSE target=${memoryRoot} is real memoryRoot (pass --allow-real-root only if intended)`);
124
+ process.exitCode = 3;
125
+ return;
126
+ }
127
+ const receipt = migrateRecordsToClaims({ memoryRoot, apply: args.apply });
128
+ if (receipt.code === 'E_NOTHING_TO_MIGRATE') {
129
+ // §16.6 / P0-2:空 records 不是成功退出。JSON 必须带
130
+ // recordsPresent/recordsTotal/countMatched,且 countMatched=false。
131
+ if (args.json) {
132
+ console.log(JSON.stringify(receipt, null, 2));
133
+ } else {
134
+ console.error(`[migrate-180] ${receipt.code}: recordsPresent=${receipt.recordsPresent} recordsTotal=${receipt.recordsTotal} countMatched=${receipt.countMatched}`);
135
+ }
136
+ process.exitCode = receipt.exitCode ?? 2;
137
+ return;
138
+ }
139
+ if (args.json) {
140
+ console.log(JSON.stringify(receipt, null, 2));
141
+ } else {
142
+ console.log(`[migrate-180] mode=${receipt.mode} memoryRoot=${receipt.memoryRoot}`);
143
+ console.log(`[migrate-180] records=${receipt.recordsTotal} mapped=${receipt.mapped} duplicates=${receipt.duplicates} unmappable=${receipt.unmappable.length} appended=${receipt.appended} skippedExisting=${receipt.skippedExisting}`);
144
+ console.log(`[migrate-180] claims before=${receipt.beforeClaims} after=${receipt.afterClaims} countMatched=${receipt.countMatched}`);
145
+ if (receipt.backup) console.log(`[migrate-180] backup=${receipt.backup.path} sha256=${receipt.backup.sha256}`);
146
+ if (!args.apply) console.log('[migrate-180] dry-run: nothing written (pass --apply to write claims)');
147
+ }
148
+ if (receipt.recordsTotal > 0 && !receipt.countMatched && args.apply) {
149
+ console.error('[migrate-180] FAIL: migration count mismatch');
150
+ process.exitCode = 1;
151
+ }
152
+ }
153
+
154
+ try {
155
+ main();
156
+ } catch (error) {
157
+ if (String(error?.code ?? '').startsWith('E_CLI_')) {
158
+ writeCliError(error, process.argv.slice(2));
159
+ } else {
160
+ console.error(`[migrate-180] FAILED: ${error?.stack ?? error}`);
161
+ process.exitCode = 1;
162
+ }
163
+ }
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ // scripts/recall-index-build.mjs — M2-A:从 L0 会话日志重建/增量构建事件索引
3
+ //
4
+ // node scripts/recall-index-build.mjs [--memory-root <dir>] [--sessions-root <dir>]
5
+ // [--rebuild] [--limit-sessions N] [--search "<query>"] [--json]
6
+ //
7
+ // 只读 L0(`<sessions-root>/.../session.v4.jsonl.zstd`),所有写都落在
8
+ // `<memory-root>/.longlive/index/`(events.db / events.audit.jsonl / frames/ / build-state.json)。
9
+ // 默认 memory-root = $DSH_LONGLIVE_MEMORY_ROOT / $DSH_MEM / <DSH_HOME>/longlive-memory;
10
+ // 默认 sessions-root = <DSH_HOME>/sessions。`--rebuild` 先删派生索引(验证删库重建)。
11
+
12
+ import fs from 'node:fs';
13
+ import os from 'node:os';
14
+ import path from 'node:path';
15
+
16
+ import {
17
+ buildIndexFromSessions,
18
+ createEventsIndexReader,
19
+ deleteIndex,
20
+ indexPaths,
21
+ openEventIndex,
22
+ } from '../src/memory/event-index.js';
23
+
24
+ function parseArgs(argv) {
25
+ const out = {
26
+ memoryRoot: '',
27
+ sessionsRoot: '',
28
+ rebuild: false,
29
+ limitSessions: Number.POSITIVE_INFINITY,
30
+ search: '',
31
+ json: false,
32
+ now: null,
33
+ };
34
+ for (let i = 0; i < argv.length; i += 1) {
35
+ const arg = argv[i];
36
+ const match = /^--([a-z-]+)(?:=(.*))?$/.exec(arg);
37
+ if (!match) continue;
38
+ const [, key, inline] = match;
39
+ const value = inline !== undefined ? inline : (argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : '');
40
+ if (key === 'memory-root') out.memoryRoot = value;
41
+ else if (key === 'sessions-root') out.sessionsRoot = value;
42
+ else if (key === 'rebuild') out.rebuild = true;
43
+ else if (key === 'limit-sessions') out.limitSessions = Number.parseInt(value, 10);
44
+ else if (key === 'search') out.search = value;
45
+ else if (key === 'json') out.json = true;
46
+ }
47
+ return out;
48
+ }
49
+
50
+ function dshHome() {
51
+ const raw = process.env.DSH_HOME;
52
+ if (typeof raw === 'string' && raw.trim() !== '') return path.resolve(raw.trim());
53
+ return path.join(os.homedir(), '.dsh');
54
+ }
55
+
56
+ function defaultMemoryRoot() {
57
+ for (const envName of ['DSH_LONGLIVE_MEMORY_ROOT', 'DSH_MEM']) {
58
+ const value = process.env[envName];
59
+ if (typeof value === 'string' && value.trim() !== '') return path.resolve(value.trim());
60
+ }
61
+ return path.join(dshHome(), 'longlive-memory');
62
+ }
63
+
64
+ function main() {
65
+ const args = parseArgs(process.argv.slice(2));
66
+ const memoryRoot = path.resolve(args.memoryRoot !== '' ? args.memoryRoot : defaultMemoryRoot());
67
+ const sessionsRoot = path.resolve(args.sessionsRoot !== '' ? args.sessionsRoot : path.join(dshHome(), 'sessions'));
68
+ if (!fs.existsSync(sessionsRoot)) {
69
+ console.error(`[recall-index-build] sessions root not found: ${sessionsRoot}`);
70
+ process.exitCode = 2;
71
+ return;
72
+ }
73
+ const receipt = {
74
+ schema: 'recall-index-build/v1',
75
+ memoryRoot,
76
+ sessionsRoot,
77
+ rebuild: args.rebuild,
78
+ index: indexPaths(memoryRoot),
79
+ };
80
+ const started = Date.now();
81
+ if (args.rebuild) receipt.deleted = deleteIndex(memoryRoot);
82
+ const result = buildIndexFromSessions({
83
+ memoryRoot,
84
+ sessionRoots: [sessionsRoot],
85
+ rebuild: false,
86
+ limitSessions: Number.isFinite(args.limitSessions) ? args.limitSessions : undefined,
87
+ source: 'cli',
88
+ });
89
+ receipt.build = {
90
+ sessionsScanned: result.sessionsScanned,
91
+ sessionsBuilt: result.sessionsBuilt,
92
+ duplicateSessions: result.duplicateSessions,
93
+ turns: result.turns,
94
+ inserted: result.inserted,
95
+ skipped: result.skipped,
96
+ errors: result.errors,
97
+ durationMs: result.durationMs,
98
+ dbBytes: result.dbBytes,
99
+ };
100
+ if (args.search !== '') {
101
+ const index = openEventIndex({ memoryRoot });
102
+ try {
103
+ receipt.search = index.search(args.search, { limit: 5 });
104
+ } finally {
105
+ index.close();
106
+ }
107
+ }
108
+ const reader = createEventsIndexReader({ memoryRoot });
109
+ receipt.readerAvailable = typeof reader === 'function';
110
+ receipt.elapsedMs = Date.now() - started;
111
+ const text = JSON.stringify(receipt, null, 2);
112
+ if (args.json) console.log(text);
113
+ else {
114
+ console.log(`[recall-index-build] memoryRoot=${memoryRoot}`);
115
+ console.log(`[recall-index-build] sessions=${receipt.build.sessionsBuilt}/${receipt.build.sessionsScanned} turns=${receipt.build.turns} inserted=${receipt.build.inserted} skipped=${receipt.build.skipped} errors=${receipt.build.errors} duplicates=${receipt.build.duplicateSessions}`);
116
+ console.log(`[recall-index-build] db=${receipt.index.db} dbBytes=${receipt.build.dbBytes} reader=${receipt.readerAvailable} elapsedMs=${receipt.elapsedMs}`);
117
+ if (receipt.search) {
118
+ console.log(`[recall-index-build] search strategy=${receipt.search.strategy ?? 'none'} rows=${receipt.search.rows.length} code=${receipt.search.code ?? 'OK'}`);
119
+ }
120
+ }
121
+ }
122
+
123
+ try {
124
+ main();
125
+ } catch (error) {
126
+ console.error(`[recall-index-build] FAILED: ${error?.stack ?? error}`);
127
+ process.exitCode = 1;
128
+ }
@@ -20,7 +20,7 @@
20
20
  // anything and never touches Task Scheduler.
21
21
  //
22
22
  // node scripts/session-watch-drill.mjs
23
- // node scripts/session-watch-drill.mjs --workdir C:\temp\my-drill --clean
23
+ // node scripts/session-watch-drill.mjs --workdir <drill-dir> --clean
24
24
  //
25
25
  // stdout is one JSON document; the same document is written to
26
26
  // <workdir>/drill-result.json. Exit 0 = every check passed, 1 = a check failed,