@hraness/oh 0.3.2 → 0.4.1

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
package/dist/memory.js CHANGED
@@ -190,7 +190,7 @@ var OH_GRAPH_LIMITS_V1 = Object.freeze({
190
190
  recordBytes: 1024 * 1024,
191
191
  recordsPerSnapshot: 65536
192
192
  });
193
- var OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1 = [
193
+ var OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1 = Object.freeze([
194
194
  "activity",
195
195
  "assertion",
196
196
  "context",
@@ -209,7 +209,7 @@ var OH_KNOWLEDGE_GRAPH_RECORD_KINDS_V1 = [
209
209
  "type-membership",
210
210
  "view",
211
211
  "vocabulary"
212
- ];
212
+ ]);
213
213
  var KNOWLEDGE_GRAPH_RECORD_KEYS_V1 = [
214
214
  "dependencies",
215
215
  "key",
@@ -422,6 +422,141 @@ class OhRecordCodecRegistry {
422
422
  return this.#sealed;
423
423
  }
424
424
  }
425
+ // src/errors.ts
426
+ var OH_OPERATION_SIZE_ERROR_CODE_V1 = "oh.operation-size.v1";
427
+ var OH_CONFLICT_ERROR_BRAND_V1 = Symbol.for("@hraness/oh/OhConflictError/v1");
428
+ var OH_DEPENDENCY_ERROR_BRAND_V1 = Symbol.for("@hraness/oh/OhDependencyError/v1");
429
+ var OH_INTEGRITY_ERROR_BRAND_V1 = Symbol.for("@hraness/oh/OhIntegrityError/v1");
430
+ var OH_OPERATION_SIZE_ERROR_BRAND_V1 = Symbol.for("@hraness/oh/OhOperationSizeError/v1");
431
+ var OH_PROFILE_ERROR_BRAND_V1 = Symbol.for("@hraness/oh/OhProfileError/v1");
432
+ function immutableOwnValue(value, key) {
433
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
434
+ return descriptor !== undefined && descriptor.get === undefined && descriptor.set === undefined && descriptor.configurable === false && descriptor.writable === false ? descriptor.value : undefined;
435
+ }
436
+ function brandNativeError(value, brand) {
437
+ Object.defineProperty(value, brand, {
438
+ configurable: false,
439
+ enumerable: false,
440
+ value: true,
441
+ writable: false
442
+ });
443
+ }
444
+ function hasNativeErrorBrand(value, brand) {
445
+ try {
446
+ return Error.isError(value) && immutableOwnValue(value, brand) === true;
447
+ } catch {
448
+ return false;
449
+ }
450
+ }
451
+ function hasNativeSubclassInstance(constructor, value) {
452
+ return Function.prototype[Symbol.hasInstance].call(constructor, value);
453
+ }
454
+ function isOhConflictError(value) {
455
+ return hasNativeErrorBrand(value, OH_CONFLICT_ERROR_BRAND_V1);
456
+ }
457
+
458
+ class OhConflictError extends Error {
459
+ static [Symbol.hasInstance](value) {
460
+ return this === OhConflictError ? isOhConflictError(value) : hasNativeSubclassInstance(this, value);
461
+ }
462
+ constructor(message) {
463
+ super(message);
464
+ this.name = "OhConflictError";
465
+ brandNativeError(this, OH_CONFLICT_ERROR_BRAND_V1);
466
+ }
467
+ }
468
+ function isOhIntegrityError(value) {
469
+ return hasNativeErrorBrand(value, OH_INTEGRITY_ERROR_BRAND_V1);
470
+ }
471
+
472
+ class OhIntegrityError extends Error {
473
+ static [Symbol.hasInstance](value) {
474
+ return this === OhIntegrityError ? isOhIntegrityError(value) : hasNativeSubclassInstance(this, value);
475
+ }
476
+ constructor(message) {
477
+ super(message);
478
+ this.name = "OhIntegrityError";
479
+ brandNativeError(this, OH_INTEGRITY_ERROR_BRAND_V1);
480
+ }
481
+ }
482
+ function isOhDependencyError(value) {
483
+ return hasNativeErrorBrand(value, OH_DEPENDENCY_ERROR_BRAND_V1);
484
+ }
485
+
486
+ class OhDependencyError extends Error {
487
+ static [Symbol.hasInstance](value) {
488
+ return this === OhDependencyError ? isOhDependencyError(value) : hasNativeSubclassInstance(this, value);
489
+ }
490
+ constructor(message) {
491
+ super(message);
492
+ this.name = "OhDependencyError";
493
+ brandNativeError(this, OH_DEPENDENCY_ERROR_BRAND_V1);
494
+ }
495
+ }
496
+ function isOhProfileError(value) {
497
+ return hasNativeErrorBrand(value, OH_PROFILE_ERROR_BRAND_V1);
498
+ }
499
+
500
+ class OhProfileError extends Error {
501
+ static [Symbol.hasInstance](value) {
502
+ return this === OhProfileError ? isOhProfileError(value) : hasNativeSubclassInstance(this, value);
503
+ }
504
+ constructor(message) {
505
+ super(message);
506
+ this.name = "OhProfileError";
507
+ brandNativeError(this, OH_PROFILE_ERROR_BRAND_V1);
508
+ }
509
+ }
510
+ function isOhOperationSizeError(value) {
511
+ try {
512
+ if (!Error.isError(value) || !(value instanceof RangeError))
513
+ return false;
514
+ const operationBytes = immutableOwnValue(value, "operationBytes");
515
+ const maximumOperationBytes = immutableOwnValue(value, "maximumOperationBytes");
516
+ return immutableOwnValue(value, OH_OPERATION_SIZE_ERROR_BRAND_V1) === true && immutableOwnValue(value, "code") === OH_OPERATION_SIZE_ERROR_CODE_V1 && Number.isSafeInteger(operationBytes) && operationBytes > 0 && Number.isSafeInteger(maximumOperationBytes) && maximumOperationBytes > 0 && operationBytes > maximumOperationBytes;
517
+ } catch {
518
+ return false;
519
+ }
520
+ }
521
+
522
+ class OhOperationSizeError extends RangeError {
523
+ static [Symbol.hasInstance](value) {
524
+ return this === OhOperationSizeError ? isOhOperationSizeError(value) : hasNativeSubclassInstance(this, value);
525
+ }
526
+ constructor(operationBytes, maximumOperationBytes) {
527
+ if (!Number.isSafeInteger(operationBytes) || operationBytes < 1 || !Number.isSafeInteger(maximumOperationBytes) || maximumOperationBytes < 1 || operationBytes <= maximumOperationBytes) {
528
+ throw new TypeError("Invalid Oh operation size refusal.");
529
+ }
530
+ super(`The ${operationBytes}-byte operation exceeds the host-declared ${maximumOperationBytes}-byte canonical bound.`);
531
+ this.name = "OhOperationSizeError";
532
+ Object.defineProperties(this, {
533
+ [OH_OPERATION_SIZE_ERROR_BRAND_V1]: {
534
+ configurable: false,
535
+ enumerable: false,
536
+ value: true,
537
+ writable: false
538
+ },
539
+ code: {
540
+ configurable: false,
541
+ enumerable: true,
542
+ value: OH_OPERATION_SIZE_ERROR_CODE_V1,
543
+ writable: false
544
+ },
545
+ maximumOperationBytes: {
546
+ configurable: false,
547
+ enumerable: true,
548
+ value: maximumOperationBytes,
549
+ writable: false
550
+ },
551
+ operationBytes: {
552
+ configurable: false,
553
+ enumerable: true,
554
+ value: operationBytes,
555
+ writable: false
556
+ }
557
+ });
558
+ }
559
+ }
425
560
  // src/operation.ts
426
561
  var OH_OPERATION_MAX_BYTES_V1 = 64 * 1024 * 1024;
427
562
  function parsePayload(value) {
@@ -469,13 +604,18 @@ function parsePayload(value) {
469
604
  v: 1
470
605
  } : null;
471
606
  }
472
- function createOhOperationV1(input) {
607
+ function createOhOperationV1(input, options = {}) {
608
+ const maximumOperationBytes = options.maximumOperationBytes ?? OH_OPERATION_MAX_BYTES_V1;
609
+ if (!Number.isSafeInteger(maximumOperationBytes) || maximumOperationBytes < 1 || maximumOperationBytes > OH_OPERATION_MAX_BYTES_V1) {
610
+ throw new TypeError("Invalid Oh operation byte bound.");
611
+ }
473
612
  const payload = parsePayload(input);
474
613
  if (payload === null)
475
614
  throw new TypeError("Invalid Oh operation payload.");
476
615
  const operation = { ...payload, operationSha256: canonicalSha256(payload) };
477
- if (Buffer.byteLength(canonicalJson(operation), "utf8") > OH_OPERATION_MAX_BYTES_V1) {
478
- throw new RangeError("Oh operation exceeds its canonical byte limit.");
616
+ const operationBytes = Buffer.byteLength(canonicalJson(operation), "utf8");
617
+ if (operationBytes > maximumOperationBytes) {
618
+ throw new OhOperationSizeError(operationBytes, maximumOperationBytes);
479
619
  }
480
620
  return operation;
481
621
  }
@@ -489,33 +629,6 @@ function parseOhOperationV1(value) {
489
629
  }
490
630
 
491
631
  // src/store.ts
492
- class OhConflictError extends Error {
493
- constructor(message) {
494
- super(message);
495
- this.name = "OhConflictError";
496
- }
497
- }
498
-
499
- class OhIntegrityError extends Error {
500
- constructor(message) {
501
- super(message);
502
- this.name = "OhIntegrityError";
503
- }
504
- }
505
-
506
- class OhDependencyError extends Error {
507
- constructor(message) {
508
- super(message);
509
- this.name = "OhDependencyError";
510
- }
511
- }
512
-
513
- class OhProfileError extends Error {
514
- constructor(message) {
515
- super(message);
516
- this.name = "OhProfileError";
517
- }
518
- }
519
632
  var OH_CANONICAL_STORE_PROFILE_V1 = createOhStoreProfileV1({
520
633
  applicationProfileSha256: null,
521
634
  capabilities: {
@@ -828,6 +941,8 @@ function transitionOhSnapshotV1(input) {
828
941
  sequence: head.sequence + 1,
829
942
  spaceId,
830
943
  v: 1
944
+ }, input.maximumOperationBytes === undefined ? {} : {
945
+ maximumOperationBytes: input.maximumOperationBytes
831
946
  });
832
947
  const nextHead = {
833
948
  generation: operation.sequence,
@@ -1057,6 +1172,7 @@ class OhSemanticBundleIngressV1 {
1057
1172
 
1058
1173
  // src/memory.ts
1059
1174
  import { createHmac, randomBytes as randomBytes2, timingSafeEqual } from "node:crypto";
1175
+ import { isProxy } from "node:util/types";
1060
1176
 
1061
1177
  // src/memory-pages.ts
1062
1178
  var OH_MEMORY_PAGE_FORMAT_V1 = "oh.memory-page.v1";
@@ -2706,6 +2822,9 @@ function isOhProjectionRecordKindV1(value) {
2706
2822
  var OH_MEMORY_FORMAT_VERSION_V1 = 1;
2707
2823
  var OH_MEMORY_CONFLICT_POLICY_V1 = "visible-conflicts.v1";
2708
2824
  var OH_MEMORY_LIMITS_V1 = Object.freeze({
2825
+ detachedCanonicalBreadth: 65536,
2826
+ detachedCanonicalDepth: 128,
2827
+ detachedCanonicalNodes: 1048576,
2709
2828
  explainCapabilityEntryBytes: 32 * 1024 * 1024,
2710
2829
  explainCapabilities: 256,
2711
2830
  explainCapabilityLifetimeMs: 15 * 60 * 1000,
@@ -2745,6 +2864,40 @@ var OH_MEMORY_QUERY_LIMITS_V2 = Object.freeze({
2745
2864
  minimumPageBytes: 64 * 1024,
2746
2865
  requestBytes: 80 * 1024
2747
2866
  });
2867
+
2868
+ class OhMemoryContinuationError extends OhIntegrityError {
2869
+ constructor(reason, message) {
2870
+ super(message);
2871
+ this.name = "OhMemoryContinuationError";
2872
+ Object.defineProperties(this, {
2873
+ code: { configurable: false, enumerable: true, value: "memory-continuation", writable: false },
2874
+ reason: { configurable: false, enumerable: true, value: reason, writable: false }
2875
+ });
2876
+ }
2877
+ }
2878
+ var OH_MEMORY_AUTHORITY_LIMITS_V1 = Object.freeze({
2879
+ adoptionReplacements: 128,
2880
+ adoptionRequestBytes: OH_DEPENDENCY_CLOSURE_LIMITS_V1.bytes + 192 * 1024,
2881
+ canonicalAdvanceOperations: 16384,
2882
+ canonicalAdvancePages: 64,
2883
+ canonicalChangeFeedPage: 1000,
2884
+ canonicalChangeFeedPageBytes: 64 * 1024 * 1024,
2885
+ retainedExplanationRoutes: OH_MEMORY_LIMITS_V1.explainCapabilities,
2886
+ reportedAdoptionConflicts: 128
2887
+ });
2888
+
2889
+ class OhMemoryAdoptionConflictError extends OhConflictError {
2890
+ constructor(conflict) {
2891
+ super("The nominated records conflict with the current canonical memory head.");
2892
+ this.name = "OhMemoryAdoptionConflictError";
2893
+ Object.defineProperty(this, "conflict", {
2894
+ configurable: false,
2895
+ enumerable: true,
2896
+ value: immutableClone(conflict),
2897
+ writable: false
2898
+ });
2899
+ }
2900
+ }
2748
2901
  var builtInFactPolicy = Object.freeze({
2749
2902
  extractorSha256: OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1.extractorSha256,
2750
2903
  factPackId: OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1.factPackId,
@@ -2771,6 +2924,149 @@ function immutableClone(value) {
2771
2924
  }
2772
2925
  return value;
2773
2926
  }
2927
+ function canonicalStringByteLength(value, label, path, maximumBytes) {
2928
+ let bytes = 2;
2929
+ for (let index = 0;index < value.length; index += 1) {
2930
+ const code = value.charCodeAt(index);
2931
+ if (code >= 55296 && code <= 56319) {
2932
+ const next = value.charCodeAt(index + 1);
2933
+ if (!(next >= 56320 && next <= 57343)) {
2934
+ throw new TypeError(`${label} contains invalid Unicode at ${path}.`);
2935
+ }
2936
+ bytes += 4;
2937
+ index += 1;
2938
+ } else if (code >= 56320 && code <= 57343) {
2939
+ throw new TypeError(`${label} contains invalid Unicode at ${path}.`);
2940
+ } else if (code === 34 || code === 92 || code === 8 || code === 9 || code === 10 || code === 12 || code === 13) {
2941
+ bytes += 2;
2942
+ } else if (code <= 31) {
2943
+ bytes += 6;
2944
+ } else if (code <= 127) {
2945
+ bytes += 1;
2946
+ } else if (code <= 2047) {
2947
+ bytes += 2;
2948
+ } else {
2949
+ bytes += 3;
2950
+ }
2951
+ if (bytes > maximumBytes) {
2952
+ throw new RangeError(`${label} exceeds its canonical byte bound.`);
2953
+ }
2954
+ }
2955
+ return bytes;
2956
+ }
2957
+ function detachCanonicalData(value, label, maximumBytes) {
2958
+ const ancestors = new Set;
2959
+ let bytes = 0;
2960
+ let nodes = 0;
2961
+ const spendBytes = (count) => {
2962
+ bytes += count;
2963
+ if (bytes > maximumBytes)
2964
+ throw new RangeError(`${label} exceeds its canonical byte bound.`);
2965
+ };
2966
+ const detach = (candidate, path, depth) => {
2967
+ if (depth > OH_MEMORY_LIMITS_V1.detachedCanonicalDepth) {
2968
+ throw new RangeError(`${label} exceeds its canonical nesting depth bound.`);
2969
+ }
2970
+ nodes += 1;
2971
+ if (nodes > OH_MEMORY_LIMITS_V1.detachedCanonicalNodes) {
2972
+ throw new RangeError(`${label} exceeds its canonical node bound.`);
2973
+ }
2974
+ if (candidate === null) {
2975
+ spendBytes(4);
2976
+ return candidate;
2977
+ }
2978
+ if (typeof candidate === "boolean") {
2979
+ spendBytes(candidate ? 4 : 5);
2980
+ return candidate;
2981
+ }
2982
+ if (typeof candidate === "string") {
2983
+ spendBytes(canonicalStringByteLength(candidate, label, path, maximumBytes - bytes));
2984
+ return candidate;
2985
+ }
2986
+ if (typeof candidate === "number") {
2987
+ if (!Number.isFinite(candidate) || Object.is(candidate, -0)) {
2988
+ throw new TypeError(`${label} contains a noncanonical number at ${path}.`);
2989
+ }
2990
+ spendBytes(utf8ByteLength(canonicalJson(candidate)));
2991
+ return candidate;
2992
+ }
2993
+ if (typeof candidate !== "object") {
2994
+ throw new TypeError(`${label} contains a non-JSON value at ${path}.`);
2995
+ }
2996
+ if (isProxy(candidate))
2997
+ throw new TypeError(`${label} contains a proxy at ${path}.`);
2998
+ if (ancestors.has(candidate))
2999
+ throw new TypeError(`${label} contains a cycle at ${path}.`);
3000
+ ancestors.add(candidate);
3001
+ try {
3002
+ if (Array.isArray(candidate)) {
3003
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(candidate, "length");
3004
+ const length = lengthDescriptor?.value;
3005
+ if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0) {
3006
+ throw new TypeError(`${label} contains an invalid array at ${path}.`);
3007
+ }
3008
+ if (length > OH_MEMORY_LIMITS_V1.detachedCanonicalBreadth) {
3009
+ throw new RangeError(`${label} exceeds its canonical breadth bound.`);
3010
+ }
3011
+ if (length > OH_MEMORY_LIMITS_V1.detachedCanonicalNodes - nodes) {
3012
+ throw new RangeError(`${label} exceeds its canonical node bound.`);
3013
+ }
3014
+ spendBytes(2 + Math.max(0, length - 1));
3015
+ const keys2 = Reflect.ownKeys(candidate);
3016
+ if (keys2.length !== length + 1 || !keys2.includes("length") || keys2.some((key) => key !== "length" && (typeof key !== "string" || !/^(?:0|[1-9][0-9]*)$/u.test(key) || Number(key) >= length))) {
3017
+ throw new TypeError(`${label} contains a non-data array at ${path}.`);
3018
+ }
3019
+ const detached3 = [];
3020
+ for (let index = 0;index < length; index += 1) {
3021
+ const descriptor = Object.getOwnPropertyDescriptor(candidate, String(index));
3022
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined) {
3023
+ throw new TypeError(`${label} contains a non-data array entry at ${path}[${index}].`);
3024
+ }
3025
+ detached3.push(detach(descriptor.value, `${path}[${index}]`, depth + 1));
3026
+ }
3027
+ return Object.freeze(detached3);
3028
+ }
3029
+ const prototype = Object.getPrototypeOf(candidate);
3030
+ if (prototype !== Object.prototype && prototype !== null) {
3031
+ throw new TypeError(`${label} contains a non-plain object at ${path}.`);
3032
+ }
3033
+ const keys = Reflect.ownKeys(candidate);
3034
+ if (keys.some((key) => typeof key !== "string")) {
3035
+ throw new TypeError(`${label} contains a symbol property at ${path}.`);
3036
+ }
3037
+ if (keys.length > OH_MEMORY_LIMITS_V1.detachedCanonicalBreadth) {
3038
+ throw new RangeError(`${label} exceeds its canonical breadth bound.`);
3039
+ }
3040
+ if (keys.length > OH_MEMORY_LIMITS_V1.detachedCanonicalNodes - nodes) {
3041
+ throw new RangeError(`${label} exceeds its canonical node bound.`);
3042
+ }
3043
+ spendBytes(2 + Math.max(0, keys.length - 1));
3044
+ const detached2 = {};
3045
+ for (const key of keys) {
3046
+ spendBytes(canonicalStringByteLength(key, label, `${path}.<key>`, maximumBytes - bytes - 1) + 1);
3047
+ const descriptor = Object.getOwnPropertyDescriptor(candidate, key);
3048
+ if (descriptor === undefined || !descriptor.enumerable || descriptor.get !== undefined || descriptor.set !== undefined) {
3049
+ throw new TypeError(`${label} contains a non-data property at ${path}.${key}.`);
3050
+ }
3051
+ Object.defineProperty(detached2, key, {
3052
+ configurable: false,
3053
+ enumerable: true,
3054
+ value: detach(descriptor.value, `${path}.${key}`, depth + 1),
3055
+ writable: false
3056
+ });
3057
+ }
3058
+ return Object.freeze(detached2);
3059
+ } finally {
3060
+ ancestors.delete(candidate);
3061
+ }
3062
+ };
3063
+ const detached = detach(value, "$root", 0);
3064
+ const canonical = canonicalJson(detached);
3065
+ if (utf8ByteLength(canonical) !== bytes) {
3066
+ throw new OhIntegrityError(`${label} canonical byte accounting did not reproduce its snapshot.`);
3067
+ }
3068
+ return Object.freeze({ canonical, value: detached });
3069
+ }
2774
3070
  function compareText(left, right) {
2775
3071
  return left < right ? -1 : left > right ? 1 : 0;
2776
3072
  }
@@ -2804,8 +3100,43 @@ function laneIdentity(value) {
2804
3100
  v: 1
2805
3101
  });
2806
3102
  }
2807
- function datasetForSnapshot(binding, snapshot) {
2808
- const projectionSnapshot = createOhProjectionSnapshotV1({
3103
+ function parseDetachedStoreHead(value, label) {
3104
+ const head = parseOhHeadV1(detachCanonicalData(value, `${label} head`, 4 * 1024).value);
3105
+ if (head === null)
3106
+ throw new OhIntegrityError(`${label} returned an invalid head.`);
3107
+ return immutableClone(head);
3108
+ }
3109
+ function parseDetachedStoreSnapshot(value, label, expectedHead, spaceId) {
3110
+ const detachedSnapshot = detachCanonicalData(value, `${label} snapshot`, OH_MEMORY_LIMITS_V1.snapshotBytesPerLane);
3111
+ if (!isPlainRecord(detachedSnapshot.value) || !hasExactKeys(detachedSnapshot.value, ["head", "records", "v"]) || detachedSnapshot.value.v !== 1 || !Array.isArray(detachedSnapshot.value.records)) {
3112
+ throw new OhIntegrityError(`${label} returned an invalid snapshot envelope.`);
3113
+ }
3114
+ const detached = detachedSnapshot.value;
3115
+ const detachedHead = parseOhHeadV1(detached.head);
3116
+ if (detachedHead === null)
3117
+ throw new OhIntegrityError(`${label} returned an invalid snapshot head.`);
3118
+ const snapshot = immutableClone({
3119
+ head: detachedHead,
3120
+ records: detached.records,
3121
+ v: 1
3122
+ });
3123
+ if (!exactHead(snapshot.head, expectedHead)) {
3124
+ throw new OhIntegrityError(`${label} snapshot differs from its pinned head.`);
3125
+ }
3126
+ let projectionSnapshot;
3127
+ try {
3128
+ projectionSnapshot = createOhProjectionSnapshotV1({
3129
+ head: snapshot.head,
3130
+ records: snapshot.records,
3131
+ spaceId
3132
+ });
3133
+ } catch {
3134
+ throw new OhIntegrityError(`${label} returned invalid snapshot records.`);
3135
+ }
3136
+ return Object.freeze({ projectionSnapshot, snapshot });
3137
+ }
3138
+ function datasetForSnapshot(binding, snapshot, validatedProjectionSnapshot) {
3139
+ const projectionSnapshot = validatedProjectionSnapshot ?? createOhProjectionSnapshotV1({
2809
3140
  head: snapshot.head,
2810
3141
  records: snapshot.records,
2811
3142
  spaceId: binding.spaceId
@@ -2820,40 +3151,21 @@ function datasetForSnapshot(binding, snapshot) {
2820
3151
  return { dataset, projectionSnapshot };
2821
3152
  }
2822
3153
  async function readLane(authority, lane, expectedHead) {
2823
- const returnedHead = expectedHead ?? await authority.store.head();
2824
- const head = parseOhHeadV1(immutableClone(returnedHead));
2825
- if (head === null)
2826
- throw new OhIntegrityError(`The ${lane} store returned an invalid head.`);
3154
+ const label = `The ${lane} store`;
3155
+ const head = expectedHead === undefined ? parseDetachedStoreHead(await authority.store.head(), label) : immutableClone(expectedHead);
2827
3156
  const returnedSnapshot = await authority.store.snapshot({
2828
3157
  head: { operationSha256: head.operationSha256, sequence: head.sequence },
2829
3158
  maximumRecords: OH_MEMORY_LIMITS_V1.maximumRecordsPerLane
2830
3159
  });
2831
- if (!isPlainRecord(returnedSnapshot) || !hasExactKeys(returnedSnapshot, ["head", "records", "v"]) || returnedSnapshot.v !== 1 || !Array.isArray(returnedSnapshot.records)) {
2832
- throw new OhIntegrityError(`The ${lane} store returned an invalid snapshot envelope.`);
2833
- }
2834
- const detached = immutableClone(returnedSnapshot);
2835
- const detachedHead = parseOhHeadV1(detached.head);
2836
- if (detachedHead === null)
2837
- throw new OhIntegrityError(`The ${lane} store returned an invalid snapshot head.`);
2838
- const snapshot = immutableClone({
2839
- head: detachedHead,
2840
- records: detached.records,
2841
- v: 1
2842
- });
2843
- if (!exactHead(snapshot.head, head)) {
2844
- throw new OhIntegrityError(`The ${lane} snapshot differs from its pinned head.`);
2845
- }
2846
- if (utf8ByteLength(canonicalJson(snapshot)) > OH_MEMORY_LIMITS_V1.snapshotBytesPerLane) {
2847
- throw new RangeError(`The ${lane} memory snapshot exceeds its canonical byte bound.`);
2848
- }
2849
- const projected = datasetForSnapshot(authority.binding, snapshot);
3160
+ const parsed = parseDetachedStoreSnapshot(returnedSnapshot, label, head, authority.binding.spaceId);
3161
+ const projected = datasetForSnapshot(authority.binding, parsed.snapshot, parsed.projectionSnapshot);
2850
3162
  return Object.freeze({
2851
3163
  authorityId: authority.authorityId,
2852
3164
  binding: authority.binding,
2853
3165
  dataset: projected.dataset,
2854
3166
  lane,
2855
3167
  projectionSnapshot: projected.projectionSnapshot,
2856
- snapshot
3168
+ snapshot: parsed.snapshot
2857
3169
  });
2858
3170
  }
2859
3171
  function syntheticKey(lane, recordSha256) {
@@ -3167,32 +3479,93 @@ function resolveNominationRoutes(routes) {
3167
3479
  return resolved;
3168
3480
  }
3169
3481
  function parseQueryRequest(value) {
3170
- if (!isPlainRecord(value) || !hasExactKeys(value, ["programId", "v"]) || value.v !== 1)
3482
+ const detached = detachCanonicalData(value, "The named memory query", OH_MEMORY_QUERY_LIMITS_V2.requestBytes).value;
3483
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["programId", "v"]) || detached.v !== 1)
3171
3484
  throw new TypeError("Invalid named memory query.");
3172
- const programId = safeCode(value.programId, 128);
3485
+ const programId = safeCode(detached.programId, 128);
3173
3486
  if (programId === null)
3174
3487
  throw new TypeError("Invalid named memory query identity.");
3175
3488
  return { programId };
3176
3489
  }
3177
3490
  function parseExplainRequest(value) {
3178
- if (!isPlainRecord(value) || !hasExactKeys(value, ["resultSha256", "row", "token", "v"]) || value.v !== 1 || typeof value.token !== "string" || value.token.length !== 43 || !Number.isSafeInteger(value.row) || value.row < 0) {
3491
+ const detached = detachCanonicalData(value, "The memory explanation request", OH_MEMORY_QUERY_LIMITS_V2.requestBytes).value;
3492
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["resultSha256", "row", "token", "v"]) || detached.v !== 1 || typeof detached.token !== "string" || detached.token.length !== 43 || !Number.isSafeInteger(detached.row) || detached.row < 0) {
3179
3493
  throw new TypeError("Invalid memory explanation request.");
3180
3494
  }
3181
- const resultSha256 = parseSha256Hex(value.resultSha256);
3495
+ const resultSha256 = parseSha256Hex(detached.resultSha256);
3182
3496
  if (resultSha256 === null)
3183
3497
  throw new TypeError("Invalid memory explanation result identity.");
3184
- return { resultSha256, row: value.row, token: value.token };
3498
+ return { resultSha256, row: detached.row, token: detached.token };
3185
3499
  }
3186
3500
  function parseNominationRequest(value) {
3187
- if (!isPlainRecord(value) || !hasExactKeys(value, ["nominationId", "roots", "v"]) || value.v !== 1 || !Array.isArray(value.roots) || value.roots.length < 1 || value.roots.length > OH_DEPENDENCY_CLOSURE_LIMITS_V1.roots) {
3501
+ const detached = detachCanonicalData(value, "The memory nomination request", OH_MEMORY_QUERY_LIMITS_V2.requestBytes * 8).value;
3502
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["nominationId", "roots", "v"]) || detached.v !== 1 || !Array.isArray(detached.roots) || detached.roots.length < 1 || detached.roots.length > OH_DEPENDENCY_CLOSURE_LIMITS_V1.roots) {
3188
3503
  throw new TypeError("Invalid memory nomination request.");
3189
3504
  }
3190
- const nominationId = safeCode(value.nominationId, 128);
3191
- const roots = value.roots.map((root) => safeCode(root, 512)).sort();
3505
+ const nominationId = safeCode(detached.nominationId, 128);
3506
+ const roots = detached.roots.map((root) => safeCode(root, 512)).sort();
3192
3507
  if (nominationId === null || roots.some((root) => root === null) || new Set(roots).size !== roots.length)
3193
3508
  throw new TypeError("Invalid memory nomination identity.");
3194
3509
  return { nominationId, roots };
3195
3510
  }
3511
+ function parseDetachedMemoryNominationV1(value) {
3512
+ try {
3513
+ const keys = ownDataKeysV2(value, 7, "The memory nomination");
3514
+ if (keys.length !== 7 || ![
3515
+ "closure",
3516
+ "destinationPurpose",
3517
+ "nominationId",
3518
+ "nominationSha256",
3519
+ "source",
3520
+ "status",
3521
+ "v"
3522
+ ].every((key) => keys.includes(key)))
3523
+ return null;
3524
+ const record = value;
3525
+ if (record.status !== "prepared" || record.v !== 1)
3526
+ return null;
3527
+ const closure = parseOhDependencyClosureV1(record.closure);
3528
+ const destinationPurpose = safeCode(record.destinationPurpose, 256);
3529
+ const nominationId = safeCode(record.nominationId, 128);
3530
+ const nominationSha256 = parseSha256Hex(record.nominationSha256);
3531
+ if (closure === null || destinationPurpose === null || nominationId === null || nominationSha256 === null || closure.binding.profile.profileKind !== "working" || [...ownDataKeysV2(record.source, 5, "The memory nomination source")].sort().join("\x00") !== ["authorityId", "bindingSha256", "head", "lane", "v"].sort().join("\x00"))
3532
+ return null;
3533
+ const sourceRecord = record.source;
3534
+ if (sourceRecord.lane !== "working" || sourceRecord.v !== 1)
3535
+ return null;
3536
+ const authorityIdValue = safeCode(sourceRecord.authorityId, 128);
3537
+ const bindingSha256 = parseSha256Hex(sourceRecord.bindingSha256);
3538
+ const head = parseOhHeadV1(sourceRecord.head);
3539
+ if (authorityIdValue === null || bindingSha256 === null || head === null || bindingSha256 !== closure.binding.bindingSha256 || !exactHead(head, closure.head))
3540
+ return null;
3541
+ const source = {
3542
+ authorityId: authorityIdValue,
3543
+ bindingSha256,
3544
+ head,
3545
+ lane: "working",
3546
+ v: 1
3547
+ };
3548
+ const payload = {
3549
+ closure,
3550
+ destinationPurpose,
3551
+ nominationId,
3552
+ source,
3553
+ status: "prepared",
3554
+ v: 1
3555
+ };
3556
+ return canonicalSha256(payload) === nominationSha256 ? immutableClone({ ...payload, nominationSha256 }) : null;
3557
+ } catch {
3558
+ return null;
3559
+ }
3560
+ }
3561
+ function parseOhMemoryNominationV1(value) {
3562
+ try {
3563
+ const detached = detachCanonicalData(value, "The memory nomination", OH_MEMORY_AUTHORITY_LIMITS_V1.adoptionRequestBytes);
3564
+ return parseDetachedMemoryNominationV1(detached.value);
3565
+ } catch {
3566
+ return null;
3567
+ }
3568
+ }
3196
3569
  function isoInstant(date) {
3197
3570
  const value = date.toISOString();
3198
3571
  if (parseCanonicalInstantV1(value) === null)
@@ -3226,13 +3599,11 @@ async function createOhMemoryAgentV1(options) {
3226
3599
  }
3227
3600
  const canonicalBinding = bindingFor(canonicalStore, options.canonical.expectedBindingSha256, "canonical");
3228
3601
  const workingBinding = bindingFor(workingStore, options.working.expectedBindingSha256, "working");
3229
- const expectedCanonicalHead = parseOhHeadV1(options.canonical.expectedHead);
3230
- if (expectedCanonicalHead === null)
3231
- throw new TypeError("Invalid pinned canonical memory head.");
3602
+ const expectedCanonicalHead = parseMemoryAuthorityHead(options.canonical.expectedHead, "pinned canonical");
3232
3603
  const programs = resolvePrograms(options.programs);
3233
3604
  const extractors = resolveExtractors(options.extractors ?? []);
3234
3605
  const nominationRoutes = resolveNominationRoutes(options.nominationRoutes ?? []);
3235
- const ingress = new OhSemanticBundleIngressV1(workingStore, workingCodecs);
3606
+ const ingress = new OhSemanticBundleIngressV1(capacityGuardedWorkingStore(workingStore, workingBinding), workingCodecs);
3236
3607
  const now = options.now ?? (() => new Date);
3237
3608
  const monotonicNow = options.monotonicNow ?? (() => performance.now());
3238
3609
  const capabilityLifetime = options.explainCapabilityLifetimeMs ?? OH_MEMORY_LIMITS_V1.explainCapabilityLifetimeMs;
@@ -3268,13 +3639,11 @@ async function createOhMemoryAgentV1(options) {
3268
3639
  explanationBytes -= stored.bytes;
3269
3640
  };
3270
3641
  const remember = async (value) => {
3271
- if (utf8ByteLength(canonicalJson(value)) > OH_MEMORY_LIMITS_V1.rememberBytes) {
3272
- throw new RangeError("The memory semantic bundle exceeds its canonical byte bound.");
3273
- }
3274
- if (!isPlainRecord(value) || !hasExactKeys(value, ["expectedHead", "puts", "requestId", "tombstones", "v"]) || value.v !== 1) {
3642
+ const detached = detachCanonicalData(value, "The memory semantic bundle", OH_MEMORY_LIMITS_V1.rememberBytes).value;
3643
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["expectedHead", "puts", "requestId", "tombstones", "v"]) || detached.v !== 1) {
3275
3644
  throw new TypeError("Invalid memory remember request.");
3276
3645
  }
3277
- const requestId = safeCode(value.requestId, 128);
3646
+ const requestId = safeCode(detached.requestId, 128);
3278
3647
  if (requestId === null)
3279
3648
  throw new TypeError("Invalid memory remember request identity.");
3280
3649
  const operationId = `memory_${canonicalSha256({
@@ -3283,15 +3652,19 @@ async function createOhMemoryAgentV1(options) {
3283
3652
  requestId,
3284
3653
  v: 1
3285
3654
  }).slice(0, 48)}`;
3286
- const operation = await ingress.commit({
3655
+ const returnedOperation = await ingress.commit({
3287
3656
  actorId: memoryActorId,
3288
- expectedHead: value.expectedHead,
3657
+ expectedHead: detached.expectedHead,
3289
3658
  instant: isoInstant(new Date(wallClock())),
3290
3659
  operationId,
3291
- puts: value.puts,
3292
- tombstones: value.tombstones,
3660
+ puts: detached.puts,
3661
+ tombstones: detached.tombstones,
3293
3662
  v: 1
3294
3663
  });
3664
+ const operation = parseOhOperationV1(detachCanonicalData(returnedOperation, "The returned working memory operation", OH_MEMORY_LIMITS_V1.rememberBytes * 2).value);
3665
+ if (operation === null || operation.actorId !== memoryActorId || operation.operationId !== operationId || operation.spaceId !== workingBinding.spaceId) {
3666
+ throw new OhIntegrityError("The working authority returned a different memory operation.");
3667
+ }
3295
3668
  const head = {
3296
3669
  generation: operation.sequence,
3297
3670
  graphRevisionSha256: operation.graphRevisionSha256,
@@ -3428,13 +3801,14 @@ async function createOhMemoryAgentV1(options) {
3428
3801
  const route = nominationRoutes.get(request.nominationId);
3429
3802
  if (route === undefined)
3430
3803
  throw new TypeError("Unknown named memory nomination route.");
3431
- const head = parseOhHeadV1(immutableClone(await workingStore.head()));
3804
+ const head = parseOhHeadV1(detachCanonicalData(await workingStore.head(), "The working nomination store head", 4 * 1024).value);
3432
3805
  if (head === null)
3433
3806
  throw new OhIntegrityError("The working nomination store returned an invalid head.");
3434
- const closure = await workingStore.exportDependencyClosure({ head: {
3807
+ const returnedClosure = await workingStore.exportDependencyClosure({ head: {
3435
3808
  operationSha256: head.operationSha256,
3436
3809
  sequence: head.sequence
3437
3810
  }, roots: request.roots });
3811
+ const closure = detachCanonicalData(returnedClosure, "The working nomination closure", OH_DEPENDENCY_CLOSURE_LIMITS_V1.bytes).value;
3438
3812
  const verified = verifyOhDependencyClosureAgainstV1(closure, { binding: workingBinding, head });
3439
3813
  if (!verified.ok)
3440
3814
  throw new OhIntegrityError("The working nomination closure failed exact verification.");
@@ -3460,6 +3834,21 @@ async function createOhMemoryAgentV1(options) {
3460
3834
  };
3461
3835
  return Object.freeze({ explain, nominate, query, remember });
3462
3836
  }
3837
+ function createOhMemoryRuntimeV2(options) {
3838
+ const capabilityLifetime = options.explainCapabilityLifetimeMs ?? OH_MEMORY_LIMITS_V1.explainCapabilityLifetimeMs;
3839
+ if (!Number.isSafeInteger(capabilityLifetime) || capabilityLifetime < 1000 || capabilityLifetime > 60 * 60 * 1000) {
3840
+ throw new RangeError("Invalid memory explanation capability lifetime.");
3841
+ }
3842
+ return {
3843
+ capabilityLifetime,
3844
+ explanationBytes: 0,
3845
+ explanations: new Map,
3846
+ lastMonotonicMs: -1,
3847
+ lastWallClockMs: Number.NEGATIVE_INFINITY,
3848
+ monotonicNow: options.monotonicNow ?? (() => performance.now()),
3849
+ now: options.now ?? (() => new Date)
3850
+ };
3851
+ }
3463
3852
  function ownDataKeysV2(value, maximum, label) {
3464
3853
  if (!isPlainRecord(value))
3465
3854
  throw new TypeError(`${label} must be a plain data object.`);
@@ -3599,25 +3988,48 @@ function parsePrimitiveBindingV2(value) {
3599
3988
  return value;
3600
3989
  }
3601
3990
  function parseQueryRequestV2(value) {
3991
+ let detached;
3992
+ let detachedCanonical = "";
3602
3993
  let keys;
3603
3994
  try {
3604
- keys = ownDataKeysV2(value, 4, "The parameterized memory query");
3605
- } catch {
3995
+ const detachedData = detachCanonicalData(value, "The parameterized memory query", OH_MEMORY_QUERY_LIMITS_V2.requestBytes);
3996
+ detached = detachedData.value;
3997
+ detachedCanonical = detachedData.canonical;
3998
+ } catch (error) {
3999
+ if (error instanceof RangeError)
4000
+ throw error;
4001
+ if (error instanceof Error && error.message.includes("$root.bindings")) {
4002
+ throw new TypeError("Memory bindings must be JSON primitives.");
4003
+ }
4004
+ throw new TypeError("Invalid parameterized memory query.");
4005
+ }
4006
+ try {
4007
+ keys = ownDataKeysV2(detached, 4, "The parameterized memory query");
4008
+ } catch (error) {
4009
+ if (error instanceof Error && error.message.includes("$root.bindings")) {
4010
+ throw new TypeError("Memory bindings must be JSON primitives.");
4011
+ }
3606
4012
  throw new TypeError("Invalid parameterized memory query.");
3607
4013
  }
3608
4014
  if (keys.length !== 4 || !["bindings", "continuation", "programId", "v"].every((key) => keys.includes(key))) {
3609
4015
  throw new TypeError("Invalid parameterized memory query.");
3610
4016
  }
3611
- const record = value;
3612
- if (record.v !== 2 || record.continuation !== null && typeof record.continuation !== "string") {
4017
+ if (utf8ByteLength(detachedCanonical) > OH_MEMORY_QUERY_LIMITS_V2.requestBytes) {
4018
+ throw new RangeError("The parameterized memory query exceeds its canonical byte bound.");
4019
+ }
4020
+ const record = detached;
4021
+ if (record.v !== 2) {
3613
4022
  throw new TypeError("Invalid parameterized memory query.");
3614
4023
  }
4024
+ if (record.continuation !== null && typeof record.continuation !== "string") {
4025
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation encoding.");
4026
+ }
3615
4027
  const programId = safeCode(record.programId, 128);
3616
4028
  if (programId === null)
3617
4029
  throw new TypeError("Invalid parameterized memory query identity.");
3618
4030
  const continuation = record.continuation;
3619
4031
  if (typeof continuation === "string" && (continuation.length < 1 || continuation.length > OH_MEMORY_QUERY_LIMITS_V2.continuationBytes || utf8ByteLength(continuation) > OH_MEMORY_QUERY_LIMITS_V2.continuationBytes)) {
3620
- throw new RangeError("The memory continuation exceeds its byte bound.");
4032
+ throw new OhMemoryContinuationError("encoding", "The memory continuation exceeds its byte bound.");
3621
4033
  }
3622
4034
  const bindingKeys = ownDataKeysV2(record.bindings, OH_MEMORY_QUERY_LIMITS_V2.bindings, "The parameterized memory query bindings");
3623
4035
  const bindingRecord = record.bindings;
@@ -3696,18 +4108,19 @@ function encodeContinuationV2(value, key) {
3696
4108
  return Object.freeze({ continuation, continuationSha256 });
3697
4109
  }
3698
4110
  function parseContinuationV2(value, key) {
3699
- if (value.length < 1 || utf8ByteLength(value) > OH_MEMORY_QUERY_LIMITS_V2.continuationBytes || !/^[A-Za-z0-9_-]+$/u.test(value))
3700
- throw new TypeError("Invalid memory continuation encoding.");
4111
+ if (value.length < 1 || utf8ByteLength(value) > OH_MEMORY_QUERY_LIMITS_V2.continuationBytes || !/^[A-Za-z0-9_-]+$/u.test(value)) {
4112
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation encoding.");
4113
+ }
3701
4114
  const bytes = Buffer.from(value, "base64url");
3702
4115
  if (bytes.toString("base64url") !== value || bytes.byteLength > OH_MEMORY_QUERY_LIMITS_V2.continuationBytes) {
3703
- throw new TypeError("Invalid memory continuation encoding.");
4116
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation encoding.");
3704
4117
  }
3705
4118
  const text = bytes.toString("utf8");
3706
4119
  let decoded;
3707
4120
  try {
3708
4121
  decoded = JSON.parse(text);
3709
4122
  } catch {
3710
- throw new TypeError("Invalid memory continuation JSON.");
4123
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation JSON.");
3711
4124
  }
3712
4125
  if (!isPlainRecord(decoded) || !hasExactKeys(decoded, [
3713
4126
  "bindingsSha256",
@@ -3720,8 +4133,9 @@ function parseContinuationV2(value, key) {
3720
4133
  "projectionResultSha256",
3721
4134
  "totalRows",
3722
4135
  "v"
3723
- ]) || decoded.v !== 2)
3724
- throw new TypeError("Invalid memory continuation payload.");
4136
+ ]) || decoded.v !== 2) {
4137
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation payload.");
4138
+ }
3725
4139
  const bindingsSha256 = parseSha256Hex(decoded.bindingsSha256);
3726
4140
  const continuationHmacSha256 = parseSha256Hex(decoded.continuationHmacSha256);
3727
4141
  const continuationSha256 = parseSha256Hex(decoded.continuationSha256);
@@ -3729,7 +4143,7 @@ function parseContinuationV2(value, key) {
3729
4143
  const programSha256 = parseSha256Hex(decoded.programSha256);
3730
4144
  const projectionResultSha256 = parseSha256Hex(decoded.projectionResultSha256);
3731
4145
  if (bindingsSha256 === null || continuationHmacSha256 === null || continuationSha256 === null || memorySha256 === null || programSha256 === null || projectionResultSha256 === null || !Number.isSafeInteger(decoded.nextOffset) || decoded.nextOffset < 1 || decoded.nextOffset > OH_MEMORY_QUERY_LIMITS_V2.maximumProgramRows || !Number.isSafeInteger(decoded.pageSize) || decoded.pageSize < 1 || decoded.pageSize > OH_MEMORY_QUERY_LIMITS_V2.maximumPageRows || !Number.isSafeInteger(decoded.totalRows) || decoded.totalRows < 1 || decoded.totalRows > OH_MEMORY_QUERY_LIMITS_V2.maximumProgramRows || decoded.nextOffset >= decoded.totalRows || decoded.nextOffset % decoded.pageSize !== 0) {
3732
- throw new TypeError("Invalid memory continuation identity.");
4146
+ throw new OhMemoryContinuationError("identity", "Invalid memory continuation identity.");
3733
4147
  }
3734
4148
  const identity = {
3735
4149
  bindingsSha256,
@@ -3743,28 +4157,30 @@ function parseContinuationV2(value, key) {
3743
4157
  };
3744
4158
  const signed = { ...identity, continuationSha256 };
3745
4159
  const envelope = { ...signed, continuationHmacSha256 };
3746
- if (canonicalJson(envelope) !== text)
3747
- throw new TypeError("Invalid memory continuation payload.");
4160
+ if (canonicalJson(envelope) !== text) {
4161
+ throw new OhMemoryContinuationError("encoding", "Invalid memory continuation payload.");
4162
+ }
3748
4163
  const expectedHmac = continuationHmacV2(key, signed);
3749
4164
  const receivedHmac = Buffer.from(continuationHmacSha256, "hex");
3750
4165
  if (!timingSafeEqual(expectedHmac, receivedHmac)) {
3751
- throw new OhIntegrityError("The memory continuation is not an issued capability.");
4166
+ throw new OhMemoryContinuationError("authentication", "The memory continuation is not an issued capability.");
3752
4167
  }
3753
4168
  if (canonicalSha256(identity) !== continuationSha256) {
3754
- throw new OhIntegrityError("The memory continuation digest is invalid.");
4169
+ throw new OhMemoryContinuationError("identity", "The memory continuation digest is invalid.");
3755
4170
  }
3756
4171
  return Object.freeze(signed);
3757
4172
  }
3758
4173
  function parseExplainRequestV2(value) {
3759
- if (!isPlainRecord(value) || !hasExactKeys(value, ["pageRow", "resultSha256", "token", "v"]) || value.v !== 2 || typeof value.token !== "string" || value.token.length !== 43 || !Number.isSafeInteger(value.pageRow) || value.pageRow < 0) {
4174
+ const detached = detachCanonicalData(value, "The V2 memory explanation request", OH_MEMORY_QUERY_LIMITS_V2.requestBytes).value;
4175
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["pageRow", "resultSha256", "token", "v"]) || detached.v !== 2 || typeof detached.token !== "string" || detached.token.length !== 43 || !Number.isSafeInteger(detached.pageRow) || detached.pageRow < 0) {
3760
4176
  throw new TypeError("Invalid V2 memory explanation request.");
3761
4177
  }
3762
- const resultSha256 = parseSha256Hex(value.resultSha256);
4178
+ const resultSha256 = parseSha256Hex(detached.resultSha256);
3763
4179
  if (resultSha256 === null)
3764
4180
  throw new TypeError("Invalid V2 memory explanation result identity.");
3765
- return { pageRow: value.pageRow, resultSha256, token: value.token };
4181
+ return { pageRow: detached.pageRow, resultSha256, token: detached.token };
3766
4182
  }
3767
- async function createOhMemoryAgentV2(options) {
4183
+ async function createOhMemoryAgentV2WithRuntime(options, sharedRuntime) {
3768
4184
  const memoryActorId = safeCode(options.actorId, 128);
3769
4185
  if (memoryActorId === null)
3770
4186
  throw new TypeError("Invalid host-bound memory actor ID.");
@@ -3779,55 +4195,45 @@ async function createOhMemoryAgentV2(options) {
3779
4195
  }
3780
4196
  const canonicalBinding = bindingFor(canonicalStore, options.canonical.expectedBindingSha256, "canonical");
3781
4197
  const workingBinding = bindingFor(workingStore, options.working.expectedBindingSha256, "working");
3782
- const expectedCanonicalHead = parseOhHeadV1(options.canonical.expectedHead);
3783
- if (expectedCanonicalHead === null)
3784
- throw new TypeError("Invalid pinned canonical memory head.");
4198
+ const expectedCanonicalHead = parseMemoryAuthorityHead(options.canonical.expectedHead, "pinned canonical");
3785
4199
  const programs = resolveProgramsV2(options.programs);
3786
4200
  const extractors = resolveExtractors(options.extractors ?? []);
3787
4201
  const nominationRoutes = resolveNominationRoutes(options.nominationRoutes ?? []);
3788
- const ingress = new OhSemanticBundleIngressV1(workingStore, workingCodecs);
3789
- const now = options.now ?? (() => new Date);
3790
- const monotonicNow = options.monotonicNow ?? (() => performance.now());
3791
- const capabilityLifetime = options.explainCapabilityLifetimeMs ?? OH_MEMORY_LIMITS_V1.explainCapabilityLifetimeMs;
3792
- if (!Number.isSafeInteger(capabilityLifetime) || capabilityLifetime < 1000 || capabilityLifetime > 60 * 60 * 1000) {
3793
- throw new RangeError("Invalid memory explanation capability lifetime.");
3794
- }
4202
+ const ingress = new OhSemanticBundleIngressV1(capacityGuardedWorkingStore(workingStore, workingBinding), workingCodecs);
4203
+ const runtime = sharedRuntime ?? createOhMemoryRuntimeV2(options);
3795
4204
  const canonical = await readLane({
3796
4205
  authorityId: canonicalAuthorityId,
3797
4206
  binding: canonicalBinding,
3798
4207
  store: canonicalStore
3799
4208
  }, "canonical", expectedCanonicalHead);
3800
- const explanations = new Map;
3801
- let explanationBytes = 0;
3802
- let lastMonotonicMs = -1;
3803
- let lastWallClockMs = Number.NEGATIVE_INFINITY;
3804
4209
  const wallClock = () => {
3805
- const milliseconds = clockMilliseconds(now);
3806
- if (milliseconds < lastWallClockMs)
4210
+ const milliseconds = clockMilliseconds(runtime.now);
4211
+ if (milliseconds < runtime.lastWallClockMs) {
3807
4212
  throw new OhProfileError("The memory wall clock regressed.");
3808
- lastWallClockMs = milliseconds;
4213
+ }
4214
+ runtime.lastWallClockMs = milliseconds;
3809
4215
  return milliseconds;
3810
4216
  };
3811
4217
  const monotonicClock = () => {
3812
- const milliseconds = monotonicMilliseconds(monotonicNow);
3813
- if (milliseconds < lastMonotonicMs)
4218
+ const milliseconds = monotonicMilliseconds(runtime.monotonicNow);
4219
+ if (milliseconds < runtime.lastMonotonicMs) {
3814
4220
  throw new OhProfileError("The memory monotonic clock regressed.");
3815
- lastMonotonicMs = milliseconds;
4221
+ }
4222
+ runtime.lastMonotonicMs = milliseconds;
3816
4223
  return milliseconds;
3817
4224
  };
3818
4225
  const deleteExplanation = (token) => {
3819
- const stored = explanations.get(token);
3820
- if (stored !== undefined && explanations.delete(token))
3821
- explanationBytes -= stored.bytes;
4226
+ const stored = runtime.explanations.get(token);
4227
+ if (stored !== undefined && runtime.explanations.delete(token)) {
4228
+ runtime.explanationBytes -= stored.bytes;
4229
+ }
3822
4230
  };
3823
4231
  const remember = async (value) => {
3824
- if (utf8ByteLength(canonicalJson(value)) > OH_MEMORY_LIMITS_V1.rememberBytes) {
3825
- throw new RangeError("The memory semantic bundle exceeds its canonical byte bound.");
3826
- }
3827
- if (!isPlainRecord(value) || !hasExactKeys(value, ["expectedHead", "puts", "requestId", "tombstones", "v"]) || value.v !== 1) {
4232
+ const detached = detachCanonicalData(value, "The memory semantic bundle", OH_MEMORY_LIMITS_V1.rememberBytes).value;
4233
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["expectedHead", "puts", "requestId", "tombstones", "v"]) || detached.v !== 1) {
3828
4234
  throw new TypeError("Invalid memory remember request.");
3829
4235
  }
3830
- const requestId = safeCode(value.requestId, 128);
4236
+ const requestId = safeCode(detached.requestId, 128);
3831
4237
  if (requestId === null)
3832
4238
  throw new TypeError("Invalid memory remember request identity.");
3833
4239
  const operationId = `memory_${canonicalSha256({
@@ -3836,15 +4242,19 @@ async function createOhMemoryAgentV2(options) {
3836
4242
  requestId,
3837
4243
  v: 1
3838
4244
  }).slice(0, 48)}`;
3839
- const operation = await ingress.commit({
4245
+ const returnedOperation = await ingress.commit({
3840
4246
  actorId: memoryActorId,
3841
- expectedHead: value.expectedHead,
4247
+ expectedHead: detached.expectedHead,
3842
4248
  instant: isoInstant(new Date(wallClock())),
3843
4249
  operationId,
3844
- puts: value.puts,
3845
- tombstones: value.tombstones,
4250
+ puts: detached.puts,
4251
+ tombstones: detached.tombstones,
3846
4252
  v: 1
3847
4253
  });
4254
+ const operation = parseOhOperationV1(detachCanonicalData(returnedOperation, "The returned working memory operation", OH_MEMORY_LIMITS_V1.rememberBytes * 2).value);
4255
+ if (operation === null || operation.actorId !== memoryActorId || operation.operationId !== operationId || operation.spaceId !== workingBinding.spaceId) {
4256
+ throw new OhIntegrityError("The working authority returned a different memory operation.");
4257
+ }
3848
4258
  const head = {
3849
4259
  generation: operation.sequence,
3850
4260
  graphRevisionSha256: operation.graphRevisionSha256,
@@ -3875,7 +4285,7 @@ async function createOhMemoryAgentV2(options) {
3875
4285
  const bound = parseBindingsV2(request.bindingsValue, program.parameters);
3876
4286
  const requestedContinuation = request.continuation === null ? null : parseContinuationV2(request.continuation, continuationKey);
3877
4287
  if (requestedContinuation !== null && (requestedContinuation.bindingsSha256 !== bound.bindingsSha256 || requestedContinuation.pageSize !== program.pageSize || requestedContinuation.programSha256 !== program.programSha256 || requestedContinuation.totalRows > program.maximumRows || requestedContinuation.nextOffset >= requestedContinuation.totalRows || requestedContinuation.nextOffset % program.pageSize !== 0)) {
3878
- throw new OhIntegrityError("The memory continuation does not match this exact program, binding, and page identity.");
4288
+ throw new OhMemoryContinuationError("identity", "The memory continuation does not match this exact program, binding, and page identity.");
3879
4289
  }
3880
4290
  const boundQuery = bindQueryV2(program.query, bound.bindings);
3881
4291
  const working = await readLane({
@@ -3920,10 +4330,10 @@ async function createOhMemoryAgentV2(options) {
3920
4330
  memorySha256: canonicalSha256(identityPayload)
3921
4331
  });
3922
4332
  if (requestedContinuation !== null && (requestedContinuation.memorySha256 !== identity.memorySha256 || requestedContinuation.projectionResultSha256 !== projection.resultSha256)) {
3923
- throw new OhIntegrityError("The memory continuation does not match this exact source and projection identity.");
4333
+ throw new OhMemoryContinuationError("identity", "The memory continuation does not match this exact source and projection identity.");
3924
4334
  }
3925
4335
  if (requestedContinuation !== null && (requestedContinuation.totalRows !== projection.rows.length || requestedContinuation.nextOffset >= projection.rows.length || requestedContinuation.nextOffset % program.pageSize !== 0)) {
3926
- throw new OhIntegrityError("The memory continuation does not match this exact row identity.");
4336
+ throw new OhMemoryContinuationError("identity", "The memory continuation does not match this exact row identity.");
3927
4337
  }
3928
4338
  const start = requestedContinuation?.nextOffset ?? 0;
3929
4339
  const endExclusive = Math.min(start + program.pageSize, projection.rows.length);
@@ -3974,8 +4384,8 @@ async function createOhMemoryAgentV2(options) {
3974
4384
  const resultPayload = immutableClone({ ...resultIdentityPayload, continuation });
3975
4385
  const issuedAt = wallClock();
3976
4386
  const issuedAtMonotonic = monotonicClock();
3977
- const expiresAtMs = issuedAt + capabilityLifetime;
3978
- const expiresAtMonotonicMs = issuedAtMonotonic + capabilityLifetime;
4387
+ const expiresAtMs = issuedAt + runtime.capabilityLifetime;
4388
+ const expiresAtMonotonicMs = issuedAtMonotonic + runtime.capabilityLifetime;
3979
4389
  const expiresAt = isoInstant(new Date(expiresAtMs));
3980
4390
  const pageBytePreflight = {
3981
4391
  ...resultPayload,
@@ -3985,7 +4395,7 @@ async function createOhMemoryAgentV2(options) {
3985
4395
  if (utf8ByteLength(canonicalJson(pageBytePreflight)) > program.maximumPageBytes) {
3986
4396
  throw new RangeError("The V2 memory page exceeds its host-declared canonical byte bound.");
3987
4397
  }
3988
- for (const [existingToken, stored] of explanations) {
4398
+ for (const [existingToken, stored] of runtime.explanations) {
3989
4399
  if (issuedAtMonotonic >= stored.expiresAtMonotonicMs)
3990
4400
  deleteExplanation(existingToken);
3991
4401
  }
@@ -4001,17 +4411,17 @@ async function createOhMemoryAgentV2(options) {
4001
4411
  if (storedBytes > OH_MEMORY_LIMITS_V1.explainCapabilityEntryBytes || storedBytes > OH_MEMORY_LIMITS_V1.explainCapabilityTotalBytes) {
4002
4412
  throw new RangeError("The V2 memory explanation exceeds its retained capability bound.");
4003
4413
  }
4004
- while (explanations.size >= OH_MEMORY_LIMITS_V1.explainCapabilities || explanationBytes + storedBytes > OH_MEMORY_LIMITS_V1.explainCapabilityTotalBytes) {
4005
- const oldest = explanations.keys().next().value;
4414
+ while (runtime.explanations.size >= OH_MEMORY_LIMITS_V1.explainCapabilities || runtime.explanationBytes + storedBytes > OH_MEMORY_LIMITS_V1.explainCapabilityTotalBytes) {
4415
+ const oldest = runtime.explanations.keys().next().value;
4006
4416
  if (oldest === undefined)
4007
4417
  break;
4008
4418
  deleteExplanation(oldest);
4009
4419
  }
4010
4420
  let token = randomBytes2(32).toString("base64url");
4011
- while (explanations.has(token))
4421
+ while (runtime.explanations.has(token))
4012
4422
  token = randomBytes2(32).toString("base64url");
4013
- explanations.set(token, immutableClone({ ...storedPayload, bytes: storedBytes }));
4014
- explanationBytes += storedBytes;
4423
+ runtime.explanations.set(token, immutableClone({ ...storedPayload, bytes: storedBytes }));
4424
+ runtime.explanationBytes += storedBytes;
4015
4425
  const result = immutableClone({
4016
4426
  ...resultPayload,
4017
4427
  explainCapability: { expiresAt, token, v: 2 },
@@ -4025,7 +4435,7 @@ async function createOhMemoryAgentV2(options) {
4025
4435
  };
4026
4436
  const explain = async (value) => {
4027
4437
  const request = parseExplainRequestV2(value);
4028
- const stored = explanations.get(request.token);
4438
+ const stored = runtime.explanations.get(request.token);
4029
4439
  const currentTime = monotonicClock();
4030
4440
  if (stored === undefined || stored.resultSha256 !== request.resultSha256 || currentTime >= stored.expiresAtMonotonicMs) {
4031
4441
  deleteExplanation(request.token);
@@ -4057,13 +4467,14 @@ async function createOhMemoryAgentV2(options) {
4057
4467
  const route = nominationRoutes.get(request.nominationId);
4058
4468
  if (route === undefined)
4059
4469
  throw new TypeError("Unknown named memory nomination route.");
4060
- const head = parseOhHeadV1(immutableClone(await workingStore.head()));
4470
+ const head = parseOhHeadV1(detachCanonicalData(await workingStore.head(), "The working nomination store head", 4 * 1024).value);
4061
4471
  if (head === null)
4062
4472
  throw new OhIntegrityError("The working nomination store returned an invalid head.");
4063
- const closure = await workingStore.exportDependencyClosure({ head: {
4473
+ const returnedClosure = await workingStore.exportDependencyClosure({ head: {
4064
4474
  operationSha256: head.operationSha256,
4065
4475
  sequence: head.sequence
4066
4476
  }, roots: request.roots });
4477
+ const closure = detachCanonicalData(returnedClosure, "The working nomination closure", OH_DEPENDENCY_CLOSURE_LIMITS_V1.bytes).value;
4067
4478
  const verified = verifyOhDependencyClosureAgainstV1(closure, { binding: workingBinding, head });
4068
4479
  if (!verified.ok)
4069
4480
  throw new OhIntegrityError("The working nomination closure failed exact verification.");
@@ -4089,15 +4500,561 @@ async function createOhMemoryAgentV2(options) {
4089
4500
  };
4090
4501
  return Object.freeze({ explain, nominate, query, remember });
4091
4502
  }
4503
+ async function createOhMemoryAgentV2(options) {
4504
+ return await createOhMemoryAgentV2WithRuntime(options);
4505
+ }
4506
+ function parseDetachedMemoryAuthorityHead(value, label) {
4507
+ const head = parseOhHeadV1(value);
4508
+ if (head === null)
4509
+ throw new TypeError(`Invalid ${label} memory head.`);
4510
+ return immutableClone(head);
4511
+ }
4512
+ function parseMemoryAuthorityHead(value, label) {
4513
+ return parseDetachedMemoryAuthorityHead(detachCanonicalData(value, `The ${label} memory head`, 4 * 1024).value, label);
4514
+ }
4515
+ function parseCanonicalAdvanceRequest(value) {
4516
+ const detached = detachCanonicalData(value, "The canonical memory advance request", OH_MEMORY_QUERY_LIMITS_V2.requestBytes).value;
4517
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["expectedHead", "nextHead", "v"]) || detached.v !== 1)
4518
+ throw new TypeError("Invalid canonical memory advance request.");
4519
+ return Object.freeze({
4520
+ expectedHead: parseDetachedMemoryAuthorityHead(detached.expectedHead, "expected canonical"),
4521
+ nextHead: parseDetachedMemoryAuthorityHead(detached.nextHead, "next canonical")
4522
+ });
4523
+ }
4524
+ function parseAdoptionRequest(value) {
4525
+ const detached = detachCanonicalData(value, "The memory adoption request", OH_MEMORY_AUTHORITY_LIMITS_V1.adoptionRequestBytes).value;
4526
+ if (!isPlainRecord(detached) || !hasExactKeys(detached, ["expectedCanonicalHead", "nomination", "v"]) && !hasExactKeys(detached, ["expectedCanonicalHead", "nomination", "replacements", "v"]) || detached.v !== 1)
4527
+ throw new TypeError("Invalid memory adoption request.");
4528
+ const nomination = parseDetachedMemoryNominationV1(detached.nomination);
4529
+ if (nomination === null)
4530
+ throw new TypeError("Invalid memory adoption nomination.");
4531
+ const replacementValues = "replacements" in detached ? detached.replacements : [];
4532
+ if (!Array.isArray(replacementValues) || replacementValues.length > OH_MEMORY_AUTHORITY_LIMITS_V1.adoptionReplacements) {
4533
+ throw new TypeError("Invalid memory adoption replacements.");
4534
+ }
4535
+ const nominatedByKey = new Map(nomination.closure.records.map((record) => [record.key, record]));
4536
+ const replacements = replacementValues.map((replacement) => {
4537
+ if (!isPlainRecord(replacement) || !hasExactKeys(replacement, ["expectedPriorRecordSha256", "key", "v"]) || replacement.v !== 1)
4538
+ throw new TypeError("Invalid memory adoption replacement.");
4539
+ const key = safeCode(replacement.key, 512);
4540
+ const expectedPriorRecordSha256 = parseSha256Hex(replacement.expectedPriorRecordSha256);
4541
+ const nominated = key === null ? undefined : nominatedByKey.get(key);
4542
+ if (key === null || expectedPriorRecordSha256 === null || nominated === undefined) {
4543
+ throw new TypeError("Invalid memory adoption replacement.");
4544
+ }
4545
+ return { expectedPriorRecordSha256, key, v: 1 };
4546
+ }).sort((left, right) => compareText(left.key, right.key));
4547
+ if (!orderedUnique(replacements, (replacement) => replacement.key)) {
4548
+ throw new TypeError("Memory adoption replacement keys must be unique.");
4549
+ }
4550
+ return Object.freeze({
4551
+ expectedCanonicalHead: parseDetachedMemoryAuthorityHead(detached.expectedCanonicalHead, "expected canonical adoption"),
4552
+ nomination,
4553
+ replacements: immutableClone(replacements)
4554
+ });
4555
+ }
4556
+ function headRef(head) {
4557
+ return Object.freeze({ operationSha256: head.operationSha256, sequence: head.sequence });
4558
+ }
4559
+ async function proveCanonicalDescendant(authority, priorHead, nextHead, requiredFirstHead) {
4560
+ if (nextHead.sequence <= priorHead.sequence) {
4561
+ throw new OhConflictError("The next canonical memory head is not a descendant of the current pin.");
4562
+ }
4563
+ const distance = nextHead.sequence - priorHead.sequence;
4564
+ if (distance > OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalAdvanceOperations || Math.ceil(distance / OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalChangeFeedPage) > OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalAdvancePages) {
4565
+ throw new RangeError("The canonical memory advance exceeds its total proof bound; advance in host-reviewed chunks.");
4566
+ }
4567
+ const through = headRef(nextHead);
4568
+ let cursor = headRef(priorHead);
4569
+ let pageCount = 0;
4570
+ let reachedHead = null;
4571
+ let firstHead = null;
4572
+ while (cursor.sequence < through.sequence) {
4573
+ if (pageCount >= OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalAdvancePages) {
4574
+ throw new RangeError("The canonical memory advance exceeded its page proof bound; advance in host-reviewed chunks.");
4575
+ }
4576
+ pageCount += 1;
4577
+ const remaining = through.sequence - cursor.sequence;
4578
+ const limit = Math.min(remaining, OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalChangeFeedPage);
4579
+ const returnedData = detachCanonicalData(await authority.store.changesSince(cursor, { limit, through }), "The canonical change-feed page", OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalChangeFeedPageBytes).value;
4580
+ const returned = returnedData;
4581
+ if (!isPlainRecord(returned) || !hasExactKeys(returned, ["from", "hasMore", "operations", "through", "to", "v"]) || returned.v !== 1 || typeof returned.hasMore !== "boolean" || !Array.isArray(returned.operations) || returned.operations.length > limit) {
4582
+ throw new OhIntegrityError("The canonical change feed returned an invalid page envelope.");
4583
+ }
4584
+ const from = parseOhHeadRefV1(returned.from);
4585
+ const returnedThrough = parseOhHeadV1(returned.through);
4586
+ const returnedTo = parseOhHeadRefV1(returned.to);
4587
+ if (from === null || returnedThrough === null || returnedTo === null || canonicalJson(from) !== canonicalJson(cursor) || !exactHead(returnedThrough, nextHead)) {
4588
+ throw new OhIntegrityError("The canonical change feed changed its pinned bounds.");
4589
+ }
4590
+ let reached = cursor;
4591
+ for (const value of returned.operations) {
4592
+ const operation = parseOhOperationV1(value);
4593
+ if (operation === null || operation.spaceId !== authority.binding.spaceId || operation.sequence !== reached.sequence + 1 || operation.parentOperationSha256 !== reached.operationSha256) {
4594
+ throw new OhIntegrityError("The canonical change feed contains a gap or different authority.");
4595
+ }
4596
+ reached = Object.freeze({
4597
+ operationSha256: operation.operationSha256,
4598
+ sequence: operation.sequence
4599
+ });
4600
+ reachedHead = immutableClone({
4601
+ generation: operation.sequence,
4602
+ graphRevisionSha256: operation.graphRevisionSha256,
4603
+ operationSha256: operation.operationSha256,
4604
+ recordsSha256: operation.recordsSha256,
4605
+ sequence: operation.sequence,
4606
+ v: 1
4607
+ });
4608
+ firstHead ??= reachedHead;
4609
+ }
4610
+ if (canonicalJson(reached) !== canonicalJson(returnedTo) || returned.hasMore && returned.operations.length === 0 || returned.hasMore && reached.sequence >= through.sequence || reached.sequence > through.sequence || !returned.hasMore && canonicalJson(reached) !== canonicalJson(through)) {
4611
+ throw new OhIntegrityError("The canonical change feed did not prove the requested descendant.");
4612
+ }
4613
+ cursor = reached;
4614
+ }
4615
+ if (reachedHead === null || !exactHead(reachedHead, nextHead)) {
4616
+ throw new OhIntegrityError("The canonical change feed did not prove the requested full head.");
4617
+ }
4618
+ if (requiredFirstHead !== undefined && (firstHead === null || !exactHead(firstHead, requiredFirstHead))) {
4619
+ throw new OhIntegrityError("The returned adoption operation is not on the current canonical path.");
4620
+ }
4621
+ return await readLane(authority, "canonical", nextHead);
4622
+ }
4623
+ function canonicalAdvanceReceipt(authorityIdValue, bindingSha256, priorHead, head, status) {
4624
+ const payload = {
4625
+ authorityId: authorityIdValue,
4626
+ bindingSha256,
4627
+ head,
4628
+ priorHead,
4629
+ status,
4630
+ v: 1
4631
+ };
4632
+ return immutableClone({ ...payload, receiptSha256: canonicalSha256(payload) });
4633
+ }
4634
+ function adoptionReceipt(actorId, authorityIdValue, bindingSha256, nominationSha256, operationSha256, priorHead, head, status) {
4635
+ const payload = {
4636
+ actorId,
4637
+ authorityId: authorityIdValue,
4638
+ bindingSha256,
4639
+ head,
4640
+ nominationSha256,
4641
+ operationSha256,
4642
+ priorHead,
4643
+ status,
4644
+ v: 1
4645
+ };
4646
+ return immutableClone({ ...payload, receiptSha256: canonicalSha256(payload) });
4647
+ }
4648
+ function adoptionDifferences(snapshot, records) {
4649
+ const canonicalByKey = new Map(snapshot.records.map((record) => [record.key, record]));
4650
+ return immutableClone(records.flatMap((record) => {
4651
+ const canonicalRecord = canonicalByKey.get(record.key);
4652
+ return canonicalRecord?.recordSha256 === record.recordSha256 ? [] : [{
4653
+ canonicalRecordSha256: canonicalRecord?.recordSha256 ?? null,
4654
+ key: record.key,
4655
+ nominatedRecordSha256: record.recordSha256,
4656
+ v: 1
4657
+ }];
4658
+ }).sort((left, right) => compareText(left.key, right.key)));
4659
+ }
4660
+ function unauthorizedAdoptionDifferences(reviewedSnapshot, currentSnapshot, records, replacements) {
4661
+ const reviewedByKey = new Map(reviewedSnapshot.records.map((record) => [record.key, record]));
4662
+ const currentByKey = new Map(currentSnapshot.records.map((record) => [record.key, record]));
4663
+ const replacementByKey = new Map(replacements.map((replacement) => [
4664
+ replacement.key,
4665
+ replacement.expectedPriorRecordSha256
4666
+ ]));
4667
+ const conflicts = records.flatMap((nominated) => {
4668
+ const reviewed = reviewedByKey.get(nominated.key);
4669
+ const expectedPriorRecordSha256 = replacementByKey.get(nominated.key);
4670
+ const alreadyEqual = reviewed?.recordSha256 === nominated.recordSha256;
4671
+ const authorized = reviewed === undefined ? expectedPriorRecordSha256 === undefined : alreadyEqual ? expectedPriorRecordSha256 === undefined || expectedPriorRecordSha256 === reviewed.recordSha256 : expectedPriorRecordSha256 === reviewed.recordSha256;
4672
+ if (authorized)
4673
+ return [];
4674
+ return [{
4675
+ canonicalRecordSha256: currentByKey.get(nominated.key)?.recordSha256 ?? null,
4676
+ key: nominated.key,
4677
+ nominatedRecordSha256: nominated.recordSha256,
4678
+ v: 1
4679
+ }];
4680
+ });
4681
+ return immutableClone(conflicts.sort((left, right) => compareText(left.key, right.key)));
4682
+ }
4683
+ async function assertWorkingCommitCapacity(store, binding, changes, head) {
4684
+ const returnedSnapshot = await store.snapshot({
4685
+ head: { operationSha256: head.operationSha256, sequence: head.sequence },
4686
+ maximumRecords: OH_MEMORY_LIMITS_V1.maximumRecordsPerLane
4687
+ });
4688
+ const { snapshot } = parseDetachedStoreSnapshot(returnedSnapshot, "The working capacity store", head, binding.spaceId);
4689
+ const recordsByKey = new Map(snapshot.records.map((record) => [record.key, record]));
4690
+ for (const change of canonicalKnowledgeGraphChangesV1(changes)) {
4691
+ if (change.kind === "put")
4692
+ recordsByKey.set(change.record.key, change.record);
4693
+ else
4694
+ recordsByKey.delete(change.key);
4695
+ }
4696
+ if (recordsByKey.size > OH_MEMORY_LIMITS_V1.maximumRecordsPerLane) {
4697
+ throw new RangeError("The remembered working memory would exceed its record snapshot bound.");
4698
+ }
4699
+ const nextSequence = snapshot.head.sequence + 1;
4700
+ if (!Number.isSafeInteger(nextSequence)) {
4701
+ throw new RangeError("The remembered working memory would exceed its head sequence bound.");
4702
+ }
4703
+ const records = [...recordsByKey.values()].sort((left, right) => compareText(left.key, right.key));
4704
+ const placeholderDigest = canonicalSha256({ kind: "oh.memory.remember-capacity", v: 1 });
4705
+ const prospective = {
4706
+ head: {
4707
+ generation: nextSequence,
4708
+ graphRevisionSha256: placeholderDigest,
4709
+ operationSha256: placeholderDigest,
4710
+ recordsSha256: canonicalSha256(records.map(knowledgeGraphRecordRefV1)),
4711
+ sequence: nextSequence,
4712
+ v: 1
4713
+ },
4714
+ records,
4715
+ v: 1
4716
+ };
4717
+ if (utf8ByteLength(canonicalJson(prospective)) > OH_MEMORY_LIMITS_V1.snapshotBytesPerLane) {
4718
+ throw new RangeError("The remembered working memory would exceed its snapshot byte bound.");
4719
+ }
4720
+ }
4721
+ function capacityGuardedWorkingStore(store, binding) {
4722
+ const guarded = {
4723
+ binding,
4724
+ changesSince: async (from, options) => await store.changesSince(from, options),
4725
+ close: async () => await store.close(),
4726
+ commit: async (input) => {
4727
+ const current = parseDetachedStoreHead(await store.head(), "The working capacity store");
4728
+ if (current.generation === input.expectedHead.generation && current.operationSha256 === input.expectedHead.operationSha256)
4729
+ await assertWorkingCommitCapacity(store, binding, input.changes, current);
4730
+ return await store.commit(input);
4731
+ },
4732
+ exportDependencyClosure: async (input) => await store.exportDependencyClosure(input),
4733
+ head: async () => await store.head(),
4734
+ snapshot: async (options) => await store.snapshot(options),
4735
+ verify: async () => await store.verify()
4736
+ };
4737
+ return Object.freeze(guarded);
4738
+ }
4739
+ function assertAdoptionSnapshotCapacity(snapshot, changedRecords) {
4740
+ const recordsByKey = new Map(snapshot.records.map((record) => [record.key, record]));
4741
+ for (const record of changedRecords)
4742
+ recordsByKey.set(record.key, record);
4743
+ if (recordsByKey.size > OH_MEMORY_LIMITS_V1.maximumRecordsPerLane) {
4744
+ throw new RangeError("The adopted canonical memory would exceed its record snapshot bound.");
4745
+ }
4746
+ const nextSequence = snapshot.head.sequence + 1;
4747
+ if (!Number.isSafeInteger(nextSequence)) {
4748
+ throw new RangeError("The adopted canonical memory would exceed its head sequence bound.");
4749
+ }
4750
+ const records = [...recordsByKey.values()].sort((left, right) => compareText(left.key, right.key));
4751
+ const placeholderDigest = canonicalSha256({ kind: "oh.memory.adoption-capacity", v: 1 });
4752
+ const prospective = {
4753
+ head: {
4754
+ generation: nextSequence,
4755
+ graphRevisionSha256: placeholderDigest,
4756
+ operationSha256: placeholderDigest,
4757
+ recordsSha256: canonicalSha256(records.map(knowledgeGraphRecordRefV1)),
4758
+ sequence: nextSequence,
4759
+ v: 1
4760
+ },
4761
+ records,
4762
+ v: 1
4763
+ };
4764
+ if (utf8ByteLength(canonicalJson(prospective)) > OH_MEMORY_LIMITS_V1.snapshotBytesPerLane) {
4765
+ throw new RangeError("The adopted canonical memory would exceed its canonical snapshot byte bound.");
4766
+ }
4767
+ }
4768
+ function adoptionConflict(expectedHead, actualHead, completeConflicts) {
4769
+ const sorted = immutableClone([...completeConflicts].sort((left, right) => compareText(left.key, right.key)));
4770
+ const conflicts = immutableClone(sorted.slice(0, OH_MEMORY_AUTHORITY_LIMITS_V1.reportedAdoptionConflicts));
4771
+ const conflict = immutableClone({
4772
+ actualHead,
4773
+ conflicts,
4774
+ conflictsSha256: canonicalSha256({ conflicts: sorted, v: 1 }),
4775
+ expectedHead,
4776
+ reportedConflicts: conflicts.length,
4777
+ totalConflicts: sorted.length,
4778
+ truncated: conflicts.length !== sorted.length,
4779
+ v: 1
4780
+ });
4781
+ return new OhMemoryAdoptionConflictError(conflict);
4782
+ }
4783
+ async function createOhMemoryAuthorityV1(options) {
4784
+ const maximumCanonicalOperationBytes = options.maximumCanonicalOperationBytes ?? OH_OPERATION_MAX_BYTES_V1;
4785
+ if (!Number.isSafeInteger(maximumCanonicalOperationBytes) || maximumCanonicalOperationBytes < 1 || maximumCanonicalOperationBytes > OH_OPERATION_MAX_BYTES_V1) {
4786
+ throw new TypeError("Invalid canonical memory operation byte bound.");
4787
+ }
4788
+ const memoryActorId = safeCode(options.actorId, 128);
4789
+ const adoptionActorId = safeCode(options.adoptionActorId, 128);
4790
+ if (memoryActorId === null || adoptionActorId === null) {
4791
+ throw new TypeError("Invalid host-bound memory authority actor ID.");
4792
+ }
4793
+ const canonicalStore = options.canonical.store;
4794
+ const workingStore = options.working.store;
4795
+ const canonicalAuthorityId = authorityId(options.canonical.authorityId);
4796
+ const workingAuthorityId = authorityId(options.working.authorityId);
4797
+ if (canonicalAuthorityId === workingAuthorityId) {
4798
+ throw new OhProfileError("Working and canonical memory must be distinct physical authorities.");
4799
+ }
4800
+ const canonicalBinding = bindingFor(canonicalStore, options.canonical.expectedBindingSha256, "canonical");
4801
+ const workingBinding = bindingFor(workingStore, options.working.expectedBindingSha256, "working");
4802
+ const initialCanonicalHead = parseMemoryAuthorityHead(options.canonical.expectedHead, "initial canonical");
4803
+ const workingCodecs = options.working.codecs;
4804
+ const explainCapabilityLifetimeMs = options.explainCapabilityLifetimeMs;
4805
+ const monotonicNow = options.monotonicNow;
4806
+ const now = options.now;
4807
+ const continuationKey = continuationKeyV2(options.continuationKey);
4808
+ const programs = Object.freeze([...resolveProgramsV2(options.programs).values()].map((program) => immutableClone({
4809
+ evaluation: program.evaluation,
4810
+ maximumPageBytes: program.maximumPageBytes,
4811
+ maximumRows: program.maximumRows,
4812
+ pageSize: program.pageSize,
4813
+ parameters: program.parameters,
4814
+ programId: program.programId,
4815
+ purpose: program.purpose,
4816
+ query: program.query,
4817
+ rulePack: program.rulePack,
4818
+ v: 2
4819
+ })));
4820
+ const extractors = resolveExtractors(options.extractors ?? []);
4821
+ const nominationRoutes = Object.freeze([...resolveNominationRoutes(options.nominationRoutes ?? []).values()]);
4822
+ const routesById = new Map(nominationRoutes.map((route) => [route.nominationId, route]));
4823
+ const runtime = createOhMemoryRuntimeV2(options);
4824
+ const createAgentAt = async (expectedHead) => await createOhMemoryAgentV2WithRuntime({
4825
+ actorId: memoryActorId,
4826
+ canonical: {
4827
+ authorityId: canonicalAuthorityId,
4828
+ expectedBindingSha256: canonicalBinding.bindingSha256,
4829
+ expectedHead,
4830
+ store: canonicalStore
4831
+ },
4832
+ continuationKey,
4833
+ ...explainCapabilityLifetimeMs === undefined ? {} : {
4834
+ explainCapabilityLifetimeMs
4835
+ },
4836
+ extractors,
4837
+ ...monotonicNow === undefined ? {} : { monotonicNow },
4838
+ nominationRoutes,
4839
+ ...now === undefined ? {} : { now },
4840
+ programs,
4841
+ working: {
4842
+ authorityId: workingAuthorityId,
4843
+ codecs: workingCodecs,
4844
+ expectedBindingSha256: workingBinding.bindingSha256,
4845
+ store: workingStore
4846
+ }
4847
+ }, runtime);
4848
+ let activeCanonicalHead = initialCanonicalHead;
4849
+ let activeAgent = await createAgentAt(activeCanonicalHead);
4850
+ const agent = Object.freeze({
4851
+ async explain(value) {
4852
+ const selected = activeAgent;
4853
+ return await selected.explain(value);
4854
+ },
4855
+ nominate(value) {
4856
+ const selected = activeAgent;
4857
+ return selected.nominate(value);
4858
+ },
4859
+ async query(value) {
4860
+ const selected = activeAgent;
4861
+ return await selected.query(value);
4862
+ },
4863
+ remember(value) {
4864
+ const selected = activeAgent;
4865
+ return selected.remember(value);
4866
+ }
4867
+ });
4868
+ let hostTail = Promise.resolve();
4869
+ const serialized = (operation) => {
4870
+ const result = hostTail.then(operation);
4871
+ hostTail = result.then(() => {
4872
+ return;
4873
+ }, () => {
4874
+ return;
4875
+ });
4876
+ return result;
4877
+ };
4878
+ const installCanonicalHead = async (head) => {
4879
+ const nextAgent = await createAgentAt(head);
4880
+ activeAgent = nextAgent;
4881
+ activeCanonicalHead = immutableClone(head);
4882
+ };
4883
+ const canonicalAuthority = Object.freeze({
4884
+ authorityId: canonicalAuthorityId,
4885
+ binding: canonicalBinding,
4886
+ store: canonicalStore
4887
+ });
4888
+ const readPhysicalCanonicalHead = async () => parseMemoryAuthorityHead(await canonicalStore.head(), "physical canonical");
4889
+ const advanceCanonical = (value) => {
4890
+ let request;
4891
+ try {
4892
+ request = parseCanonicalAdvanceRequest(value);
4893
+ } catch (error) {
4894
+ return Promise.reject(error);
4895
+ }
4896
+ return serialized(async () => {
4897
+ const priorHead = activeCanonicalHead;
4898
+ if (!exactHead(request.expectedHead, priorHead)) {
4899
+ throw new OhConflictError("The expected canonical memory head does not match the current pin.");
4900
+ }
4901
+ if (exactHead(request.nextHead, priorHead)) {
4902
+ return canonicalAdvanceReceipt(canonicalAuthorityId, canonicalBinding.bindingSha256, priorHead, priorHead, "unchanged");
4903
+ }
4904
+ await proveCanonicalDescendant(canonicalAuthority, priorHead, request.nextHead);
4905
+ await installCanonicalHead(request.nextHead);
4906
+ return canonicalAdvanceReceipt(canonicalAuthorityId, canonicalBinding.bindingSha256, priorHead, request.nextHead, "advanced");
4907
+ });
4908
+ };
4909
+ const adoptNomination = (value) => {
4910
+ let request;
4911
+ try {
4912
+ request = parseAdoptionRequest(value);
4913
+ } catch (error) {
4914
+ return Promise.reject(error);
4915
+ }
4916
+ return serialized(async () => {
4917
+ const route = routesById.get(request.nomination.nominationId);
4918
+ if (route === undefined || route.destinationPurpose !== request.nomination.destinationPurpose) {
4919
+ throw new OhProfileError("The memory nomination is not bound to this adoption route.");
4920
+ }
4921
+ if (request.nomination.source.authorityId !== workingAuthorityId || request.nomination.source.bindingSha256 !== workingBinding.bindingSha256 || request.nomination.closure.binding.bindingSha256 !== workingBinding.bindingSha256) {
4922
+ throw new OhProfileError("The memory nomination is not from the bound working authority.");
4923
+ }
4924
+ const returnedReexport = await workingStore.exportDependencyClosure({
4925
+ head: headRef(request.nomination.source.head),
4926
+ maximumRecords: OH_DEPENDENCY_CLOSURE_LIMITS_V1.records,
4927
+ roots: request.nomination.closure.roots
4928
+ });
4929
+ const reexported = detachCanonicalData(returnedReexport, "The working re-exported nomination", OH_DEPENDENCY_CLOSURE_LIMITS_V1.bytes);
4930
+ if (reexported.canonical !== canonicalJson(request.nomination.closure)) {
4931
+ throw new OhIntegrityError("The working authority did not re-export the nominated closure exactly.");
4932
+ }
4933
+ const priorHead = activeCanonicalHead;
4934
+ const physicalHead = await readPhysicalCanonicalHead();
4935
+ const replacementConflictsAt = async (currentLane) => {
4936
+ if (request.replacements.length === 0)
4937
+ return [];
4938
+ const reviewedLane = exactHead(request.expectedCanonicalHead, currentLane.snapshot.head) ? currentLane : await readLane(canonicalAuthority, "canonical", request.expectedCanonicalHead);
4939
+ return unauthorizedAdoptionDifferences(reviewedLane.snapshot, currentLane.snapshot, request.nomination.closure.records, request.replacements);
4940
+ };
4941
+ if (!exactHead(physicalHead, priorHead)) {
4942
+ const physicalLane = await proveCanonicalDescendant(canonicalAuthority, priorHead, physicalHead);
4943
+ const physicalDifferences = adoptionDifferences(physicalLane.snapshot, request.nomination.closure.records);
4944
+ if (physicalDifferences.length === 0) {
4945
+ const replacementConflicts = await replacementConflictsAt(physicalLane);
4946
+ if (replacementConflicts.length > 0) {
4947
+ throw adoptionConflict(request.expectedCanonicalHead, physicalHead, replacementConflicts);
4948
+ }
4949
+ await installCanonicalHead(physicalHead);
4950
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, physicalHead, "already-present");
4951
+ }
4952
+ throw adoptionConflict(request.expectedCanonicalHead, physicalHead, physicalDifferences);
4953
+ }
4954
+ const lane = await readLane(canonicalAuthority, "canonical", priorHead);
4955
+ const differences = adoptionDifferences(lane.snapshot, request.nomination.closure.records);
4956
+ if (!exactHead(request.expectedCanonicalHead, priorHead)) {
4957
+ if (differences.length === 0) {
4958
+ const replacementConflicts = await replacementConflictsAt(lane);
4959
+ if (replacementConflicts.length > 0) {
4960
+ throw adoptionConflict(request.expectedCanonicalHead, priorHead, replacementConflicts);
4961
+ }
4962
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, priorHead, "already-present");
4963
+ }
4964
+ throw adoptionConflict(request.expectedCanonicalHead, priorHead, differences);
4965
+ }
4966
+ if (differences.length === 0) {
4967
+ const replacementConflicts = await replacementConflictsAt(lane);
4968
+ if (replacementConflicts.length > 0) {
4969
+ throw adoptionConflict(request.expectedCanonicalHead, priorHead, replacementConflicts);
4970
+ }
4971
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, priorHead, "already-present");
4972
+ }
4973
+ const unauthorized = unauthorizedAdoptionDifferences(lane.snapshot, lane.snapshot, request.nomination.closure.records, request.replacements);
4974
+ if (unauthorized.length > 0) {
4975
+ throw adoptionConflict(request.expectedCanonicalHead, priorHead, unauthorized);
4976
+ }
4977
+ const changedKeys = new Set(differences.map(({ key }) => key));
4978
+ const changedRecords = request.nomination.closure.records.filter(({ key }) => changedKeys.has(key));
4979
+ if (changedRecords.length === 0) {
4980
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, priorHead, "already-present");
4981
+ }
4982
+ assertAdoptionSnapshotCapacity(lane.snapshot, changedRecords);
4983
+ const changes = canonicalKnowledgeGraphChangesV1(changedRecords.map((record) => ({ kind: "put", record, v: 1 })));
4984
+ const operationId = `memory_adopt_${canonicalSha256({
4985
+ actorId: adoptionActorId,
4986
+ bindingSha256: canonicalBinding.bindingSha256,
4987
+ nominationSha256: request.nomination.nominationSha256,
4988
+ priorHead,
4989
+ v: 1
4990
+ }).slice(0, 48)}`;
4991
+ let returnedOperation;
4992
+ try {
4993
+ returnedOperation = await canonicalStore.commit({
4994
+ actorId: adoptionActorId,
4995
+ changes,
4996
+ expectedHead: {
4997
+ generation: priorHead.generation,
4998
+ operationSha256: priorHead.operationSha256
4999
+ },
5000
+ maximumOperationBytes: maximumCanonicalOperationBytes,
5001
+ operationId
5002
+ });
5003
+ } catch (error) {
5004
+ if (!(error instanceof OhConflictError))
5005
+ throw error;
5006
+ const actualHead2 = await readPhysicalCanonicalHead();
5007
+ const actualLane = exactHead(actualHead2, priorHead) ? await readLane(canonicalAuthority, "canonical", actualHead2) : await proveCanonicalDescendant(canonicalAuthority, priorHead, actualHead2);
5008
+ const actualDifferences = adoptionDifferences(actualLane.snapshot, request.nomination.closure.records);
5009
+ if (actualDifferences.length === 0) {
5010
+ if (!exactHead(actualHead2, priorHead)) {
5011
+ await installCanonicalHead(actualHead2);
5012
+ }
5013
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, actualHead2, "already-present");
5014
+ }
5015
+ throw adoptionConflict(request.expectedCanonicalHead, actualHead2, actualDifferences);
5016
+ }
5017
+ const operation = parseOhOperationV1(detachCanonicalData(returnedOperation, "The returned canonical adoption operation", OH_MEMORY_AUTHORITY_LIMITS_V1.canonicalChangeFeedPageBytes).value);
5018
+ if (operation === null || operation.actorId !== adoptionActorId || operation.operationId !== operationId || operation.spaceId !== canonicalBinding.spaceId || operation.parentOperationSha256 !== priorHead.operationSha256 || operation.sequence !== priorHead.sequence + 1 || canonicalJson(operation.changes) !== canonicalJson(changes)) {
5019
+ throw new OhIntegrityError("The canonical authority returned a different adoption operation.");
5020
+ }
5021
+ const head = immutableClone({
5022
+ generation: operation.sequence,
5023
+ graphRevisionSha256: operation.graphRevisionSha256,
5024
+ operationSha256: operation.operationSha256,
5025
+ recordsSha256: operation.recordsSha256,
5026
+ sequence: operation.sequence,
5027
+ v: 1
5028
+ });
5029
+ const actualHead = await readPhysicalCanonicalHead();
5030
+ if (!exactHead(actualHead, head)) {
5031
+ const actualLane = exactHead(actualHead, priorHead) ? await readLane(canonicalAuthority, "canonical", actualHead) : await proveCanonicalDescendant(canonicalAuthority, priorHead, actualHead, head);
5032
+ const actualDifferences = adoptionDifferences(actualLane.snapshot, request.nomination.closure.records);
5033
+ if (actualDifferences.length !== 0) {
5034
+ throw adoptionConflict(request.expectedCanonicalHead, actualHead, actualDifferences);
5035
+ }
5036
+ await installCanonicalHead(actualHead);
5037
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, null, priorHead, actualHead, "already-present");
5038
+ }
5039
+ await installCanonicalHead(actualHead);
5040
+ return adoptionReceipt(adoptionActorId, canonicalAuthorityId, canonicalBinding.bindingSha256, request.nomination.nominationSha256, operation.operationSha256, priorHead, actualHead, "adopted");
5041
+ });
5042
+ };
5043
+ return Object.freeze({ agent, host: Object.freeze({ adoptNomination, advanceCanonical }) });
5044
+ }
4092
5045
  export {
4093
5046
  renderOhMemoryPageMarkdownV1,
4094
5047
  parseOhMemoryPageValueV1,
4095
5048
  parseOhMemoryPageRecordV1,
4096
5049
  parseOhMemoryPageMarkdownV1,
5050
+ parseOhMemoryNominationV1,
4097
5051
  createOhMemoryPageValueV1,
4098
5052
  createOhMemoryPageRecordV1,
5053
+ createOhMemoryAuthorityV1,
4099
5054
  createOhMemoryAgentV2,
4100
5055
  createOhMemoryAgentV1,
5056
+ OhMemoryContinuationError,
5057
+ OhMemoryAdoptionConflictError,
4101
5058
  OH_MEMORY_QUERY_LIMITS_V2,
4102
5059
  OH_MEMORY_PAGE_RECORD_CODEC_V1,
4103
5060
  OH_MEMORY_PAGE_MARKDOWN_EXTENSION_V1,
@@ -4106,5 +5063,6 @@ export {
4106
5063
  OH_MEMORY_LIMITS_V1,
4107
5064
  OH_MEMORY_FORMAT_VERSION_V1,
4108
5065
  OH_MEMORY_CONFLICT_POLICY_V1,
4109
- OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1
5066
+ OH_MEMORY_COMPOSITE_FACT_EXTRACTOR_V1,
5067
+ OH_MEMORY_AUTHORITY_LIMITS_V1
4110
5068
  };