{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/components/memory/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { join, resolve } from \"node:path\";\nimport { isDigest } from \"../../bundle/schema.ts\";\nimport type { EvoPaths } from \"../../paths.ts\";\nimport {\n\tappendRegularFileNoFollow,\n\tatomicWriteRegularFileNoFollow,\n\tdurableUnlinkRegularFileNoFollow,\n\tensurePrivateDirectoryNoFollow,\n\treadRegularFileNoFollow,\n} from \"../../secure-file.ts\";\nimport { canonicalJson, sha256, withFileLock } from \"../../storage.ts\";\nimport type { EvoCapabilityComponentIdentity } from \"../capabilities/service.ts\";\nimport { assertEvoComponentId } from \"../manifest.ts\";\n\nconst MEMORY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst MAX_FRAGMENTS = 10_000;\nconst MAX_FRAGMENT_TEXT_CHARACTERS = 32_000;\nconst MAX_FRAGMENT_METADATA_BYTES = 64 * 1024;\nconst MAX_RETRIEVE_LIMIT = 100;\nconst MAX_TRANSACTION_ACTIONS = 16;\nconst MAX_TRANSACTION_AUDIT_ENTRIES = 16;\n\nexport type EvoMemoryNamespaceKind = \"stable\" | \"trial\";\nexport type EvoMemoryAuditOperation =\n\t| \"initialize\"\n\t| \"trial-start\"\n\t| \"append\"\n\t| \"update\"\n\t| \"forget\"\n\t| \"promote\"\n\t| \"rollback\";\n\nexport type EvoMemoryFaultPoint =\n\t| \"after-outbox-write\"\n\t| \"after-pointer-action\"\n\t| \"after-audit-append\"\n\t| \"before-outbox-remove\";\n\nexport interface EvoMemoryFragmentInput {\n\tid: string;\n\ttext: string;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface EvoMemoryFragment {\n\tid: string;\n\ttext: string;\n\tmetadata: Record<string, unknown>;\n\tcreatedAt: string;\n\tupdatedAt: string;\n}\n\nexport interface EvoMemorySnapshot {\n\tschemaVersion: 1;\n\tfragments: EvoMemoryFragment[];\n}\n\nexport interface EvoMemoryReadResult {\n\tstateDigest: string;\n\tfragments: EvoMemoryFragment[];\n}\n\nexport interface EvoMemoryMutationResult {\n\tstateDigest: string;\n\tfragment: EvoMemoryFragment | null;\n}\n\nexport interface EvoMemoryRetrievedFragment extends EvoMemoryFragment {\n\tscore: number;\n}\n\nexport interface EvoMemoryRetrieveResult {\n\tstateDigest: string;\n\tfragments: EvoMemoryRetrievedFragment[];\n}\n\nexport interface EvoMemoryAuditEntry {\n\tschemaVersion: 1;\n\teventId: string;\n\ttimestamp: string;\n\tcomponentId: string;\n\tartifactDigest: string;\n\toperation: EvoMemoryAuditOperation;\n\tnamespace: EvoMemoryNamespaceKind;\n\tbundleDigest: string;\n\tparentBundleDigest: string | null;\n\tfragmentId: string | null;\n\tstateBefore: string | null;\n\tstateAfter: string | null;\n}\n\nexport interface EvoMemoryStoreOptions {\n\tpaths: EvoPaths;\n\tcomponentId: string;\n\tartifactDigest: string;\n\troot?: string;\n\tnow?: () => string;\n\trandomId?: () => string;\n\tfaultInjection?: (point: EvoMemoryFaultPoint) => void | Promise<void>;\n}\n\nexport interface EvoMemoryTrialOptions {\n\tparentBundleDigest: string;\n\ttrialBundleDigest: string;\n}\n\nexport interface EvoMemoryBundleRollbackOptions {\n\trolledBackBundleDigests: readonly string[];\n\ttargetBundleDigest: string;\n\ttargetAncestorBundleDigests: readonly string[];\n\ttargetSelected: boolean;\n}\n\nexport interface EvoMemoryStableMaterializationOptions {\n\ttargetBundleDigest: string;\n\ttargetAncestorBundleDigests: readonly string[];\n}\n\nconst COMPONENT_MEMORY_CAPABILITIES = new Set([\"memory-read\", \"memory-write\", \"retrieve\"]);\n\nexport function usesEvoComponentMemory(surface: string, capabilities: readonly string[]): boolean {\n\treturn surface === \"memory\" || capabilities.some((capability) => COMPONENT_MEMORY_CAPABILITIES.has(capability));\n}\n\ninterface EvoMemoryNamespacePointer {\n\tschemaVersion: 1;\n\tkind: EvoMemoryNamespaceKind;\n\tbundleDigest: string;\n\tparentBundleDigest: string | null;\n\tstateDigest: string;\n}\n\ntype EvoMemoryPointerLocation =\n\t| { kind: \"stable\" }\n\t| { kind: \"trial\"; bundleDigest: string }\n\t| { kind: \"stable-history\"; bundleDigest: string };\n\ninterface EvoMemoryPointerAction {\n\tlocation: EvoMemoryPointerLocation;\n\tbefore: EvoMemoryNamespacePointer | null;\n\tafter: EvoMemoryNamespacePointer | null;\n}\n\ninterface EvoMemoryTransaction {\n\tschemaVersion: 1;\n\tactions: EvoMemoryPointerAction[];\n\tauditEntries: EvoMemoryAuditEntry[];\n}\n\ninterface EvoMemoryBundleRollbackState {\n\tstable?: EvoMemoryNamespacePointer;\n\ttrials: EvoMemoryNamespacePointer[];\n\ttarget?: EvoMemoryNamespacePointer;\n\ttargetTrial?: EvoMemoryNamespacePointer;\n\ttargetTrialStateBefore?: string;\n}\n\ntype EvoMemoryMutation =\n\t| { operation: \"append\"; fragment: EvoMemoryFragmentInput; expectedStateDigest?: string }\n\t| { operation: \"update\"; fragment: EvoMemoryFragmentInput; expectedStateDigest?: string }\n\t| { operation: \"forget\"; id: string; expectedStateDigest?: string };\n\nfunction asRecord(value: unknown, label: string): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be an object`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction rejectUnknownKeys(record: Record<string, unknown>, allowed: readonly string[], label: string): void {\n\tconst allowedKeys = new Set(allowed);\n\tfor (const key of Object.keys(record)) {\n\t\tif (!allowedKeys.has(key)) throw new Error(`${label} has unknown key: ${key}`);\n\t}\n}\n\nfunction requireDigest(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || !isDigest(value)) throw new Error(`${label} must be a sha256 digest`);\n\treturn value;\n}\n\nfunction parseBundleRollbackOptions(options: EvoMemoryBundleRollbackOptions): {\n\trolledBackBundleDigests: string[];\n\ttargetBundleDigest: string;\n\ttargetAncestorBundleDigests: string[];\n\ttargetSelected: boolean;\n} {\n\tconst targetBundleDigest = requireDigest(options.targetBundleDigest, \"rollback target bundle digest\");\n\tif (typeof options.targetSelected !== \"boolean\") throw new Error(\"rollback targetSelected must be a boolean\");\n\tif (!Array.isArray(options.rolledBackBundleDigests) || options.rolledBackBundleDigests.length === 0) {\n\t\tthrow new Error(\"rollback bundle lineage must not be empty\");\n\t}\n\tconst rolledBackBundleDigests = options.rolledBackBundleDigests.map((digest, index) =>\n\t\trequireDigest(digest, `rollback bundle lineage[${index}]`),\n\t);\n\tif (new Set(rolledBackBundleDigests).size !== rolledBackBundleDigests.length) {\n\t\tthrow new Error(\"rollback bundle lineage must not contain duplicates\");\n\t}\n\tif (rolledBackBundleDigests.includes(targetBundleDigest)) {\n\t\tthrow new Error(\"rollback bundle lineage must not contain its target\");\n\t}\n\tif (!Array.isArray(options.targetAncestorBundleDigests)) {\n\t\tthrow new Error(\"rollback target ancestor lineage must be an array\");\n\t}\n\tconst targetAncestorBundleDigests = options.targetAncestorBundleDigests.map((digest, index) =>\n\t\trequireDigest(digest, `rollback target ancestor lineage[${index}]`),\n\t);\n\tif (new Set(targetAncestorBundleDigests).size !== targetAncestorBundleDigests.length) {\n\t\tthrow new Error(\"rollback target ancestor lineage must not contain duplicates\");\n\t}\n\tif (\n\t\ttargetAncestorBundleDigests.includes(targetBundleDigest) ||\n\t\ttargetAncestorBundleDigests.some((digest) => rolledBackBundleDigests.includes(digest))\n\t) {\n\t\tthrow new Error(\"rollback target ancestor lineage overlaps the rollback lineage\");\n\t}\n\treturn {\n\t\trolledBackBundleDigests,\n\t\ttargetBundleDigest,\n\t\ttargetAncestorBundleDigests,\n\t\ttargetSelected: options.targetSelected,\n\t};\n}\n\nfunction requireMemoryId(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || !MEMORY_ID_PATTERN.test(value)) throw new Error(`${label} is invalid`);\n\treturn value;\n}\n\nfunction requireTimestamp(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || !Number.isFinite(Date.parse(value)) || new Date(value).toISOString() !== value) {\n\t\tthrow new Error(`${label} must be an ISO timestamp`);\n\t}\n\treturn value;\n}\n\nfunction jsonRecord(value: unknown, label: string): Record<string, unknown> {\n\tconst record = asRecord(value, label);\n\tconst normalized = JSON.parse(canonicalJson(record)) as unknown;\n\tconst result = asRecord(normalized, label);\n\tif (Buffer.byteLength(canonicalJson(result), \"utf8\") > MAX_FRAGMENT_METADATA_BYTES) {\n\t\tthrow new Error(`${label} exceeds the metadata byte limit`);\n\t}\n\treturn result;\n}\n\nexport function parseEvoMemoryFragmentInput(value: unknown, label = \"memory fragment\"): EvoMemoryFragmentInput {\n\tconst fragment = asRecord(value, label);\n\trejectUnknownKeys(fragment, [\"id\", \"text\", \"metadata\"], label);\n\tconst id = requireMemoryId(fragment.id, `${label}.id`);\n\tif (\n\t\ttypeof fragment.text !== \"string\" ||\n\t\t!fragment.text.trim() ||\n\t\tfragment.text !== fragment.text.trim() ||\n\t\tfragment.text.length > MAX_FRAGMENT_TEXT_CHARACTERS\n\t) {\n\t\tthrow new Error(`${label}.text must be trimmed and contain 1-${MAX_FRAGMENT_TEXT_CHARACTERS} characters`);\n\t}\n\treturn {\n\t\tid,\n\t\ttext: fragment.text,\n\t\t...(fragment.metadata === undefined ? {} : { metadata: jsonRecord(fragment.metadata, `${label}.metadata`) }),\n\t};\n}\n\nfunction parseFragment(value: unknown, label: string): EvoMemoryFragment {\n\tconst fragment = asRecord(value, label);\n\trejectUnknownKeys(fragment, [\"id\", \"text\", \"metadata\", \"createdAt\", \"updatedAt\"], label);\n\tconst input = parseEvoMemoryFragmentInput(\n\t\t{ id: fragment.id, text: fragment.text, metadata: fragment.metadata },\n\t\tlabel,\n\t);\n\treturn {\n\t\t...input,\n\t\tmetadata: input.metadata ?? {},\n\t\tcreatedAt: requireTimestamp(fragment.createdAt, `${label}.createdAt`),\n\t\tupdatedAt: requireTimestamp(fragment.updatedAt, `${label}.updatedAt`),\n\t};\n}\n\nfunction parseSnapshot(value: unknown, label: string): EvoMemorySnapshot {\n\tconst snapshot = asRecord(value, label);\n\trejectUnknownKeys(snapshot, [\"schemaVersion\", \"fragments\"], label);\n\tif (snapshot.schemaVersion !== 1) throw new Error(`${label}.schemaVersion must be 1`);\n\tif (!Array.isArray(snapshot.fragments) || snapshot.fragments.length > MAX_FRAGMENTS) {\n\t\tthrow new Error(`${label}.fragments must contain at most ${MAX_FRAGMENTS} entries`);\n\t}\n\tconst fragments = snapshot.fragments.map((fragment, index) =>\n\t\tparseFragment(fragment, `${label}.fragments[${index}]`),\n\t);\n\tif (new Set(fragments.map((fragment) => fragment.id)).size !== fragments.length) {\n\t\tthrow new Error(`${label}.fragments contains duplicate ids`);\n\t}\n\tconst sorted = [...fragments].sort((left, right) => left.id.localeCompare(right.id));\n\tif (fragments.some((fragment, index) => fragment.id !== sorted[index]?.id)) {\n\t\tthrow new Error(`${label}.fragments must be sorted by id`);\n\t}\n\treturn { schemaVersion: 1, fragments };\n}\n\nfunction parsePointer(value: unknown, label: string): EvoMemoryNamespacePointer {\n\tconst pointer = asRecord(value, label);\n\trejectUnknownKeys(pointer, [\"schemaVersion\", \"kind\", \"bundleDigest\", \"parentBundleDigest\", \"stateDigest\"], label);\n\tif (pointer.schemaVersion !== 1) throw new Error(`${label}.schemaVersion must be 1`);\n\tif (pointer.kind !== \"stable\" && pointer.kind !== \"trial\") throw new Error(`${label}.kind is invalid`);\n\tconst bundleDigest = requireDigest(pointer.bundleDigest, `${label}.bundleDigest`);\n\tconst stateDigest = requireDigest(pointer.stateDigest, `${label}.stateDigest`);\n\tlet parentBundleDigest: string | null;\n\tif (pointer.kind === \"stable\") {\n\t\tif (pointer.parentBundleDigest !== null) throw new Error(`${label}.parentBundleDigest must be null for stable`);\n\t\tparentBundleDigest = null;\n\t} else {\n\t\tparentBundleDigest = requireDigest(pointer.parentBundleDigest, `${label}.parentBundleDigest`);\n\t\tif (parentBundleDigest === bundleDigest) throw new Error(`${label} trial must differ from its parent bundle`);\n\t}\n\treturn { schemaVersion: 1, kind: pointer.kind, bundleDigest, parentBundleDigest, stateDigest };\n}\n\nconst AUDIT_OPERATIONS = new Set<EvoMemoryAuditOperation>([\n\t\"initialize\",\n\t\"trial-start\",\n\t\"append\",\n\t\"update\",\n\t\"forget\",\n\t\"promote\",\n\t\"rollback\",\n]);\n\nfunction parseAuditEntry(value: unknown, label: string): EvoMemoryAuditEntry {\n\tconst entry = asRecord(value, label);\n\trejectUnknownKeys(\n\t\tentry,\n\t\t[\n\t\t\t\"schemaVersion\",\n\t\t\t\"eventId\",\n\t\t\t\"timestamp\",\n\t\t\t\"componentId\",\n\t\t\t\"artifactDigest\",\n\t\t\t\"operation\",\n\t\t\t\"namespace\",\n\t\t\t\"bundleDigest\",\n\t\t\t\"parentBundleDigest\",\n\t\t\t\"fragmentId\",\n\t\t\t\"stateBefore\",\n\t\t\t\"stateAfter\",\n\t\t],\n\t\tlabel,\n\t);\n\tif (entry.schemaVersion !== 1) throw new Error(`${label}.schemaVersion must be 1`);\n\tif (typeof entry.eventId !== \"string\" || !MEMORY_ID_PATTERN.test(entry.eventId)) {\n\t\tthrow new Error(`${label}.eventId is invalid`);\n\t}\n\tif (typeof entry.componentId !== \"string\") throw new Error(`${label}.componentId must be a string`);\n\tassertEvoComponentId(entry.componentId, `${label}.componentId`);\n\tif (typeof entry.operation !== \"string\" || !AUDIT_OPERATIONS.has(entry.operation as EvoMemoryAuditOperation)) {\n\t\tthrow new Error(`${label}.operation is invalid`);\n\t}\n\tif (entry.namespace !== \"stable\" && entry.namespace !== \"trial\") {\n\t\tthrow new Error(`${label}.namespace is invalid`);\n\t}\n\tconst optionalDigest = (field: \"parentBundleDigest\" | \"stateBefore\" | \"stateAfter\"): string | null =>\n\t\tentry[field] === null ? null : requireDigest(entry[field], `${label}.${field}`);\n\treturn {\n\t\tschemaVersion: 1,\n\t\teventId: entry.eventId,\n\t\ttimestamp: requireTimestamp(entry.timestamp, `${label}.timestamp`),\n\t\tcomponentId: entry.componentId,\n\t\tartifactDigest: requireDigest(entry.artifactDigest, `${label}.artifactDigest`),\n\t\toperation: entry.operation as EvoMemoryAuditOperation,\n\t\tnamespace: entry.namespace,\n\t\tbundleDigest: requireDigest(entry.bundleDigest, `${label}.bundleDigest`),\n\t\tparentBundleDigest: optionalDigest(\"parentBundleDigest\"),\n\t\tfragmentId: entry.fragmentId === null ? null : requireMemoryId(entry.fragmentId, `${label}.fragmentId`),\n\t\tstateBefore: optionalDigest(\"stateBefore\"),\n\t\tstateAfter: optionalDigest(\"stateAfter\"),\n\t};\n}\n\nfunction pointerEquals(\n\tleft: EvoMemoryNamespacePointer | null | undefined,\n\tright: EvoMemoryNamespacePointer | null | undefined,\n): boolean {\n\treturn canonicalJson(left ?? null) === canonicalJson(right ?? null);\n}\n\nfunction parsePointerLocation(value: unknown, label: string): EvoMemoryPointerLocation {\n\tconst location = asRecord(value, label);\n\tif (location.kind === \"stable\") {\n\t\trejectUnknownKeys(location, [\"kind\"], label);\n\t\treturn { kind: \"stable\" };\n\t}\n\tif (location.kind === \"trial\" || location.kind === \"stable-history\") {\n\t\trejectUnknownKeys(location, [\"kind\", \"bundleDigest\"], label);\n\t\treturn {\n\t\t\tkind: location.kind,\n\t\t\tbundleDigest: requireDigest(location.bundleDigest, `${label}.bundleDigest`),\n\t\t};\n\t}\n\tthrow new Error(`${label}.kind is invalid`);\n}\n\nfunction assertPointerMatchesLocation(\n\tpointer: EvoMemoryNamespacePointer | null,\n\tlocation: EvoMemoryPointerLocation,\n\tlabel: string,\n): void {\n\tif (!pointer) return;\n\tif (location.kind === \"stable\") {\n\t\tif (pointer.kind !== \"stable\") throw new Error(`${label} must contain a stable pointer`);\n\t\treturn;\n\t}\n\tif (location.kind === \"trial\") {\n\t\tif (pointer.kind !== \"trial\" || pointer.bundleDigest !== location.bundleDigest) {\n\t\t\tthrow new Error(`${label} does not match its trial location`);\n\t\t}\n\t\treturn;\n\t}\n\tif (pointer.kind !== \"stable\" || pointer.bundleDigest !== location.bundleDigest) {\n\t\tthrow new Error(`${label} does not match its stable history location`);\n\t}\n}\n\nfunction parsePointerAction(value: unknown, label: string): EvoMemoryPointerAction {\n\tconst action = asRecord(value, label);\n\trejectUnknownKeys(action, [\"location\", \"before\", \"after\"], label);\n\tconst location = parsePointerLocation(action.location, `${label}.location`);\n\tconst before = action.before === null ? null : parsePointer(action.before, `${label}.before`);\n\tconst after = action.after === null ? null : parsePointer(action.after, `${label}.after`);\n\tif (!before && !after) throw new Error(`${label} must change a pointer`);\n\tif (pointerEquals(before, after)) throw new Error(`${label} must change pointer state`);\n\tassertPointerMatchesLocation(before, location, `${label}.before`);\n\tassertPointerMatchesLocation(after, location, `${label}.after`);\n\treturn { location, before, after };\n}\n\nfunction parseTransaction(value: unknown, label: string): EvoMemoryTransaction {\n\tconst transaction = asRecord(value, label);\n\trejectUnknownKeys(transaction, [\"schemaVersion\", \"actions\", \"auditEntries\"], label);\n\tif (transaction.schemaVersion !== 1) throw new Error(`${label}.schemaVersion must be 1`);\n\tif (!Array.isArray(transaction.actions) || transaction.actions.length > MAX_TRANSACTION_ACTIONS) {\n\t\tthrow new Error(`${label}.actions must contain at most ${MAX_TRANSACTION_ACTIONS} entries`);\n\t}\n\tif (!Array.isArray(transaction.auditEntries) || transaction.auditEntries.length > MAX_TRANSACTION_AUDIT_ENTRIES) {\n\t\tthrow new Error(`${label}.auditEntries must contain at most ${MAX_TRANSACTION_AUDIT_ENTRIES} entries`);\n\t}\n\tconst actions = transaction.actions.map((action, index) => parsePointerAction(action, `${label}.actions[${index}]`));\n\tconst auditEntries = transaction.auditEntries.map((entry, index) =>\n\t\tparseAuditEntry(entry, `${label}.auditEntries[${index}]`),\n\t);\n\tif (actions.length === 0 && auditEntries.length === 0) throw new Error(`${label} must not be empty`);\n\tif (new Set(auditEntries.map((entry) => entry.eventId)).size !== auditEntries.length) {\n\t\tthrow new Error(`${label}.auditEntries contains duplicate event ids`);\n\t}\n\treturn { schemaVersion: 1, actions, auditEntries };\n}\n\nfunction fileMissing(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n\nasync function readRegularFileIfExists(path: string, label: string): Promise<string | undefined> {\n\ttry {\n\t\treturn (await readRegularFileNoFollow(path, label)).toString(\"utf8\");\n\t} catch (error) {\n\t\tif (fileMissing(error)) return undefined;\n\t\tthrow error;\n\t}\n}\n\nasync function atomicWriteJsonNoFollow(path: string, value: unknown, label: string): Promise<void> {\n\tawait atomicWriteRegularFileNoFollow(path, `${JSON.stringify(value, undefined, \"\\t\")}\\n`, label);\n}\n\nfunction cloneFragment(fragment: EvoMemoryFragment): EvoMemoryFragment {\n\treturn parseFragment(JSON.parse(canonicalJson(fragment)) as unknown, \"memory fragment\");\n}\n\nfunction tokenize(value: string): Set<string> {\n\treturn new Set(\n\t\tvalue\n\t\t\t.toLocaleLowerCase(\"en-US\")\n\t\t\t.split(/[^\\p{L}\\p{N}]+/u)\n\t\t\t.filter(Boolean),\n\t);\n}\n\nexport class EvoMemoryStore {\n\treadonly componentId: string;\n\treadonly artifactDigest: string;\n\treadonly root: string;\n\tprivate readonly paths: EvoPaths;\n\tprivate readonly namespaceRoot: string;\n\tprivate readonly objectsRoot: string;\n\tprivate readonly stableHistoryRoot: string;\n\tprivate readonly trialsRoot: string;\n\tprivate readonly stablePath: string;\n\tprivate readonly auditPath: string;\n\tprivate readonly transactionPath: string;\n\tprivate readonly lockName: string;\n\tprivate readonly layoutAnchor: string | undefined;\n\tprivate readonly now: () => string;\n\tprivate readonly randomId: () => string;\n\tprivate readonly faultInjection: ((point: EvoMemoryFaultPoint) => void | Promise<void>) | undefined;\n\n\tconstructor(options: EvoMemoryStoreOptions) {\n\t\tassertEvoComponentId(options.componentId);\n\t\tif (!isDigest(options.artifactDigest)) throw new Error(\"artifactDigest must be a sha256 digest\");\n\t\tthis.paths = options.paths;\n\t\tthis.componentId = options.componentId;\n\t\tthis.artifactDigest = options.artifactDigest;\n\t\tthis.root = resolve(options.root ?? join(options.paths.root, \"component-memory\"));\n\t\tthis.layoutAnchor = options.root === undefined ? resolve(options.paths.root) : undefined;\n\t\tthis.namespaceRoot = join(this.root, \"namespaces\", this.componentId, this.artifactDigest);\n\t\tthis.objectsRoot = join(this.namespaceRoot, \"objects\", \"sha256\");\n\t\tthis.stableHistoryRoot = join(this.namespaceRoot, \"stable-history\");\n\t\tthis.trialsRoot = join(this.namespaceRoot, \"trials\");\n\t\tthis.stablePath = join(this.namespaceRoot, \"stable.json\");\n\t\tthis.auditPath = join(this.namespaceRoot, \"audit.jsonl\");\n\t\tthis.transactionPath = join(this.namespaceRoot, \"transaction.json\");\n\t\tthis.lockName = `memory-${sha256(`${this.componentId}\\0${this.artifactDigest}`).slice(0, 32)}`;\n\t\tthis.now = options.now ?? (() => new Date().toISOString());\n\t\tthis.randomId = options.randomId ?? randomUUID;\n\t\tthis.faultInjection = options.faultInjection;\n\t}\n\n\tprivate async ensureLayout(): Promise<void> {\n\t\tif (!this.layoutAnchor) {\n\t\t\tawait ensurePrivateDirectoryNoFollow(this.root, \"component memory root\");\n\t\t}\n\t\tconst trustedRoot = this.layoutAnchor ?? this.root;\n\t\tfor (const directory of [\n\t\t\tthis.root,\n\t\t\tjoin(this.root, \"namespaces\"),\n\t\t\tthis.namespaceRoot,\n\t\t\tthis.objectsRoot,\n\t\t\tthis.stableHistoryRoot,\n\t\t\tthis.trialsRoot,\n\t\t]) {\n\t\t\tawait ensurePrivateDirectoryNoFollow(directory, \"component memory directory\", trustedRoot);\n\t\t}\n\t}\n\n\tprivate trialPath(bundleDigest: string): string {\n\t\treturn join(this.trialsRoot, `${requireDigest(bundleDigest, \"trial bundle digest\")}.json`);\n\t}\n\n\tprivate stableHistoryPath(bundleDigest: string): string {\n\t\treturn join(this.stableHistoryRoot, `${requireDigest(bundleDigest, \"stable bundle digest\")}.json`);\n\t}\n\n\tprivate pointerPath(kind: EvoMemoryNamespaceKind, bundleDigest: string): string {\n\t\treturn kind === \"stable\" ? this.stablePath : this.trialPath(bundleDigest);\n\t}\n\n\tprivate async readPointer(path: string, label: string): Promise<EvoMemoryNamespacePointer | undefined> {\n\t\tconst content = await readRegularFileIfExists(path, label);\n\t\tif (content === undefined) return undefined;\n\t\tlet value: unknown;\n\t\ttry {\n\t\t\tvalue = JSON.parse(content) as unknown;\n\t\t} catch (error) {\n\t\t\tthrow new Error(`${label} contains invalid JSON`, { cause: error });\n\t\t}\n\t\treturn parsePointer(value, label);\n\t}\n\n\tprivate async writeSnapshot(snapshot: EvoMemorySnapshot): Promise<string> {\n\t\tconst parsed = parseSnapshot(snapshot, \"memory snapshot\");\n\t\tconst digest = sha256(canonicalJson(parsed));\n\t\tconst path = join(this.objectsRoot, `${digest}.json`);\n\t\tconst existing = await readRegularFileIfExists(path, `memory object ${digest}`);\n\t\tif (existing !== undefined) {\n\t\t\tlet value: unknown;\n\t\t\ttry {\n\t\t\t\tvalue = JSON.parse(existing) as unknown;\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(`memory object ${digest} contains invalid JSON`, { cause: error });\n\t\t\t}\n\t\t\tconst persisted = parseSnapshot(value, `memory object ${digest}`);\n\t\t\tif (sha256(canonicalJson(persisted)) !== digest)\n\t\t\t\tthrow new Error(`memory object ${digest} failed digest verification`);\n\t\t\treturn digest;\n\t\t}\n\t\tawait atomicWriteJsonNoFollow(path, parsed, `memory object ${digest}`);\n\t\treturn digest;\n\t}\n\n\tprivate async readSnapshot(stateDigest: string): Promise<EvoMemorySnapshot> {\n\t\tconst digest = requireDigest(stateDigest, \"memory state digest\");\n\t\tconst label = `memory object ${digest}`;\n\t\tconst content = await readRegularFileIfExists(join(this.objectsRoot, `${digest}.json`), label);\n\t\tif (content === undefined) throw new Error(`${label} does not exist`);\n\t\tlet value: unknown;\n\t\ttry {\n\t\t\tvalue = JSON.parse(content) as unknown;\n\t\t} catch (error) {\n\t\t\tthrow new Error(`${label} contains invalid JSON`, { cause: error });\n\t\t}\n\t\tconst snapshot = parseSnapshot(value, label);\n\t\tif (sha256(canonicalJson(snapshot)) !== digest) throw new Error(`${label} failed digest verification`);\n\t\treturn snapshot;\n\t}\n\n\tprivate timestamp(): string {\n\t\treturn requireTimestamp(this.now(), \"memory timestamp\");\n\t}\n\n\tprivate eventId(): string {\n\t\treturn requireMemoryId(this.randomId(), \"memory audit event id\");\n\t}\n\n\tprivate createAuditEntry(\n\t\toperation: EvoMemoryAuditOperation,\n\t\tpointer: EvoMemoryNamespacePointer,\n\t\tfragmentId: string | null,\n\t\tstateBefore: string | null,\n\t\tstateAfter: string | null,\n\t): EvoMemoryAuditEntry {\n\t\treturn {\n\t\t\tschemaVersion: 1,\n\t\t\teventId: this.eventId(),\n\t\t\ttimestamp: this.timestamp(),\n\t\t\tcomponentId: this.componentId,\n\t\t\tartifactDigest: this.artifactDigest,\n\t\t\toperation,\n\t\t\tnamespace: pointer.kind,\n\t\t\tbundleDigest: pointer.bundleDigest,\n\t\t\tparentBundleDigest: pointer.parentBundleDigest,\n\t\t\tfragmentId,\n\t\t\tstateBefore,\n\t\t\tstateAfter,\n\t\t};\n\t}\n\n\tprivate async repairAuditTail(): Promise<void> {\n\t\tconst content = await readRegularFileIfExists(this.auditPath, \"memory audit log\");\n\t\tif (content === undefined || !content || content.endsWith(\"\\n\")) return;\n\t\tconst finalNewline = content.lastIndexOf(\"\\n\");\n\t\tawait atomicWriteRegularFileNoFollow(this.auditPath, content.slice(0, finalNewline + 1), \"memory audit log\");\n\t}\n\n\tprivate async readAuditEntries(): Promise<EvoMemoryAuditEntry[]> {\n\t\tawait this.repairAuditTail();\n\t\tconst content = await readRegularFileIfExists(this.auditPath, \"memory audit log\");\n\t\tif (content === undefined || !content.trim()) return [];\n\t\tconst entries = content\n\t\t\t.trimEnd()\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line, index) => {\n\t\t\t\tlet value: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tvalue = JSON.parse(line) as unknown;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new Error(`memory audit log line ${index + 1} contains invalid JSON`, { cause: error });\n\t\t\t\t}\n\t\t\t\treturn parseAuditEntry(value, `memory audit log line ${index + 1}`);\n\t\t\t});\n\t\tconst eventIds = new Set<string>();\n\t\tfor (const entry of entries) {\n\t\t\tif (eventIds.has(entry.eventId)) throw new Error(`memory audit log repeats event id ${entry.eventId}`);\n\t\t\teventIds.add(entry.eventId);\n\t\t}\n\t\treturn entries;\n\t}\n\n\tprivate async appendAuditEntriesOnce(entries: readonly EvoMemoryAuditEntry[]): Promise<void> {\n\t\tconst existing = new Map((await this.readAuditEntries()).map((entry) => [entry.eventId, entry]));\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.componentId !== this.componentId || entry.artifactDigest !== this.artifactDigest) {\n\t\t\t\tthrow new Error(\"Memory transaction audit identity does not match this store\");\n\t\t\t}\n\t\t\tconst persisted = existing.get(entry.eventId);\n\t\t\tif (persisted) {\n\t\t\t\tif (canonicalJson(persisted) !== canonicalJson(entry)) {\n\t\t\t\t\tthrow new Error(`Memory audit event id ${entry.eventId} has conflicting content`);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait appendRegularFileNoFollow(this.auditPath, `${JSON.stringify(entry)}\\n`, \"memory audit log\");\n\t\t\texisting.set(entry.eventId, entry);\n\t\t\tawait this.faultInjection?.(\"after-audit-append\");\n\t\t}\n\t}\n\n\tprivate pointerLocationPath(location: EvoMemoryPointerLocation): { path: string; label: string } {\n\t\tif (location.kind === \"stable\") return { path: this.stablePath, label: \"stable memory pointer\" };\n\t\tif (location.kind === \"trial\") {\n\t\t\treturn { path: this.trialPath(location.bundleDigest), label: \"trial memory pointer\" };\n\t\t}\n\t\treturn {\n\t\t\tpath: this.stableHistoryPath(location.bundleDigest),\n\t\t\tlabel: \"stable memory history pointer\",\n\t\t};\n\t}\n\n\tprivate async applyPointerAction(action: EvoMemoryPointerAction): Promise<void> {\n\t\tconst { path, label } = this.pointerLocationPath(action.location);\n\t\tconst current = (await this.readPointer(path, label)) ?? null;\n\t\tif (pointerEquals(current, action.after)) return;\n\t\tif (!pointerEquals(current, action.before)) {\n\t\t\tthrow new Error(`${label} changed outside its pending memory transaction`);\n\t\t}\n\t\tif (action.after) await atomicWriteJsonNoFollow(path, action.after, label);\n\t\telse await durableUnlinkRegularFileNoFollow(path, label);\n\t}\n\n\tprivate async readPendingTransaction(): Promise<EvoMemoryTransaction | undefined> {\n\t\tconst content = await readRegularFileIfExists(this.transactionPath, \"memory transaction outbox\");\n\t\tif (content === undefined) return undefined;\n\t\tlet value: unknown;\n\t\ttry {\n\t\t\tvalue = JSON.parse(content) as unknown;\n\t\t} catch (error) {\n\t\t\tthrow new Error(\"memory transaction outbox contains invalid JSON\", { cause: error });\n\t\t}\n\t\treturn parseTransaction(value, \"memory transaction outbox\");\n\t}\n\n\tprivate async recoverPendingTransaction(): Promise<void> {\n\t\tconst transaction = await this.readPendingTransaction();\n\t\tif (!transaction) return;\n\t\tconst existingAudit = new Map((await this.readAuditEntries()).map((entry) => [entry.eventId, entry]));\n\t\tfor (const entry of transaction.auditEntries) {\n\t\t\tif (entry.componentId !== this.componentId || entry.artifactDigest !== this.artifactDigest) {\n\t\t\t\tthrow new Error(\"Memory transaction audit identity does not match this store\");\n\t\t\t}\n\t\t\tconst existing = existingAudit.get(entry.eventId);\n\t\t\tif (existing && canonicalJson(existing) !== canonicalJson(entry)) {\n\t\t\t\tthrow new Error(`Memory audit event id ${entry.eventId} has conflicting content`);\n\t\t\t}\n\t\t}\n\t\tfor (const action of transaction.actions) {\n\t\t\tawait this.applyPointerAction(action);\n\t\t\tawait this.faultInjection?.(\"after-pointer-action\");\n\t\t}\n\t\tawait this.appendAuditEntriesOnce(transaction.auditEntries);\n\t\tawait this.faultInjection?.(\"before-outbox-remove\");\n\t\tawait durableUnlinkRegularFileNoFollow(this.transactionPath, \"memory transaction outbox\");\n\t}\n\n\tprivate async commitTransaction(\n\t\tactions: readonly EvoMemoryPointerAction[],\n\t\tauditEntries: readonly EvoMemoryAuditEntry[],\n\t): Promise<void> {\n\t\tif (actions.length === 0 && auditEntries.length === 0) return;\n\t\tif (await this.readPendingTransaction()) throw new Error(\"A memory transaction is already pending\");\n\t\tconst transaction = parseTransaction({ schemaVersion: 1, actions, auditEntries }, \"memory transaction outbox\");\n\t\tawait atomicWriteJsonNoFollow(this.transactionPath, transaction, \"memory transaction outbox\");\n\t\tawait this.faultInjection?.(\"after-outbox-write\");\n\t\tawait this.recoverPendingTransaction();\n\t}\n\n\tprivate async withMemoryLock<T>(operation: () => Promise<T>): Promise<T> {\n\t\treturn withFileLock(this.paths, this.lockName, async () => {\n\t\t\tawait this.ensureLayout();\n\t\t\tawait this.recoverPendingTransaction();\n\t\t\treturn operation();\n\t\t});\n\t}\n\n\tprivate async stableHistoryAction(pointer: EvoMemoryNamespacePointer): Promise<EvoMemoryPointerAction | undefined> {\n\t\tif (pointer.kind !== \"stable\") throw new Error(\"Only stable memory pointers can be archived\");\n\t\tconst location: EvoMemoryPointerLocation = { kind: \"stable-history\", bundleDigest: pointer.bundleDigest };\n\t\tconst { path, label } = this.pointerLocationPath(location);\n\t\tconst existing = (await this.readPointer(path, label)) ?? null;\n\t\tif (pointerEquals(existing, pointer)) return undefined;\n\t\tif (existing) throw new Error(\"Stable memory history conflicts with the pending checkpoint\");\n\t\treturn { location, before: null, after: pointer };\n\t}\n\n\tprivate async resolveStableCheckpoint(bundleDigest: string): Promise<EvoMemoryNamespacePointer | undefined> {\n\t\tconst digest = requireDigest(bundleDigest, \"stable checkpoint bundle digest\");\n\t\tconst archived = await this.readPointer(this.stableHistoryPath(digest), \"stable memory history pointer\");\n\t\tif (archived) {\n\t\t\tif (archived.kind !== \"stable\" || archived.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Stable memory history pointer does not match its bundle\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(archived.stateDigest);\n\t\t\treturn archived;\n\t\t}\n\t\tconst audit = await this.readAuditEntries();\n\t\tfor (let index = audit.length - 1; index >= 0; index--) {\n\t\t\tconst entry = audit[index];\n\t\t\tif (\n\t\t\t\tentry?.operation !== \"promote\" ||\n\t\t\t\tentry.namespace !== \"trial\" ||\n\t\t\t\tentry.parentBundleDigest !== digest ||\n\t\t\t\tentry.stateBefore === null\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait this.readSnapshot(entry.stateBefore);\n\t\t\treturn {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tkind: \"stable\",\n\t\t\t\tbundleDigest: digest,\n\t\t\t\tparentBundleDigest: null,\n\t\t\t\tstateDigest: entry.stateBefore,\n\t\t\t};\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tprivate async createPromoteAuditEntryOnce(\n\t\ttrial: EvoMemoryNamespacePointer,\n\t\tstateBefore: string,\n\t\tstateAfter: string,\n\t): Promise<EvoMemoryAuditEntry | undefined> {\n\t\tconst existing = (await this.readAuditEntries()).some(\n\t\t\t(entry) =>\n\t\t\t\tentry.operation === \"promote\" &&\n\t\t\t\tentry.namespace === \"trial\" &&\n\t\t\t\tentry.bundleDigest === trial.bundleDigest &&\n\t\t\t\tentry.parentBundleDigest === trial.parentBundleDigest &&\n\t\t\t\tentry.stateBefore === stateBefore &&\n\t\t\t\tentry.stateAfter === stateAfter,\n\t\t);\n\t\treturn existing ? undefined : this.createAuditEntry(\"promote\", trial, null, stateBefore, stateAfter);\n\t}\n\n\tprivate async hasUnresolvedTrialAudit(bundleDigest: string): Promise<boolean> {\n\t\tlet unresolved = false;\n\t\tfor (const entry of await this.readAuditEntries()) {\n\t\t\tif (entry.namespace !== \"trial\" || entry.bundleDigest !== bundleDigest) continue;\n\t\t\tif (entry.operation === \"trial-start\") unresolved = true;\n\t\t\tif (entry.operation === \"promote\" || entry.operation === \"rollback\") unresolved = false;\n\t\t}\n\t\treturn unresolved;\n\t}\n\n\tprivate async readBundleRollbackState(options: {\n\t\trolledBackBundleDigests: string[];\n\t\ttargetBundleDigest: string;\n\t\ttargetAncestorBundleDigests: string[];\n\t\ttargetSelected: boolean;\n\t}): Promise<EvoMemoryBundleRollbackState> {\n\t\tconst stable = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\tconst trials: EvoMemoryNamespacePointer[] = [];\n\t\tfor (const digest of options.rolledBackBundleDigests) {\n\t\t\tconst trial = await this.readPointer(this.trialPath(digest), \"trial memory pointer\");\n\t\t\tif (!trial) continue;\n\t\t\tif (trial.kind !== \"trial\" || trial.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Trial memory does not match the registry rollback lineage\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(trial.stateDigest);\n\t\t\ttrials.push(trial);\n\t\t}\n\t\tconst targetTrial = options.targetSelected\n\t\t\t? await this.readPointer(this.trialPath(options.targetBundleDigest), \"rollback target trial memory pointer\")\n\t\t\t: undefined;\n\t\tif (targetTrial) {\n\t\t\tif (targetTrial.kind !== \"trial\" || targetTrial.bundleDigest !== options.targetBundleDigest) {\n\t\t\t\tthrow new Error(\"Target trial memory does not match the registry rollback target\");\n\t\t\t}\n\t\t\tif (targetTrial.parentBundleDigest !== options.targetAncestorBundleDigests[0]) {\n\t\t\t\tthrow new Error(\"Target trial memory parent does not match the verified target lineage\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(targetTrial.stateDigest);\n\t\t}\n\t\tif (!stable) {\n\t\t\tif (trials.length > 0 || targetTrial) throw new Error(\"Trial memory exists without a stable parent\");\n\t\t\treturn { trials };\n\t\t}\n\t\tawait this.readSnapshot(stable.stateDigest);\n\t\tconst allowedStableDigests = new Set([\n\t\t\t...options.rolledBackBundleDigests,\n\t\t\toptions.targetBundleDigest,\n\t\t\t...options.targetAncestorBundleDigests,\n\t\t]);\n\t\tif (!allowedStableDigests.has(stable.bundleDigest)) {\n\t\t\tthrow new Error(\"Stable memory points outside the registry rollback lineage\");\n\t\t}\n\t\tif (!options.targetSelected) return { stable, trials };\n\t\tif (stable.bundleDigest === options.targetBundleDigest) {\n\t\t\tif (!targetTrial) return { stable, trials, target: stable };\n\t\t\tif (targetTrial.stateDigest !== stable.stateDigest) {\n\t\t\t\tthrow new Error(\"Rollback target stable memory disagrees with its remaining trial pointer\");\n\t\t\t}\n\t\t\tconst parentBundleDigest = targetTrial.parentBundleDigest;\n\t\t\tif (!parentBundleDigest) throw new Error(\"Rollback target trial memory is missing its parent bundle\");\n\t\t\tconst parent = await this.resolveStableCheckpoint(parentBundleDigest);\n\t\t\tif (!parent) throw new Error(\"Rollback target trial memory is missing its parent checkpoint\");\n\t\t\treturn {\n\t\t\t\tstable,\n\t\t\t\ttrials,\n\t\t\t\ttarget: stable,\n\t\t\t\ttargetTrial,\n\t\t\t\ttargetTrialStateBefore: parent.stateDigest,\n\t\t\t};\n\t\t}\n\t\tif (targetTrial) {\n\t\t\tif (targetTrial.parentBundleDigest !== stable.bundleDigest) {\n\t\t\t\tthrow new Error(\"Rollback target trial parent no longer matches stable memory\");\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstable,\n\t\t\t\ttrials,\n\t\t\t\ttarget: {\n\t\t\t\t\tschemaVersion: 1,\n\t\t\t\t\tkind: \"stable\",\n\t\t\t\t\tbundleDigest: options.targetBundleDigest,\n\t\t\t\t\tparentBundleDigest: null,\n\t\t\t\t\tstateDigest: targetTrial.stateDigest,\n\t\t\t\t},\n\t\t\t\ttargetTrial,\n\t\t\t\ttargetTrialStateBefore: stable.stateDigest,\n\t\t\t};\n\t\t}\n\t\tif (await this.hasUnresolvedTrialAudit(options.targetBundleDigest)) {\n\t\t\tthrow new Error(`Trial memory audit is unresolved for rollback target ${options.targetBundleDigest}`);\n\t\t}\n\t\tconst target = await this.resolveStableCheckpoint(options.targetBundleDigest);\n\t\tif (target) return { stable, trials, target };\n\t\tif (options.targetAncestorBundleDigests.includes(stable.bundleDigest)) {\n\t\t\treturn {\n\t\t\t\tstable,\n\t\t\t\ttrials,\n\t\t\t\ttarget: {\n\t\t\t\t\tschemaVersion: 1,\n\t\t\t\t\tkind: \"stable\",\n\t\t\t\t\tbundleDigest: options.targetBundleDigest,\n\t\t\t\t\tparentBundleDigest: null,\n\t\t\t\t\tstateDigest: stable.stateDigest,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tthrow new Error(`Stable memory history is not initialized for rollback target ${options.targetBundleDigest}`);\n\t}\n\n\tasync initializeStable(bundleDigest: string): Promise<EvoMemoryNamespace> {\n\t\tconst digest = requireDigest(bundleDigest, \"stable bundle digest\");\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst existing = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (existing) {\n\t\t\t\tif (existing.kind !== \"stable\" || existing.bundleDigest !== digest) {\n\t\t\t\t\tthrow new Error(\"Stable memory is already initialized for a different bundle\");\n\t\t\t\t}\n\t\t\t\tawait this.readSnapshot(existing.stateDigest);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst stateDigest = await this.writeSnapshot({ schemaVersion: 1, fragments: [] });\n\t\t\tconst pointer: EvoMemoryNamespacePointer = {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tkind: \"stable\",\n\t\t\t\tbundleDigest: digest,\n\t\t\t\tparentBundleDigest: null,\n\t\t\t\tstateDigest,\n\t\t\t};\n\t\t\tawait this.commitTransaction(\n\t\t\t\t[{ location: { kind: \"stable\" }, before: null, after: pointer }],\n\t\t\t\t[this.createAuditEntry(\"initialize\", pointer, null, null, stateDigest)],\n\t\t\t);\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"stable\", digest);\n\t}\n\n\tasync openStable(bundleDigest: string): Promise<EvoMemoryNamespace> {\n\t\tconst digest = requireDigest(bundleDigest, \"stable bundle digest\");\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst pointer = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (!pointer || pointer.kind !== \"stable\" || pointer.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Stable memory is not initialized for this bundle\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(pointer.stateDigest);\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"stable\", digest);\n\t}\n\n\tasync beginTrial(options: EvoMemoryTrialOptions): Promise<EvoMemoryNamespace> {\n\t\tconst parentBundleDigest = requireDigest(options.parentBundleDigest, \"trial parent bundle digest\");\n\t\tconst trialBundleDigest = requireDigest(options.trialBundleDigest, \"trial bundle digest\");\n\t\tif (parentBundleDigest === trialBundleDigest) throw new Error(\"Trial bundle must differ from its parent\");\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst stable = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (!stable || stable.kind !== \"stable\" || stable.bundleDigest !== parentBundleDigest) {\n\t\t\t\tthrow new Error(\"Trial parent does not match stable memory\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(stable.stateDigest);\n\t\t\tconst path = this.trialPath(trialBundleDigest);\n\t\t\tconst existing = await this.readPointer(path, \"trial memory pointer\");\n\t\t\tif (existing) {\n\t\t\t\tif (\n\t\t\t\t\texisting.kind !== \"trial\" ||\n\t\t\t\t\texisting.bundleDigest !== trialBundleDigest ||\n\t\t\t\t\texisting.parentBundleDigest !== parentBundleDigest\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Existing trial memory does not match the requested trial\");\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst pointer: EvoMemoryNamespacePointer = {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tkind: \"trial\",\n\t\t\t\tbundleDigest: trialBundleDigest,\n\t\t\t\tparentBundleDigest,\n\t\t\t\tstateDigest: stable.stateDigest,\n\t\t\t};\n\t\t\tawait this.commitTransaction(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: trialBundleDigest },\n\t\t\t\t\t\tbefore: null,\n\t\t\t\t\t\tafter: pointer,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t[this.createAuditEntry(\"trial-start\", pointer, null, stable.stateDigest, stable.stateDigest)],\n\t\t\t);\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"trial\", trialBundleDigest);\n\t}\n\n\tasync openTrial(trialBundleDigest: string): Promise<EvoMemoryNamespace> {\n\t\tconst digest = requireDigest(trialBundleDigest, \"trial bundle digest\");\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst pointer = await this.readPointer(this.trialPath(digest), \"trial memory pointer\");\n\t\t\tif (!pointer || pointer.kind !== \"trial\" || pointer.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Trial memory is not initialized for this bundle\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(pointer.stateDigest);\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"trial\", digest);\n\t}\n\n\tasync promoteTrial(trialBundleDigest: string): Promise<EvoMemoryNamespace> {\n\t\tconst digest = requireDigest(trialBundleDigest, \"trial bundle digest\");\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst trial = await this.readPointer(this.trialPath(digest), \"trial memory pointer\");\n\t\t\tconst stable = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (!trial) {\n\t\t\t\tif (!stable || stable.kind !== \"stable\" || stable.bundleDigest !== digest) {\n\t\t\t\t\tthrow new Error(\"Trial memory is not initialized for this bundle\");\n\t\t\t\t}\n\t\t\t\tawait this.readSnapshot(stable.stateDigest);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (trial.kind !== \"trial\" || trial.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Trial memory does not match the promoted bundle\");\n\t\t\t}\n\t\t\tif (!stable || stable.kind !== \"stable\") {\n\t\t\t\tthrow new Error(\"Trial parent no longer matches stable memory\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(trial.stateDigest);\n\t\t\tconst parentBundleDigest = trial.parentBundleDigest;\n\t\t\tif (!parentBundleDigest) throw new Error(\"Trial memory is missing its parent bundle\");\n\t\t\tif (stable.bundleDigest === digest) {\n\t\t\t\tif (stable.stateDigest !== trial.stateDigest) {\n\t\t\t\t\tthrow new Error(\"Promoted stable memory disagrees with its remaining trial pointer\");\n\t\t\t\t}\n\t\t\t\tconst parent = await this.resolveStableCheckpoint(parentBundleDigest);\n\t\t\t\tif (!parent) throw new Error(\"Promoted memory is missing its parent checkpoint\");\n\t\t\t\tconst auditEntry = await this.createPromoteAuditEntryOnce(trial, parent.stateDigest, trial.stateDigest);\n\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: digest },\n\t\t\t\t\t\t\tbefore: trial,\n\t\t\t\t\t\t\tafter: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tauditEntry ? [auditEntry] : [],\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (stable.bundleDigest !== parentBundleDigest) {\n\t\t\t\tthrow new Error(\"Trial parent no longer matches stable memory\");\n\t\t\t}\n\t\t\tawait this.readSnapshot(stable.stateDigest);\n\t\t\tconst promoted: EvoMemoryNamespacePointer = {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tkind: \"stable\",\n\t\t\t\tbundleDigest: trial.bundleDigest,\n\t\t\t\tparentBundleDigest: null,\n\t\t\t\tstateDigest: trial.stateDigest,\n\t\t\t};\n\t\t\tconst historyAction = await this.stableHistoryAction(stable);\n\t\t\tconst auditEntry = await this.createPromoteAuditEntryOnce(trial, stable.stateDigest, trial.stateDigest);\n\t\t\tconst actions: EvoMemoryPointerAction[] = [\n\t\t\t\t...(historyAction ? [historyAction] : []),\n\t\t\t\t{ location: { kind: \"stable\" }, before: stable, after: promoted },\n\t\t\t\t{ location: { kind: \"trial\", bundleDigest: digest }, before: trial, after: null },\n\t\t\t];\n\t\t\tawait this.commitTransaction(actions, auditEntry ? [auditEntry] : []);\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"stable\", digest);\n\t}\n\n\tasync materializeStableForBundle(options: EvoMemoryStableMaterializationOptions): Promise<EvoMemoryNamespace> {\n\t\tconst targetBundleDigest = requireDigest(options.targetBundleDigest, \"materialized stable bundle digest\");\n\t\tif (!Array.isArray(options.targetAncestorBundleDigests)) {\n\t\t\tthrow new Error(\"materialized stable ancestor lineage must be an array\");\n\t\t}\n\t\tconst targetAncestorBundleDigests = options.targetAncestorBundleDigests.map((digest, index) =>\n\t\t\trequireDigest(digest, `materialized stable ancestor lineage[${index}]`),\n\t\t);\n\t\tif (new Set(targetAncestorBundleDigests).size !== targetAncestorBundleDigests.length) {\n\t\t\tthrow new Error(\"materialized stable ancestor lineage must not contain duplicates\");\n\t\t}\n\t\tif (targetAncestorBundleDigests.includes(targetBundleDigest)) {\n\t\t\tthrow new Error(\"materialized stable ancestor lineage must not contain its target\");\n\t\t}\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tlet stable = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (!stable) {\n\t\t\t\tfor (const digest of [targetBundleDigest, ...targetAncestorBundleDigests]) {\n\t\t\t\t\tif (await this.readPointer(this.trialPath(digest), \"materialized lineage trial memory pointer\")) {\n\t\t\t\t\t\tthrow new Error(\"Trial memory exists without a stable parent\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst stateDigest = await this.writeSnapshot({ schemaVersion: 1, fragments: [] });\n\t\t\t\tconst initialized: EvoMemoryNamespacePointer = {\n\t\t\t\t\tschemaVersion: 1,\n\t\t\t\t\tkind: \"stable\",\n\t\t\t\t\tbundleDigest: targetBundleDigest,\n\t\t\t\t\tparentBundleDigest: null,\n\t\t\t\t\tstateDigest,\n\t\t\t\t};\n\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t[{ location: { kind: \"stable\" }, before: null, after: initialized }],\n\t\t\t\t\t[this.createAuditEntry(\"initialize\", initialized, null, null, stateDigest)],\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (stable.kind !== \"stable\") throw new Error(\"Stable memory pointer has the wrong namespace kind\");\n\t\t\tawait this.readSnapshot(stable.stateDigest);\n\t\t\tconst stableAncestorIndex =\n\t\t\t\tstable.bundleDigest === targetBundleDigest ? -1 : targetAncestorBundleDigests.indexOf(stable.bundleDigest);\n\t\t\tif (stable.bundleDigest !== targetBundleDigest && stableAncestorIndex < 0) {\n\t\t\t\tthrow new Error(\"Stable memory points outside the registry-verified materialization lineage\");\n\t\t\t}\n\n\t\t\tconst remainingStableTrial = await this.readPointer(\n\t\t\t\tthis.trialPath(stable.bundleDigest),\n\t\t\t\t\"remaining promoted trial memory pointer\",\n\t\t\t);\n\t\t\tif (remainingStableTrial) {\n\t\t\t\tconst expectedParentBundleDigest =\n\t\t\t\t\tstable.bundleDigest === targetBundleDigest\n\t\t\t\t\t\t? targetAncestorBundleDigests[0]\n\t\t\t\t\t\t: targetAncestorBundleDigests[stableAncestorIndex + 1];\n\t\t\t\tif (\n\t\t\t\t\tremainingStableTrial.kind !== \"trial\" ||\n\t\t\t\t\tremainingStableTrial.bundleDigest !== stable.bundleDigest ||\n\t\t\t\t\tremainingStableTrial.parentBundleDigest !== expectedParentBundleDigest ||\n\t\t\t\t\tremainingStableTrial.stateDigest !== stable.stateDigest\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Remaining promoted trial memory does not match the registry-verified lineage\");\n\t\t\t\t}\n\t\t\t\tif (!expectedParentBundleDigest) {\n\t\t\t\t\tthrow new Error(\"Remaining promoted trial memory has no verified parent\");\n\t\t\t\t}\n\t\t\t\tconst parent = await this.resolveStableCheckpoint(expectedParentBundleDigest);\n\t\t\t\tif (!parent) throw new Error(\"Remaining promoted trial memory is missing its parent checkpoint\");\n\t\t\t\tconst auditEntry = await this.createPromoteAuditEntryOnce(\n\t\t\t\t\tremainingStableTrial,\n\t\t\t\t\tparent.stateDigest,\n\t\t\t\t\tremainingStableTrial.stateDigest,\n\t\t\t\t);\n\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: remainingStableTrial.bundleDigest },\n\t\t\t\t\t\t\tbefore: remainingStableTrial,\n\t\t\t\t\t\t\tafter: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tauditEntry ? [auditEntry] : [],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (stable.bundleDigest === targetBundleDigest) return;\n\n\t\t\tconst materializedBundleDigests = [\n\t\t\t\t...targetAncestorBundleDigests.slice(0, stableAncestorIndex).reverse(),\n\t\t\t\ttargetBundleDigest,\n\t\t\t];\n\t\t\tfor (const bundleDigest of materializedBundleDigests) {\n\t\t\t\tlet trial = await this.readPointer(\n\t\t\t\t\tthis.trialPath(bundleDigest),\n\t\t\t\t\t\"materialized lineage trial memory pointer\",\n\t\t\t\t);\n\t\t\t\tif (trial) {\n\t\t\t\t\tif (\n\t\t\t\t\t\ttrial.kind !== \"trial\" ||\n\t\t\t\t\t\ttrial.bundleDigest !== bundleDigest ||\n\t\t\t\t\t\ttrial.parentBundleDigest !== stable.bundleDigest\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new Error(\"Materialized trial memory does not match the registry-verified lineage\");\n\t\t\t\t\t}\n\t\t\t\t\tawait this.readSnapshot(trial.stateDigest);\n\t\t\t\t} else {\n\t\t\t\t\ttrial = {\n\t\t\t\t\t\tschemaVersion: 1,\n\t\t\t\t\t\tkind: \"trial\",\n\t\t\t\t\t\tbundleDigest,\n\t\t\t\t\t\tparentBundleDigest: stable.bundleDigest,\n\t\t\t\t\t\tstateDigest: stable.stateDigest,\n\t\t\t\t\t};\n\t\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest },\n\t\t\t\t\t\t\t\tbefore: null,\n\t\t\t\t\t\t\t\tafter: trial,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\t[this.createAuditEntry(\"trial-start\", trial, null, stable.stateDigest, stable.stateDigest)],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst promoted: EvoMemoryNamespacePointer = {\n\t\t\t\t\tschemaVersion: 1,\n\t\t\t\t\tkind: \"stable\",\n\t\t\t\t\tbundleDigest,\n\t\t\t\t\tparentBundleDigest: null,\n\t\t\t\t\tstateDigest: trial.stateDigest,\n\t\t\t\t};\n\t\t\t\tconst historyAction = await this.stableHistoryAction(stable);\n\t\t\t\tconst auditEntry = await this.createPromoteAuditEntryOnce(trial, stable.stateDigest, trial.stateDigest);\n\t\t\t\tconst actions: EvoMemoryPointerAction[] = [\n\t\t\t\t\t...(historyAction ? [historyAction] : []),\n\t\t\t\t\t{ location: { kind: \"stable\" }, before: stable, after: promoted },\n\t\t\t\t\t{ location: { kind: \"trial\", bundleDigest }, before: trial, after: null },\n\t\t\t\t];\n\t\t\t\tawait this.commitTransaction(actions, auditEntry ? [auditEntry] : []);\n\t\t\t\tstable = promoted;\n\t\t\t}\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"stable\", targetBundleDigest);\n\t}\n\n\tasync preflightBundleRollback(options: EvoMemoryBundleRollbackOptions): Promise<void> {\n\t\tconst parsed = parseBundleRollbackOptions(options);\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tawait this.readBundleRollbackState(parsed);\n\t\t});\n\t}\n\n\tasync rollbackBundles(options: EvoMemoryBundleRollbackOptions): Promise<void> {\n\t\tconst parsed = parseBundleRollbackOptions(options);\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst state = await this.readBundleRollbackState(parsed);\n\t\t\tconst stateAfter = state.target?.stateDigest ?? null;\n\t\t\tfor (const trial of state.trials) {\n\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: trial.bundleDigest },\n\t\t\t\t\t\t\tbefore: trial,\n\t\t\t\t\t\t\tafter: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\t[this.createAuditEntry(\"rollback\", trial, null, trial.stateDigest, stateAfter)],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!state.stable) return;\n\t\t\tif (!parsed.targetSelected) {\n\t\t\t\tconst historyAction = await this.stableHistoryAction(state.stable);\n\t\t\t\tconst actions: EvoMemoryPointerAction[] = [\n\t\t\t\t\t...(historyAction ? [historyAction] : []),\n\t\t\t\t\t{ location: { kind: \"stable\" }, before: state.stable, after: null },\n\t\t\t\t];\n\t\t\t\tawait this.commitTransaction(actions, [\n\t\t\t\t\tthis.createAuditEntry(\"rollback\", state.stable, null, state.stable.stateDigest, null),\n\t\t\t\t]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (state.stable.bundleDigest === parsed.targetBundleDigest) {\n\t\t\t\tif (state.targetTrial) {\n\t\t\t\t\tif (!state.targetTrialStateBefore) {\n\t\t\t\t\t\tthrow new Error(\"Rollback target trial memory lost its validated parent state\");\n\t\t\t\t\t}\n\t\t\t\t\tconst auditEntry = await this.createPromoteAuditEntryOnce(\n\t\t\t\t\t\tstate.targetTrial,\n\t\t\t\t\t\tstate.targetTrialStateBefore,\n\t\t\t\t\t\tstate.targetTrial.stateDigest,\n\t\t\t\t\t);\n\t\t\t\t\tawait this.commitTransaction(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: state.targetTrial.bundleDigest },\n\t\t\t\t\t\t\t\tbefore: state.targetTrial,\n\t\t\t\t\t\t\t\tafter: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tauditEntry ? [auditEntry] : [],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!state.target) throw new Error(\"Memory rollback target disappeared after preflight\");\n\t\t\tconst targetHistoryAction = await this.stableHistoryAction(state.target);\n\t\t\tconst stableHistoryAction = await this.stableHistoryAction(state.stable);\n\t\t\tconst actions: EvoMemoryPointerAction[] = [\n\t\t\t\t...(targetHistoryAction ? [targetHistoryAction] : []),\n\t\t\t\t...(stableHistoryAction ? [stableHistoryAction] : []),\n\t\t\t\t{ location: { kind: \"stable\" }, before: state.stable, after: state.target },\n\t\t\t];\n\t\t\tlet auditEntry: EvoMemoryAuditEntry | undefined;\n\t\t\tif (state.targetTrial) {\n\t\t\t\tif (!state.targetTrialStateBefore) {\n\t\t\t\t\tthrow new Error(\"Rollback target trial memory lost its validated parent state\");\n\t\t\t\t}\n\t\t\t\tauditEntry = await this.createPromoteAuditEntryOnce(\n\t\t\t\t\tstate.targetTrial,\n\t\t\t\t\tstate.targetTrialStateBefore,\n\t\t\t\t\tstate.targetTrial.stateDigest,\n\t\t\t\t);\n\t\t\t\tactions.push({\n\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: state.targetTrial.bundleDigest },\n\t\t\t\t\tbefore: state.targetTrial,\n\t\t\t\t\tafter: null,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tauditEntry = this.createAuditEntry(\n\t\t\t\t\t\"rollback\",\n\t\t\t\t\tstate.stable,\n\t\t\t\t\tnull,\n\t\t\t\t\tstate.stable.stateDigest,\n\t\t\t\t\tstate.target.stateDigest,\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.commitTransaction(actions, auditEntry ? [auditEntry] : []);\n\t\t});\n\t}\n\n\tasync rollbackTrial(trialBundleDigest: string): Promise<EvoMemoryNamespace> {\n\t\tconst digest = requireDigest(trialBundleDigest, \"trial bundle digest\");\n\t\tlet stableDigest = \"\";\n\t\tawait this.withMemoryLock(async () => {\n\t\t\tconst trial = await this.readPointer(this.trialPath(digest), \"trial memory pointer\");\n\t\t\tif (!trial || trial.kind !== \"trial\" || trial.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(\"Trial memory is not initialized for this bundle\");\n\t\t\t}\n\t\t\tconst stable = await this.readPointer(this.stablePath, \"stable memory pointer\");\n\t\t\tif (!stable || stable.kind !== \"stable\" || stable.bundleDigest !== trial.parentBundleDigest) {\n\t\t\t\tthrow new Error(\"Trial parent no longer matches stable memory\");\n\t\t\t}\n\t\t\tawait this.commitTransaction(\n\t\t\t\t[\n\t\t\t\t\t{\n\t\t\t\t\t\tlocation: { kind: \"trial\", bundleDigest: digest },\n\t\t\t\t\t\tbefore: trial,\n\t\t\t\t\t\tafter: null,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t[this.createAuditEntry(\"rollback\", trial, null, trial.stateDigest, stable.stateDigest)],\n\t\t\t);\n\t\t\tstableDigest = stable.bundleDigest;\n\t\t});\n\t\treturn new EvoMemoryNamespace(this, \"stable\", stableDigest);\n\t}\n\n\tasync readAudit(): Promise<EvoMemoryAuditEntry[]> {\n\t\treturn this.withMemoryLock(() => this.readAuditEntries());\n\t}\n\n\tasync readNamespace(kind: EvoMemoryNamespaceKind, bundleDigest: string): Promise<EvoMemoryReadResult> {\n\t\tconst digest = requireDigest(bundleDigest, `${kind} bundle digest`);\n\t\treturn this.withMemoryLock(async () => {\n\t\t\tconst pointer = await this.readPointer(this.pointerPath(kind, digest), `${kind} memory pointer`);\n\t\t\tif (!pointer || pointer.kind !== kind || pointer.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(`${kind} memory is not initialized for this bundle`);\n\t\t\t}\n\t\t\tconst snapshot = await this.readSnapshot(pointer.stateDigest);\n\t\t\treturn { stateDigest: pointer.stateDigest, fragments: snapshot.fragments.map(cloneFragment) };\n\t\t});\n\t}\n\n\tasync mutateNamespace(\n\t\tkind: EvoMemoryNamespaceKind,\n\t\tbundleDigest: string,\n\t\tmutation: EvoMemoryMutation,\n\t): Promise<EvoMemoryMutationResult> {\n\t\tconst digest = requireDigest(bundleDigest, `${kind} bundle digest`);\n\t\tif (mutation.expectedStateDigest !== undefined) {\n\t\t\trequireDigest(mutation.expectedStateDigest, \"expected memory state digest\");\n\t\t}\n\t\treturn this.withMemoryLock(async () => {\n\t\t\tconst path = this.pointerPath(kind, digest);\n\t\t\tconst pointer = await this.readPointer(path, `${kind} memory pointer`);\n\t\t\tif (!pointer || pointer.kind !== kind || pointer.bundleDigest !== digest) {\n\t\t\t\tthrow new Error(`${kind} memory is not initialized for this bundle`);\n\t\t\t}\n\t\t\tif (mutation.expectedStateDigest !== undefined && mutation.expectedStateDigest !== pointer.stateDigest) {\n\t\t\t\tthrow new Error(\"Memory state changed since the component read it\");\n\t\t\t}\n\t\t\tconst snapshot = await this.readSnapshot(pointer.stateDigest);\n\t\t\tconst fragments = snapshot.fragments.map(cloneFragment);\n\t\t\tconst timestamp = this.timestamp();\n\t\t\tlet fragment: EvoMemoryFragment | null;\n\t\t\tlet fragmentId: string;\n\t\t\tif (mutation.operation === \"forget\") {\n\t\t\t\tfragmentId = requireMemoryId(mutation.id, \"memory fragment id\");\n\t\t\t\tconst index = fragments.findIndex((entry) => entry.id === fragmentId);\n\t\t\t\tif (index < 0) throw new Error(`Memory fragment does not exist: ${fragmentId}`);\n\t\t\t\tfragment = fragments[index] ?? null;\n\t\t\t\tfragments.splice(index, 1);\n\t\t\t} else {\n\t\t\t\tconst input = parseEvoMemoryFragmentInput(mutation.fragment);\n\t\t\t\tfragmentId = input.id;\n\t\t\t\tconst index = fragments.findIndex((entry) => entry.id === input.id);\n\t\t\t\tif (mutation.operation === \"append\" && index >= 0) {\n\t\t\t\t\tthrow new Error(`Memory fragment already exists: ${input.id}`);\n\t\t\t\t}\n\t\t\t\tif (mutation.operation === \"update\" && index < 0) {\n\t\t\t\t\tthrow new Error(`Memory fragment does not exist: ${input.id}`);\n\t\t\t\t}\n\t\t\t\tfragment = {\n\t\t\t\t\tid: input.id,\n\t\t\t\t\ttext: input.text,\n\t\t\t\t\tmetadata: input.metadata ?? {},\n\t\t\t\t\tcreatedAt: index < 0 ? timestamp : (fragments[index]?.createdAt ?? timestamp),\n\t\t\t\t\tupdatedAt: timestamp,\n\t\t\t\t};\n\t\t\t\tif (index < 0) fragments.push(fragment);\n\t\t\t\telse fragments[index] = fragment;\n\t\t\t}\n\t\t\tfragments.sort((left, right) => left.id.localeCompare(right.id));\n\t\t\tconst stateDigest = await this.writeSnapshot({ schemaVersion: 1, fragments });\n\t\t\tconst nextPointer: EvoMemoryNamespacePointer = { ...pointer, stateDigest };\n\t\t\tconst location: EvoMemoryPointerLocation =\n\t\t\t\tkind === \"stable\" ? { kind: \"stable\" } : { kind: \"trial\", bundleDigest: digest };\n\t\t\tawait this.commitTransaction(\n\t\t\t\tpointerEquals(pointer, nextPointer) ? [] : [{ location, before: pointer, after: nextPointer }],\n\t\t\t\t[this.createAuditEntry(mutation.operation, pointer, fragmentId, pointer.stateDigest, stateDigest)],\n\t\t\t);\n\t\t\treturn { stateDigest, fragment: fragment ? cloneFragment(fragment) : null };\n\t\t});\n\t}\n}\n\nexport class EvoMemoryNamespace {\n\treadonly kind: EvoMemoryNamespaceKind;\n\treadonly bundleDigest: string;\n\tprivate readonly store: EvoMemoryStore;\n\n\tconstructor(store: EvoMemoryStore, kind: EvoMemoryNamespaceKind, bundleDigest: string) {\n\t\tthis.store = store;\n\t\tthis.kind = kind;\n\t\tthis.bundleDigest = requireDigest(bundleDigest, `${kind} bundle digest`);\n\t}\n\n\tassertComponent(component: EvoCapabilityComponentIdentity): void {\n\t\tif (component.id !== this.store.componentId || component.artifactDigest !== this.store.artifactDigest) {\n\t\t\tthrow new Error(\"Memory namespace is not assigned to this component artifact\");\n\t\t}\n\t}\n\n\tread(): Promise<EvoMemoryReadResult> {\n\t\treturn this.store.readNamespace(this.kind, this.bundleDigest);\n\t}\n\n\tappend(fragment: EvoMemoryFragmentInput, expectedStateDigest?: string): Promise<EvoMemoryMutationResult> {\n\t\treturn this.store.mutateNamespace(this.kind, this.bundleDigest, {\n\t\t\toperation: \"append\",\n\t\t\tfragment,\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t});\n\t}\n\n\tupdate(fragment: EvoMemoryFragmentInput, expectedStateDigest?: string): Promise<EvoMemoryMutationResult> {\n\t\treturn this.store.mutateNamespace(this.kind, this.bundleDigest, {\n\t\t\toperation: \"update\",\n\t\t\tfragment,\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t});\n\t}\n\n\tforget(id: string, expectedStateDigest?: string): Promise<EvoMemoryMutationResult> {\n\t\treturn this.store.mutateNamespace(this.kind, this.bundleDigest, {\n\t\t\toperation: \"forget\",\n\t\t\tid,\n\t\t\t...(expectedStateDigest === undefined ? {} : { expectedStateDigest }),\n\t\t});\n\t}\n\n\tasync retrieve(query: string, limit = 10): Promise<EvoMemoryRetrieveResult> {\n\t\tif (typeof query !== \"string\" || !query.trim() || query !== query.trim() || query.length > 8_000) {\n\t\t\tthrow new Error(\"retrieve query must be a trimmed non-empty string of at most 8000 characters\");\n\t\t}\n\t\tif (!Number.isSafeInteger(limit) || limit <= 0 || limit > MAX_RETRIEVE_LIMIT) {\n\t\t\tthrow new Error(`retrieve limit must be an integer from 1 to ${MAX_RETRIEVE_LIMIT}`);\n\t\t}\n\t\tconst state = await this.read();\n\t\tconst queryTokens = tokenize(query);\n\t\tconst fragments = state.fragments\n\t\t\t.map((fragment): EvoMemoryRetrievedFragment => {\n\t\t\t\tconst fragmentTokens = tokenize(`${fragment.text}\\n${canonicalJson(fragment.metadata)}`);\n\t\t\t\tlet score = 0;\n\t\t\t\tfor (const token of queryTokens) if (fragmentTokens.has(token)) score += 1;\n\t\t\t\treturn { ...fragment, score };\n\t\t\t})\n\t\t\t.filter((fragment) => fragment.score > 0)\n\t\t\t.sort((left, right) => right.score - left.score || left.id.localeCompare(right.id))\n\t\t\t.slice(0, limit);\n\t\treturn { stateDigest: state.stateDigest, fragments };\n\t}\n}\n"]}