@hraness/oh 0.3.2 → 0.4.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 (57) hide show
  1. package/README.md +164 -114
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +811 -97
  5. package/dist/errors.d.ts +39 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/graph.d.ts.map +1 -1
  8. package/dist/index.js +676 -61
  9. package/dist/libsql.d.ts.map +1 -1
  10. package/dist/libsql.js +162 -35
  11. package/dist/memory-page.js +2 -2
  12. package/dist/memory.d.ts +87 -6
  13. package/dist/memory.d.ts.map +1 -1
  14. package/dist/memory.js +1106 -148
  15. package/dist/operation.d.ts +3 -1
  16. package/dist/operation.d.ts.map +1 -1
  17. package/dist/projection-public.js +2 -2
  18. package/dist/projection-suss.js +2 -2
  19. package/dist/sdk.js +780 -88
  20. package/dist/semantic-cloud.js +2 -2
  21. package/dist/semantic.js +2 -2
  22. package/dist/sqlite/index.js +1251 -306
  23. package/dist/sqlite/port.d.ts +31 -3
  24. package/dist/sqlite/port.d.ts.map +1 -1
  25. package/dist/sqlite/store.d.ts +18 -2
  26. package/dist/sqlite/store.d.ts.map +1 -1
  27. package/dist/store.d.ts +3 -12
  28. package/dist/store.d.ts.map +1 -1
  29. package/dist/store.js +154 -32
  30. package/dist/sync.d.ts +7 -1
  31. package/dist/sync.d.ts.map +1 -1
  32. package/dist/sync.js +668 -35
  33. package/package.json +5 -1
  34. package/skills/oh/SKILL.md +42 -16
  35. package/spec/README.md +2 -2
  36. package/spec/v1/memory.md +134 -16
  37. package/spec/v1/storage.md +8 -5
  38. package/spec/v1/store.md +20 -0
  39. package/spec/v1/sync.md +77 -8
  40. package/src/cli.test.ts +53 -1
  41. package/src/cli.ts +34 -8
  42. package/src/errors.test.ts +87 -0
  43. package/src/errors.ts +185 -0
  44. package/src/graph.ts +2 -2
  45. package/src/libsql.test.ts +36 -0
  46. package/src/libsql.ts +26 -5
  47. package/src/memory.test.ts +1488 -18
  48. package/src/memory.ts +1199 -122
  49. package/src/operation.ts +13 -3
  50. package/src/sqlite/port.test.ts +209 -0
  51. package/src/sqlite/port.ts +118 -4
  52. package/src/sqlite/store.test.ts +106 -1
  53. package/src/sqlite/store.ts +168 -30
  54. package/src/store.test.ts +12 -0
  55. package/src/store.ts +30 -20
  56. package/src/sync.test.ts +570 -2
  57. package/src/sync.ts +586 -36
@@ -2,12 +2,19 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import { canonicalJson, canonicalSha256, type JsonValue } from "./canonical";
4
4
  import { OhRecordCodecRegistry } from "./contract";
5
- import { createKnowledgeGraphRecordV1 } from "./graph";
5
+ import { createKnowledgeGraphRecordV1, knowledgeGraphRecordRefV1,
6
+ type KnowledgeGraphRecordV1 } from "./graph";
6
7
  import {
7
8
  createOhMemoryAgentV1,
8
9
  createOhMemoryAgentV2,
10
+ createOhMemoryAuthorityV1,
11
+ OH_MEMORY_AUTHORITY_LIMITS_V1,
9
12
  OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1,
13
+ OH_MEMORY_LIMITS_V1,
10
14
  OH_MEMORY_QUERY_LIMITS_V2,
15
+ OhMemoryAdoptionConflictError,
16
+ OhMemoryContinuationError,
17
+ parseOhMemoryNominationV1,
11
18
  type OhMemoryAuthoritySourceV1,
12
19
  type OhMemoryProofV1,
13
20
  } from "./memory";
@@ -22,8 +29,12 @@ import { createOhSqliteStoreAuthorityV1 } from "./sqlite/port";
22
29
  import {
23
30
  OH_CANONICAL_STORE_PROFILE_V1,
24
31
  OH_WORKING_STORE_PROFILE_V1,
32
+ OhConflictError,
25
33
  OhIntegrityError,
34
+ OhOperationSizeError,
26
35
  OhProfileError,
36
+ type OhHeadV1,
37
+ type OhSnapshotV1,
27
38
  type OhStoreV1,
28
39
  } from "./store";
29
40
 
@@ -118,6 +129,173 @@ function chunkProgram(maximumRows = 400, pageSize = 64,
118
129
  } as const;
119
130
  }
120
131
 
132
+ function stableVisibleProgram(pageSize = 50) {
133
+ const program = visibleProgram();
134
+ return {
135
+ evaluation: {
136
+ maximumDerivedTuples: 2_048,
137
+ maximumProofDepth: 16,
138
+ maximumProofNodes: 64,
139
+ maximumResultBytes: 8 * 1024 * 1024,
140
+ maximumRounds: 16,
141
+ maximumTotalProofNodes: 8_192,
142
+ maximumWorkUnits: 2_000_000,
143
+ },
144
+ maximumPageBytes: 1024 * 1024,
145
+ maximumRows: 50,
146
+ pageSize,
147
+ parameters: [],
148
+ programId: program.programId,
149
+ purpose: program.purpose,
150
+ query: program.query,
151
+ rulePack: program.rulePack,
152
+ v: 2 as const,
153
+ };
154
+ }
155
+
156
+ async function authorityFixture(configuration: Readonly<{
157
+ canonicalStore?: (store: OhStoreV1) => OhStoreV1;
158
+ canonicalRecords?: readonly ReturnType<typeof entity>[];
159
+ explainCapabilityLifetimeMs?: number;
160
+ maximumCanonicalOperationBytes?: number;
161
+ monotonicNow?: () => number;
162
+ now?: () => Date;
163
+ pageSize?: number;
164
+ workingStore?: (store: OhStoreV1) => OhStoreV1;
165
+ }> = {}) {
166
+ const canonical = createOhSqliteStoreAuthorityV1({ path: ":memory:",
167
+ profile: OH_CANONICAL_STORE_PROFILE_V1, realmId: "realm:authority-c", spaceId: "authority-c" });
168
+ const working = createOhSqliteStoreAuthorityV1({ path: ":memory:",
169
+ profile: OH_WORKING_STORE_PROFILE_V1, realmId: "realm:authority-w", spaceId: "authority-w" });
170
+ const records = configuration.canonicalRecords ?? [entity("entity:canonical", "Canonical")];
171
+ if (records.length > 0) {
172
+ await canonical.store.commit({ actorId: "test.canonical-seed",
173
+ changes: records.map((record) => ({ kind: "put" as const, record, v: 1 as const })),
174
+ expectedHead: await canonical.store.head(), operationId: "op_authority_seed" });
175
+ }
176
+ const initialCanonicalHead = await canonical.store.head();
177
+ const selectedCanonicalStore = configuration.canonicalStore?.(canonical.store) ?? canonical.store;
178
+ const selectedWorkingStore = configuration.workingStore?.(working.store) ?? working.store;
179
+ const authority = await createOhMemoryAuthorityV1({
180
+ actorId: "test.memory-agent", adoptionActorId: "test.memory-reviewer",
181
+ canonical: { authorityId: "authority.canonical",
182
+ expectedBindingSha256: selectedCanonicalStore.binding.bindingSha256,
183
+ expectedHead: initialCanonicalHead, store: selectedCanonicalStore },
184
+ continuationKey: Uint8Array.from({ length: 32 }, (_, index) => index),
185
+ ...(configuration.explainCapabilityLifetimeMs === undefined ? {} : {
186
+ explainCapabilityLifetimeMs: configuration.explainCapabilityLifetimeMs,
187
+ }),
188
+ ...(configuration.maximumCanonicalOperationBytes === undefined ? {} : {
189
+ maximumCanonicalOperationBytes: configuration.maximumCanonicalOperationBytes,
190
+ }),
191
+ ...(configuration.monotonicNow === undefined ? {} : {
192
+ monotonicNow: configuration.monotonicNow,
193
+ }),
194
+ nominationRoutes: [{ destinationPurpose: "kb.review", nominationId: "kb.review" }],
195
+ ...(configuration.now === undefined ? {} : { now: configuration.now }),
196
+ programs: [stableVisibleProgram(configuration.pageSize)],
197
+ working: { authorityId: "authority.working", codecs: entityCodecs(),
198
+ expectedBindingSha256: selectedWorkingStore.binding.bindingSha256,
199
+ store: selectedWorkingStore },
200
+ });
201
+ return { authority, canonical, initialCanonicalHead, working };
202
+ }
203
+
204
+ async function peerAuthority(
205
+ canonicalStore: OhStoreV1,
206
+ workingStore: OhStoreV1,
207
+ expectedCanonicalHead: OhHeadV1,
208
+ ) {
209
+ return await createOhMemoryAuthorityV1({
210
+ actorId: "test.memory-agent", adoptionActorId: "test.memory-reviewer",
211
+ canonical: { authorityId: "authority.canonical",
212
+ expectedBindingSha256: canonicalStore.binding.bindingSha256,
213
+ expectedHead: expectedCanonicalHead, store: canonicalStore },
214
+ continuationKey: Uint8Array.from({ length: 32 }, (_, index) => index),
215
+ nominationRoutes: [{ destinationPurpose: "kb.review", nominationId: "kb.review" }],
216
+ programs: [stableVisibleProgram()],
217
+ working: { authorityId: "authority.working", codecs: entityCodecs(),
218
+ expectedBindingSha256: workingStore.binding.bindingSha256, store: workingStore },
219
+ });
220
+ }
221
+
222
+ function twoPartyCanonicalCommitRendezvous() {
223
+ const commitCalls: [number, number] = [0, 0];
224
+ const arrived = new Set<number>();
225
+ let release!: () => void;
226
+ const released = new Promise<void>((resolve) => { release = resolve; });
227
+ const wrap = (store: OhStoreV1, participant: 0 | 1): OhStoreV1 => new Proxy(store, {
228
+ get(target, property) {
229
+ const member = Reflect.get(target, property, target) as unknown;
230
+ if (typeof member !== "function") return member;
231
+ if (property !== "commit") {
232
+ return (...args: unknown[]) => Reflect.apply(member, target, args);
233
+ }
234
+ return async (...args: unknown[]) => {
235
+ commitCalls[participant] += 1;
236
+ arrived.add(participant);
237
+ if (arrived.size === 2) release();
238
+ await released;
239
+ return await Reflect.apply(member, target, args);
240
+ };
241
+ },
242
+ }) as OhStoreV1;
243
+ return { commitCalls, wrap };
244
+ }
245
+
246
+ function staticSnapshot(records: readonly KnowledgeGraphRecordV1[]): OhSnapshotV1 {
247
+ const sorted = [...records].sort((left, right) => left.key < right.key ? -1 : 1);
248
+ const recordsSha256 = canonicalSha256(sorted.map(knowledgeGraphRecordRefV1));
249
+ return Object.freeze({
250
+ head: Object.freeze({
251
+ generation: 1,
252
+ graphRevisionSha256: canonicalSha256({ kind: "test.static-graph", recordsSha256, v: 1 }),
253
+ operationSha256: canonicalSha256({ kind: "test.static-operation", recordsSha256, v: 1 }),
254
+ recordsSha256,
255
+ sequence: 1,
256
+ v: 1 as const,
257
+ }),
258
+ records: Object.freeze(sorted),
259
+ v: 1 as const,
260
+ });
261
+ }
262
+
263
+ async function capacityAuthority(records: readonly KnowledgeGraphRecordV1[]) {
264
+ const canonical = createOhSqliteStoreAuthorityV1({ path: ":memory:",
265
+ profile: OH_CANONICAL_STORE_PROFILE_V1, realmId: "realm:capacity-c", spaceId: "capacity-c" });
266
+ const working = createOhSqliteStoreAuthorityV1({ path: ":memory:",
267
+ profile: OH_WORKING_STORE_PROFILE_V1, realmId: "realm:capacity-w", spaceId: "capacity-w" });
268
+ const snapshot = staticSnapshot(records);
269
+ let commitCalls = 0;
270
+ const canonicalStore: OhStoreV1 = {
271
+ binding: canonical.store.binding,
272
+ changesSince: canonical.store.changesSince.bind(canonical.store),
273
+ close: canonical.store.close.bind(canonical.store),
274
+ async commit() { commitCalls += 1; throw new Error("capacity preflight must precede CAS"); },
275
+ exportDependencyClosure: canonical.store.exportDependencyClosure.bind(canonical.store),
276
+ async head() { return snapshot.head; },
277
+ async snapshot(options) {
278
+ if (options?.maximumRecords !== undefined && records.length > options.maximumRecords) {
279
+ throw new RangeError("static snapshot record bound");
280
+ }
281
+ return snapshot;
282
+ },
283
+ verify: canonical.store.verify.bind(canonical.store),
284
+ };
285
+ const authority = await createOhMemoryAuthorityV1({
286
+ actorId: "test.capacity-agent", adoptionActorId: "test.capacity-reviewer",
287
+ canonical: { authorityId: "authority.capacity-canonical",
288
+ expectedBindingSha256: canonicalStore.binding.bindingSha256,
289
+ expectedHead: snapshot.head, store: canonicalStore },
290
+ continuationKey: Uint8Array.from({ length: 32 }, (_, index) => index),
291
+ nominationRoutes: [{ destinationPurpose: "kb.review", nominationId: "kb.review" }],
292
+ programs: [stableVisibleProgram()],
293
+ working: { authorityId: "authority.capacity-working", codecs: entityCodecs(),
294
+ expectedBindingSha256: working.store.binding.bindingSha256, store: working.store },
295
+ });
296
+ return { authority, canonical, canonicalStore, commitCalls: () => commitCalls, snapshot, working };
297
+ }
298
+
121
299
  async function fixtureV2(maximumRows = 400, pageSize = 64,
122
300
  maximumResultBytes = 8 * 1024 * 1024, configuration: Readonly<{
123
301
  chunkBytes?: number;
@@ -190,7 +368,136 @@ function countedWorkingStore(store: OhStoreV1, counter: { reads: number }): OhSt
190
368
  }) as OhStoreV1;
191
369
  }
192
370
 
193
- async function fixture() {
371
+ function frozenForwardingStore(store: OhStoreV1): OhStoreV1 {
372
+ return Object.freeze({
373
+ binding: store.binding,
374
+ changesSince: store.changesSince.bind(store),
375
+ close: store.close.bind(store),
376
+ commit: store.commit.bind(store),
377
+ exportDependencyClosure: store.exportDependencyClosure.bind(store),
378
+ head: store.head.bind(store),
379
+ snapshot: store.snapshot.bind(store),
380
+ verify: store.verify.bind(store),
381
+ });
382
+ }
383
+
384
+ function saturatedWorkingStore(
385
+ store: OhStoreV1,
386
+ snapshot: OhSnapshotV1,
387
+ counter: { commits: number },
388
+ ): OhStoreV1 {
389
+ return new Proxy(store, {
390
+ get(target, property) {
391
+ const value = Reflect.get(target, property, target) as unknown;
392
+ if (property === "commit") {
393
+ return async () => {
394
+ counter.commits += 1;
395
+ throw new Error("working capacity preflight must precede CAS");
396
+ };
397
+ }
398
+ if (property === "head") return async () => snapshot.head;
399
+ if (property === "snapshot") return async () => snapshot;
400
+ return typeof value === "function"
401
+ ? (...args: unknown[]) => Reflect.apply(value, target, args)
402
+ : value;
403
+ },
404
+ }) as OhStoreV1;
405
+ }
406
+
407
+ function replayProbeWorkingStore(
408
+ store: OhStoreV1,
409
+ state: { rejectSnapshots: boolean; snapshotReads: number },
410
+ ): OhStoreV1 {
411
+ return new Proxy(store, {
412
+ get(target, property) {
413
+ const value = Reflect.get(target, property, target) as unknown;
414
+ if (property === "snapshot") {
415
+ return async (...args: unknown[]) => {
416
+ state.snapshotReads += 1;
417
+ if (state.rejectSnapshots) {
418
+ throw new RangeError("a stale replay must not run a prospective capacity snapshot");
419
+ }
420
+ return await Reflect.apply(value as (...values: unknown[]) => unknown, target, args);
421
+ };
422
+ }
423
+ return typeof value === "function"
424
+ ? (...args: unknown[]) => Reflect.apply(value, target, args)
425
+ : value;
426
+ },
427
+ }) as OhStoreV1;
428
+ }
429
+
430
+ type HostileCapacityResponse = "accessor-snapshot" | "mismatched-snapshot"
431
+ | "mutated-head-snapshot" | "oversize-head" | "oversize-snapshot";
432
+
433
+ function hostileCapacityWorkingStore(
434
+ store: OhStoreV1,
435
+ mode: HostileCapacityResponse,
436
+ counter: { accessorReads?: number; commits: number; snapshotReads: number },
437
+ ): OhStoreV1 {
438
+ let returnedMutableHead: OhHeadV1 | undefined;
439
+ return new Proxy(store, {
440
+ get(target, property) {
441
+ const value = Reflect.get(target, property, target) as unknown;
442
+ if (property === "commit") {
443
+ return async () => {
444
+ counter.commits += 1;
445
+ throw new Error("a hostile capacity response must fail before CAS");
446
+ };
447
+ }
448
+ if (property === "head" && mode === "oversize-head") {
449
+ return async () => ({ ...await target.head(), padding: "x".repeat(8 * 1024) });
450
+ }
451
+ if (property === "head" && mode === "mutated-head-snapshot") {
452
+ return async () => {
453
+ returnedMutableHead = { ...await target.head() };
454
+ return returnedMutableHead;
455
+ };
456
+ }
457
+ if (property === "snapshot") {
458
+ return async (...args: unknown[]) => {
459
+ counter.snapshotReads += 1;
460
+ if (mode === "mismatched-snapshot") return staticSnapshot([]);
461
+ if (mode === "mutated-head-snapshot") {
462
+ if (returnedMutableHead === undefined) throw new Error("Expected a prior head read.");
463
+ const substituted = staticSnapshot([]);
464
+ Object.assign(returnedMutableHead as unknown as Record<string, unknown>,
465
+ substituted.head);
466
+ return { head: returnedMutableHead, records: substituted.records, v: 1 };
467
+ }
468
+ const snapshot = await Reflect.apply(value as (...values: unknown[]) => unknown,
469
+ target, args) as OhSnapshotV1;
470
+ if (mode === "oversize-snapshot") {
471
+ return { ...snapshot, padding: "x".repeat(OH_MEMORY_LIMITS_V1.snapshotBytesPerLane) };
472
+ }
473
+ if (mode === "accessor-snapshot") {
474
+ const response = { head: snapshot.head, v: 1 } as {
475
+ head: OhHeadV1;
476
+ readonly records: readonly KnowledgeGraphRecordV1[];
477
+ v: 1;
478
+ };
479
+ Object.defineProperty(response, "records", {
480
+ enumerable: true,
481
+ get: () => {
482
+ counter.accessorReads = (counter.accessorReads ?? 0) + 1;
483
+ return snapshot.records;
484
+ },
485
+ });
486
+ return response;
487
+ }
488
+ return snapshot;
489
+ };
490
+ }
491
+ return typeof value === "function"
492
+ ? (...args: unknown[]) => Reflect.apply(value, target, args)
493
+ : value;
494
+ },
495
+ }) as OhStoreV1;
496
+ }
497
+
498
+ async function fixture(configuration: Readonly<{
499
+ wrapWorkingStore?: (store: OhStoreV1) => OhStoreV1;
500
+ }> = {}) {
194
501
  const canonical = createOhSqliteStoreAuthorityV1({ path: ":memory:",
195
502
  profile: OH_CANONICAL_STORE_PROFILE_V1, realmId: "realm:canonical", spaceId: "canonical" });
196
503
  const working = createOhSqliteStoreAuthorityV1({ path: ":memory:",
@@ -202,6 +509,7 @@ async function fixture() {
202
509
  const clockOrigin = now.getTime();
203
510
  let monotonicNow = 0;
204
511
  const baseProgram = visibleProgram();
512
+ const selectedWorkingStore = configuration.wrapWorkingStore?.(working.store) ?? working.store;
205
513
  const agent = await createOhMemoryAgentV1({
206
514
  actorId: "test.memory-agent",
207
515
  canonical: { authorityId: "authority.canonical", expectedBindingSha256: canonical.store.binding.bindingSha256,
@@ -213,14 +521,15 @@ async function fixture() {
213
521
  purpose: "answer.alternate" }, { ...baseProgram,
214
522
  evaluation: { maximumRounds: 2 }, programId: "memory.visible-records-bounded" }],
215
523
  working: { authorityId: "authority.working", codecs: entityCodecs(),
216
- expectedBindingSha256: working.store.binding.bindingSha256, store: working.store },
524
+ expectedBindingSha256: selectedWorkingStore.binding.bindingSha256,
525
+ store: selectedWorkingStore },
217
526
  });
218
527
  return { agent, canonical, canonicalHead, setNow(value: string) {
219
528
  now = new Date(value); monotonicNow = now.getTime() - clockOrigin;
220
529
  }, working };
221
530
  }
222
531
 
223
- describe("experimental composite Oh memory", () => {
532
+ describe("composite Oh memory V1", () => {
224
533
  test("keeps two physical authorities explicit and makes working conflicts visible", async () => {
225
534
  expect(Object.isFrozen(OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1.relations)).toBe(true);
226
535
  const value = await fixture();
@@ -483,9 +792,150 @@ describe("experimental composite Oh memory", () => {
483
792
  store: working.store } })).rejects.toThrow(OhProfileError);
484
793
  await canonical.store.close(); await working.store.close();
485
794
  });
795
+
796
+ test("rejects a V1 remember that would exceed working record capacity before CAS", async () => {
797
+ const snapshot = staticSnapshot(Array.from({
798
+ length: OH_MEMORY_LIMITS_V1.maximumRecordsPerLane,
799
+ }, (_, index) => entity(`entity:v1-capacity-${index.toString().padStart(4, "0")}`, "x")));
800
+ const counter = { commits: 0 };
801
+ const value = await fixture({
802
+ wrapWorkingStore: (store) => saturatedWorkingStore(store, snapshot, counter),
803
+ });
804
+ await expect(value.agent.remember({ expectedHead: {
805
+ generation: snapshot.head.generation,
806
+ operationSha256: snapshot.head.operationSha256,
807
+ }, puts: [{ dependencies: [], key: "entity:v1-capacity-extra", kind: "entity", v: 1,
808
+ value: { name: "Extra" } }], requestId: "v1-capacity-extra", tombstones: [], v: 1 }))
809
+ .rejects.toThrow("working memory would exceed its record snapshot bound");
810
+ expect(counter.commits).toBe(0);
811
+ await value.canonical.store.close(); await value.working.store.close();
812
+ });
813
+
814
+ test("accepts an immutable host working-store capability", async () => {
815
+ const value = await fixture({ wrapWorkingStore: frozenForwardingStore });
816
+ const head = await value.working.store.head();
817
+ const receipt = await value.agent.remember({
818
+ expectedHead: {
819
+ generation: head.generation,
820
+ operationSha256: head.operationSha256,
821
+ },
822
+ puts: [{
823
+ dependencies: [],
824
+ key: "entity:frozen-host-store",
825
+ kind: "entity",
826
+ v: 1,
827
+ value: { name: "Frozen host store" },
828
+ }],
829
+ requestId: "v1-frozen-host-store",
830
+ tombstones: [],
831
+ v: 1,
832
+ });
833
+ expect(receipt.status).toBe("committed");
834
+ expect((await value.working.store.snapshot()).records.map(({ key }) => key))
835
+ .toContain("entity:frozen-host-store");
836
+ await value.canonical.store.close(); await value.working.store.close();
837
+ });
838
+
839
+ test("lets the V1 store resolve an exact stale replay after a later write", async () => {
840
+ const state = { rejectSnapshots: false, snapshotReads: 0 };
841
+ const value = await fixture({
842
+ wrapWorkingStore: (store) => replayProbeWorkingStore(store, state),
843
+ });
844
+ const initialHead = await value.working.store.head();
845
+ const request = { expectedHead: { generation: initialHead.generation,
846
+ operationSha256: initialHead.operationSha256 }, puts: [{ dependencies: [],
847
+ key: "entity:v1-replay", kind: "entity", v: 1, value: { name: "Replay" } }],
848
+ requestId: "v1-exact-replay", tombstones: [], v: 1 } as const;
849
+ const receipt = await value.agent.remember(request);
850
+ await put(value.working.store, "entity:v1-later", "Later", "v1_later_write");
851
+ const snapshotReads = state.snapshotReads;
852
+ state.rejectSnapshots = true;
853
+ expect(await value.agent.remember(request)).toEqual(receipt);
854
+ expect(state.snapshotReads).toBe(snapshotReads);
855
+ await value.canonical.store.close(); await value.working.store.close();
856
+ });
857
+
858
+ test("bounds a host-supplied working head before capacity preflight", async () => {
859
+ const counter = { commits: 0, snapshotReads: 0 };
860
+ const value = await fixture({
861
+ wrapWorkingStore: (store) => hostileCapacityWorkingStore(store, "oversize-head", counter),
862
+ });
863
+ const head = await value.working.store.head();
864
+ await expect(value.agent.remember({ expectedHead: {
865
+ generation: head.generation, operationSha256: head.operationSha256,
866
+ }, puts: [{ dependencies: [], key: "entity:v1-hostile-head", kind: "entity", v: 1,
867
+ value: { name: "Hostile head" } }], requestId: "v1-hostile-head", tombstones: [], v: 1 }))
868
+ .rejects.toThrow("canonical byte bound");
869
+ expect(counter).toEqual({ commits: 0, snapshotReads: 0 });
870
+ await value.canonical.store.close(); await value.working.store.close();
871
+ });
872
+
873
+ test("rejects a capacity snapshot that is not at the requested current head", async () => {
874
+ const counter = { commits: 0, snapshotReads: 0 };
875
+ const value = await fixture({
876
+ wrapWorkingStore: (store) => hostileCapacityWorkingStore(store,
877
+ "mismatched-snapshot", counter),
878
+ });
879
+ const head = await value.working.store.head();
880
+ await expect(value.agent.remember({ expectedHead: {
881
+ generation: head.generation, operationSha256: head.operationSha256,
882
+ }, puts: [{ dependencies: [], key: "entity:v1-mismatched-snapshot", kind: "entity", v: 1,
883
+ value: { name: "Mismatched snapshot" } }], requestId: "v1-mismatched-snapshot",
884
+ tombstones: [], v: 1 })).rejects.toThrow(OhIntegrityError);
885
+ expect(counter).toEqual({ commits: 0, snapshotReads: 1 });
886
+ await value.canonical.store.close(); await value.working.store.close();
887
+ });
888
+
889
+ test("detaches the working head before a store mutates and reuses its response", async () => {
890
+ const counter = { commits: 0, snapshotReads: 0 };
891
+ const value = await fixture({
892
+ wrapWorkingStore: (store) => hostileCapacityWorkingStore(store,
893
+ "mutated-head-snapshot", counter),
894
+ });
895
+ const head = await value.working.store.head();
896
+ await expect(value.agent.remember({ expectedHead: {
897
+ generation: head.generation, operationSha256: head.operationSha256,
898
+ }, puts: [{ dependencies: [], key: "entity:v1-mutated-head", kind: "entity", v: 1,
899
+ value: { name: "Mutated head" } }], requestId: "v1-mutated-head",
900
+ tombstones: [], v: 1 })).rejects.toThrow(OhIntegrityError);
901
+ expect(counter).toEqual({ commits: 0, snapshotReads: 1 });
902
+ await value.canonical.store.close(); await value.working.store.close();
903
+ });
904
+
905
+ test("bounds a host-supplied working snapshot before capacity math", async () => {
906
+ const counter = { commits: 0, snapshotReads: 0 };
907
+ const value = await fixture({
908
+ wrapWorkingStore: (store) => hostileCapacityWorkingStore(store,
909
+ "oversize-snapshot", counter),
910
+ });
911
+ const head = await value.working.store.head();
912
+ await expect(value.agent.remember({ expectedHead: {
913
+ generation: head.generation, operationSha256: head.operationSha256,
914
+ }, puts: [{ dependencies: [], key: "entity:v1-oversize-snapshot", kind: "entity", v: 1,
915
+ value: { name: "Oversize snapshot" } }], requestId: "v1-oversize-snapshot",
916
+ tombstones: [], v: 1 })).rejects.toThrow("canonical byte bound");
917
+ expect(counter).toEqual({ commits: 0, snapshotReads: 1 });
918
+ await value.canonical.store.close(); await value.working.store.close();
919
+ });
920
+
921
+ test("rejects accessor-bearing working snapshots without invoking them", async () => {
922
+ const counter = { accessorReads: 0, commits: 0, snapshotReads: 0 };
923
+ const value = await fixture({
924
+ wrapWorkingStore: (store) => hostileCapacityWorkingStore(store,
925
+ "accessor-snapshot", counter),
926
+ });
927
+ const head = await value.working.store.head();
928
+ await expect(value.agent.remember({ expectedHead: {
929
+ generation: head.generation, operationSha256: head.operationSha256,
930
+ }, puts: [{ dependencies: [], key: "entity:v1-accessor-snapshot", kind: "entity", v: 1,
931
+ value: { name: "Accessor snapshot" } }], requestId: "v1-accessor-snapshot",
932
+ tombstones: [], v: 1 })).rejects.toThrow("non-data property");
933
+ expect(counter).toEqual({ accessorReads: 0, commits: 0, snapshotReads: 1 });
934
+ await value.canonical.store.close(); await value.working.store.close();
935
+ });
486
936
  });
487
937
 
488
- describe("experimental parameterized and paginated Oh memory V2", () => {
938
+ describe("parameterized and paginated Oh memory V2", () => {
489
939
  test("binds host-declared lane and key constants and returns more than 256 value chunks in stable pages",
490
940
  async () => {
491
941
  const value = await fixtureV2();
@@ -553,7 +1003,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
553
1003
  await expect(value.agent.query({ bindings: {
554
1004
  key: "entity:chunked", lane: "canonical",
555
1005
  }, continuation: tampered, programId: "memory.value-chunks", v: 2 }))
556
- .rejects.toThrow();
1006
+ .rejects.toThrow(OhMemoryContinuationError);
557
1007
  const decoded = JSON.parse(Buffer.from(continuation, "base64url").toString("utf8")) as
558
1008
  Record<string, unknown>;
559
1009
  const noncanonical = Buffer.from(JSON.stringify(Object.fromEntries(
@@ -561,15 +1011,15 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
561
1011
  await expect(value.agent.query({ bindings: {
562
1012
  key: "entity:chunked", lane: "canonical",
563
1013
  }, continuation: noncanonical, programId: "memory.value-chunks", v: 2 }))
564
- .rejects.toThrow("Invalid memory continuation payload");
1014
+ .rejects.toMatchObject({ code: "memory-continuation", reason: "encoding" });
565
1015
  await expect(value.agent.query({ bindings: {
566
1016
  key: "entity:chunked", lane: "canonical",
567
1017
  }, continuation, programId: "memory.value-chunks-alternate", v: 2 }))
568
- .rejects.toThrow("exact program, binding, and page identity");
1018
+ .rejects.toThrow(OhMemoryContinuationError);
569
1019
  await expect(value.agent.query({ bindings: {
570
1020
  key: "entity:other", lane: "canonical",
571
1021
  }, continuation, programId: "memory.value-chunks", v: 2 }))
572
- .rejects.toThrow(OhIntegrityError);
1022
+ .rejects.toThrow(OhMemoryContinuationError);
573
1023
 
574
1024
  const head = await value.working.store.head();
575
1025
  await value.agent.remember({ expectedHead: { generation: head.generation,
@@ -579,7 +1029,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
579
1029
  await expect(value.agent.query({ bindings: {
580
1030
  key: "entity:chunked", lane: "canonical",
581
1031
  }, continuation, programId: "memory.value-chunks", v: 2 }))
582
- .rejects.toThrow("exact source and projection identity");
1032
+ .rejects.toMatchObject({ code: "memory-continuation", reason: "identity" });
583
1033
  await value.canonical.store.close(); await value.working.store.close();
584
1034
  });
585
1035
 
@@ -601,7 +1051,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
601
1051
  decoded.continuationSha256 = canonicalSha256(unsigned);
602
1052
  const forged = Buffer.from(canonicalJson(decoded), "utf8").toString("base64url");
603
1053
  await expect(value.agent.query({ ...request, continuation: forged }))
604
- .rejects.toThrow("not an issued capability");
1054
+ .rejects.toMatchObject({ code: "memory-continuation", reason: "authentication" });
605
1055
 
606
1056
  const replayOne = await value.agent.query({ ...request, continuation: first.continuation });
607
1057
  const replayTwo = await value.agent.query({ ...request, continuation: first.continuation });
@@ -633,7 +1083,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
633
1083
  expect(otherKey.continuationSha256).toBe(keyed.continuationSha256);
634
1084
  expect(otherKey.resultSha256).toBe(keyed.resultSha256);
635
1085
  await expect(otherKeyAgent.query({ ...request, continuation: keyed.continuation }))
636
- .rejects.toThrow("not an issued capability");
1086
+ .rejects.toThrow(OhMemoryContinuationError);
637
1087
 
638
1088
  const reconstructed = await value.createAgent(persistedHostKey);
639
1089
  const resumed = await reconstructed.query({ ...request, continuation: keyed.continuation });
@@ -644,7 +1094,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
644
1094
  if (localFirst.continuation === null) throw new Error("Expected a local continuation.");
645
1095
  const localTwo = await value.createAgent();
646
1096
  await expect(localTwo.query({ ...request, continuation: localFirst.continuation }))
647
- .rejects.toThrow("not an issued capability");
1097
+ .rejects.toThrow(OhMemoryContinuationError);
648
1098
  await expect(value.createAgent(new Uint8Array(
649
1099
  OH_MEMORY_QUERY_LIMITS_V2.continuationKeyMinimumBytes - 1)))
650
1100
  .rejects.toThrow("32 through 64 raw bytes");
@@ -672,7 +1122,12 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
672
1122
  counter.extractorInvocations = 0;
673
1123
  counter.workingReads = 0;
674
1124
 
675
- await expect(value.agent.query({ ...request, continuation: "!" })).rejects.toThrow();
1125
+ let encodingFailure: unknown;
1126
+ try { await value.agent.query({ ...request, continuation: "!" }); }
1127
+ catch (error) { encodingFailure = error; }
1128
+ expect(encodingFailure).toBeInstanceOf(OhMemoryContinuationError);
1129
+ expect(encodingFailure).toMatchObject({ code: "memory-continuation", reason: "encoding" });
1130
+ expect(Object.getOwnPropertyDescriptor(encodingFailure, "reason")?.writable).toBe(false);
676
1131
  const invalidMacPayload = JSON.parse(
677
1132
  Buffer.from(first.continuation, "base64url").toString("utf8"),
678
1133
  ) as Record<string, unknown>;
@@ -680,18 +1135,50 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
680
1135
  === "f".repeat(64) ? "e".repeat(64) : "f".repeat(64);
681
1136
  const invalidMac = Buffer.from(canonicalJson(invalidMacPayload), "utf8").toString("base64url");
682
1137
  await expect(value.agent.query({ ...request, continuation: invalidMac }))
683
- .rejects.toThrow("not an issued capability");
1138
+ .rejects.toMatchObject({ code: "memory-continuation", reason: "authentication" });
684
1139
  await expect(value.agent.query({ ...request, continuation: first.continuation,
685
1140
  programId: "memory.value-chunks-alternate" }))
686
- .rejects.toThrow("exact program, binding, and page identity");
1141
+ .rejects.toMatchObject({ code: "memory-continuation", reason: "identity" });
687
1142
  await expect(value.agent.query({ ...request,
688
1143
  bindings: { key: "entity:other", lane: "canonical" },
689
1144
  continuation: first.continuation }))
690
- .rejects.toThrow("exact program, binding, and page identity");
1145
+ .rejects.toThrow(OhMemoryContinuationError);
691
1146
  expect(counter).toEqual({ extractorInvocations: 0, workingReads: 0 });
692
1147
  await value.canonical.store.close(); await value.working.store.close();
693
1148
  });
694
1149
 
1150
+ test("does not relabel store failures as continuation failures", async () => {
1151
+ let failWorkingRead = false;
1152
+ const value = await fixtureV2(8, 2, 8 * 1024 * 1024, {
1153
+ chunkCount: 8,
1154
+ continuationKey: new Uint8Array(32).fill(6),
1155
+ wrapWorkingStore: (store) => new Proxy(store, {
1156
+ get(target, property) {
1157
+ const member = Reflect.get(target, property, target) as unknown;
1158
+ if (property === "head") return async () => {
1159
+ if (failWorkingRead) throw new OhIntegrityError("The working store failed verification.");
1160
+ return await target.head();
1161
+ };
1162
+ return typeof member === "function"
1163
+ ? (...args: unknown[]) => Reflect.apply(member, target, args)
1164
+ : member;
1165
+ },
1166
+ }) as OhStoreV1,
1167
+ });
1168
+ const request = { bindings: { key: "entity:chunked", lane: "canonical" },
1169
+ continuation: null, programId: "memory.value-chunks", v: 2 as const };
1170
+ const first = await value.agent.query(request);
1171
+ if (first.continuation === null) throw new Error("Expected an issued continuation.");
1172
+ failWorkingRead = true;
1173
+ let thrown: unknown;
1174
+ try { await value.agent.query({ ...request, continuation: first.continuation }); }
1175
+ catch (error) { thrown = error; }
1176
+ expect(thrown).toBeInstanceOf(OhIntegrityError);
1177
+ expect(thrown).not.toBeInstanceOf(OhMemoryContinuationError);
1178
+ expect(thrown).toHaveProperty("message", "The working store failed verification.");
1179
+ await value.canonical.store.close(); await value.working.store.close();
1180
+ });
1181
+
695
1182
  test("bounds and flattens V2 query input before canonical serialization", async () => {
696
1183
  const value = await fixtureV2();
697
1184
  const base = { continuation: null, programId: "memory.value-chunks", v: 2 as const };
@@ -712,7 +1199,7 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
712
1199
  ) })).rejects.toThrow("canonical byte bound");
713
1200
  await expect(value.agent.query({ ...base, bindings: {},
714
1201
  continuation: "A".repeat(OH_MEMORY_QUERY_LIMITS_V2.continuationBytes + 1) }))
715
- .rejects.toThrow("continuation exceeds its byte bound");
1202
+ .rejects.toThrow(OhMemoryContinuationError);
716
1203
  await value.canonical.store.close(); await value.working.store.close();
717
1204
  });
718
1205
 
@@ -780,4 +1267,987 @@ describe("experimental parameterized and paginated Oh memory V2", () => {
780
1267
  .rejects.toThrow("Invalid parameterized memory query");
781
1268
  await value.canonical.store.close(); await value.working.store.close();
782
1269
  });
1270
+
1271
+ test("rejects a V2 remember that would exceed working byte capacity before CAS", async () => {
1272
+ const largeName = "x".repeat(875_000);
1273
+ const snapshot = staticSnapshot(Array.from({ length: 38 }, (_, index) =>
1274
+ entity(`entity:v2-capacity-${index.toString().padStart(2, "0")}`, largeName)));
1275
+ expect(Buffer.byteLength(canonicalJson(snapshot), "utf8"))
1276
+ .toBeLessThanOrEqual(OH_MEMORY_LIMITS_V1.snapshotBytesPerLane);
1277
+ const counter = { commits: 0 };
1278
+ const value = await fixtureV2(400, 64, 8 * 1024 * 1024, {
1279
+ wrapWorkingStore: (store) => saturatedWorkingStore(store, snapshot, counter),
1280
+ });
1281
+ await expect(value.agent.remember({ expectedHead: {
1282
+ generation: snapshot.head.generation,
1283
+ operationSha256: snapshot.head.operationSha256,
1284
+ }, puts: [{ dependencies: [], key: "entity:v2-capacity-extra", kind: "entity", v: 1,
1285
+ value: { name: largeName } }], requestId: "v2-capacity-extra", tombstones: [], v: 1 }))
1286
+ .rejects.toThrow("working memory would exceed its snapshot byte bound");
1287
+ expect(counter.commits).toBe(0);
1288
+ await value.canonical.store.close(); await value.working.store.close();
1289
+ });
1290
+
1291
+ test("lets the V2 store resolve an exact stale replay after a later write", async () => {
1292
+ const state = { rejectSnapshots: false, snapshotReads: 0 };
1293
+ const value = await fixtureV2(400, 64, 8 * 1024 * 1024, {
1294
+ wrapWorkingStore: (store) => replayProbeWorkingStore(store, state),
1295
+ });
1296
+ const initialHead = await value.working.store.head();
1297
+ const request = { expectedHead: { generation: initialHead.generation,
1298
+ operationSha256: initialHead.operationSha256 }, puts: [{ dependencies: [],
1299
+ key: "entity:v2-replay", kind: "entity", v: 1, value: { name: "Replay" } }],
1300
+ requestId: "v2-exact-replay", tombstones: [], v: 1 } as const;
1301
+ const receipt = await value.agent.remember(request);
1302
+ await put(value.working.store, "entity:v2-later", "Later", "v2_later_write");
1303
+ const snapshotReads = state.snapshotReads;
1304
+ state.rejectSnapshots = true;
1305
+ expect(await value.agent.remember(request)).toEqual(receipt);
1306
+ expect(state.snapshotReads).toBe(snapshotReads);
1307
+ await value.canonical.store.close(); await value.working.store.close();
1308
+ });
1309
+ });
1310
+
1311
+ describe("stable host-bound Oh memory authority", () => {
1312
+ test("strictly parses prepared nominations and separates agent and host authority", async () => {
1313
+ const value = await authorityFixture();
1314
+ expect(Object.keys(value.authority).sort()).toEqual(["agent", "host"]);
1315
+ expect(Object.keys(value.authority.agent).sort()).toEqual(["explain", "nominate", "query", "remember"]);
1316
+ expect(Object.keys(value.authority.host).sort()).toEqual(["adoptNomination", "advanceCanonical"]);
1317
+ expect("host" in value.authority.agent).toBe(false);
1318
+
1319
+ const workingHead = await value.working.store.head();
1320
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1321
+ operationSha256: workingHead.operationSha256 },
1322
+ puts: [{ dependencies: [], key: "entity:candidate", kind: "entity", v: 1,
1323
+ value: { name: "Candidate" } }], requestId: "remember_candidate",
1324
+ tombstones: [], v: 1 });
1325
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1326
+ roots: ["entity:candidate"], v: 1 });
1327
+ expect(parseOhMemoryNominationV1(nomination)).toEqual(nomination);
1328
+ expect(parseOhMemoryNominationV1({ ...nomination, extra: true })).toBeNull();
1329
+ expect(parseOhMemoryNominationV1({ ...nomination,
1330
+ nominationSha256: "f".repeat(64) })).toBeNull();
1331
+ expect(parseOhMemoryNominationV1({ ...nomination,
1332
+ source: { ...nomination.source, bindingSha256: "f".repeat(64) } })).toBeNull();
1333
+ expect(Object.isFrozen(parseOhMemoryNominationV1(nomination)?.closure.records)).toBe(true);
1334
+ await expect(value.authority.host.adoptNomination({
1335
+ expectedCanonicalHead: value.initialCanonicalHead, extra: true, nomination, v: 1 }))
1336
+ .rejects.toThrow("Invalid memory adoption request");
1337
+ await expect(value.authority.host.advanceCanonical({
1338
+ expectedHead: value.initialCanonicalHead, extra: true,
1339
+ nextHead: value.initialCanonicalHead, v: 1 }))
1340
+ .rejects.toThrow("Invalid canonical memory advance request");
1341
+ await value.canonical.store.close(); await value.working.store.close();
1342
+ });
1343
+
1344
+ test("refuses an adopted operation above the host canonical byte bound before commit", async () => {
1345
+ const value = await authorityFixture({ maximumCanonicalOperationBytes: 1 });
1346
+ const workingHead = await value.working.store.head();
1347
+ await value.authority.agent.remember({ expectedHead: {
1348
+ generation: workingHead.generation,
1349
+ operationSha256: workingHead.operationSha256,
1350
+ }, puts: [{ dependencies: [], key: "entity:bounded-adoption", kind: "entity", v: 1,
1351
+ value: { name: "Bounded adoption" } }], requestId: "remember_bounded_adoption",
1352
+ tombstones: [], v: 1 });
1353
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1354
+ roots: ["entity:bounded-adoption"], v: 1 });
1355
+ await expect(value.authority.host.adoptNomination({
1356
+ expectedCanonicalHead: value.initialCanonicalHead,
1357
+ nomination,
1358
+ v: 1,
1359
+ })).rejects.toThrow(OhOperationSizeError);
1360
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1361
+ expect((await value.canonical.store.snapshot()).records.map(({ key }) => key))
1362
+ .not.toContain("entity:bounded-adoption");
1363
+ await value.canonical.store.close();
1364
+ await value.working.store.close();
1365
+ });
1366
+
1367
+ test("descriptor-detaches stable unknown inputs and never executes accessors or proxies", async () => {
1368
+ const value = await authorityFixture();
1369
+ const workingHead = await value.working.store.head();
1370
+ let accessorReads = 0;
1371
+ const hostilePut = { dependencies: [], key: "entity:hostile", kind: "entity", v: 1 } as
1372
+ Record<PropertyKey, unknown>;
1373
+ Object.defineProperty(hostilePut, "value", { enumerable: true,
1374
+ get() { accessorReads += 1; throw new Error("must not execute"); } });
1375
+ await expect(value.authority.agent.remember({
1376
+ expectedHead: { generation: workingHead.generation,
1377
+ operationSha256: workingHead.operationSha256 },
1378
+ puts: [hostilePut], requestId: "remember_accessor", tombstones: [], v: 1,
1379
+ })).rejects.toThrow("non-data property");
1380
+ expect(accessorReads).toBe(0);
1381
+ expect(await value.working.store.head()).toEqual(workingHead);
1382
+
1383
+ let proxyDescriptorReads = 0;
1384
+ const proxyBundle = new Proxy({
1385
+ expectedHead: { generation: workingHead.generation,
1386
+ operationSha256: workingHead.operationSha256 },
1387
+ puts: [{ dependencies: [], key: "entity:proxy", kind: "entity", v: 1,
1388
+ value: { name: "Proxy" } }], requestId: "remember_proxy", tombstones: [], v: 1,
1389
+ }, { getOwnPropertyDescriptor(target, property) {
1390
+ proxyDescriptorReads += 1;
1391
+ return Reflect.getOwnPropertyDescriptor(target, property);
1392
+ } });
1393
+ await expect(value.authority.agent.remember(proxyBundle)).rejects.toThrow("contains a proxy");
1394
+ expect(proxyDescriptorReads).toBe(0);
1395
+ expect(await value.working.store.head()).toEqual(workingHead);
1396
+
1397
+ const hostileBindings = new Proxy({}, {});
1398
+ await expect(value.authority.agent.query({ bindings: hostileBindings, continuation: null,
1399
+ programId: "memory.visible-records", v: 2 })).rejects.toThrow("JSON primitives");
1400
+ const explainPromise = value.authority.agent.explain(new Proxy({}, {}));
1401
+ expect(explainPromise).toBeInstanceOf(Promise);
1402
+ await expect(explainPromise).rejects.toThrow("contains a proxy");
1403
+
1404
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1405
+ operationSha256: workingHead.operationSha256 },
1406
+ puts: [{ dependencies: [], key: "entity:valid", kind: "entity", v: 1,
1407
+ value: { name: "Valid" } }], requestId: "remember_valid_after_hostile",
1408
+ tombstones: [], v: 1 });
1409
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1410
+ roots: ["entity:valid"], v: 1 });
1411
+ const hostileNomination = { ...nomination } as Record<PropertyKey, unknown>;
1412
+ Object.defineProperty(hostileNomination, "source", { enumerable: true,
1413
+ get() { accessorReads += 1; throw new Error("must not execute"); } });
1414
+ expect(parseOhMemoryNominationV1(hostileNomination)).toBeNull();
1415
+ expect(accessorReads).toBe(0);
1416
+ const hostileAdoption = { expectedCanonicalHead: value.initialCanonicalHead, v: 1 } as
1417
+ Record<PropertyKey, unknown>;
1418
+ Object.defineProperty(hostileAdoption, "nomination", { enumerable: true,
1419
+ get() { accessorReads += 1; throw new Error("must not execute"); } });
1420
+ const adoptionPromise = value.authority.host.adoptNomination(hostileAdoption);
1421
+ expect(adoptionPromise).toBeInstanceOf(Promise);
1422
+ await expect(adoptionPromise).rejects.toThrow("non-data property");
1423
+ expect(accessorReads).toBe(0);
1424
+ const priorRecord = (await value.canonical.store.snapshot()).records[0]!;
1425
+ const hostileReplacement = { key: priorRecord.key, v: 1 } as Record<PropertyKey, unknown>;
1426
+ Object.defineProperty(hostileReplacement, "expectedPriorRecordSha256", { enumerable: true,
1427
+ get() { accessorReads += 1; throw new Error("must not execute"); } });
1428
+ await expect(value.authority.host.adoptNomination({
1429
+ expectedCanonicalHead: value.initialCanonicalHead, nomination,
1430
+ replacements: [hostileReplacement], v: 1,
1431
+ })).rejects.toThrow("non-data property");
1432
+ expect(accessorReads).toBe(0);
1433
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1434
+ let deeplyNested: unknown = "f".repeat(64);
1435
+ for (let depth = 0; depth <= OH_MEMORY_LIMITS_V1.detachedCanonicalDepth; depth += 1) {
1436
+ deeplyNested = { value: deeplyNested };
1437
+ }
1438
+ await expect(value.authority.host.adoptNomination({
1439
+ expectedCanonicalHead: value.initialCanonicalHead, nomination,
1440
+ replacements: [{ expectedPriorRecordSha256: deeplyNested,
1441
+ key: priorRecord.key, v: 1 }], v: 1,
1442
+ })).rejects.toThrow("canonical nesting depth bound");
1443
+ const tooBroad = new Array(OH_MEMORY_LIMITS_V1.detachedCanonicalBreadth + 1);
1444
+ await expect(value.authority.host.adoptNomination({
1445
+ expectedCanonicalHead: value.initialCanonicalHead, nomination,
1446
+ replacements: tooBroad, v: 1,
1447
+ })).rejects.toThrow("canonical breadth bound");
1448
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1449
+ const symbolAdvance = { expectedHead: value.initialCanonicalHead,
1450
+ nextHead: value.initialCanonicalHead, v: 1 } as Record<PropertyKey, unknown>;
1451
+ symbolAdvance[Symbol("extra")] = true;
1452
+ await expect(value.authority.host.advanceCanonical(symbolAdvance))
1453
+ .rejects.toThrow("symbol property");
1454
+ await value.canonical.store.close(); await value.working.store.close();
1455
+ });
1456
+
1457
+ test("adopts a re-exported closure once and makes a concurrent replay already present", async () => {
1458
+ const value = await authorityFixture();
1459
+ const workingHead = await value.working.store.head();
1460
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1461
+ operationSha256: workingHead.operationSha256 },
1462
+ puts: [{ dependencies: [], key: "entity:parent", kind: "entity", v: 1,
1463
+ value: { name: "Parent" } }, { dependencies: ["entity:parent"],
1464
+ key: "entity:child", kind: "entity", v: 1, value: { name: "Child" } }],
1465
+ requestId: "remember_adoption_closure", tombstones: [], v: 1 });
1466
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1467
+ roots: ["entity:child"], v: 1 });
1468
+ const request = { expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 } as const;
1469
+ const [first, second] = await Promise.all([
1470
+ value.authority.host.adoptNomination(request),
1471
+ value.authority.host.adoptNomination(request),
1472
+ ]);
1473
+ expect([first.status, second.status]).toEqual(["adopted", "already-present"]);
1474
+ expect(first.actorId).toBe("test.memory-reviewer");
1475
+ expect(first.operationSha256).not.toBeNull();
1476
+ expect(second.operationSha256).toBeNull();
1477
+ expect(Object.isFrozen(first.head)).toBe(true);
1478
+ expect(first.receiptSha256).toBe(canonicalSha256({ actorId: first.actorId,
1479
+ authorityId: first.authorityId, bindingSha256: first.bindingSha256, head: first.head,
1480
+ nominationSha256: first.nominationSha256, operationSha256: first.operationSha256,
1481
+ priorHead: first.priorHead, status: first.status, v: 1 }));
1482
+ const canonical = await value.canonical.store.snapshot();
1483
+ expect(canonical.records.map(({ key }) => key)).toEqual([
1484
+ "entity:canonical", "entity:child", "entity:parent",
1485
+ ]);
1486
+ const visible = await value.authority.agent.query({ bindings: {}, continuation: null,
1487
+ programId: "memory.visible-records", v: 2 });
1488
+ expect(visible.identity.canonical.head).toEqual(first.head);
1489
+ expect(visible.rows.some(({ values }) => values[0] === "canonical"
1490
+ && values[1] === "entity:child")).toBe(true);
1491
+ await value.canonical.store.close(); await value.working.store.close();
1492
+ });
1493
+
1494
+ test("records one physical adoption under two cross-instance CAS attempts and fails closed",
1495
+ async () => {
1496
+ const sameRendezvous = twoPartyCanonicalCommitRendezvous();
1497
+ let samePrimaryCanonical!: OhStoreV1;
1498
+ const same = await authorityFixture({ canonicalStore: (store) => {
1499
+ samePrimaryCanonical = sameRendezvous.wrap(store, 0);
1500
+ return samePrimaryCanonical;
1501
+ } });
1502
+ const samePeerCanonical = sameRendezvous.wrap(same.canonical.store, 1);
1503
+ expect(samePrimaryCanonical).not.toBe(samePeerCanonical);
1504
+ const samePeer = await peerAuthority(samePeerCanonical, same.working.store,
1505
+ same.initialCanonicalHead);
1506
+ const sameWorkingHead = await same.working.store.head();
1507
+ await same.authority.agent.remember({ expectedHead: {
1508
+ generation: sameWorkingHead.generation,
1509
+ operationSha256: sameWorkingHead.operationSha256,
1510
+ }, puts: [{ dependencies: [], key: "entity:cross-instance-same", kind: "entity", v: 1,
1511
+ value: { name: "Same nomination" } }], requestId: "remember_cross_instance_same",
1512
+ tombstones: [], v: 1 });
1513
+ const sameNomination = await same.authority.agent.nominate({ nominationId: "kb.review",
1514
+ roots: ["entity:cross-instance-same"], v: 1 });
1515
+ const sameRequest = { expectedCanonicalHead: same.initialCanonicalHead,
1516
+ nomination: sameNomination, v: 1 } as const;
1517
+ const sameReceipts = await Promise.all([
1518
+ same.authority.host.adoptNomination(sameRequest),
1519
+ samePeer.host.adoptNomination(sameRequest),
1520
+ ]);
1521
+ // These are separate authority/store-capability instances around one durable SQLite store.
1522
+ // The rendezvous proves that both planned from the prior head and each invoked its distinct
1523
+ // commit capability once before either CAS reached that store. The [1, 1] below is two bounded
1524
+ // CAS attempts; the change history separately proves their one-physical-operation outcome.
1525
+ // This does not simulate independent processes or remote transport.
1526
+ expect(sameRendezvous.commitCalls).toEqual([1, 1]);
1527
+ const sameHead = await same.canonical.store.head();
1528
+ expect(sameReceipts.every(({ head }) => canonicalJson(head) === canonicalJson(sameHead)))
1529
+ .toBe(true);
1530
+ // An exact operation replay may return the one durable operation to both callers; a store
1531
+ // that reports the losing CAS instead lets the authority reconcile it as already present.
1532
+ expect(sameReceipts.every(({ status }) => status === "adopted"
1533
+ || status === "already-present")).toBe(true);
1534
+ expect(sameReceipts.some(({ status }) => status === "adopted")).toBe(true);
1535
+ expect((await same.canonical.store.changesSince(same.initialCanonicalHead,
1536
+ { through: sameHead })).operations).toHaveLength(1);
1537
+ for (const authority of [same.authority, samePeer]) {
1538
+ const page = await authority.agent.query({ bindings: {}, continuation: null,
1539
+ programId: "memory.visible-records", v: 2 });
1540
+ expect(page.identity.canonical.head).toEqual(sameHead);
1541
+ }
1542
+ await same.canonical.store.close(); await same.working.store.close();
1543
+
1544
+ const original = entity("entity:canonical", "Canonical");
1545
+ const differentRendezvous = twoPartyCanonicalCommitRendezvous();
1546
+ let differentPrimaryCanonical!: OhStoreV1;
1547
+ const different = await authorityFixture({ canonicalRecords: [original],
1548
+ canonicalStore: (store) => {
1549
+ differentPrimaryCanonical = differentRendezvous.wrap(store, 0);
1550
+ return differentPrimaryCanonical;
1551
+ } });
1552
+ const differentPeerCanonical = differentRendezvous.wrap(different.canonical.store, 1);
1553
+ expect(differentPrimaryCanonical).not.toBe(differentPeerCanonical);
1554
+ const differentPeer = await peerAuthority(differentPeerCanonical, different.working.store,
1555
+ different.initialCanonicalHead);
1556
+ const firstWorkingHead = await different.working.store.head();
1557
+ await different.authority.agent.remember({ expectedHead: {
1558
+ generation: firstWorkingHead.generation,
1559
+ operationSha256: firstWorkingHead.operationSha256,
1560
+ }, puts: [{ dependencies: [], key: original.key, kind: "entity", v: 1,
1561
+ value: { name: "Replacement A" } }], requestId: "remember_cross_instance_a",
1562
+ tombstones: [], v: 1 });
1563
+ const nominationA = await different.authority.agent.nominate({ nominationId: "kb.review",
1564
+ roots: [original.key], v: 1 });
1565
+ const secondWorkingHead = await different.working.store.head();
1566
+ await different.authority.agent.remember({ expectedHead: {
1567
+ generation: secondWorkingHead.generation,
1568
+ operationSha256: secondWorkingHead.operationSha256,
1569
+ }, puts: [{ dependencies: [], key: original.key, kind: "entity", v: 1,
1570
+ value: { name: "Replacement B" } }], requestId: "remember_cross_instance_b",
1571
+ tombstones: [], v: 1 });
1572
+ const nominationB = await different.authority.agent.nominate({ nominationId: "kb.review",
1573
+ roots: [original.key], v: 1 });
1574
+ const contenders = [{ authority: different.authority, nomination: nominationA },
1575
+ { authority: differentPeer, nomination: nominationB }];
1576
+ const outcomes = await Promise.allSettled(contenders.map(({ authority, nomination }) =>
1577
+ authority.host.adoptNomination({ expectedCanonicalHead: different.initialCanonicalHead,
1578
+ nomination, replacements: [{ expectedPriorRecordSha256: original.recordSha256,
1579
+ key: original.key, v: 1 }], v: 1 })));
1580
+ const fulfilled = outcomes.flatMap((outcome, index) => outcome.status === "fulfilled"
1581
+ ? [{ index, receipt: outcome.value }] : []);
1582
+ const rejected = outcomes.flatMap((outcome, index) => outcome.status === "rejected"
1583
+ ? [{ index, reason: outcome.reason as unknown }] : []);
1584
+ expect(differentRendezvous.commitCalls).toEqual([1, 1]);
1585
+ expect(fulfilled).toHaveLength(1);
1586
+ expect(fulfilled[0]?.receipt.status).toBe("adopted");
1587
+ expect(rejected).toHaveLength(1);
1588
+ expect(rejected[0]?.reason).toBeInstanceOf(OhMemoryAdoptionConflictError);
1589
+ const differentHead = await different.canonical.store.head();
1590
+ const winningNomination = contenders[fulfilled[0]!.index]!.nomination;
1591
+ const winningDigest = winningNomination.closure.records
1592
+ .find(({ key }) => key === original.key)!.recordSha256;
1593
+ expect((await different.canonical.store.snapshot()).records
1594
+ .find(({ key }) => key === original.key)?.recordSha256).toBe(winningDigest);
1595
+ expect((await different.canonical.store.changesSince(different.initialCanonicalHead,
1596
+ { through: differentHead })).operations).toHaveLength(1);
1597
+ expect((rejected[0]!.reason as OhMemoryAdoptionConflictError).conflict.actualHead)
1598
+ .toEqual(differentHead);
1599
+ const losingPage = await contenders[rejected[0]!.index]!.authority.agent.query({
1600
+ bindings: {}, continuation: null, programId: "memory.visible-records", v: 2,
1601
+ });
1602
+ expect(losingPage.identity.canonical.head).toEqual(different.initialCanonicalHead);
1603
+ const winningPage = await contenders[fulfilled[0]!.index]!.authority.agent.query({
1604
+ bindings: {}, continuation: null, programId: "memory.visible-records", v: 2,
1605
+ });
1606
+ expect(winningPage.identity.canonical.head).toEqual(differentHead);
1607
+ await different.canonical.store.close(); await different.working.store.close();
1608
+ });
1609
+
1610
+ test("replaces canonical records only with exact host-supplied prior digests", async () => {
1611
+ const original = entity("entity:canonical", "Canonical");
1612
+ const equal = entity("entity:equal", "Already equal");
1613
+ const value = await authorityFixture({ canonicalRecords: [original, equal] });
1614
+ const workingHead = await value.working.store.head();
1615
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1616
+ operationSha256: workingHead.operationSha256 }, puts: [{ dependencies: [],
1617
+ key: original.key, kind: "entity", v: 1, value: { name: "Reviewed replacement" } },
1618
+ { dependencies: [], key: equal.key, kind: "entity", v: 1,
1619
+ value: { name: "Already equal" } },
1620
+ { dependencies: [], key: "entity:new", kind: "entity", v: 1,
1621
+ value: { name: "New alongside replacement" } }], requestId: "remember_replacement",
1622
+ tombstones: [], v: 1 });
1623
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1624
+ roots: [original.key, equal.key, "entity:new"], v: 1 });
1625
+ const request = { expectedCanonicalHead: value.initialCanonicalHead, nomination,
1626
+ replacements: [{ expectedPriorRecordSha256: original.recordSha256,
1627
+ key: original.key, v: 1 }], v: 1 } as const;
1628
+
1629
+ const bogusEqualClaim = canonicalSha256({ kind: "test.bogus-equal-prior", v: 1 });
1630
+ await expect(value.authority.host.adoptNomination({ ...request, replacements: [
1631
+ ...request.replacements,
1632
+ { expectedPriorRecordSha256: bogusEqualClaim, key: equal.key, v: 1 as const },
1633
+ ] })).rejects.toMatchObject({ conflict: { conflicts: [{
1634
+ canonicalRecordSha256: equal.recordSha256, key: equal.key,
1635
+ nominatedRecordSha256: equal.recordSha256, v: 1,
1636
+ }] } });
1637
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1638
+ expect((await value.canonical.store.snapshot()).records.map(({ key }) => key))
1639
+ .toEqual(["entity:canonical", "entity:equal"]);
1640
+
1641
+ const adopted = await value.authority.host.adoptNomination(request);
1642
+ expect(adopted.status).toBe("adopted");
1643
+ expect(adopted.priorHead).toEqual(value.initialCanonicalHead);
1644
+ const snapshot = await value.canonical.store.snapshot();
1645
+ expect(snapshot.records.map(({ key }) => key)).toEqual([
1646
+ "entity:canonical", "entity:equal", "entity:new",
1647
+ ]);
1648
+ expect(snapshot.records.find(({ key }) => key === original.key)?.recordSha256)
1649
+ .toBe(nomination.closure.records.find(({ key }) => key === original.key)?.recordSha256);
1650
+ const page = await value.canonical.store.changesSince({
1651
+ operationSha256: value.initialCanonicalHead.operationSha256,
1652
+ sequence: value.initialCanonicalHead.sequence,
1653
+ }, { through: adopted.head });
1654
+ expect(page.operations).toHaveLength(1);
1655
+ expect(page.operations[0]?.operationId).toBe(`memory_adopt_${canonicalSha256({
1656
+ actorId: "test.memory-reviewer",
1657
+ bindingSha256: value.canonical.store.binding.bindingSha256,
1658
+ nominationSha256: nomination.nominationSha256,
1659
+ priorHead: value.initialCanonicalHead,
1660
+ v: 1,
1661
+ }).slice(0, 48)}`);
1662
+ expect(page.operations[0]?.changes.map((change) => change.kind === "put"
1663
+ ? change.record.key : change.key)).toEqual(["entity:canonical", "entity:new"]);
1664
+
1665
+ const replay = await value.authority.host.adoptNomination(request);
1666
+ expect(replay.status).toBe("already-present");
1667
+ expect(replay.operationSha256).toBeNull();
1668
+ expect(replay.head).toEqual(adopted.head);
1669
+ expect(await value.canonical.store.head()).toEqual(adopted.head);
1670
+ await expect(value.authority.host.adoptNomination({ ...request, replacements: [
1671
+ ...request.replacements,
1672
+ { expectedPriorRecordSha256: bogusEqualClaim, key: equal.key, v: 1 as const },
1673
+ ] })).rejects.toMatchObject({ conflict: { conflicts: [{
1674
+ canonicalRecordSha256: equal.recordSha256, key: equal.key,
1675
+ nominatedRecordSha256: equal.recordSha256, v: 1,
1676
+ }] } });
1677
+ expect(await value.canonical.store.head()).toEqual(adopted.head);
1678
+
1679
+ await value.canonical.store.commit({ actorId: "test.canonical-reviser",
1680
+ changes: [{ kind: "put", record: original, v: 1 }], expectedHead: adopted.head,
1681
+ operationId: "op_restore_prior_canonical" });
1682
+ const restoredHead = await value.canonical.store.head();
1683
+ await value.authority.host.advanceCanonical({ expectedHead: adopted.head,
1684
+ nextHead: restoredHead, v: 1 });
1685
+ const readopted = await value.authority.host.adoptNomination({ ...request,
1686
+ expectedCanonicalHead: restoredHead });
1687
+ expect(readopted.status).toBe("adopted");
1688
+ expect(readopted.operationSha256).not.toBe(adopted.operationSha256);
1689
+ expect((await value.canonical.store.snapshot()).records
1690
+ .find(({ key }) => key === original.key)?.recordSha256)
1691
+ .toBe(nomination.closure.records.find(({ key }) => key === original.key)?.recordSha256);
1692
+ await value.canonical.store.close(); await value.working.store.close();
1693
+ });
1694
+
1695
+ test("fails a replacement batch atomically when any prior digest is absent or wrong", async () => {
1696
+ const originals = [entity("entity:first-replacement", "First canonical"),
1697
+ entity("entity:second-replacement", "Second canonical")];
1698
+ const value = await authorityFixture({ canonicalRecords: originals });
1699
+ const workingHead = await value.working.store.head();
1700
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1701
+ operationSha256: workingHead.operationSha256 }, puts: [
1702
+ { dependencies: [], key: originals[0]!.key, kind: "entity", v: 1,
1703
+ value: { name: "First replacement" } },
1704
+ { dependencies: [], key: originals[1]!.key, kind: "entity", v: 1,
1705
+ value: { name: "Second replacement" } },
1706
+ { dependencies: [], key: "entity:would-be-added", kind: "entity", v: 1,
1707
+ value: { name: "New record" } },
1708
+ ], requestId: "remember_atomic_replacements", tombstones: [], v: 1 });
1709
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1710
+ roots: [originals[0]!.key, originals[1]!.key, "entity:would-be-added"], v: 1 });
1711
+ const wrongDigest = canonicalSha256({ kind: "test.wrong-prior-record", v: 1 });
1712
+ let thrown: unknown;
1713
+ try {
1714
+ await value.authority.host.adoptNomination({
1715
+ expectedCanonicalHead: value.initialCanonicalHead, nomination, replacements: [
1716
+ { expectedPriorRecordSha256: originals[0]!.recordSha256,
1717
+ key: originals[0]!.key, v: 1 },
1718
+ { expectedPriorRecordSha256: wrongDigest, key: originals[1]!.key, v: 1 },
1719
+ ], v: 1,
1720
+ });
1721
+ } catch (error) { thrown = error; }
1722
+ expect(thrown).toBeInstanceOf(OhMemoryAdoptionConflictError);
1723
+ expect((thrown as OhMemoryAdoptionConflictError).conflict.conflicts).toEqual([{
1724
+ canonicalRecordSha256: originals[1]!.recordSha256,
1725
+ key: originals[1]!.key,
1726
+ nominatedRecordSha256: nomination.closure.records
1727
+ .find(({ key }) => key === originals[1]!.key)!.recordSha256,
1728
+ v: 1,
1729
+ }]);
1730
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1731
+ expect((await value.canonical.store.snapshot()).records).toEqual(originals);
1732
+
1733
+ const absent = nomination.closure.records.find(({ key }) => key === "entity:would-be-added")!;
1734
+ await expect(value.authority.host.adoptNomination({
1735
+ expectedCanonicalHead: value.initialCanonicalHead, nomination,
1736
+ replacements: [
1737
+ { expectedPriorRecordSha256: originals[0]!.recordSha256,
1738
+ key: originals[0]!.key, v: 1 },
1739
+ { expectedPriorRecordSha256: originals[1]!.recordSha256,
1740
+ key: originals[1]!.key, v: 1 },
1741
+ { expectedPriorRecordSha256: wrongDigest, key: absent.key, v: 1 },
1742
+ ], v: 1,
1743
+ })).rejects.toMatchObject({ conflict: { conflicts: [{
1744
+ canonicalRecordSha256: null, key: absent.key,
1745
+ nominatedRecordSha256: absent.recordSha256, v: 1,
1746
+ }] } });
1747
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1748
+ await value.canonical.store.close(); await value.working.store.close();
1749
+ });
1750
+
1751
+ test("rejects stale replacement proof and bounds exact replacement claims", async () => {
1752
+ const original = entity("entity:canonical", "Canonical");
1753
+ const value = await authorityFixture({ canonicalRecords: [original] });
1754
+ const workingHead = await value.working.store.head();
1755
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1756
+ operationSha256: workingHead.operationSha256 }, puts: [{ dependencies: [], key: original.key,
1757
+ kind: "entity", v: 1, value: { name: "Nominated replacement" } }],
1758
+ requestId: "remember_stale_replacement", tombstones: [], v: 1 });
1759
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1760
+ roots: [original.key], v: 1 });
1761
+ const current = entity(original.key, "Newer canonical");
1762
+ await value.canonical.store.commit({ actorId: "test.canonical-writer",
1763
+ changes: [{ kind: "put", record: current, v: 1 }],
1764
+ expectedHead: value.initialCanonicalHead, operationId: "op_newer_canonical" });
1765
+ const currentHead = await value.canonical.store.head();
1766
+ await value.authority.host.advanceCanonical({ expectedHead: value.initialCanonicalHead,
1767
+ nextHead: currentHead, v: 1 });
1768
+ await expect(value.authority.host.adoptNomination({ expectedCanonicalHead: currentHead,
1769
+ nomination, replacements: [{ expectedPriorRecordSha256: original.recordSha256,
1770
+ key: original.key, v: 1 }], v: 1 })).rejects.toMatchObject({ conflict: {
1771
+ actualHead: currentHead, conflicts: [{ canonicalRecordSha256: current.recordSha256,
1772
+ key: original.key, v: 1 }],
1773
+ } });
1774
+ await expect(value.authority.host.adoptNomination({
1775
+ expectedCanonicalHead: value.initialCanonicalHead, nomination,
1776
+ replacements: [{ expectedPriorRecordSha256: current.recordSha256,
1777
+ key: original.key, v: 1 }], v: 1,
1778
+ })).rejects.toMatchObject({ conflict: {
1779
+ actualHead: currentHead, expectedHead: value.initialCanonicalHead,
1780
+ } });
1781
+ expect(await value.canonical.store.head()).toEqual(currentHead);
1782
+
1783
+ const tooMany = Array.from({ length: OH_MEMORY_AUTHORITY_LIMITS_V1.adoptionReplacements + 1 },
1784
+ () => ({ expectedPriorRecordSha256: current.recordSha256, key: original.key, v: 1 }));
1785
+ await expect(value.authority.host.adoptNomination({ expectedCanonicalHead: currentHead,
1786
+ nomination, replacements: tooMany, v: 1 })).rejects
1787
+ .toThrow("Invalid memory adoption replacements");
1788
+ await expect(value.authority.host.adoptNomination({ expectedCanonicalHead: currentHead,
1789
+ nomination, replacements: [
1790
+ { expectedPriorRecordSha256: current.recordSha256, key: original.key, v: 1 },
1791
+ { expectedPriorRecordSha256: current.recordSha256, key: original.key, v: 1 },
1792
+ ], v: 1 })).rejects.toThrow("replacement keys must be unique");
1793
+ await value.canonical.store.close(); await value.working.store.close();
1794
+ });
1795
+
1796
+ test("aborts adoption atomically with bounded, complete conflict evidence", async () => {
1797
+ const count = OH_MEMORY_AUTHORITY_LIMITS_V1.reportedAdoptionConflicts + 2;
1798
+ const canonicalRecords = Array.from({ length: count }, (_, index) =>
1799
+ entity(`entity:conflict-${index.toString().padStart(3, "0")}`, `Canonical ${index}`));
1800
+ const value = await authorityFixture({ canonicalRecords });
1801
+ const workingHead = await value.working.store.head();
1802
+ const puts = canonicalRecords.map((record, index) => ({ dependencies: [], key: record.key,
1803
+ kind: "entity" as const, v: 1 as const, value: { name: `Working ${index}` } }));
1804
+ puts.push({ dependencies: [], key: "entity:would-be-inserted", kind: "entity", v: 1,
1805
+ value: { name: "Absent" } });
1806
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1807
+ operationSha256: workingHead.operationSha256 }, puts,
1808
+ requestId: "remember_conflicts", tombstones: [], v: 1 });
1809
+ const roots = puts.map(({ key }) => key);
1810
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review", roots, v: 1 });
1811
+ let thrown: unknown;
1812
+ try {
1813
+ await value.authority.host.adoptNomination({
1814
+ expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 });
1815
+ } catch (error) { thrown = error; }
1816
+ expect(thrown).toBeInstanceOf(OhMemoryAdoptionConflictError);
1817
+ const conflict = (thrown as OhMemoryAdoptionConflictError).conflict;
1818
+ expect(conflict.totalConflicts).toBe(count);
1819
+ expect(conflict.reportedConflicts).toBe(OH_MEMORY_AUTHORITY_LIMITS_V1.reportedAdoptionConflicts);
1820
+ expect(conflict.truncated).toBe(true);
1821
+ expect(conflict.conflicts.map(({ key }) => key)).toEqual(canonicalRecords
1822
+ .slice(0, OH_MEMORY_AUTHORITY_LIMITS_V1.reportedAdoptionConflicts).map(({ key }) => key));
1823
+ const nominatedByKey = new Map(nomination.closure.records.map((record) => [record.key, record]));
1824
+ const complete = canonicalRecords.map((record) => ({
1825
+ canonicalRecordSha256: record.recordSha256,
1826
+ key: record.key,
1827
+ nominatedRecordSha256: nominatedByKey.get(record.key)!.recordSha256,
1828
+ v: 1 as const,
1829
+ }));
1830
+ expect(conflict.conflictsSha256).toBe(canonicalSha256({ conflicts: complete, v: 1 }));
1831
+ expect(Object.isFrozen(conflict.conflicts)).toBe(true);
1832
+ expect(Object.getOwnPropertyDescriptor(thrown, "conflict")?.writable).toBe(false);
1833
+ expect((await value.canonical.store.snapshot()).records
1834
+ .some(({ key }) => key === "entity:would-be-inserted")).toBe(false);
1835
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1836
+ await value.canonical.store.close(); await value.working.store.close();
1837
+ });
1838
+
1839
+ test("reconciles a duplicate adoption against the later physical head", async () => {
1840
+ const value = await authorityFixture();
1841
+ let returnPinnedHeadOnce = true;
1842
+ const laggingStore = new Proxy(value.canonical.store, {
1843
+ get(target, property) {
1844
+ const member = Reflect.get(target, property, target) as unknown;
1845
+ if (property === "head") {
1846
+ return async () => {
1847
+ if (returnPinnedHeadOnce) {
1848
+ returnPinnedHeadOnce = false;
1849
+ return value.initialCanonicalHead;
1850
+ }
1851
+ return await target.head();
1852
+ };
1853
+ }
1854
+ return typeof member === "function"
1855
+ ? (...args: unknown[]) => Reflect.apply(member, target, args)
1856
+ : member;
1857
+ },
1858
+ }) as OhStoreV1;
1859
+ const replaying = await createOhMemoryAuthorityV1({
1860
+ actorId: "test.memory-agent", adoptionActorId: "test.memory-reviewer",
1861
+ canonical: { authorityId: "authority.canonical",
1862
+ expectedBindingSha256: laggingStore.binding.bindingSha256,
1863
+ expectedHead: value.initialCanonicalHead, store: laggingStore },
1864
+ continuationKey: Uint8Array.from({ length: 32 }, (_, index) => index),
1865
+ nominationRoutes: [{ destinationPurpose: "kb.review", nominationId: "kb.review" }],
1866
+ programs: [stableVisibleProgram()],
1867
+ working: { authorityId: "authority.working", codecs: entityCodecs(),
1868
+ expectedBindingSha256: value.working.store.binding.bindingSha256,
1869
+ store: value.working.store },
1870
+ });
1871
+ const workingHead = await value.working.store.head();
1872
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1873
+ operationSha256: workingHead.operationSha256 },
1874
+ puts: [{ dependencies: [], key: "entity:replayed", kind: "entity", v: 1,
1875
+ value: { name: "Nominated" } }], requestId: "remember_replayed",
1876
+ tombstones: [], v: 1 });
1877
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1878
+ roots: ["entity:replayed"], v: 1 });
1879
+ const adopted = await value.authority.host.adoptNomination({
1880
+ expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 });
1881
+ const overwrittenRecord = entity("entity:replayed", "Overwritten");
1882
+ await value.canonical.store.commit({ actorId: "test.overwriter",
1883
+ changes: [{ kind: "put", record: overwrittenRecord, v: 1 }],
1884
+ expectedHead: adopted.head, operationId: "op_overwrite_adopted_memory" });
1885
+ const physicalHead = await value.canonical.store.head();
1886
+ let thrown: unknown;
1887
+ try {
1888
+ await replaying.host.adoptNomination({ expectedCanonicalHead: value.initialCanonicalHead,
1889
+ nomination, v: 1 });
1890
+ } catch (error) { thrown = error; }
1891
+ expect(thrown).toBeInstanceOf(OhMemoryAdoptionConflictError);
1892
+ expect((thrown as OhMemoryAdoptionConflictError).conflict.actualHead).toEqual(physicalHead);
1893
+ expect((thrown as OhMemoryAdoptionConflictError).conflict.conflicts[0]).toMatchObject({
1894
+ canonicalRecordSha256: overwrittenRecord.recordSha256,
1895
+ key: "entity:replayed",
1896
+ nominatedRecordSha256: nomination.closure.records[0]!.recordSha256,
1897
+ });
1898
+ const stillPinned = await replaying.agent.query({ bindings: {}, continuation: null,
1899
+ programId: "memory.visible-records", v: 2 });
1900
+ expect(stillPinned.identity.canonical.head).toEqual(value.initialCanonicalHead);
1901
+ expect(stillPinned.identity.canonical.head).not.toEqual(adopted.head);
1902
+ await value.canonical.store.close(); await value.working.store.close();
1903
+ });
1904
+
1905
+ test("rejects a nomination when the working authority cannot reproduce its exact bytes", async () => {
1906
+ const value = await authorityFixture();
1907
+ const workingHead = await value.working.store.head();
1908
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1909
+ operationSha256: workingHead.operationSha256 },
1910
+ puts: [{ dependencies: [], key: "entity:first", kind: "entity", v: 1,
1911
+ value: { name: "First" } }, { dependencies: [], key: "entity:second",
1912
+ kind: "entity", v: 1, value: { name: "Second" } }],
1913
+ requestId: "remember_reexport", tombstones: [], v: 1 });
1914
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1915
+ roots: ["entity:first"], v: 1 });
1916
+ const sourceHead = await value.working.store.head();
1917
+ const substitute = await value.working.store.exportDependencyClosure({ head: sourceHead,
1918
+ roots: ["entity:second"] });
1919
+ (value.working.store as unknown as { exportDependencyClosure: () => Promise<typeof substitute> })
1920
+ .exportDependencyClosure = async () => substitute;
1921
+ await expect(value.authority.host.adoptNomination({
1922
+ expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 }))
1923
+ .rejects.toThrow("did not re-export the nominated closure exactly");
1924
+ expect(await value.canonical.store.head()).toEqual(value.initialCanonicalHead);
1925
+ await value.canonical.store.close(); await value.working.store.close();
1926
+ });
1927
+
1928
+ test("performs one adoption CAS and reports a racing canonical write without retrying", async () => {
1929
+ const value = await authorityFixture();
1930
+ const workingHead = await value.working.store.head();
1931
+ await value.authority.agent.remember({ expectedHead: { generation: workingHead.generation,
1932
+ operationSha256: workingHead.operationSha256 },
1933
+ puts: [{ dependencies: [], key: "entity:raced-candidate", kind: "entity", v: 1,
1934
+ value: { name: "Candidate" } }], requestId: "remember_raced_candidate",
1935
+ tombstones: [], v: 1 });
1936
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1937
+ roots: ["entity:raced-candidate"], v: 1 });
1938
+ const originalCommit = value.canonical.store.commit.bind(value.canonical.store);
1939
+ let authorityCommitCalls = 0;
1940
+ value.canonical.store.commit = async (input) => {
1941
+ authorityCommitCalls += 1;
1942
+ await originalCommit({ actorId: "test.competing-writer",
1943
+ changes: [{ kind: "put", record: entity("entity:competing", "Competing"), v: 1 }],
1944
+ expectedHead: input.expectedHead, operationId: "op_competing_write" });
1945
+ return await originalCommit(input);
1946
+ };
1947
+ let thrown: unknown;
1948
+ try {
1949
+ await value.authority.host.adoptNomination({
1950
+ expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 });
1951
+ } catch (error) { thrown = error; }
1952
+ expect(authorityCommitCalls).toBe(1);
1953
+ expect(thrown).toBeInstanceOf(OhMemoryAdoptionConflictError);
1954
+ expect((thrown as OhMemoryAdoptionConflictError).conflict.conflicts).toEqual([{
1955
+ canonicalRecordSha256: null,
1956
+ key: "entity:raced-candidate",
1957
+ nominatedRecordSha256: nomination.closure.records[0]!.recordSha256,
1958
+ v: 1,
1959
+ }]);
1960
+ const snapshot = await value.canonical.store.snapshot();
1961
+ expect(snapshot.records.map(({ key }) => key)).toEqual(["entity:canonical", "entity:competing"]);
1962
+ await value.canonical.store.close(); await value.working.store.close();
1963
+ });
1964
+
1965
+ test("recovers an uncertain successful adoption exactly and rejects a later mismatch", async () => {
1966
+ let throwAfterCommit = true;
1967
+ let authorityCommitCalls = 0;
1968
+ const value = await authorityFixture({
1969
+ canonicalStore: (store) => new Proxy(store, {
1970
+ get(target, property) {
1971
+ const member = Reflect.get(target, property, target) as unknown;
1972
+ if (property === "commit") {
1973
+ return async (...args: unknown[]) => {
1974
+ authorityCommitCalls += 1;
1975
+ const operation = await Reflect.apply(member as (...values: unknown[]) => unknown,
1976
+ target, args);
1977
+ if (throwAfterCommit) {
1978
+ throwAfterCommit = false;
1979
+ throw new Error("simulated transport loss after canonical effect");
1980
+ }
1981
+ return operation;
1982
+ };
1983
+ }
1984
+ return typeof member === "function"
1985
+ ? (...args: unknown[]) => Reflect.apply(member, target, args)
1986
+ : member;
1987
+ },
1988
+ }) as OhStoreV1,
1989
+ });
1990
+ const workingHead = await value.working.store.head();
1991
+ await value.authority.agent.remember({ expectedHead: {
1992
+ generation: workingHead.generation,
1993
+ operationSha256: workingHead.operationSha256,
1994
+ }, puts: [{ dependencies: [], key: "entity:uncertain-adoption", kind: "entity", v: 1,
1995
+ value: { name: "Adopted despite lost response" } }], requestId: "remember_uncertain_adoption",
1996
+ tombstones: [], v: 1 });
1997
+ const nomination = await value.authority.agent.nominate({ nominationId: "kb.review",
1998
+ roots: ["entity:uncertain-adoption"], v: 1 });
1999
+ const request = { expectedCanonicalHead: value.initialCanonicalHead, nomination, v: 1 } as const;
2000
+
2001
+ await expect(value.authority.host.adoptNomination(request))
2002
+ .rejects.toThrow("simulated transport loss after canonical effect");
2003
+ expect(authorityCommitCalls).toBe(1);
2004
+ const effectedHead = await value.canonical.store.head();
2005
+ expect(effectedHead).not.toEqual(value.initialCanonicalHead);
2006
+ expect((await value.canonical.store.snapshot()).records
2007
+ .find(({ key }) => key === "entity:uncertain-adoption")?.recordSha256)
2008
+ .toBe(nomination.closure.records[0]?.recordSha256);
2009
+ const stillPinned = await value.authority.agent.query({ bindings: {}, continuation: null,
2010
+ programId: "memory.visible-records", v: 2 });
2011
+ expect(stillPinned.identity.canonical.head).toEqual(value.initialCanonicalHead);
2012
+
2013
+ const recovered = await value.authority.host.adoptNomination(request);
2014
+ expect(authorityCommitCalls).toBe(1);
2015
+ expect(recovered).toMatchObject({ head: effectedHead, operationSha256: null,
2016
+ priorHead: value.initialCanonicalHead, status: "already-present" });
2017
+ expect((await value.canonical.store.changesSince(value.initialCanonicalHead,
2018
+ { through: effectedHead })).operations).toHaveLength(1);
2019
+ const recoveredPage = await value.authority.agent.query({ bindings: {}, continuation: null,
2020
+ programId: "memory.visible-records", v: 2 });
2021
+ expect(recoveredPage.identity.canonical.head).toEqual(effectedHead);
2022
+
2023
+ const overwritten = entity("entity:uncertain-adoption", "Later conflicting value");
2024
+ await value.canonical.store.commit({ actorId: "test.later-writer",
2025
+ changes: [{ kind: "put", record: overwritten, v: 1 }], expectedHead: effectedHead,
2026
+ operationId: "op_later_uncertain_mismatch" });
2027
+ const mismatchedHead = await value.canonical.store.head();
2028
+ let thrown: unknown;
2029
+ try { await value.authority.host.adoptNomination(request); }
2030
+ catch (error) { thrown = error; }
2031
+ expect(authorityCommitCalls).toBe(1);
2032
+ expect(thrown).toBeInstanceOf(OhMemoryAdoptionConflictError);
2033
+ expect((thrown as OhMemoryAdoptionConflictError).conflict).toMatchObject({
2034
+ actualHead: mismatchedHead,
2035
+ conflicts: [{ canonicalRecordSha256: overwritten.recordSha256,
2036
+ key: "entity:uncertain-adoption",
2037
+ nominatedRecordSha256: nomination.closure.records[0]?.recordSha256, v: 1 }],
2038
+ expectedHead: value.initialCanonicalHead,
2039
+ });
2040
+ const pinnedAfterMismatch = await value.authority.agent.query({ bindings: {}, continuation: null,
2041
+ programId: "memory.visible-records", v: 2 });
2042
+ expect(pinnedAfterMismatch.identity.canonical.head).toEqual(effectedHead);
2043
+ expect(pinnedAfterMismatch.identity.canonical.head).not.toEqual(mismatchedHead);
2044
+ await value.canonical.store.close(); await value.working.store.close();
2045
+ });
2046
+
2047
+ test("captures the old canonical pin for in-flight queries and retains their explanations", async () => {
2048
+ let shouldBlock = false;
2049
+ let releaseSnapshot!: () => void;
2050
+ let enteredSnapshot!: () => void;
2051
+ const released = new Promise<void>((resolve) => { releaseSnapshot = resolve; });
2052
+ const entered = new Promise<void>((resolve) => { enteredSnapshot = resolve; });
2053
+ const wrapWorkingStore = (store: OhStoreV1): OhStoreV1 => new Proxy(store, {
2054
+ get(target, property) {
2055
+ const member = Reflect.get(target, property, target) as unknown;
2056
+ if (typeof member !== "function") return member;
2057
+ if (property !== "snapshot") {
2058
+ return (...args: unknown[]) => Reflect.apply(member, target, args);
2059
+ }
2060
+ return async (...args: unknown[]) => {
2061
+ if (shouldBlock) {
2062
+ shouldBlock = false;
2063
+ enteredSnapshot();
2064
+ await released;
2065
+ }
2066
+ return await Reflect.apply(member, target, args);
2067
+ };
2068
+ },
2069
+ }) as OhStoreV1;
2070
+ const value = await authorityFixture({ canonicalRecords: [
2071
+ entity("entity:first", "First"), entity("entity:second", "Second"),
2072
+ ], pageSize: 1, workingStore: wrapWorkingStore });
2073
+ shouldBlock = true;
2074
+ const pending = value.authority.agent.query({ bindings: {}, continuation: null,
2075
+ programId: "memory.visible-records", v: 2 });
2076
+ await entered;
2077
+ await value.canonical.store.commit({ actorId: "test.canonical-writer",
2078
+ changes: [{ kind: "put", record: entity("entity:third", "Third"), v: 1 }],
2079
+ expectedHead: value.initialCanonicalHead, operationId: "op_canonical_rollover" });
2080
+ const nextHead = await value.canonical.store.head();
2081
+ const advance = await value.authority.host.advanceCanonical({
2082
+ expectedHead: value.initialCanonicalHead, nextHead, v: 1 });
2083
+ expect(advance.status).toBe("advanced");
2084
+ releaseSnapshot();
2085
+ const oldPage = await pending;
2086
+ expect(oldPage.identity.canonical.head).toEqual(value.initialCanonicalHead);
2087
+ const explanation = await value.authority.agent.explain({ pageRow: 0,
2088
+ resultSha256: oldPage.resultSha256, token: oldPage.explainCapability.token, v: 2 });
2089
+ expect(explanation.resultSha256).toBe(oldPage.resultSha256);
2090
+ await expect(value.authority.agent.query({ bindings: {},
2091
+ continuation: oldPage.continuation, programId: "memory.visible-records", v: 2 }))
2092
+ .rejects.toThrow("does not match this exact source and projection identity");
2093
+ const newPage = await value.authority.agent.query({ bindings: {}, continuation: null,
2094
+ programId: "memory.visible-records", v: 2 });
2095
+ expect(newPage.identity.canonical.head).toEqual(nextHead);
2096
+ const unchanged = await value.authority.host.advanceCanonical({
2097
+ expectedHead: nextHead, nextHead, v: 1 });
2098
+ expect(unchanged.status).toBe("unchanged");
2099
+ await expect(value.authority.host.advanceCanonical({ expectedHead: value.initialCanonicalHead,
2100
+ nextHead, v: 1 })).rejects.toThrow(OhConflictError);
2101
+ await value.canonical.store.close(); await value.working.store.close();
2102
+ });
2103
+
2104
+ test("bounds and exactly validates canonical descendant proofs before rollover", async () => {
2105
+ const value = await authorityFixture();
2106
+ await value.canonical.store.commit({ actorId: "test.canonical-writer",
2107
+ changes: [{ kind: "put", record: entity("entity:next", "Next"), v: 1 }],
2108
+ expectedHead: value.initialCanonicalHead, operationId: "op_advance_validation" });
2109
+ const nextHead = await value.canonical.store.head();
2110
+ const originalChangesSince = value.canonical.store.changesSince.bind(value.canonical.store);
2111
+ let accessorReads = 0;
2112
+ value.canonical.store.changesSince = async (from, options) => {
2113
+ const page = await originalChangesSince(from, options);
2114
+ const hostile = { ...page } as Record<PropertyKey, unknown>;
2115
+ Object.defineProperty(hostile, "operations", { enumerable: true,
2116
+ get() { accessorReads += 1; throw new Error("must not execute"); } });
2117
+ return hostile as never;
2118
+ };
2119
+ await expect(value.authority.host.advanceCanonical({
2120
+ expectedHead: value.initialCanonicalHead, nextHead, v: 1 }))
2121
+ .rejects.toThrow("non-data property");
2122
+ expect(accessorReads).toBe(0);
2123
+
2124
+ value.canonical.store.changesSince = async (from) => ({
2125
+ from, hasMore: true, operations: [], through: nextHead, to: from, v: 1,
2126
+ });
2127
+ await expect(value.authority.host.advanceCanonical({
2128
+ expectedHead: value.initialCanonicalHead, nextHead, v: 1 }))
2129
+ .rejects.toThrow("did not prove the requested descendant");
2130
+
2131
+ value.canonical.store.changesSince = originalChangesSince;
2132
+ const wrongFullHead: OhHeadV1 = { ...nextHead,
2133
+ graphRevisionSha256: canonicalSha256({ kind: "test.wrong-full-head", v: 1 }) };
2134
+ await expect(value.authority.host.advanceCanonical({
2135
+ expectedHead: value.initialCanonicalHead, nextHead: wrongFullHead, v: 1 }))
2136
+ .rejects.toThrow("pinned bounds");
2137
+
2138
+ let feedCalls = 0;
2139
+ value.canonical.store.changesSince = async (...args) => {
2140
+ feedCalls += 1;
2141
+ return await originalChangesSince(...args);
2142
+ };
2143
+ const fork: OhHeadV1 = { ...value.initialCanonicalHead,
2144
+ operationSha256: canonicalSha256({ kind: "test.fork", v: 1 }) };
2145
+ await expect(value.authority.host.advanceCanonical({
2146
+ expectedHead: value.initialCanonicalHead, nextHead: fork, v: 1 }))
2147
+ .rejects.toThrow("not a descendant");
2148
+ const rollback: OhHeadV1 = { generation: 0, graphRevisionSha256: null,
2149
+ operationSha256: null, recordsSha256: canonicalSha256([]), sequence: 0, v: 1 };
2150
+ await expect(value.authority.host.advanceCanonical({
2151
+ expectedHead: value.initialCanonicalHead, nextHead: rollback, v: 1 }))
2152
+ .rejects.toThrow("not a descendant");
2153
+ const distantSequence = value.initialCanonicalHead.sequence
2154
+ + OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalAdvanceOperations + 1;
2155
+ const tooDistant: OhHeadV1 = { generation: distantSequence,
2156
+ graphRevisionSha256: canonicalSha256({ kind: "test.distant-graph", v: 1 }),
2157
+ operationSha256: canonicalSha256({ kind: "test.distant-operation", v: 1 }),
2158
+ recordsSha256: canonicalSha256({ kind: "test.distant-records", v: 1 }),
2159
+ sequence: distantSequence, v: 1 };
2160
+ await expect(value.authority.host.advanceCanonical({
2161
+ expectedHead: value.initialCanonicalHead, nextHead: tooDistant, v: 1 }))
2162
+ .rejects.toThrow("advance in host-reviewed chunks");
2163
+ expect(feedCalls).toBe(0);
2164
+ await value.canonical.store.close(); await value.working.store.close();
2165
+ });
2166
+
2167
+ test("shares explanation eviction and monotonic clock state across canonical generations", async () => {
2168
+ const value = await authorityFixture();
2169
+ const oldPages = [];
2170
+ for (let index = 0; index < OH_MEMORY_LIMITS_V1.explainCapabilities - 1; index += 1) {
2171
+ oldPages.push(await value.authority.agent.query({ bindings: {}, continuation: null,
2172
+ programId: "memory.visible-records", v: 2 }));
2173
+ }
2174
+ await value.canonical.store.commit({ actorId: "test.cache-writer",
2175
+ changes: [{ kind: "put", record: entity("entity:cache-next", "Cache next"), v: 1 }],
2176
+ expectedHead: value.initialCanonicalHead, operationId: "op_cache_rollover" });
2177
+ const nextHead = await value.canonical.store.head();
2178
+ await value.authority.host.advanceCanonical({ expectedHead: value.initialCanonicalHead,
2179
+ nextHead, v: 1 });
2180
+ await value.authority.agent.query({ bindings: {}, continuation: null,
2181
+ programId: "memory.visible-records", v: 2 });
2182
+ await value.authority.agent.query({ bindings: {}, continuation: null,
2183
+ programId: "memory.visible-records", v: 2 });
2184
+ const evicted = oldPages[0]!;
2185
+ await expect(value.authority.agent.explain({ pageRow: 0,
2186
+ resultSha256: evicted.resultSha256, token: evicted.explainCapability.token, v: 2 }))
2187
+ .rejects.toThrow("absent, expired, or misbound");
2188
+ const retained = oldPages[1]!;
2189
+ expect((await value.authority.agent.explain({ pageRow: 0,
2190
+ resultSha256: retained.resultSha256,
2191
+ token: retained.explainCapability.token, v: 2 })).resultSha256)
2192
+ .toBe(retained.resultSha256);
2193
+ await value.canonical.store.close(); await value.working.store.close();
2194
+
2195
+ let monotonic = 100;
2196
+ const clocked = await authorityFixture({ monotonicNow: () => monotonic,
2197
+ now: () => new Date("2026-08-29T12:00:00.000Z") });
2198
+ await clocked.authority.agent.query({ bindings: {}, continuation: null,
2199
+ programId: "memory.visible-records", v: 2 });
2200
+ await clocked.canonical.store.commit({ actorId: "test.clock-writer",
2201
+ changes: [{ kind: "put", record: entity("entity:clock-next", "Clock next"), v: 1 }],
2202
+ expectedHead: clocked.initialCanonicalHead, operationId: "op_clock_rollover" });
2203
+ const clockHead = await clocked.canonical.store.head();
2204
+ await clocked.authority.host.advanceCanonical({ expectedHead: clocked.initialCanonicalHead,
2205
+ nextHead: clockHead, v: 1 });
2206
+ monotonic = 50;
2207
+ await expect(clocked.authority.agent.query({ bindings: {}, continuation: null,
2208
+ programId: "memory.visible-records", v: 2 })).rejects.toThrow("monotonic clock regressed");
2209
+ await clocked.canonical.store.close(); await clocked.working.store.close();
2210
+ });
2211
+
2212
+ test("rejects record-count and byte-capacity adoption before the only CAS", async () => {
2213
+ const fullRecords = Array.from({ length: OH_MEMORY_LIMITS_V1.maximumRecordsPerLane },
2214
+ (_, index) => entity(`entity:capacity-${index.toString().padStart(4, "0")}`, "x"));
2215
+ const countBound = await capacityAuthority(fullRecords);
2216
+ const workingHead = await countBound.working.store.head();
2217
+ await countBound.authority.agent.remember({ expectedHead: {
2218
+ generation: workingHead.generation, operationSha256: workingHead.operationSha256 },
2219
+ puts: [{ dependencies: [], key: "entity:capacity-extra", kind: "entity", v: 1,
2220
+ value: { name: "Extra" } }], requestId: "remember_count_capacity",
2221
+ tombstones: [], v: 1 });
2222
+ const countNomination = await countBound.authority.agent.nominate({ nominationId: "kb.review",
2223
+ roots: ["entity:capacity-extra"], v: 1 });
2224
+ await expect(countBound.authority.host.adoptNomination({
2225
+ expectedCanonicalHead: countBound.snapshot.head, nomination: countNomination, v: 1 }))
2226
+ .rejects.toThrow("record snapshot bound");
2227
+ expect(countBound.commitCalls()).toBe(0);
2228
+ expect(await countBound.canonicalStore.head()).toEqual(countBound.snapshot.head);
2229
+ await countBound.canonical.store.close(); await countBound.working.store.close();
2230
+
2231
+ const largeName = "x".repeat(875_000);
2232
+ const byteRecords = Array.from({ length: 38 }, (_, index) =>
2233
+ entity(`entity:bytes-${index.toString().padStart(2, "0")}`, largeName));
2234
+ const byteBound = await capacityAuthority(byteRecords);
2235
+ expect(Buffer.byteLength(canonicalJson(byteBound.snapshot), "utf8"))
2236
+ .toBeLessThanOrEqual(OH_MEMORY_LIMITS_V1.snapshotBytesPerLane);
2237
+ const byteWorkingHead = await byteBound.working.store.head();
2238
+ await byteBound.authority.agent.remember({ expectedHead: {
2239
+ generation: byteWorkingHead.generation,
2240
+ operationSha256: byteWorkingHead.operationSha256 },
2241
+ puts: [{ dependencies: [], key: "entity:bytes-extra", kind: "entity", v: 1,
2242
+ value: { name: largeName } }], requestId: "remember_byte_capacity",
2243
+ tombstones: [], v: 1 });
2244
+ const byteNomination = await byteBound.authority.agent.nominate({ nominationId: "kb.review",
2245
+ roots: ["entity:bytes-extra"], v: 1 });
2246
+ await expect(byteBound.authority.host.adoptNomination({
2247
+ expectedCanonicalHead: byteBound.snapshot.head, nomination: byteNomination, v: 1 }))
2248
+ .rejects.toThrow("canonical snapshot byte bound");
2249
+ expect(byteBound.commitCalls()).toBe(0);
2250
+ expect(await byteBound.canonicalStore.head()).toEqual(byteBound.snapshot.head);
2251
+ await byteBound.canonical.store.close(); await byteBound.working.store.close();
2252
+ });
783
2253
  });