@remnic/core 9.3.757 → 9.3.759

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 (174) hide show
  1. package/dist/access-admin-ops-surface.d.ts +2 -2
  2. package/dist/access-admin-ops-surface.js +20 -20
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +2 -2
  5. package/dist/access-boundary.js +21 -21
  6. package/dist/access-cli.js +68 -68
  7. package/dist/access-http.d.ts +2 -2
  8. package/dist/access-http.js +28 -28
  9. package/dist/access-identity-continuity-surface.d.ts +166 -0
  10. package/dist/access-identity-continuity-surface.js +128 -0
  11. package/dist/access-lcm-surface.d.ts +2 -2
  12. package/dist/access-lcm-surface.js +20 -20
  13. package/dist/access-mcp.d.ts +2 -2
  14. package/dist/access-mcp.js +27 -27
  15. package/dist/access-observe-write-surface.d.ts +2 -2
  16. package/dist/access-observe-write-surface.js +20 -20
  17. package/dist/access-operations-batch.js +24 -24
  18. package/dist/access-operations.d.ts +2 -2
  19. package/dist/access-operations.js +26 -26
  20. package/dist/access-recall-surface.d.ts +2 -2
  21. package/dist/access-recall-surface.js +20 -20
  22. package/dist/access-schema.js +5 -5
  23. package/dist/{access-service-CJwcDoQp.d.ts → access-service-BW-gb3DL.d.ts} +4 -3
  24. package/dist/access-service.d.ts +2 -2
  25. package/dist/access-service.js +20 -20
  26. package/dist/access-surface-catalog.d.ts +2 -2
  27. package/dist/bootstrap.d.ts +1 -1
  28. package/dist/briefing.js +3 -3
  29. package/dist/{capsule-crypto-RAARDY3M.js → capsule-crypto-CZJSLEFG.js} +2 -2
  30. package/dist/causal-behavior.js +2 -2
  31. package/dist/causal-chain.js +2 -2
  32. package/dist/causal-consolidation.js +8 -8
  33. package/dist/causal-retrieval.js +2 -2
  34. package/dist/causal-trajectory-graph.js +2 -2
  35. package/dist/causal-trajectory.js +1 -1
  36. package/dist/{chunk-EEIROWEG.js → chunk-2BFLDH5F.js} +2 -2
  37. package/dist/{chunk-UPSAT4PY.js → chunk-2MR3MFQB.js} +2 -2
  38. package/dist/{chunk-MQQO56LN.js → chunk-2XE4F3VZ.js} +30 -30
  39. package/dist/{chunk-6A76LSX6.js → chunk-3JBW3GHN.js} +2 -2
  40. package/dist/{chunk-IZP62CEF.js → chunk-3QLPBCFG.js} +4 -4
  41. package/dist/{chunk-LNQUAJNC.js → chunk-437S3G37.js} +1 -1
  42. package/dist/{chunk-GI7PRVMV.js → chunk-6CUUFFU7.js} +2 -2
  43. package/dist/{chunk-6FYRCQ7K.js → chunk-7HWOEYHW.js} +2 -2
  44. package/dist/{chunk-AGNBY3VG.js → chunk-APJQ6UEA.js} +4 -4
  45. package/dist/{chunk-PXHY2E3S.js → chunk-AZSSKOG6.js} +4 -4
  46. package/dist/{chunk-XKUYMM34.js → chunk-DTSOB2YF.js} +2 -2
  47. package/dist/{chunk-6DMTYBNY.js → chunk-EGQ3AVZV.js} +2 -2
  48. package/dist/{chunk-XROP4ZHB.js → chunk-EHQ5HO5T.js} +4 -4
  49. package/dist/{chunk-KTULX4YO.js → chunk-FLVL4L3L.js} +4 -4
  50. package/dist/{chunk-2NTWULEQ.js → chunk-FYJWEGYP.js} +2 -2
  51. package/dist/{chunk-7HJ3XBMD.js → chunk-ILVF6TIY.js} +2 -2
  52. package/dist/{chunk-L5DU7THE.js → chunk-IOZZG75J.js} +2 -2
  53. package/dist/{chunk-4L2KHKLY.js → chunk-IZLGHKWA.js} +271 -197
  54. package/dist/chunk-IZLGHKWA.js.map +1 -0
  55. package/dist/{chunk-AINK3KDE.js → chunk-LLVKDFNU.js} +2 -2
  56. package/dist/{chunk-GIJDW2YO.js → chunk-M2AAYJVI.js} +3 -3
  57. package/dist/{chunk-CYWCKFCL.js → chunk-M5QKGHCR.js} +5 -5
  58. package/dist/{chunk-ZL3Y3ZTQ.js → chunk-OLEBPUZ7.js} +5 -5
  59. package/dist/{chunk-ZG2WP425.js → chunk-ORAK3LNZ.js} +2 -2
  60. package/dist/{chunk-SUN6XVNI.js → chunk-P26O6R3Q.js} +3 -3
  61. package/dist/{chunk-FFPH47IX.js → chunk-PKRRBRY2.js} +2 -2
  62. package/dist/{chunk-PHWBKQHK.js → chunk-QOM3F6YW.js} +8 -8
  63. package/dist/{chunk-FBS6V6LJ.js → chunk-QQJMVF6P.js} +4 -4
  64. package/dist/{chunk-T3UW6NRQ.js → chunk-QUGPXPFJ.js} +7 -7
  65. package/dist/{chunk-LVMVYLNB.js → chunk-SLAZZXBU.js} +2 -2
  66. package/dist/{chunk-RQXVVENY.js → chunk-SMLMH7S5.js} +174 -135
  67. package/dist/chunk-SMLMH7S5.js.map +1 -0
  68. package/dist/{chunk-IR6ATBUI.js → chunk-SN2EWIAI.js} +2 -2
  69. package/dist/{chunk-ZE7GJ76H.js → chunk-SQNED75R.js} +1 -1
  70. package/dist/{chunk-PMBWVQ7D.js → chunk-TQT3USCG.js} +2 -2
  71. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  72. package/dist/{chunk-I65IQD7Y.js → chunk-WIXQ3F5P.js} +2 -2
  73. package/dist/{chunk-IF6BTZCB.js → chunk-XQT5GSWU.js} +2 -2
  74. package/dist/{chunk-5PHPNUZN.js → chunk-YP23FQPT.js} +288 -233
  75. package/dist/chunk-YP23FQPT.js.map +1 -0
  76. package/dist/{chunk-QVQG7W2H.js → chunk-ZEQVS6AZ.js} +2 -2
  77. package/dist/{chunk-CTGK5VK3.js → chunk-ZQNCHPTZ.js} +2 -2
  78. package/dist/{cli-cZyANcmY.d.ts → cli-D551dnva.d.ts} +2 -2
  79. package/dist/cli.d.ts +3 -3
  80. package/dist/cli.js +46 -46
  81. package/dist/compounding/engine.js +3 -3
  82. package/dist/connectors/codex-materialize-runner.js +3 -3
  83. package/dist/connectors/index.js +3 -3
  84. package/dist/contradiction/index.js +4 -4
  85. package/dist/entity-retrieval.js +3 -3
  86. package/dist/explicit-capture.d.ts +1 -1
  87. package/dist/{first-start-migration-RYY7PPGF.js → first-start-migration-DY6YCRC2.js} +4 -4
  88. package/dist/{graph-edge-decay-U2GKDAVM.js → graph-edge-decay-RXUCJIN4.js} +4 -4
  89. package/dist/graph-edge-decay-RXUCJIN4.js.map +1 -0
  90. package/dist/graph-snapshot.js +3 -3
  91. package/dist/graph.js +2 -2
  92. package/dist/index.d.ts +4 -4
  93. package/dist/index.js +85 -85
  94. package/dist/lcm/index.js +3 -3
  95. package/dist/maintenance/memory-governance.js +3 -3
  96. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  97. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  98. package/dist/mcp-memory-inspector-app.d.ts +2 -2
  99. package/dist/namespaces/migrate.js +7 -7
  100. package/dist/namespaces/search.js +3 -3
  101. package/dist/namespaces/storage.js +3 -3
  102. package/dist/operator-toolkit.js +12 -12
  103. package/dist/orchestration/maintenance.js +5 -5
  104. package/dist/{orchestrator-Xm6sK5jw.d.ts → orchestrator-BnM187cb.d.ts} +2 -1
  105. package/dist/orchestrator.d.ts +1 -1
  106. package/dist/orchestrator.js +70 -70
  107. package/dist/search/factory.js +2 -2
  108. package/dist/search/index.js +4 -4
  109. package/dist/semantic-consolidation.js +4 -4
  110. package/dist/semantic-rule-promotion.js +3 -3
  111. package/dist/semantic-rule-verifier.js +3 -3
  112. package/dist/storage.d.ts +3 -4
  113. package/dist/storage.js +2 -2
  114. package/dist/transfer/backup.js +3 -3
  115. package/dist/transfer/capsule-export.js +4 -4
  116. package/dist/transfer/capsule-import.js +3 -3
  117. package/dist/transfer/import-sqlite.js +2 -2
  118. package/dist/verified-recall.js +3 -3
  119. package/package.json +2 -2
  120. package/src/access-identity-continuity-surface.test.ts +374 -0
  121. package/src/access-identity-continuity-surface.ts +322 -0
  122. package/src/access-service.ts +23 -171
  123. package/src/orchestration/recall-background-writes.ts +24 -0
  124. package/src/orchestration/recall-entry.ts +5 -0
  125. package/src/orchestration/recall-internal.ts +15 -11
  126. package/src/orchestration/recall-introspection.ts +5 -0
  127. package/src/orchestrator-background-writes.test.ts +101 -0
  128. package/src/orchestrator.ts +13 -13
  129. package/src/storage/identity-continuity-store.ts +223 -0
  130. package/src/storage-contract/round-trip.test.ts +5 -0
  131. package/src/storage.ts +27 -145
  132. package/src/trust-score-recall-paths.test.ts +2 -0
  133. package/dist/chunk-4L2KHKLY.js.map +0 -1
  134. package/dist/chunk-5PHPNUZN.js.map +0 -1
  135. package/dist/chunk-RQXVVENY.js.map +0 -1
  136. /package/dist/{capsule-crypto-RAARDY3M.js.map → access-identity-continuity-surface.js.map} +0 -0
  137. /package/dist/{graph-edge-decay-U2GKDAVM.js.map → capsule-crypto-CZJSLEFG.js.map} +0 -0
  138. /package/dist/{chunk-EEIROWEG.js.map → chunk-2BFLDH5F.js.map} +0 -0
  139. /package/dist/{chunk-UPSAT4PY.js.map → chunk-2MR3MFQB.js.map} +0 -0
  140. /package/dist/{chunk-MQQO56LN.js.map → chunk-2XE4F3VZ.js.map} +0 -0
  141. /package/dist/{chunk-6A76LSX6.js.map → chunk-3JBW3GHN.js.map} +0 -0
  142. /package/dist/{chunk-IZP62CEF.js.map → chunk-3QLPBCFG.js.map} +0 -0
  143. /package/dist/{chunk-LNQUAJNC.js.map → chunk-437S3G37.js.map} +0 -0
  144. /package/dist/{chunk-GI7PRVMV.js.map → chunk-6CUUFFU7.js.map} +0 -0
  145. /package/dist/{chunk-6FYRCQ7K.js.map → chunk-7HWOEYHW.js.map} +0 -0
  146. /package/dist/{chunk-AGNBY3VG.js.map → chunk-APJQ6UEA.js.map} +0 -0
  147. /package/dist/{chunk-PXHY2E3S.js.map → chunk-AZSSKOG6.js.map} +0 -0
  148. /package/dist/{chunk-XKUYMM34.js.map → chunk-DTSOB2YF.js.map} +0 -0
  149. /package/dist/{chunk-6DMTYBNY.js.map → chunk-EGQ3AVZV.js.map} +0 -0
  150. /package/dist/{chunk-XROP4ZHB.js.map → chunk-EHQ5HO5T.js.map} +0 -0
  151. /package/dist/{chunk-KTULX4YO.js.map → chunk-FLVL4L3L.js.map} +0 -0
  152. /package/dist/{chunk-2NTWULEQ.js.map → chunk-FYJWEGYP.js.map} +0 -0
  153. /package/dist/{chunk-7HJ3XBMD.js.map → chunk-ILVF6TIY.js.map} +0 -0
  154. /package/dist/{chunk-L5DU7THE.js.map → chunk-IOZZG75J.js.map} +0 -0
  155. /package/dist/{chunk-AINK3KDE.js.map → chunk-LLVKDFNU.js.map} +0 -0
  156. /package/dist/{chunk-GIJDW2YO.js.map → chunk-M2AAYJVI.js.map} +0 -0
  157. /package/dist/{chunk-CYWCKFCL.js.map → chunk-M5QKGHCR.js.map} +0 -0
  158. /package/dist/{chunk-ZL3Y3ZTQ.js.map → chunk-OLEBPUZ7.js.map} +0 -0
  159. /package/dist/{chunk-ZG2WP425.js.map → chunk-ORAK3LNZ.js.map} +0 -0
  160. /package/dist/{chunk-SUN6XVNI.js.map → chunk-P26O6R3Q.js.map} +0 -0
  161. /package/dist/{chunk-FFPH47IX.js.map → chunk-PKRRBRY2.js.map} +0 -0
  162. /package/dist/{chunk-PHWBKQHK.js.map → chunk-QOM3F6YW.js.map} +0 -0
  163. /package/dist/{chunk-FBS6V6LJ.js.map → chunk-QQJMVF6P.js.map} +0 -0
  164. /package/dist/{chunk-T3UW6NRQ.js.map → chunk-QUGPXPFJ.js.map} +0 -0
  165. /package/dist/{chunk-LVMVYLNB.js.map → chunk-SLAZZXBU.js.map} +0 -0
  166. /package/dist/{chunk-IR6ATBUI.js.map → chunk-SN2EWIAI.js.map} +0 -0
  167. /package/dist/{chunk-ZE7GJ76H.js.map → chunk-SQNED75R.js.map} +0 -0
  168. /package/dist/{chunk-PMBWVQ7D.js.map → chunk-TQT3USCG.js.map} +0 -0
  169. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  170. /package/dist/{chunk-I65IQD7Y.js.map → chunk-WIXQ3F5P.js.map} +0 -0
  171. /package/dist/{chunk-IF6BTZCB.js.map → chunk-XQT5GSWU.js.map} +0 -0
  172. /package/dist/{chunk-QVQG7W2H.js.map → chunk-ZEQVS6AZ.js.map} +0 -0
  173. /package/dist/{chunk-CTGK5VK3.js.map → chunk-ZQNCHPTZ.js.map} +0 -0
  174. /package/dist/{first-start-migration-RYY7PPGF.js.map → first-start-migration-DY6YCRC2.js.map} +0 -0
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  importSqlite
3
- } from "../chunk-AGNBY3VG.js";
4
- import "../chunk-Z734BLO3.js";
3
+ } from "../chunk-APJQ6UEA.js";
5
4
  import "../chunk-G4IAEX6D.js";
5
+ import "../chunk-Z734BLO3.js";
6
6
  import "../chunk-6KYMPV2O.js";
7
7
  import "../chunk-GCGJW34D.js";
8
8
  import "../chunk-PZ5AY32C.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  compareVerifiedEpisodeResults,
3
3
  searchVerifiedEpisodes
4
- } from "./chunk-2NTWULEQ.js";
4
+ } from "./chunk-FYJWEGYP.js";
5
5
  import "./chunk-7FL4CNPV.js";
6
- import "./chunk-5PHPNUZN.js";
6
+ import "./chunk-YP23FQPT.js";
7
7
  import "./chunk-M7XQSUBB.js";
8
8
  import "./chunk-L2B3EE7B.js";
9
9
  import "./chunk-5UZXUTVO.js";
@@ -24,8 +24,8 @@ import "./chunk-DM2T26WE.js";
24
24
  import "./chunk-LDXUBPMO.js";
25
25
  import "./chunk-YTU7WKYN.js";
26
26
  import "./chunk-AAD2ZS6P.js";
27
- import "./chunk-W5H6ZRPT.js";
28
27
  import "./chunk-VF4XKTX3.js";
28
+ import "./chunk-W5H6ZRPT.js";
29
29
  import "./chunk-G7D6GZ5J.js";
30
30
  import "./chunk-VUA4S7P6.js";
31
31
  import "./chunk-IQVQJJL7.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.3.757",
3
+ "version": "9.3.759",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3000,7 +3000,7 @@
3000
3000
  "core"
3001
3001
  ],
3002
3002
  "peerDependencies": {
3003
- "@remnic/coding-graph": "^9.3.757"
3003
+ "@remnic/coding-graph": "^9.3.759"
3004
3004
  },
3005
3005
  "peerDependenciesMeta": {
3006
3006
  "@remnic/coding-graph": {
@@ -0,0 +1,374 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ AccessIdentityContinuitySurface,
6
+ type AccessIdentityContinuitySurfaceDeps,
7
+ } from "./access-identity-continuity-surface.js";
8
+ import { EngramAccessInputError } from "./access-service.js";
9
+ import { parseConfig } from "./config.js";
10
+ import type { Orchestrator } from "./orchestrator.js";
11
+ import type { StorageManager } from "./storage.js";
12
+
13
+ interface HarnessOptions {
14
+ readonly config?: Record<string, unknown>;
15
+ readonly identityAnchor?: string | null;
16
+ readonly identityReflections?: string | null;
17
+ readonly closeIncidentFound?: boolean;
18
+ readonly reviewLoopFound?: boolean;
19
+ }
20
+
21
+ interface HarnessCalls {
22
+ readonly audit: Array<{ period: "weekly" | "monthly"; key?: string }>;
23
+ readonly storageNamespaces: string[];
24
+ readonly readableNamespaces: Array<{ namespace?: string; principal?: string }>;
25
+ readonly writableNamespaces: Array<{ namespace?: string; sessionKey?: string; principal?: string }>;
26
+ readonly incidentAppends: Array<{
27
+ symptom: string;
28
+ triggerWindow?: string;
29
+ suspectedCause?: string;
30
+ }>;
31
+ readonly incidentCloses: Array<{
32
+ id: string;
33
+ patch: { fixApplied: string; verificationResult: string; preventiveRule?: string };
34
+ }>;
35
+ readonly incidentReads: Array<{ limit: number; state: "open" | "closed" | "all" }>;
36
+ readonly loopUpserts: Array<Record<string, unknown>>;
37
+ readonly loopReviews: Array<{ id: string; patch: Record<string, unknown> }>;
38
+ readonly anchorWrites: string[];
39
+ }
40
+
41
+ function createHarness(options: HarnessOptions = {}): {
42
+ surface: AccessIdentityContinuitySurface;
43
+ calls: HarnessCalls;
44
+ } {
45
+ const calls: HarnessCalls = {
46
+ audit: [],
47
+ storageNamespaces: [],
48
+ readableNamespaces: [],
49
+ writableNamespaces: [],
50
+ incidentAppends: [],
51
+ incidentCloses: [],
52
+ incidentReads: [],
53
+ loopUpserts: [],
54
+ loopReviews: [],
55
+ anchorWrites: [],
56
+ };
57
+
58
+ const storageFixture = {
59
+ async appendContinuityIncident(input: HarnessCalls["incidentAppends"][number]) {
60
+ calls.incidentAppends.push(input);
61
+ return { id: "incident-1", state: "open", ...input };
62
+ },
63
+ async closeContinuityIncident(id: string, patch: HarnessCalls["incidentCloses"][number]["patch"]) {
64
+ calls.incidentCloses.push({ id, patch });
65
+ return options.closeIncidentFound === false ? null : { id, state: "closed", ...patch };
66
+ },
67
+ async readContinuityIncidents(limit: number, state: "open" | "closed" | "all") {
68
+ calls.incidentReads.push({ limit, state });
69
+ return [{ id: "incident-1", state }];
70
+ },
71
+ async upsertIdentityImprovementLoop(input: Record<string, unknown>) {
72
+ calls.loopUpserts.push(input);
73
+ return input;
74
+ },
75
+ async reviewIdentityImprovementLoop(id: string, patch: Record<string, unknown>) {
76
+ calls.loopReviews.push({ id, patch });
77
+ return options.reviewLoopFound === false ? null : { id, ...patch };
78
+ },
79
+ async readIdentityAnchor() {
80
+ return options.identityAnchor ?? null;
81
+ },
82
+ async writeIdentityAnchor(content: string) {
83
+ calls.anchorWrites.push(content);
84
+ },
85
+ async readIdentityReflections() {
86
+ return options.identityReflections ?? null;
87
+ },
88
+ };
89
+ // The surface deliberately consumes only this storage subset; the cast keeps
90
+ // the fixture honest at each method while avoiding a full filesystem store.
91
+ const storage = storageFixture as unknown as StorageManager;
92
+
93
+ const config = parseConfig({
94
+ memoryDir: "/tmp/remnic-access-identity-test",
95
+ identityContinuityEnabled: true,
96
+ continuityIncidentLoggingEnabled: true,
97
+ continuityAuditEnabled: true,
98
+ compoundingEnabled: true,
99
+ ...options.config,
100
+ });
101
+ const orchestratorFixture = {
102
+ config,
103
+ compounding: {
104
+ async synthesizeContinuityAudit(input: { period: "weekly" | "monthly"; key?: string }) {
105
+ calls.audit.push(input);
106
+ return {
107
+ period: input.period,
108
+ key: input.key ?? "2026-W28",
109
+ reportPath: "/tmp/continuity-audit.md",
110
+ };
111
+ },
112
+ },
113
+ async getStorage(namespace: string) {
114
+ calls.storageNamespaces.push(namespace);
115
+ return storage;
116
+ },
117
+ };
118
+ // Access surfaces accept the live orchestrator; this named fixture supplies
119
+ // the exact members this surface owns and no unrelated runtime machinery.
120
+ const orchestrator = orchestratorFixture as unknown as Orchestrator;
121
+
122
+ const deps: AccessIdentityContinuitySurfaceDeps = {
123
+ orchestrator,
124
+ resolveReadableNamespace(namespace, principal) {
125
+ calls.readableNamespaces.push({ namespace, principal });
126
+ return "readable-ns";
127
+ },
128
+ writableNamespaceFor(namespace, sessionKey, principal) {
129
+ calls.writableNamespaces.push({ namespace, sessionKey, principal });
130
+ return "writable-ns";
131
+ },
132
+ };
133
+
134
+ return { surface: new AccessIdentityContinuitySurface(deps), calls };
135
+ }
136
+
137
+ test("continuity capability gates stop before storage or compounding work", async () => {
138
+ const { surface, calls } = createHarness({
139
+ config: { identityContinuityEnabled: false },
140
+ });
141
+
142
+ assert.deepEqual(await surface.continuityAuditGenerate({}), {
143
+ enabled: false,
144
+ reason: "Identity continuity is disabled. Enable `identityContinuityEnabled: true`.",
145
+ });
146
+ assert.deepEqual(await surface.continuityIncidentOpen({ symptom: "lost context" }), {
147
+ enabled: false,
148
+ reason: "Identity continuity is disabled. Enable `identityContinuityEnabled: true`.",
149
+ });
150
+ assert.deepEqual(calls.audit, []);
151
+ assert.deepEqual(calls.storageNamespaces, []);
152
+ });
153
+
154
+ test("continuity audits normalize inputs and forward to compounding", async () => {
155
+ const { surface, calls } = createHarness();
156
+
157
+ assert.deepEqual(await surface.continuityAuditGenerate({ period: "monthly", key: " 2026-07 " }), {
158
+ enabled: true,
159
+ period: "monthly",
160
+ key: "2026-07",
161
+ reportPath: "/tmp/continuity-audit.md",
162
+ });
163
+ assert.deepEqual(calls.audit, [{ period: "monthly", key: "2026-07" }]);
164
+ });
165
+
166
+ test("incident writes validate required fields and use writable namespace routing", async () => {
167
+ const { surface, calls } = createHarness();
168
+
169
+ await assert.rejects(
170
+ surface.continuityIncidentOpen({ symptom: " " }),
171
+ (error: unknown) => error instanceof EngramAccessInputError && error.message === "symptom is required"
172
+ );
173
+ assert.deepEqual(
174
+ await surface.continuityIncidentOpen({
175
+ symptom: " lost context ",
176
+ namespace: "requested",
177
+ principal: "agent-a",
178
+ triggerWindow: " last hour ",
179
+ suspectedCause: " cache reset ",
180
+ }),
181
+ {
182
+ created: true,
183
+ incident: {
184
+ id: "incident-1",
185
+ state: "open",
186
+ symptom: "lost context",
187
+ triggerWindow: "last hour",
188
+ suspectedCause: "cache reset",
189
+ },
190
+ }
191
+ );
192
+ assert.deepEqual(calls.writableNamespaces, [{ namespace: "requested", sessionKey: undefined, principal: "agent-a" }]);
193
+ assert.deepEqual(calls.storageNamespaces, ["writable-ns"]);
194
+ assert.deepEqual(calls.incidentAppends, [
195
+ {
196
+ symptom: "lost context",
197
+ triggerWindow: "last hour",
198
+ suspectedCause: "cache reset",
199
+ },
200
+ ]);
201
+ });
202
+
203
+ test("incident reads clamp limits and use readable namespace routing", async () => {
204
+ const { surface, calls } = createHarness();
205
+
206
+ assert.deepEqual(
207
+ await surface.continuityIncidentList({
208
+ state: "all",
209
+ limit: 500,
210
+ namespace: "requested",
211
+ principal: "agent-a",
212
+ }),
213
+ {
214
+ state: "all",
215
+ incidents: [{ id: "incident-1", state: "all" }],
216
+ count: 1,
217
+ }
218
+ );
219
+ assert.deepEqual(calls.readableNamespaces, [{ namespace: "requested", principal: "agent-a" }]);
220
+ assert.deepEqual(calls.storageNamespaces, ["readable-ns"]);
221
+ assert.deepEqual(calls.incidentReads, [{ limit: 200, state: "all" }]);
222
+ });
223
+
224
+ test("incident close and continuity-loop operations preserve validation and forwarding", async () => {
225
+ const { surface, calls } = createHarness();
226
+
227
+ await assert.rejects(
228
+ surface.continuityIncidentClose({ id: "", fixApplied: "fixed", verificationResult: "green" }),
229
+ (error: unknown) => error instanceof EngramAccessInputError && error.message === "id is required"
230
+ );
231
+ assert.deepEqual(
232
+ await surface.continuityIncidentClose({
233
+ id: " incident-1 ",
234
+ fixApplied: " restored state ",
235
+ verificationResult: " replay passed ",
236
+ preventiveRule: " flush first ",
237
+ }),
238
+ {
239
+ closed: true,
240
+ incident: {
241
+ id: "incident-1",
242
+ state: "closed",
243
+ fixApplied: "restored state",
244
+ verificationResult: "replay passed",
245
+ preventiveRule: "flush first",
246
+ },
247
+ }
248
+ );
249
+ assert.deepEqual(
250
+ await surface.continuityLoopAddOrUpdate({
251
+ id: " loop-1 ",
252
+ cadence: "weekly",
253
+ purpose: " verify continuity ",
254
+ status: "active",
255
+ killCondition: " stable for a month ",
256
+ notes: " watch restarts ",
257
+ }),
258
+ {
259
+ saved: true,
260
+ loop: {
261
+ id: "loop-1",
262
+ cadence: "weekly",
263
+ purpose: "verify continuity",
264
+ status: "active",
265
+ killCondition: "stable for a month",
266
+ lastReviewed: undefined,
267
+ notes: "watch restarts",
268
+ },
269
+ }
270
+ );
271
+ assert.deepEqual(
272
+ await surface.continuityLoopReview({
273
+ id: " loop-1 ",
274
+ status: "paused",
275
+ reviewedAt: " 2026-07-10T00:00:00Z ",
276
+ }),
277
+ {
278
+ reviewed: true,
279
+ loop: {
280
+ id: "loop-1",
281
+ status: "paused",
282
+ notes: undefined,
283
+ reviewedAt: "2026-07-10T00:00:00Z",
284
+ },
285
+ }
286
+ );
287
+ assert.equal(calls.incidentCloses.length, 1);
288
+ assert.equal(calls.loopUpserts.length, 1);
289
+ assert.equal(calls.loopReviews.length, 1);
290
+ });
291
+
292
+ test("identity anchor updates merge conservatively without dropping custom sections", async () => {
293
+ const existingAnchor = [
294
+ "# Identity Continuity Anchor",
295
+ "",
296
+ "## Identity Traits",
297
+ "",
298
+ "- Careful",
299
+ "",
300
+ "## Communication Preferences",
301
+ "",
302
+ "- Brief",
303
+ "",
304
+ "## Custom Notes",
305
+ "",
306
+ "Keep me",
307
+ "",
308
+ ].join("\n");
309
+ const { surface, calls } = createHarness({ identityAnchor: existingAnchor });
310
+ const expectedAnchor = [
311
+ "# Identity Continuity Anchor",
312
+ "",
313
+ "## Identity Traits",
314
+ "",
315
+ "- Careful",
316
+ "",
317
+ "## Communication Preferences",
318
+ "",
319
+ "- Brief",
320
+ "- Direct",
321
+ "",
322
+ "## Operating Principles",
323
+ "",
324
+ "- Verify",
325
+ "",
326
+ "## Continuity Notes",
327
+ "",
328
+ "## Custom Notes",
329
+ "",
330
+ "Keep me",
331
+ "",
332
+ ].join("\n");
333
+
334
+ assert.deepEqual(
335
+ await surface.identityAnchorUpdate({
336
+ identityTraits: "- Careful",
337
+ communicationPreferences: "- Brief\n- Direct",
338
+ operatingPrinciples: "- Verify",
339
+ }),
340
+ {
341
+ updated: true,
342
+ sections: ["Identity Traits", "Communication Preferences", "Operating Principles"],
343
+ anchor: expectedAnchor,
344
+ }
345
+ );
346
+ assert.deepEqual(calls.anchorWrites, [expectedAnchor]);
347
+ });
348
+
349
+ test("identity reads use readable routing and preserve not-found results", async () => {
350
+ const foundHarness = createHarness({
351
+ identityAnchor: "# Identity Continuity Anchor\n",
352
+ identityReflections: "# Identity Reflections\n",
353
+ });
354
+
355
+ assert.deepEqual(await foundHarness.surface.identityAnchorGet({ namespace: "requested" }), {
356
+ found: true,
357
+ anchor: "# Identity Continuity Anchor\n",
358
+ });
359
+ assert.deepEqual(await foundHarness.surface.memoryIdentity({ namespace: "requested" }), {
360
+ found: true,
361
+ identity: "# Identity Reflections\n",
362
+ });
363
+ assert.deepEqual(foundHarness.calls.storageNamespaces, ["readable-ns", "readable-ns"]);
364
+
365
+ const missingHarness = createHarness();
366
+ assert.deepEqual(await missingHarness.surface.identityAnchorGet({}), {
367
+ found: false,
368
+ message: "No identity anchor found yet. Use identity_anchor_update to create one.",
369
+ });
370
+ assert.deepEqual(await missingHarness.surface.memoryIdentity({}), {
371
+ found: false,
372
+ message: "No identity reflections found.",
373
+ });
374
+ });