@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
@@ -1,170 +0,0 @@
1
- // 1.2.0 acceptance: the two passive observers write the panel contract shape.
2
- //
3
- // These are integration tests over real files in a temp memoryRoot. They never
4
- // touch the owner's real memory root, never call an LLM, and never import a
5
- // host package.
6
-
7
- import test from 'node:test';
8
- import assert from 'node:assert/strict';
9
- import fs from 'node:fs';
10
- import os from 'node:os';
11
- import path from 'node:path';
12
-
13
- import { runFilter, parseJournal } from '../src/memory/filter-runner.js';
14
- import { createRouterRuntime } from '../src/router/runtime.js';
15
-
16
- const NOW = new Date('2026-11-05T10:00:00+08:00');
17
- const SECRET = 'password: abcdef123456';
18
-
19
- const JOURNAL = [
20
- '\uFEFF---',
21
- 'title: 2026-11',
22
- 'date: 2026-11-05',
23
- '---',
24
- '',
25
- '## 2026-11-05 · 过滤器与影子验收',
26
- '',
27
- '老大要求过滤器只读记忆文件,写 decisions jsonl,异常只记 warning,绝不阻断工具调用。',
28
- '',
29
- '- **影子记录必须只记录不执行**:route() 与 guard() 的判定追加到 router-runtime.jsonl,工具原值原样返回。',
30
- '',
31
- SECRET,
32
- '',
33
- ].join('\n');
34
-
35
- function tempMemory() {
36
- const root = fs.mkdtempSync(path.join(os.tmpdir(), 'longlive-filter-shadow-'));
37
- fs.mkdirSync(path.join(root, 'journal'), { recursive: true });
38
- fs.mkdirSync(path.join(root, 'topics'), { recursive: true });
39
- fs.writeFileSync(path.join(root, 'journal', '2026-11.md'), JOURNAL, 'utf8');
40
- fs.writeFileSync(
41
- path.join(root, 'topics', 'card.md'),
42
- '---\ntitle: card\n---\n\n影子记录是只读审计,不改变工具行为。\n',
43
- 'utf8',
44
- );
45
- return root;
46
- }
47
-
48
- function readJsonl(file) {
49
- return fs.readFileSync(file, 'utf8').split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
50
- }
51
-
52
- test('parseJournal: BOM is stripped and line numbers point at the journal body', () => {
53
- const units = parseJournal(JOURNAL);
54
- assert.equal(units.length, 3);
55
- assert.equal(units[0].lineStart, 8);
56
- assert.equal(units[0].lineEnd, 8);
57
- assert.equal(units[0].heading, '2026-11-05 · 过滤器与影子验收');
58
- assert.equal(units[0].date, '2026-11-05');
59
- assert.equal(units[1].lineStart, 10);
60
- });
61
-
62
- test('filter: writes decisions jsonl with every §5 field and never echoes a secret', () => {
63
- const root = tempMemory();
64
- const result = runFilter({ memoryRoot: root, now: NOW });
65
- assert.equal(result.ok, true);
66
- assert.equal(result.units, 3);
67
- assert.equal(result.appended, 3);
68
-
69
- const file = path.join(root, '.longlive', 'filter', 'decisions-2026-11-05.jsonl');
70
- assert.equal(fs.existsSync(file), true);
71
- const rows = readJsonl(file);
72
- assert.equal(rows.length, 3);
73
-
74
- const allowed = new Set(['remember', 'archive_only', 'human', 'local_only']);
75
- for (const row of rows) {
76
- for (const key of ['ts', 'unitId', 'turn', 'target', 'score', 'dims', 'hardSignals', 'privacy',
77
- 'needsHuman', 'human', 'source', 'excerpt', 'dedup']) {
78
- assert.equal(Object.prototype.hasOwnProperty.call(row, key), true, `missing ${key}`);
79
- }
80
- assert.match(row.ts, /^\d{4}-\d{2}-\d{2}T/);
81
- assert.match(row.unitId, /^[0-9a-f]{16}$/);
82
- assert.equal(row.turn, null);
83
- assert.equal(allowed.has(row.target), true);
84
- assert.equal(typeof row.score, 'number');
85
- assert.equal(row.dims.length, 8);
86
- assert.deepEqual(row.dims.map((dim) => dim.id), ['R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8']);
87
- for (const dim of row.dims) {
88
- assert.equal(typeof dim.name, 'string');
89
- assert.equal(typeof dim.score, 'number');
90
- assert.equal(typeof dim.max, 'number');
91
- assert.equal(typeof dim.why, 'string');
92
- }
93
- assert.equal(typeof row.privacy.verdict, 'string');
94
- assert.equal(typeof row.needsHuman, 'boolean');
95
- assert.deepEqual(Object.keys(row.human).sort(), ['note', 'verdict']);
96
- assert.equal(row.source.file, 'journal/2026-11.md');
97
- assert.equal(Number.isInteger(row.source.lineStart), true);
98
- assert.equal(Number.isInteger(row.source.lineEnd), true);
99
- assert.equal(row.excerpt, null);
100
- assert.equal(typeof row.dedup.delta, 'number');
101
- assert.equal(row.dedup.delta === -3 || row.dedup.delta === 0 || row.dedup.delta === 1, true);
102
- if (row.dedup.nearestUnitId !== null) assert.equal(typeof row.dedup.nearestUnitId, 'string');
103
- }
104
-
105
- const blocked = rows.find((row) => row.target === 'local_only');
106
- assert.ok(blocked, 'the privacy paragraph must become local_only');
107
- assert.equal(blocked.privacy.verdict, 'blocked');
108
- assert.equal(blocked.privacy.marker, 'V1_PRIVACY_BLOCK');
109
- assert.equal(blocked.excerpt, null);
110
- assert.equal(JSON.stringify(blocked).includes('abcdef123456'), false, 'secret leaked into the audit row');
111
-
112
- // Audit trail exists too; the panel only needs decisions-*.jsonl.
113
- assert.equal(fs.existsSync(path.join(root, '.longlive', 'filter', 'queue', '2026-11-05.json')), true);
114
- assert.equal(fs.existsSync(path.join(root, '.longlive', 'filter', 'state.json')), true);
115
- const runs = fs.readdirSync(path.join(root, '.longlive', 'filter', 'runs'));
116
- assert.equal(runs.length, 1);
117
- const run = JSON.parse(fs.readFileSync(path.join(root, '.longlive', 'filter', 'runs', runs[0]), 'utf8'));
118
- assert.equal(run.schemaVersion, 'maf-1');
119
- assert.equal(run.policy.version, 'maf-2');
120
- assert.equal(run.units.length, 3);
121
- assert.equal(run.counts.remember + run.counts.archive_only + run.counts.human + run.counts.local_only, 3);
122
-
123
- // Same day, second startup: nothing is appended twice.
124
- const again = runFilter({ memoryRoot: root, now: NOW });
125
- assert.equal(again.ok, true);
126
- assert.equal(again.appended, 0);
127
- assert.equal(readJsonl(file).length, 3);
128
- });
129
-
130
- test('shadow: recordAllTools writes the §6 contract fields and returns the tool value unchanged', async () => {
131
- const root = tempMemory();
132
- const runtime = createRouterRuntime({ mode: 'shadow', memoryRoot: root, recordAllTools: true });
133
- const expected = { ok: true, status: 'healthy' };
134
- const value = await runtime.intercept('session_health', { sessionId: 'test' }, async () => expected);
135
- assert.equal(value, expected, 'the exact object comes back');
136
-
137
- const file = path.join(root, '.longlive', 'router-runtime.jsonl');
138
- assert.equal(fs.existsSync(file), true);
139
- const [row] = readJsonl(file);
140
- assert.equal(row.mode, 'shadow');
141
- assert.equal(row.tool, 'session_health');
142
- assert.equal(row.subject, 'session_health');
143
- assert.equal(['allow', 'deny', 'ask'].includes(row.action), true);
144
- assert.equal(row.action, 'allow');
145
- assert.equal(row.status, 'ok');
146
- assert.equal(typeof row.callText, 'string');
147
- assert.equal(Array.isArray(row.errors), true);
148
- assert.equal(row.guard.verdict, 'allow');
149
- assert.equal(row.outcome.status, 'ok');
150
- assert.equal(typeof row.totalMs, 'number');
151
- assert.equal(typeof row.decision, 'object');
152
- assert.equal(fs.existsSync(path.join(root, 'router-runtime.jsonl')), false, 'must not write the legacy top-level path');
153
- });
154
-
155
- test('shadow: a failing record sink never changes the tool call', async () => {
156
- const root = tempMemory();
157
- // Make `.longlive` a file: creating the record directory must fail, but the
158
- // tool result is still returned and the error is swallowed into onError.
159
- fs.writeFileSync(path.join(root, '.longlive'), 'not a directory', 'utf8');
160
- const errors = [];
161
- const runtime = createRouterRuntime({
162
- mode: 'shadow',
163
- memoryRoot: root,
164
- recordAllTools: true,
165
- onError: (error) => errors.push(error),
166
- });
167
- const value = await runtime.intercept('memory_recall', { query: '过滤器' }, async () => 'cards');
168
- assert.equal(value, 'cards');
169
- assert.equal(errors.length > 0, true);
170
- });
@@ -1,29 +0,0 @@
1
- // Child process used by test/activity-stream.test.mjs to prove that two
2
- // processes appending to the same board produce unique, contiguous seq values.
3
- // Usage: node activity-append-child.mjs <memoryRoot> <sessionId> <count> <tag>
4
-
5
- import crypto from 'node:crypto';
6
-
7
- import { createActivityStore } from '../../src/activity/store.js';
8
-
9
- const [memoryRoot, sessionId, countText, tag] = process.argv.slice(2);
10
- const count = Number(countText);
11
- if (!memoryRoot || !sessionId || !Number.isInteger(count) || count < 1) {
12
- console.error(JSON.stringify({ ok: false, error: 'bad-args' }));
13
- process.exit(2);
14
- }
15
- const store = createActivityStore({ memoryRoot });
16
- for (let index = 0; index < count; index += 1) {
17
- const result = store.append({
18
- sessionId,
19
- kind: 'doing',
20
- // Deliberately dissimilar texts: this test is about append/lock, not dedupe.
21
- text: `${tag} 独立任务 ${index} ${crypto.randomUUID()}`,
22
- key: `${tag}|task-${index}`,
23
- });
24
- if (!result.ok) {
25
- console.error(JSON.stringify({ ok: false, index, code: result.code }));
26
- process.exit(3);
27
- }
28
- }
29
- console.log(JSON.stringify({ ok: true, count }));