arborkit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +134 -0
  4. package/dist/addressing.d.ts +22 -0
  5. package/dist/addressing.js +56 -0
  6. package/dist/addressing.js.map +1 -0
  7. package/dist/ag-ui.d.ts +45 -0
  8. package/dist/ag-ui.js +50 -0
  9. package/dist/ag-ui.js.map +1 -0
  10. package/dist/arbor.d.ts +73 -0
  11. package/dist/arbor.js +1542 -0
  12. package/dist/arbor.js.map +1 -0
  13. package/dist/artifact-tree.d.ts +66 -0
  14. package/dist/artifact-tree.js +285 -0
  15. package/dist/artifact-tree.js.map +1 -0
  16. package/dist/clock.d.ts +15 -0
  17. package/dist/clock.js +23 -0
  18. package/dist/clock.js.map +1 -0
  19. package/dist/decompose.d.ts +18 -0
  20. package/dist/decompose.js +22 -0
  21. package/dist/decompose.js.map +1 -0
  22. package/dist/delta-storage.d.ts +55 -0
  23. package/dist/delta-storage.js +106 -0
  24. package/dist/delta-storage.js.map +1 -0
  25. package/dist/delta.d.ts +55 -0
  26. package/dist/delta.js +740 -0
  27. package/dist/delta.js.map +1 -0
  28. package/dist/embedding-port.d.ts +17 -0
  29. package/dist/embedding-port.js +21 -0
  30. package/dist/embedding-port.js.map +1 -0
  31. package/dist/embedding-text.d.ts +14 -0
  32. package/dist/embedding-text.js +21 -0
  33. package/dist/embedding-text.js.map +1 -0
  34. package/dist/errors.d.ts +37 -0
  35. package/dist/errors.js +59 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/event-log.d.ts +75 -0
  38. package/dist/event-log.js +82 -0
  39. package/dist/event-log.js.map +1 -0
  40. package/dist/file-storage.d.ts +22 -0
  41. package/dist/file-storage.js +42 -0
  42. package/dist/file-storage.js.map +1 -0
  43. package/dist/ids.d.ts +17 -0
  44. package/dist/ids.js +22 -0
  45. package/dist/ids.js.map +1 -0
  46. package/dist/index.d.ts +29 -0
  47. package/dist/index.js +1826 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/json-edit.d.ts +18 -0
  50. package/dist/json-edit.js +85 -0
  51. package/dist/json-edit.js.map +1 -0
  52. package/dist/jsonpointer.d.ts +14 -0
  53. package/dist/jsonpointer.js +33 -0
  54. package/dist/jsonpointer.js.map +1 -0
  55. package/dist/mutator.d.ts +59 -0
  56. package/dist/mutator.js +244 -0
  57. package/dist/mutator.js.map +1 -0
  58. package/dist/navigator.d.ts +85 -0
  59. package/dist/navigator.js +192 -0
  60. package/dist/navigator.js.map +1 -0
  61. package/dist/path-glob.d.ts +13 -0
  62. package/dist/path-glob.js +40 -0
  63. package/dist/path-glob.js.map +1 -0
  64. package/dist/registry-validator.d.ts +15 -0
  65. package/dist/registry-validator.js +11 -0
  66. package/dist/registry-validator.js.map +1 -0
  67. package/dist/replay.d.ts +38 -0
  68. package/dist/replay.js +183 -0
  69. package/dist/replay.js.map +1 -0
  70. package/dist/semantic-index.d.ts +88 -0
  71. package/dist/semantic-index.js +226 -0
  72. package/dist/semantic-index.js.map +1 -0
  73. package/dist/storage.d.ts +39 -0
  74. package/dist/storage.js +378 -0
  75. package/dist/storage.js.map +1 -0
  76. package/dist/toolset.d.ts +78 -0
  77. package/dist/toolset.js +306 -0
  78. package/dist/toolset.js.map +1 -0
  79. package/dist/type-aware-decision.d.ts +8 -0
  80. package/dist/type-aware-decision.js +17 -0
  81. package/dist/type-aware-decision.js.map +1 -0
  82. package/dist/type-registry.d.ts +20 -0
  83. package/dist/type-registry.js +17 -0
  84. package/dist/type-registry.js.map +1 -0
  85. package/dist/types.d.ts +28 -0
  86. package/dist/types.js +1 -0
  87. package/dist/types.js.map +1 -0
  88. package/dist/vector-index-port.d.ts +34 -0
  89. package/dist/vector-index-port.js +49 -0
  90. package/dist/vector-index-port.js.map +1 -0
  91. package/dist/zod-adapter.d.ts +13 -0
  92. package/dist/zod-adapter.js +34 -0
  93. package/dist/zod-adapter.js.map +1 -0
  94. package/package.json +47 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ids.ts","../src/clock.ts","../src/jsonpointer.ts","../src/decompose.ts","../src/errors.ts","../src/artifact-tree.ts","../src/addressing.ts","../src/event-log.ts","../src/mutator.ts","../src/type-registry.ts","../src/registry-validator.ts","../src/type-aware-decision.ts","../src/zod-adapter.ts","../src/path-glob.ts","../src/navigator.ts","../src/embedding-port.ts","../src/embedding-text.ts","../src/semantic-index.ts","../src/vector-index-port.ts","../src/storage.ts","../src/file-storage.ts","../src/json-edit.ts","../src/replay.ts","../src/delta.ts","../src/delta-storage.ts","../src/toolset.ts","../src/ag-ui.ts","../src/arbor.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\r\nimport type { NodeId } from \"./types\";\r\n\r\nexport interface IdGen {\r\n next(): NodeId;\r\n}\r\n\r\nexport class UuidIdGen implements IdGen {\r\n next(): NodeId {\r\n return randomUUID();\r\n }\r\n}\r\n\r\n/** Deterministic test double: n0, n1, n2, ... */\r\nexport class SeqIdGen implements IdGen {\r\n private n = 0;\r\n constructor(private readonly prefix = \"n\") {}\r\n next(): NodeId {\r\n return `${this.prefix}${this.n++}`;\r\n }\r\n}\r\n","export interface Clock {\r\n now(): number; // epoch milliseconds\r\n}\r\n\r\nexport class SystemClock implements Clock {\r\n now(): number {\r\n return Date.now();\r\n }\r\n}\r\n\r\n/** Deterministic test double: constant value, manually advanced. */\r\nexport class FixedClock implements Clock {\r\n constructor(private t = 0) {}\r\n now(): number {\r\n return this.t;\r\n }\r\n advance(ms: number): void {\r\n this.t += ms;\r\n }\r\n}\r\n","/** Escape a single reference token per RFC 6901: ~ -> ~0, / -> ~1. */\r\nexport function encodeSegment(s: string): string {\r\n return s.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\r\n}\r\n\r\n/** Unescape a single reference token per RFC 6901: ~1 -> /, then ~0 -> ~. */\r\nexport function decodeSegment(s: string): string {\r\n return s.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\r\n}\r\n\r\n/** Build a JSON Pointer string. Empty segment list => \"\" (root). */\r\nexport function buildPointer(segments: ReadonlyArray<string | number>): string {\r\n if (segments.length === 0) return \"\";\r\n return \"/\" + segments.map((s) => encodeSegment(String(s))).join(\"/\");\r\n}\r\n\r\n/** Append one child key to a parent pointer, escaping the key exactly as `buildPointer` does. */\r\nexport function appendPointer(parent: string, key: string | number): string {\r\n return parent + \"/\" + encodeSegment(String(key));\r\n}\r\n\r\n/** True when `path` is at or under `scope` (JSON Pointer prefix). Undefined scope = everywhere. */\r\nexport function isWithin(path: string, scope: string | undefined): boolean {\r\n return scope === undefined || path === scope || path.startsWith(scope + \"/\");\r\n}\r\n\r\n/** Parse a JSON Pointer into decoded segments. \"\" => [] (root). */\r\nexport function parsePointer(pointer: string): string[] {\r\n if (pointer === \"\") return [];\r\n if (!pointer.startsWith(\"/\")) {\r\n throw new Error(`Invalid JSON Pointer (must be \"\" or start with \"/\"): ${pointer}`);\r\n }\r\n return pointer.slice(1).split(\"/\").map(decodeSegment);\r\n}\r\n","import type { Json, NodeKind } from \"./types\";\r\n\r\n/** Policy deciding whether a value is stored whole (opaque leaf) or split into child nodes. */\r\nexport interface DecomposeDecision {\r\n /** `type` is the optional registered node type (used by the by-type override in a later milestone). */\r\n isOpaque(value: Json, type?: string): boolean;\r\n}\r\n\r\n/** UTF-8 byte length of the JSON serialization of a value. */\r\nexport function byteSize(value: Json): number {\r\n return Buffer.byteLength(JSON.stringify(value), \"utf8\");\r\n}\r\n\r\n/** Structural kind of a value given whether it is being stored opaquely. */\r\nexport function kindOf(value: Json, opaque: boolean): NodeKind {\r\n if (opaque) return \"leaf\";\r\n return Array.isArray(value) ? \"array\" : \"object\";\r\n}\r\n\r\n/**\r\n * Default policy: scalars are always opaque leaves; containers stay opaque\r\n * while their serialized size is within `maxOpaqueBytes`, otherwise they split.\r\n */\r\nexport function sizeBasedDecision(maxOpaqueBytes: number): DecomposeDecision {\r\n return {\r\n isOpaque(value: Json): boolean {\r\n if (value === null || typeof value !== \"object\") return true;\r\n return byteSize(value) <= maxOpaqueBytes;\r\n },\r\n };\r\n}\r\n","import type { NodeId } from \"./types\";\r\n\r\n/** A reference to a node: by stable id or by JSON Pointer path. */\r\nexport type Ref = { id: NodeId } | { path: string };\r\n\r\nexport class ArborError extends Error {\r\n constructor(\r\n public readonly code: string,\r\n message: string,\r\n ) {\r\n super(message);\r\n this.name = new.target.name;\r\n }\r\n}\r\n\r\nexport class NodeNotFoundError extends ArborError {\r\n constructor(public readonly ref: Ref) {\r\n super(\"NODE_NOT_FOUND\", `Node not found: ${JSON.stringify(ref)}`);\r\n }\r\n}\r\n\r\nexport class ScopeViolationError extends ArborError {\r\n constructor(\r\n public readonly targetPath: string,\r\n public readonly scope: string,\r\n ) {\r\n super(\"SCOPE_VIOLATION\", `Access outside scope: ${targetPath} (scope: ${scope})`);\r\n }\r\n}\r\n\r\nexport class StaleVersionError extends ArborError {\r\n constructor(\r\n public readonly id: NodeId,\r\n public readonly expected: number,\r\n public readonly actual: number,\r\n ) {\r\n super(\"STALE_VERSION\", `Stale version for ${id}: expected ${expected}, actual ${actual}`);\r\n }\r\n}\r\n\r\nexport class InvalidOpError extends ArborError {\r\n constructor(message: string) {\r\n super(\"INVALID_OP\", message);\r\n }\r\n}\r\n\r\nexport class ValidationError extends ArborError {\r\n constructor(\r\n public readonly type: string | undefined,\r\n public readonly details: string,\r\n ) {\r\n super(\"VALIDATION_ERROR\", `Validation failed${type ? ` for type ${type}` : \"\"}: ${details}`);\r\n }\r\n}\r\n","import type { ArbNode, Json, NodeId } from \"./types\";\r\nimport type { IdGen } from \"./ids\";\r\nimport type { Clock } from \"./clock\";\r\nimport { type DecomposeDecision, kindOf } from \"./decompose\";\r\nimport { InvalidOpError } from \"./errors\";\r\n\r\nexport interface TreeDeps {\r\n idGen: IdGen;\r\n clock: Clock;\r\n decision: DecomposeDecision;\r\n}\r\n\r\nexport interface TreeSnapshot {\r\n nodes: Map<NodeId, ArbNode>;\r\n rootId: NodeId;\r\n}\r\n\r\nexport class ArtifactTree {\r\n private readonly nodes = new Map<NodeId, ArbNode>();\r\n private rootId!: NodeId;\r\n /** Lazily built per-parent key→childId maps for O(1) object-child lookup.\r\n * A cache OUTSIDE the nodes (ArbNode/StoredArtifact stay byte-identical);\r\n * invalidated on every child-set change, rebuilt on read. Arrays never\r\n * populate it (index lookup is already O(1)). */\r\n private readonly keyMaps = new Map<NodeId, Map<string, NodeId>>();\r\n\r\n private constructor(private readonly deps: TreeDeps) {}\r\n\r\n static fromJson(json: Json, deps: TreeDeps): ArtifactTree {\r\n const tree = new ArtifactTree(deps);\r\n tree.rootId = tree.build(json, null, null);\r\n return tree;\r\n }\r\n\r\n private build(value: Json, parentId: NodeId | null, key: string | number | null, type?: string): NodeId {\r\n const opaque = this.deps.decision.isOpaque(value, type);\r\n const kind = kindOf(value, opaque);\r\n const id = this.deps.idGen.next();\r\n const node: ArbNode = {\r\n id,\r\n parentId,\r\n key,\r\n kind,\r\n content: kind === \"leaf\" ? value : null,\r\n childIds: [],\r\n meta: { version: 0, updatedAt: this.deps.clock.now(), embedding: { state: \"none\" } },\r\n };\r\n if (type !== undefined) node.type = type;\r\n this.nodes.set(id, node);\r\n\r\n if (kind === \"object\") {\r\n for (const [k, v] of Object.entries(value as Record<string, Json>)) {\r\n node.childIds.push(this.build(v, id, k));\r\n }\r\n } else if (kind === \"array\") {\r\n (value as Json[]).forEach((v, i) => {\r\n node.childIds.push(this.build(v, id, i));\r\n });\r\n }\r\n return id;\r\n }\r\n\r\n get(id: NodeId): ArbNode | undefined {\r\n return this.nodes.get(id);\r\n }\r\n\r\n root(): ArbNode {\r\n return this.nodes.get(this.rootId)!;\r\n }\r\n\r\n rootIdValue(): NodeId {\r\n return this.rootId;\r\n }\r\n\r\n /** O(1) child lookup: arrays by index, objects via a lazily built key map. */\r\n childByKey(parentId: NodeId, key: string): ArbNode | undefined {\r\n const parent = this.nodes.get(parentId);\r\n if (!parent) return undefined;\r\n if (parent.kind === \"array\") {\r\n if (!/^(0|[1-9]\\d*)$/.test(key)) return undefined; // canonical RFC 6901 index: digits only, no leading zeros\r\n const i = Number(key);\r\n if (i >= parent.childIds.length) return undefined;\r\n return this.nodes.get(parent.childIds[i]);\r\n }\r\n let map = this.keyMaps.get(parentId);\r\n if (!map) {\r\n map = new Map();\r\n for (const cid of parent.childIds) map.set(String(this.nodes.get(cid)!.key), cid);\r\n this.keyMaps.set(parentId, map);\r\n }\r\n const cid = map.get(key);\r\n return cid === undefined ? undefined : this.nodes.get(cid);\r\n }\r\n\r\n children(id: NodeId): ArbNode[] {\r\n const n = this.nodes.get(id);\r\n if (!n) return [];\r\n return n.childIds.map((cid) => this.nodes.get(cid)!);\r\n }\r\n\r\n has(id: NodeId): boolean {\r\n return this.nodes.has(id);\r\n }\r\n\r\n size(): number {\r\n return this.nodes.size;\r\n }\r\n\r\n /** Reconstruct the JSON value rooted at `id` (defaults to the tree root). */\r\n toJson(id: NodeId = this.rootId): Json {\r\n const n = this.nodes.get(id);\r\n if (!n) throw new Error(`Unknown node: ${id}`);\r\n if (n.kind === \"leaf\") return n.content;\r\n if (n.kind === \"array\") return n.childIds.map((cid) => this.toJson(cid));\r\n const obj: Record<string, Json> = {};\r\n for (const cid of n.childIds) {\r\n const c = this.nodes.get(cid)!;\r\n obj[String(c.key)] = this.toJson(cid);\r\n }\r\n return obj;\r\n }\r\n\r\n /** Replace the subtree value at `id` in place, keeping the node's id/key/parentId.\r\n * `clearType` explicitly un-types the node (used by type-aware revert). */\r\n replaceValue(id: NodeId, value: Json, type?: string, clearType = false): void {\r\n const node = this.nodes.get(id);\r\n if (!node) throw new InvalidOpError(`Unknown node: ${id}`);\r\n this.deleteDescendants(id);\r\n this.keyMaps.delete(id);\r\n const opaque = this.deps.decision.isOpaque(value, type);\r\n const kind = kindOf(value, opaque);\r\n node.kind = kind;\r\n node.content = kind === \"leaf\" ? value : null;\r\n node.childIds = [];\r\n if (clearType) node.type = undefined;\r\n else if (type !== undefined) node.type = type;\r\n if (kind === \"object\") {\r\n for (const [k, v] of Object.entries(value as Record<string, Json>)) {\r\n node.childIds.push(this.build(v, id, k));\r\n }\r\n } else if (kind === \"array\") {\r\n (value as Json[]).forEach((v, i) => {\r\n node.childIds.push(this.build(v, id, i));\r\n });\r\n }\r\n }\r\n\r\n /** Recursively remove all descendants of `id` from the node map (keeps `id` itself). */\r\n private deleteDescendants(id: NodeId): void {\r\n const node = this.nodes.get(id);\r\n if (!node) return;\r\n for (const cid of node.childIds) {\r\n this.deleteDescendants(cid);\r\n this.nodes.delete(cid);\r\n this.keyMaps.delete(cid);\r\n }\r\n node.childIds = [];\r\n }\r\n\r\n /** Deep, independent copy of the tree state for transaction rollback.\r\n * `restore` consumes the snapshot; do not reuse it afterwards. */\r\n snapshot(): TreeSnapshot {\r\n const nodes = new Map<NodeId, ArbNode>();\r\n for (const [id, node] of this.nodes) {\r\n nodes.set(id, structuredClone(node));\r\n }\r\n return { nodes, rootId: this.rootId };\r\n }\r\n\r\n /** Replace the tree state with a previously taken snapshot. The snapshot's\r\n * nodes are adopted BY REFERENCE — restore consumes the snapshot; do not\r\n * reuse it afterwards. */\r\n restore(snap: TreeSnapshot): void {\r\n this.nodes.clear();\r\n this.keyMaps.clear();\r\n for (const [id, node] of snap.nodes) {\r\n this.nodes.set(id, node);\r\n }\r\n this.rootId = snap.rootId;\r\n }\r\n\r\n /** Insert a decomposed `value` as a child of `parentId`. For objects `keyOrIndex` is the string key; for arrays it is the insert index. Returns the new child's id. */\r\n insertChild(parentId: NodeId, keyOrIndex: string | number, value: Json, type?: string): NodeId {\r\n const parent = this.nodes.get(parentId);\r\n if (!parent) throw new InvalidOpError(`Unknown node: ${parentId}`);\r\n if (parent.kind === \"object\") {\r\n if (typeof keyOrIndex !== \"string\") {\r\n throw new InvalidOpError(\"object insert requires a string key\");\r\n }\r\n if (parent.childIds.some((cid) => this.nodes.get(cid)!.key === keyOrIndex)) {\r\n throw new InvalidOpError(`key already exists: ${keyOrIndex}`);\r\n }\r\n const cid = this.build(value, parentId, keyOrIndex, type);\r\n parent.childIds.push(cid);\r\n this.keyMaps.delete(parentId);\r\n return cid;\r\n }\r\n if (parent.kind === \"array\") {\r\n if (typeof keyOrIndex !== \"number\") {\r\n throw new InvalidOpError(\"array insert requires a numeric index\");\r\n }\r\n const at = Math.max(0, Math.min(keyOrIndex, parent.childIds.length));\r\n const cid = this.build(value, parentId, at, type);\r\n parent.childIds.splice(at, 0, cid);\r\n this.renumberArray(parentId);\r\n return cid;\r\n }\r\n throw new InvalidOpError(\"cannot insert into a leaf node\");\r\n }\r\n\r\n /** Remove `childId` (and its subtree) from `parentId`. Renumbers array siblings. */\r\n removeChild(parentId: NodeId, childId: NodeId): void {\r\n const parent = this.nodes.get(parentId);\r\n if (!parent) throw new InvalidOpError(`Unknown node: ${parentId}`);\r\n const idx = parent.childIds.indexOf(childId);\r\n if (idx < 0) throw new InvalidOpError(`${childId} is not a child of ${parentId}`);\r\n this.deleteDescendants(childId);\r\n this.nodes.delete(childId);\r\n this.keyMaps.delete(childId);\r\n parent.childIds.splice(idx, 1);\r\n this.keyMaps.delete(parentId);\r\n if (parent.kind === \"array\") this.renumberArray(parentId);\r\n }\r\n\r\n /** Move `id` under `newParentId` at `keyOrIndex`, preserving `id`. Renumbers affected arrays.\r\n * ALL validation happens before any mutation — a rejected move leaves the tree untouched. */\r\n moveNode(id: NodeId, newParentId: NodeId, keyOrIndex: string | number): void {\r\n const node = this.nodes.get(id);\r\n if (!node) throw new InvalidOpError(`Unknown node: ${id}`);\r\n if (node.parentId === null) throw new InvalidOpError(\"cannot move the root\");\r\n const newParent = this.nodes.get(newParentId);\r\n if (!newParent) throw new InvalidOpError(`Unknown node: ${newParentId}`);\r\n if (newParent.kind === \"leaf\") throw new InvalidOpError(\"cannot move into a leaf node\");\r\n // Moving into itself or its own subtree would create a parent-chain cycle:\r\n // toJson silently drops the subtree and pathOf never terminates.\r\n let anc: NodeId | null = newParentId;\r\n while (anc !== null) {\r\n if (anc === id) throw new InvalidOpError(\"cannot move a node into itself or its own subtree\");\r\n anc = this.nodes.get(anc)?.parentId ?? null;\r\n }\r\n if (newParent.kind === \"object\") {\r\n if (typeof keyOrIndex !== \"string\") throw new InvalidOpError(\"object move requires a string key\");\r\n // Mirrors insertChild: a duplicate key silently shadows the existing child.\r\n if (newParent.childIds.some((cid) => cid !== id && this.nodes.get(cid)!.key === keyOrIndex)) {\r\n throw new InvalidOpError(`key already exists: ${keyOrIndex}`);\r\n }\r\n }\r\n\r\n const oldParent = this.nodes.get(node.parentId)!;\r\n const oldIdx = oldParent.childIds.indexOf(id);\r\n oldParent.childIds.splice(oldIdx, 1);\r\n this.keyMaps.delete(oldParent.id);\r\n this.keyMaps.delete(newParentId);\r\n if (oldParent.kind === \"array\") this.renumberArray(oldParent.id);\r\n\r\n if (newParent.kind === \"object\") {\r\n node.parentId = newParentId;\r\n node.key = keyOrIndex;\r\n newParent.childIds.push(id);\r\n } else {\r\n const at = typeof keyOrIndex === \"number\" ? Math.max(0, Math.min(keyOrIndex, newParent.childIds.length)) : newParent.childIds.length;\r\n node.parentId = newParentId;\r\n newParent.childIds.splice(at, 0, id);\r\n this.renumberArray(newParentId);\r\n }\r\n }\r\n\r\n /** Set each array child's `key` to its current position. */\r\n private renumberArray(parentId: NodeId): void {\r\n const parent = this.nodes.get(parentId);\r\n if (!parent) return;\r\n parent.childIds.forEach((cid, i) => {\r\n this.nodes.get(cid)!.key = i;\r\n });\r\n }\r\n\r\n /** All nodes in the tree (for serialization). */\r\n allNodes(): ArbNode[] {\r\n return [...this.nodes.values()];\r\n }\r\n\r\n /** Rebuild a tree from previously serialized nodes, preserving their ids. */\r\n static fromStored(nodes: ArbNode[], rootId: NodeId, deps: TreeDeps): ArtifactTree {\r\n const tree = new ArtifactTree(deps);\r\n for (const node of nodes) tree.nodes.set(node.id, node);\r\n tree.rootId = rootId;\r\n return tree;\r\n }\r\n\r\n /** All transitive descendant ids of `id` (depth-first), excluding `id` itself. */\r\n descendantIds(id: NodeId): NodeId[] {\r\n const out: NodeId[] = [];\r\n const node = this.nodes.get(id);\r\n if (!node) return out;\r\n for (const cid of node.childIds) {\r\n out.push(cid);\r\n out.push(...this.descendantIds(cid));\r\n }\r\n return out;\r\n }\r\n}\r\n","import type { ArbNode, NodeId } from \"./types\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport { buildPointer, parsePointer } from \"./jsonpointer\";\r\n\r\n/**\r\n * Resolves nodes by stable id and by JSON Pointer path.\r\n * `path` is DERIVED from the current structure (not stored), so it stays\r\n * consistent automatically — id is identity, path is current location.\r\n */\r\nexport class Addressing {\r\n constructor(private readonly tree: ArtifactTree) {}\r\n\r\n byId(id: NodeId): ArbNode | undefined {\r\n return this.tree.get(id);\r\n }\r\n\r\n /** Compute the JSON Pointer for a node by walking parent links to the root. */\r\n pathOf(id: NodeId): string {\r\n const cur0 = this.tree.get(id);\r\n if (!cur0) throw new Error(`Unknown node: ${id}`);\r\n const segments: (string | number)[] = [];\r\n let cur: ArbNode | undefined = cur0;\r\n while (cur && cur.parentId !== null) {\r\n segments.unshift(cur.key as string | number);\r\n cur = this.tree.get(cur.parentId);\r\n }\r\n return buildPointer(segments);\r\n }\r\n\r\n /** Resolve a JSON Pointer to a node, or undefined if any segment is missing. */\r\n byPath(pointer: string): ArbNode | undefined {\r\n const segments = parsePointer(pointer);\r\n let cur: ArbNode | undefined = this.tree.root();\r\n for (const seg of segments) {\r\n if (!cur) return undefined;\r\n // parsePointer yields UNescaped segments and node keys are raw strings —\r\n // they match childByKey's String(key) map keys directly.\r\n cur = this.tree.childByKey(cur.id, seg);\r\n if (!cur) return undefined;\r\n }\r\n return cur;\r\n }\r\n}\r\n","import type { Json, NodeId } from \"./types\";\r\nimport { InvalidOpError } from \"./errors\";\r\n\r\nexport type OpKind = \"set\" | \"insert\" | \"remove\" | \"move\";\r\n\r\n/**\r\n * A recorded mutation. Carries enough to reverse it later (M7 replay):\r\n * - set: before = old subtree value, after = new value\r\n * - insert: after = inserted value (inverse is remove of targetId)\r\n * - remove: before = removed subtree value (inverse is insert at parentId/key)\r\n * - move: from/to capture old and new (parentId, key)\r\n */\r\nexport interface MutationEvent {\r\n seq: number;\r\n kind: OpKind;\r\n targetId: NodeId;\r\n parentId: NodeId | null;\r\n key: string | number | null;\r\n before?: Json;\r\n after?: Json;\r\n from?: { parentId: NodeId | null; key: string | number | null };\r\n to?: { parentId: NodeId | null; key: string | number | null };\r\n /** JSON Pointer of the affected node (set/insert: its path; remove: its pre-removal path). */\r\n path?: string;\r\n /** move: source path (before the move). */\r\n fromPath?: string;\r\n /** move: destination path (after the move). */\r\n toPath?: string;\r\n /** set/remove: the node's type BEFORE the op; insert/set: `nodeType` = type AFTER.\r\n * `null` = explicitly untyped; ABSENT = pre-M10 event (unknown — replay keeps the current type). */\r\n nodeTypeBefore?: string | null;\r\n nodeType?: string | null;\r\n /** set/remove: the node's tags BEFORE the op ([] = untagged).\r\n * ABSENT = pre-M14 event (unknown — revert leaves the current tags alone). */\r\n tagsBefore?: string[];\r\n /** set/insert: the node's tags AFTER the op ([] = untagged). ABSENT = pre-M14. */\r\n tags?: string[];\r\n actor?: string;\r\n ts: number;\r\n}\r\n\r\n/** Append-only log of mutations with monotonic, absolute seq. Supports compaction:\r\n * events before `baseSeq` are dropped, but retained events keep their absolute seq\r\n * and `length()` stays the absolute next-seq, so versions never shift. */\r\nexport class EventLog {\r\n private readonly events: MutationEvent[] = [];\r\n private baseSeq = 0; // count of compacted-away events; events[0].seq === baseSeq\r\n\r\n append(event: Omit<MutationEvent, \"seq\">): MutationEvent {\r\n const full: MutationEvent = { ...event, seq: this.baseSeq + this.events.length };\r\n this.events.push(full);\r\n return full;\r\n }\r\n\r\n entries(): readonly MutationEvent[] {\r\n return this.events;\r\n }\r\n\r\n /** Absolute seq of the oldest retained event (0 until compaction). Versions below\r\n * this have been compacted away and are no longer reconstructable. */\r\n baseSeqValue(): number {\r\n return this.baseSeq;\r\n }\r\n\r\n /** The event at absolute `seq`, or undefined if compacted away / past the end. */\r\n at(seq: number): MutationEvent | undefined {\r\n const i = seq - this.baseSeq;\r\n return i >= 0 && i < this.events.length ? this.events[i] : undefined;\r\n }\r\n\r\n since(seq: number): MutationEvent[] {\r\n return this.events.filter((e) => e.seq >= seq);\r\n }\r\n\r\n /** Absolute next-seq / current version (unchanged across compaction). */\r\n length(): number {\r\n return this.baseSeq + this.events.length;\r\n }\r\n\r\n /** Drop events past absolute `length` — used to roll back a failed transaction.\r\n * Throws below the compaction floor: that history is gone and the log cannot roll\r\n * back past it — `compactTo` must never run inside a transaction. */\r\n truncateTo(length: number): void {\r\n if (length < this.baseSeq) {\r\n throw new InvalidOpError(\r\n `cannot truncate to ${length}: events before ${this.baseSeq} were compacted away (compactTo must not run inside a transaction)`,\r\n );\r\n }\r\n this.events.length = length - this.baseSeq;\r\n }\r\n\r\n /** Compaction: drop every retained event with seq < `floorSeq` (history before it\r\n * becomes unreconstructable). `floorSeq` is clamped to [baseSeq, length()].\r\n * Returns the number of events dropped. Must NOT be called inside a Mutator\r\n * transaction (rollback would need the dropped events). */\r\n compactTo(floorSeq: number): number {\r\n const floor = Math.max(this.baseSeq, Math.min(floorSeq, this.length()));\r\n const drop = floor - this.baseSeq;\r\n if (drop > 0) {\r\n this.events.splice(0, drop);\r\n this.baseSeq = floor;\r\n }\r\n return drop;\r\n }\r\n\r\n /** Rebuild a log from previously serialized events, preserving their seq + the\r\n * compaction floor. */\r\n static fromStored(events: MutationEvent[], baseSeq = 0): EventLog {\r\n const log = new EventLog();\r\n log.baseSeq = baseSeq;\r\n for (const e of events) log.events.push({ ...e });\r\n return log;\r\n }\r\n}\r\n","import type { ArbNode, Json, NodeId } from \"./types\";\r\nimport type { Clock } from \"./clock\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { Addressing } from \"./addressing\";\r\nimport type { EventLog, OpKind } from \"./event-log\";\r\nimport { type Ref, NodeNotFoundError, ScopeViolationError, StaleVersionError, InvalidOpError } from \"./errors\";\r\nimport { isWithin } from \"./jsonpointer\";\r\n\r\n/** Optional validation hook. Throws to reject a mutation. M3 plugs Zod in here. */\r\nexport type Validator = (input: { node: ArbNode | null; proposed: Json; type?: string; op: OpKind }) => void;\r\n\r\nexport interface MutatorDeps {\r\n clock: Clock;\r\n validate?: Validator;\r\n /** Called after a node's content changes (set/insert) — e.g. to mark a semantic index stale. */\r\n onChange?: (node: ArbNode) => void;\r\n /** Called after a node is removed — e.g. to drop it from a semantic index. */\r\n onRemove?: (nodeId: NodeId) => void;\r\n /** Called at transaction start; the returned snapshot is passed to `onTxRestore` on rollback. */\r\n onTxSnapshot?: () => unknown;\r\n /** Called on transaction rollback with the snapshot from `onTxSnapshot`. */\r\n onTxRestore?: (snapshot: unknown) => void;\r\n}\r\n\r\nexport interface MutateOpts {\r\n owner?: string;\r\n /** JSON Pointer prefix; the target must be at or under it. */\r\n writeScope?: string;\r\n /** Optimistic concurrency: reject unless the target's current version equals this. */\r\n ifVersion?: number;\r\n /** Register/override the node's type (drives validation and the decompose override).\r\n * `null` explicitly CLEARS the type (validation is skipped) — used by type-aware revert. */\r\n type?: string | null;\r\n /** Replace the node's tags (identity labels for exact `find` by tag). */\r\n tags?: string[];\r\n}\r\n\r\nexport class Mutator {\r\n constructor(\r\n private readonly tree: ArtifactTree,\r\n private readonly addressing: Addressing,\r\n private readonly log: EventLog,\r\n private readonly deps: MutatorDeps,\r\n ) {}\r\n\r\n private resolve(ref: Ref): ArbNode {\r\n const node = \"id\" in ref ? this.addressing.byId(ref.id) : this.addressing.byPath(ref.path);\r\n if (!node) throw new NodeNotFoundError(ref);\r\n return node;\r\n }\r\n\r\n private checkScope(node: ArbNode, writeScope?: string): void {\r\n if (writeScope === undefined) return;\r\n const path = this.addressing.pathOf(node.id);\r\n if (!isWithin(path, writeScope)) throw new ScopeViolationError(path, writeScope);\r\n }\r\n\r\n private checkVersion(node: ArbNode, ifVersion?: number): void {\r\n if (ifVersion !== undefined && node.meta.version !== ifVersion) {\r\n throw new StaleVersionError(node.id, ifVersion, node.meta.version);\r\n }\r\n }\r\n\r\n private bump(node: ArbNode, owner?: string): void {\r\n node.meta.version += 1;\r\n node.meta.updatedAt = this.deps.clock.now();\r\n if (owner !== undefined) node.meta.owner = owner;\r\n }\r\n\r\n set(ref: Ref, value: Json, opts: MutateOpts = {}): void {\r\n const node = this.resolve(ref);\r\n this.checkScope(node, opts.writeScope);\r\n this.checkVersion(node, opts.ifVersion);\r\n // Defensive copy: neither the tree nor the event log may alias the caller's\r\n // live object — post-call mutation would silently rewrite state AND history.\r\n const cloned = structuredClone(value);\r\n const clearType = opts.type === null;\r\n const type = clearType ? undefined : (opts.type ?? node.type);\r\n this.deps.validate?.({ node, proposed: cloned, type, op: \"set\" });\r\n const before = this.tree.toJson(node.id);\r\n const typeBefore = node.type;\r\n const tagsBefore = [...(node.tags ?? [])];\r\n const orphaned = this.tree.descendantIds(node.id);\r\n this.tree.replaceValue(node.id, cloned, type, clearType);\r\n if (opts.tags !== undefined) node.tags = [...opts.tags];\r\n this.bump(node, opts.owner);\r\n this.deps.onChange?.(node);\r\n if (this.deps.onChange) {\r\n // replaceValue rebuilt the subtree: every descendant is a NEW node and\r\n // must be announced too (text leaves are what the semantic index embeds).\r\n for (const id of this.tree.descendantIds(node.id)) {\r\n const child = this.tree.get(id);\r\n if (child) this.deps.onChange(child);\r\n }\r\n }\r\n if (this.deps.onRemove) {\r\n for (const id of orphaned) this.deps.onRemove(id);\r\n }\r\n this.log.append({\r\n kind: \"set\",\r\n targetId: node.id,\r\n parentId: node.parentId,\r\n key: node.key,\r\n path: this.addressing.pathOf(node.id),\r\n before,\r\n after: cloned,\r\n nodeTypeBefore: typeBefore ?? null,\r\n nodeType: type ?? null,\r\n tagsBefore,\r\n tags: [...(node.tags ?? [])],\r\n actor: opts.owner,\r\n ts: this.deps.clock.now(),\r\n });\r\n }\r\n\r\n insert(parentRef: Ref, keyOrIndex: string | number, value: Json, opts: MutateOpts = {}): NodeId {\r\n const parent = this.resolve(parentRef);\r\n this.checkScope(parent, opts.writeScope);\r\n this.checkVersion(parent, opts.ifVersion);\r\n // Defensive copy: neither the tree nor the event log may alias the caller's\r\n // live object — post-call mutation would silently rewrite state AND history.\r\n const cloned = structuredClone(value);\r\n const type = opts.type === null ? undefined : opts.type;\r\n this.deps.validate?.({ node: null, proposed: cloned, type, op: \"insert\" });\r\n const newId = this.tree.insertChild(parent.id, keyOrIndex, cloned, type);\r\n const child = this.tree.get(newId)!;\r\n if (opts.tags !== undefined) child.tags = [...opts.tags];\r\n this.bump(parent, opts.owner);\r\n this.deps.onChange?.(child);\r\n if (this.deps.onChange) {\r\n for (const id of this.tree.descendantIds(newId)) {\r\n const desc = this.tree.get(id);\r\n if (desc) this.deps.onChange(desc);\r\n }\r\n }\r\n this.log.append({\r\n kind: \"insert\",\r\n targetId: newId,\r\n parentId: parent.id,\r\n key: child.key,\r\n path: this.addressing.pathOf(newId),\r\n after: cloned,\r\n nodeType: child.type ?? null,\r\n tags: [...(child.tags ?? [])],\r\n actor: opts.owner,\r\n ts: this.deps.clock.now(),\r\n });\r\n return newId;\r\n }\r\n\r\n remove(ref: Ref, opts: MutateOpts = {}): void {\r\n const node = this.resolve(ref);\r\n if (node.parentId === null) throw new InvalidOpError(\"cannot remove the root\");\r\n this.checkScope(node, opts.writeScope);\r\n this.checkVersion(node, opts.ifVersion);\r\n const before = this.tree.toJson(node.id);\r\n const path = this.addressing.pathOf(node.id);\r\n const removedIds = [node.id, ...this.tree.descendantIds(node.id)];\r\n const parent = this.tree.get(node.parentId)!;\r\n const removedKey = node.key;\r\n this.tree.removeChild(node.parentId, node.id);\r\n this.bump(parent, opts.owner);\r\n if (this.deps.onRemove) {\r\n for (const id of removedIds) this.deps.onRemove(id);\r\n }\r\n // The parent's semantic unit (if any) lost content — re-hash it.\r\n this.deps.onChange?.(parent);\r\n this.log.append({\r\n kind: \"remove\",\r\n targetId: node.id,\r\n parentId: parent.id,\r\n key: removedKey,\r\n path,\r\n before,\r\n nodeTypeBefore: node.type ?? null,\r\n tagsBefore: [...(node.tags ?? [])],\r\n actor: opts.owner,\r\n ts: this.deps.clock.now(),\r\n });\r\n }\r\n\r\n move(ref: Ref, toParentRef: Ref, keyOrIndex: string | number, opts: MutateOpts = {}): void {\r\n const node = this.resolve(ref);\r\n if (node.parentId === null) throw new InvalidOpError(\"cannot move the root\");\r\n const toParent = this.resolve(toParentRef);\r\n this.checkScope(node, opts.writeScope);\r\n this.checkScope(toParent, opts.writeScope);\r\n this.checkVersion(node, opts.ifVersion);\r\n const oldParentId = node.parentId;\r\n const from = { parentId: node.parentId, key: node.key };\r\n const fromPath = this.addressing.pathOf(node.id);\r\n this.tree.moveNode(node.id, toParent.id, keyOrIndex);\r\n const toPath = this.addressing.pathOf(node.id);\r\n // bump moved node + both parents (dedupe if old === new parent)\r\n const bumped = new Set<NodeId>();\r\n for (const id of [node.id, oldParentId, toParent.id]) {\r\n if (id !== null && !bumped.has(id)) {\r\n const n = this.tree.get(id);\r\n if (n) this.bump(n, opts.owner);\r\n bumped.add(id);\r\n }\r\n }\r\n if (this.deps.onChange) {\r\n // The moved subtree's ancestry changed (suppression status may flip), and\r\n // both old and new locations' semantic units changed content.\r\n this.deps.onChange(node);\r\n for (const id of this.tree.descendantIds(node.id)) {\r\n const d = this.tree.get(id);\r\n if (d) this.deps.onChange(d);\r\n }\r\n const oldP = oldParentId !== null ? this.tree.get(oldParentId) : undefined;\r\n if (oldP) this.deps.onChange(oldP);\r\n const newP = this.tree.get(toParent.id);\r\n if (newP) this.deps.onChange(newP);\r\n }\r\n this.log.append({\r\n kind: \"move\",\r\n targetId: node.id,\r\n parentId: toParent.id,\r\n key: node.key,\r\n from,\r\n to: { parentId: toParent.id, key: node.key },\r\n fromPath,\r\n toPath,\r\n actor: opts.owner,\r\n ts: this.deps.clock.now(),\r\n });\r\n }\r\n\r\n /** Run `fn` atomically: if it throws, the tree, log, and any hooked index state are restored. */\r\n transaction(fn: () => void): void {\r\n const snap = this.tree.snapshot();\r\n const logLen = this.log.length();\r\n const hookSnap = this.deps.onTxSnapshot?.();\r\n try {\r\n fn();\r\n } catch (err) {\r\n this.tree.restore(snap);\r\n this.log.truncateTo(logLen);\r\n if (this.deps.onTxRestore) this.deps.onTxRestore(hookSnap);\r\n throw err;\r\n }\r\n }\r\n}\r\n","import type { Json } from \"./types\";\r\n\r\n/** Definition of a registered node type. */\r\nexport interface TypeDef {\r\n /** Validate a value about to be stored at a node of this type. Throw to reject. */\r\n validate?: (value: Json) => void;\r\n /** Override the size-based decomposition for nodes of this type. */\r\n decompose?: \"opaque\" | \"children\";\r\n /** Override the text used to embed nodes of this type. Return null to skip embedding. */\r\n embedText?: (value: Json) => string | null;\r\n}\r\n\r\n/** A registry of named node types (validator + decompose override). */\r\nexport class TypeRegistry {\r\n private readonly types = new Map<string, TypeDef>();\r\n\r\n register(name: string, def: TypeDef): void {\r\n this.types.set(name, def);\r\n }\r\n\r\n get(name: string): TypeDef | undefined {\r\n return this.types.get(name);\r\n }\r\n\r\n has(name: string): boolean {\r\n return this.types.has(name);\r\n }\r\n}\r\n","import type { Validator } from \"./mutator\";\r\nimport type { TypeRegistry } from \"./type-registry\";\r\n\r\n/** Build a Mutator `Validator` that runs the registered `validate()` for the node's type. */\r\nexport function makeRegistryValidator(registry: TypeRegistry): Validator {\r\n return ({ proposed, type }) => {\r\n if (type === undefined) return;\r\n registry.get(type)?.validate?.(proposed);\r\n };\r\n}\r\n","import type { Json } from \"./types\";\r\nimport type { DecomposeDecision } from \"./decompose\";\r\nimport type { TypeRegistry } from \"./type-registry\";\r\n\r\n/** Wrap a base decision so a node's registered type can override the size heuristic. */\r\nexport function typeAwareDecision(base: DecomposeDecision, registry: TypeRegistry): DecomposeDecision {\r\n return {\r\n isOpaque(value: Json, type?: string): boolean {\r\n if (type !== undefined) {\r\n const override = registry.get(type)?.decompose;\r\n if (override === \"opaque\") return true;\r\n if (override === \"children\") return false;\r\n }\r\n return base.isOpaque(value, type);\r\n },\r\n };\r\n}\r\n","import type { Json } from \"./types\";\r\nimport { ValidationError } from \"./errors\";\r\n\r\n/** Structural shape of a parser (e.g. a Zod schema). Avoids hard-coupling Arbor to a Zod version. */\r\nexport interface ParseSchema {\r\n parse(value: unknown): unknown;\r\n}\r\n\r\n/**\r\n * Build a `TypeDef.validate` function from any Zod-compatible schema (anything with `.parse()`).\r\n * Throws `ValidationError` (wrapping the parser's error message) when the value is invalid.\r\n */\r\nexport function zodValidate(schema: ParseSchema, typeName?: string): (value: Json) => void {\r\n return (value: Json) => {\r\n try {\r\n schema.parse(value);\r\n } catch (err) {\r\n const details = err instanceof Error ? err.message : String(err);\r\n throw new ValidationError(typeName, details);\r\n }\r\n };\r\n}\r\n","import { parsePointer } from \"./jsonpointer\";\r\n\r\n/** Match parsed segment arrays. `*` = one segment; `**` = zero or more segments. */\r\nfunction matchSegments(pattern: string[], path: string[]): boolean {\r\n if (pattern.length === 0) return path.length === 0;\r\n const [head, ...rest] = pattern;\r\n if (head === \"**\") {\r\n for (let i = 0; i <= path.length; i++) {\r\n if (matchSegments(rest, path.slice(i))) return true;\r\n }\r\n return false;\r\n }\r\n if (path.length === 0) return false;\r\n if (head === \"*\" || head === path[0]) {\r\n return matchSegments(rest, path.slice(1));\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * Parse a glob `pattern` ONCE and return a reusable matcher over JSON Pointer paths.\r\n * `*` matches exactly one path segment; `**` matches zero or more segments.\r\n */\r\nexport function compileGlob(pattern: string): (path: string) => boolean {\r\n const patternSegs = parsePointer(pattern);\r\n return (path: string) => matchSegments(patternSegs, parsePointer(path));\r\n}\r\n\r\n/**\r\n * Glob-match a JSON Pointer `path` against a `pattern`.\r\n * `*` matches exactly one path segment; `**` matches zero or more segments.\r\n * One-shot convenience over `compileGlob` — prefer compiling when matching many paths.\r\n */\r\nexport function matchGlob(pattern: string, path: string): boolean {\r\n return compileGlob(pattern)(path);\r\n}\r\n","import type { ArbNode, Json, NodeId, NodeKind, NodeMeta } from \"./types\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { Addressing } from \"./addressing\";\r\nimport { type Ref, NodeNotFoundError } from \"./errors\";\r\nimport { byteSize } from \"./decompose\";\r\nimport { compileGlob } from \"./path-glob\";\r\nimport { isWithin, appendPointer } from \"./jsonpointer\";\r\n\r\nconst DEFAULT_LIMIT = 100;\r\nconst PREVIEW_MAX = 50;\r\n\r\nexport interface NodeSummary {\r\n id: NodeId;\r\n path: string;\r\n key: string | number | null;\r\n kind: NodeKind;\r\n type?: string;\r\n}\r\n\r\nexport interface ChildSummary {\r\n id: NodeId;\r\n key: string | number | null;\r\n kind: NodeKind;\r\n type?: string;\r\n hasChildren: boolean;\r\n size: number;\r\n preview: string;\r\n}\r\n\r\nexport interface DescribeOpts {\r\n offset?: number;\r\n limit?: number;\r\n}\r\n\r\nexport interface DescribeResult {\r\n node: NodeSummary;\r\n children: ChildSummary[];\r\n truncated?: { shown: number; total: number; nextOffset: number };\r\n}\r\n\r\nexport interface GetOpts {\r\n maxDepth?: number;\r\n}\r\n\r\nexport interface GetResult {\r\n id: NodeId;\r\n path: string;\r\n type?: string;\r\n content: Json;\r\n meta: NodeMeta;\r\n truncated?: boolean;\r\n}\r\n\r\nexport interface FindSelector {\r\n type?: string;\r\n tag?: string;\r\n pathPattern?: string;\r\n}\r\n\r\nexport interface FindOpts {\r\n limit?: number;\r\n /** JSON Pointer prefix: only nodes at/under it are hits — checked BEFORE the\r\n * limit is consumed, so out-of-scope matches never eat the budget. */\r\n within?: string;\r\n}\r\n\r\nexport interface FindHit {\r\n id: NodeId;\r\n path: string;\r\n type?: string;\r\n}\r\n\r\nexport interface FindResult {\r\n hits: FindHit[];\r\n /** True when the walk stopped at `limit` — there MAY be more matches (an exact-fit\r\n * final hit also reports true). */\r\n truncated: boolean;\r\n}\r\n\r\nfunction previewOf(node: ArbNode): string {\r\n if (node.kind === \"leaf\") {\r\n const s = JSON.stringify(node.content);\r\n return s.length <= PREVIEW_MAX ? s : s.slice(0, PREVIEW_MAX) + \"…\";\r\n }\r\n return node.kind === \"array\" ? `[${node.childIds.length} items]` : `{${node.childIds.length} keys}`;\r\n}\r\n\r\n/** Read-only navigation over the artifact tree: describe (cheap listing) and get (bounded content). */\r\nexport class Navigator {\r\n constructor(\r\n private readonly tree: ArtifactTree,\r\n private readonly addressing: Addressing,\r\n ) {}\r\n\r\n protected resolve(ref: Ref): ArbNode {\r\n const node = \"id\" in ref ? this.addressing.byId(ref.id) : this.addressing.byPath(ref.path);\r\n if (!node) throw new NodeNotFoundError(ref);\r\n return node;\r\n }\r\n\r\n private summarize(node: ArbNode): ChildSummary {\r\n return {\r\n id: node.id,\r\n key: node.key,\r\n kind: node.kind,\r\n type: node.type,\r\n hasChildren: node.childIds.length > 0,\r\n size: node.kind === \"leaf\" ? byteSize(node.content) : node.childIds.length,\r\n preview: previewOf(node),\r\n };\r\n }\r\n\r\n describe(ref: Ref = { path: \"\" }, opts: DescribeOpts = {}): DescribeResult {\r\n const node = this.resolve(ref);\r\n const all = this.tree.children(node.id);\r\n const total = all.length;\r\n const offset = opts.offset ?? 0;\r\n const limit = opts.limit ?? DEFAULT_LIMIT;\r\n const page = all.slice(offset, offset + limit);\r\n const result: DescribeResult = {\r\n node: {\r\n id: node.id,\r\n path: this.addressing.pathOf(node.id),\r\n key: node.key,\r\n kind: node.kind,\r\n type: node.type,\r\n },\r\n children: page.map((c) => this.summarize(c)),\r\n };\r\n const nextOffset = offset + page.length;\r\n if (nextOffset < total) {\r\n result.truncated = { shown: page.length, total, nextOffset };\r\n }\r\n return result;\r\n }\r\n\r\n get(ref: Ref, opts: GetOpts = {}): GetResult {\r\n const node = this.resolve(ref);\r\n const maxDepth = opts.maxDepth;\r\n let truncated = false;\r\n const reconstruct = (id: NodeId, depth: number): Json => {\r\n const n = this.tree.get(id)!;\r\n if (n.kind === \"leaf\") return n.content;\r\n if (maxDepth !== undefined && depth >= maxDepth) {\r\n truncated = true;\r\n const label = n.kind === \"array\" ? `${n.childIds.length} items` : `${n.childIds.length} keys`;\r\n return `[truncated: ${label}]`;\r\n }\r\n if (n.kind === \"array\") return n.childIds.map((cid) => reconstruct(cid, depth + 1));\r\n const obj: Record<string, Json> = {};\r\n for (const cid of n.childIds) {\r\n const c = this.tree.get(cid)!;\r\n obj[String(c.key)] = reconstruct(cid, depth + 1);\r\n }\r\n return obj;\r\n };\r\n const content = reconstruct(node.id, 0);\r\n const result: GetResult = {\r\n id: node.id,\r\n path: this.addressing.pathOf(node.id),\r\n type: node.type,\r\n content,\r\n meta: node.meta,\r\n };\r\n if (truncated) result.truncated = true;\r\n return result;\r\n }\r\n\r\n private matches(node: ArbNode, sel: FindSelector, path: string, glob?: (path: string) => boolean): boolean {\r\n if (sel.type !== undefined && node.type !== sel.type) return false;\r\n if (sel.tag !== undefined && !(node.tags?.includes(sel.tag) ?? false)) return false;\r\n if (glob !== undefined && !glob(path)) return false;\r\n return true;\r\n }\r\n\r\n /** Find nodes matching ALL provided selector fields (exact `type`, `tag` membership, glob `pathPattern`). */\r\n find(selector: FindSelector, opts: FindOpts = {}): FindResult {\r\n const limit = opts.limit ?? DEFAULT_LIMIT;\r\n const within = opts.within;\r\n // The pattern is parsed ONCE per find; each node's path is built incrementally\r\n // down the DFS (no per-node pathOf walk to the root).\r\n const glob = selector.pathPattern !== undefined ? compileGlob(selector.pathPattern) : undefined;\r\n const hits: FindHit[] = [];\r\n let truncated = false;\r\n const visit = (id: NodeId, path: string): void => {\r\n if (hits.length >= limit) {\r\n truncated = true;\r\n return;\r\n }\r\n const node = this.tree.get(id)!;\r\n if (this.matches(node, selector, path, glob)) {\r\n if (isWithin(path, within)) {\r\n hits.push({ id: node.id, path, type: node.type });\r\n }\r\n }\r\n for (const cid of node.childIds) {\r\n if (hits.length >= limit) {\r\n truncated = true;\r\n break;\r\n }\r\n const child = this.tree.get(cid)!;\r\n visit(cid, appendPointer(path, child.key as string | number));\r\n }\r\n };\r\n visit(this.tree.rootIdValue(), \"\");\r\n return { hits, truncated };\r\n }\r\n}\r\n","/** Turns text into vectors. Swappable; production adapters (OpenAI, local, etc.) implement this. */\r\nexport interface EmbeddingPort {\r\n readonly dims: number;\r\n embed(texts: string[]): Promise<number[][]>;\r\n}\r\n\r\n/**\r\n * Deterministic test/dev embedding: sums char codes into fixed-dimension buckets.\r\n * Same text → same vector (so an exact-text query ranks its node first); no network.\r\n */\r\nexport class MockEmbeddingPort implements EmbeddingPort {\r\n constructor(readonly dims = 32) {}\r\n\r\n async embed(texts: string[]): Promise<number[][]> {\r\n return texts.map((t) => this.vectorize(t));\r\n }\r\n\r\n private vectorize(text: string): number[] {\r\n const v = new Array<number>(this.dims).fill(0);\r\n for (let i = 0; i < text.length; i++) {\r\n v[i % this.dims] += text.charCodeAt(i);\r\n }\r\n return v;\r\n }\r\n}\r\n","import type { ArbNode, Json } from \"./types\";\r\nimport type { TypeDef } from \"./type-registry\";\r\n\r\n/**\r\n * The text used to embed a node, or null if the node is not embedded.\r\n * A registered type's `embedText` wins; otherwise: string leaf → its value;\r\n * opaque object/array leaf → its JSON; numeric/boolean/null leaves and all\r\n * structural containers → null.\r\n */\r\nexport function toEmbeddingText(node: ArbNode, value: Json, typeDef?: TypeDef): string | null {\r\n if (typeDef?.embedText) return typeDef.embedText(value);\r\n if (node.kind !== \"leaf\") return null;\r\n if (typeof value === \"string\") return value;\r\n if (value !== null && typeof value === \"object\") return JSON.stringify(value);\r\n return null;\r\n}\r\n\r\n/** Deterministic 32-bit FNV-1a hash, hex-encoded — used to dedupe re-embedding. */\r\nexport function textHash(text: string): string {\r\n let h = 2166136261 >>> 0;\r\n for (let i = 0; i < text.length; i++) {\r\n h ^= text.charCodeAt(i);\r\n h = Math.imul(h, 16777619) >>> 0;\r\n }\r\n return h.toString(16);\r\n}\r\n","import type { ArbNode, NodeId, Json } from \"./types\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { Addressing } from \"./addressing\";\r\nimport type { TypeRegistry } from \"./type-registry\";\r\nimport type { EmbeddingPort } from \"./embedding-port\";\r\nimport type { VectorIndexPort } from \"./vector-index-port\";\r\nimport { toEmbeddingText, textHash } from \"./embedding-text\";\r\nimport { isWithin } from \"./jsonpointer\";\r\n\r\nexport interface SearchOpts {\r\n k?: number;\r\n under?: string;\r\n type?: string;\r\n tag?: string;\r\n freshness?: \"best-effort\" | \"wait\";\r\n}\r\n\r\nexport interface SearchHit {\r\n id: NodeId;\r\n path: string;\r\n type?: string;\r\n score: number;\r\n snippet: string;\r\n}\r\n\r\nexport interface SearchResult {\r\n results: SearchHit[];\r\n staleCount: number;\r\n}\r\n\r\n/**\r\n * Owns the per-node semantic index: a stale queue fed by mutation hooks, an async\r\n * batched reindexer, and (Task 6) search. Embedding is never in the mutation path —\r\n * mutations only mark stale; reindex does the async embedding work.\r\n */\r\nexport class SemanticIndex {\r\n private readonly stale = new Set<NodeId>();\r\n private readonly pendingRemoval = new Set<NodeId>();\r\n\r\n constructor(\r\n private readonly tree: ArtifactTree,\r\n private readonly addressing: Addressing,\r\n private readonly embedding: EmbeddingPort,\r\n private readonly vectors: VectorIndexPort,\r\n private readonly registry?: TypeRegistry,\r\n ) {\r\n // Recover the stale queue after a restore: `stale` itself is not persisted,\r\n // but each node's `meta.embedding.state` is. A fresh tree has only \"none\"\r\n // states, so this is a no-op there.\r\n for (const node of tree.allNodes()) {\r\n if (node.meta.embedding.state === \"stale\") this.stale.add(node.id);\r\n }\r\n }\r\n\r\n /** The nearest ancestor whose type declares embedText — the semantic unit that\r\n * owns this shard — or undefined. (O(depth) walk per call — fine at v1 sizes.) */\r\n private embedTextAncestor(node: ArbNode): ArbNode | undefined {\r\n let pid = node.parentId;\r\n while (pid !== null) {\r\n const anc = this.tree.get(pid);\r\n const ancDef = anc?.type ? this.registry?.get(anc.type) : undefined;\r\n if (ancDef?.embedText) return anc;\r\n pid = anc?.parentId ?? null;\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * A node is a suppressed decomposition shard iff some ANCESTOR has a typed\r\n * embedText AND the node does not itself declare a typed embedText.\r\n */\r\n private isSuppressedShard(node: ArbNode): boolean {\r\n const ownTypeDef = node.type ? this.registry?.get(node.type) : undefined;\r\n if (ownTypeDef?.embedText) return false; // node is its own semantic unit\r\n return this.embedTextAncestor(node) !== undefined;\r\n }\r\n\r\n /** Mutation hook: a node's content changed (set/insert). Marks it stale if its embedding-text changed. */\r\n onChange(node: ArbNode): void {\r\n if (this.isSuppressedShard(node)) {\r\n node.meta.embedding = { state: \"none\" };\r\n this.pendingRemoval.add(node.id);\r\n this.stale.delete(node.id);\r\n // The owning typed unit's embed text covers this shard — re-hash IT.\r\n // (Terminates: the ancestor has its own embedText, so it takes the\r\n // normal branch below.)\r\n const anc = this.embedTextAncestor(node);\r\n if (anc) this.onChange(anc);\r\n return;\r\n }\r\n const value = this.tree.toJson(node.id);\r\n const typeDef = node.type ? this.registry?.get(node.type) : undefined;\r\n const text = toEmbeddingText(node, value, typeDef);\r\n if (text === null) {\r\n node.meta.embedding = { state: \"none\" };\r\n this.pendingRemoval.add(node.id);\r\n this.stale.delete(node.id);\r\n return;\r\n }\r\n const hash = textHash(text);\r\n if (node.meta.embedding.state === \"fresh\" && node.meta.embedding.textHash === hash) {\r\n return;\r\n }\r\n node.meta.embedding = { state: \"stale\", textHash: hash };\r\n this.pendingRemoval.delete(node.id);\r\n this.stale.add(node.id);\r\n }\r\n\r\n /** Mutation hook: a node was removed. Drops it from the index and the stale queue. */\r\n onRemove(nodeId: NodeId): void {\r\n this.pendingRemoval.add(nodeId);\r\n this.stale.delete(nodeId);\r\n }\r\n\r\n /**\r\n * Snapshot of both queues for transaction rollback.\r\n *\r\n * The sync hooks (`onChange`, `onRemove`) only move ids between the `stale`\r\n * queue and the `pendingRemoval` queue; all actual vector mutations happen in\r\n * the async `reindex()`. This snapshot covers both queues so that a rollback\r\n * fully restores the observable state of the index without touching vectors.\r\n */\r\n txSnapshot(): unknown {\r\n return {\r\n stale: new Set(this.stale),\r\n pendingRemoval: new Set(this.pendingRemoval),\r\n };\r\n }\r\n\r\n /** Restore both queues captured by `txSnapshot`. */\r\n txRestore(snapshot: unknown): void {\r\n const snap = snapshot as { stale: Set<NodeId>; pendingRemoval: Set<NodeId> };\r\n this.stale.clear();\r\n for (const id of snap.stale) this.stale.add(id);\r\n this.pendingRemoval.clear();\r\n for (const id of snap.pendingRemoval) this.pendingRemoval.add(id);\r\n }\r\n\r\n /** Convenience: the hooks to wire into `MutatorDeps`. */\r\n hooks(): {\r\n onChange: (node: ArbNode) => void;\r\n onRemove: (nodeId: NodeId) => void;\r\n onTxSnapshot: () => unknown;\r\n onTxRestore: (snapshot: unknown) => void;\r\n } {\r\n return {\r\n onChange: (node) => this.onChange(node),\r\n onRemove: (nodeId) => this.onRemove(nodeId),\r\n onTxSnapshot: () => this.txSnapshot(),\r\n onTxRestore: (snapshot) => this.txRestore(snapshot),\r\n };\r\n }\r\n\r\n staleCount(): number {\r\n return this.stale.size;\r\n }\r\n\r\n /** Embed every stale node (one batch), upsert vectors, mark fresh, clear the processed ids.\r\n * Interleave-safe: mutations landing during the embed await are respected — a node\r\n * removed mid-flight is dropped (never resurrected), and a node whose text changed\r\n * stays queued for the next pass instead of being marked fresh for the old text. */\r\n async reindex(): Promise<void> {\r\n // First: drain deferred removals (HOLE 2 fix — removals queued by sync hooks).\r\n for (const id of this.pendingRemoval) await this.vectors.remove(id);\r\n this.pendingRemoval.clear();\r\n\r\n const ids = [...this.stale];\r\n if (ids.length === 0) return;\r\n const completed = new Set<NodeId>();\r\n const items: { id: NodeId; text: string; hash: string }[] = [];\r\n for (const id of ids) {\r\n const node = this.tree.get(id);\r\n if (!node) {\r\n completed.add(id);\r\n continue;\r\n }\r\n // HOLE 1 fix: guard-aware reindex — suppress shards that belong to a typed\r\n // ancestor's embedding unit.\r\n if (this.isSuppressedShard(node)) {\r\n node.meta.embedding = { state: \"none\" };\r\n await this.vectors.remove(id);\r\n completed.add(id);\r\n continue;\r\n }\r\n const value = this.tree.toJson(id);\r\n const typeDef = node.type ? this.registry?.get(node.type) : undefined;\r\n const text = toEmbeddingText(node, value, typeDef);\r\n if (text === null) {\r\n node.meta.embedding = { state: \"none\" };\r\n await this.vectors.remove(id);\r\n completed.add(id);\r\n continue;\r\n }\r\n items.push({ id, text, hash: textHash(text) });\r\n }\r\n if (items.length > 0) {\r\n const embedded = await this.embedding.embed(items.map((it) => it.text));\r\n // Mutations may have landed during the await — re-validate every item\r\n // against the live tree before trusting the embedded batch.\r\n const upserts: { nodeId: NodeId; vector: number[] }[] = [];\r\n for (const [i, it] of items.entries()) {\r\n const node = this.tree.get(it.id);\r\n if (!node) {\r\n await this.vectors.remove(it.id); // removed mid-flight — do not resurrect\r\n completed.add(it.id);\r\n continue;\r\n }\r\n // Positive trust check: mark fresh ONLY if the node still awaits exactly the\r\n // text we embedded. \"none\" (text became null / became a suppressed shard\r\n // mid-flight) means its removal is already queued — complete without\r\n // upserting; any other divergence (new hash) stays queued for the next pass.\r\n // A stale node with NO textHash (a delta-restored node — restoreFromDelta\r\n // marks {state:\"stale\"} without a hash) cannot have been touched during the\r\n // await: any mid-flight change writes a concrete hash (\"stale\"), \"none\", or\r\n // removes the node. So an undefined hash means our pre-await snapshot is\r\n // current — trust the batch.\r\n const cur = node.meta.embedding;\r\n if (cur.state !== \"stale\" || (cur.textHash !== undefined && cur.textHash !== it.hash)) {\r\n if (node.meta.embedding.state === \"none\") completed.add(it.id);\r\n continue;\r\n }\r\n upserts.push({ nodeId: it.id, vector: embedded[i] });\r\n node.meta.embedding = { state: \"fresh\", textHash: it.hash };\r\n completed.add(it.id);\r\n }\r\n if (upserts.length > 0) await this.vectors.upsert(upserts);\r\n }\r\n for (const id of ids) {\r\n if (completed.has(id)) this.stale.delete(id);\r\n }\r\n }\r\n\r\n private snippetOf(value: Json): string {\r\n const s = JSON.stringify(value);\r\n return s.length <= 80 ? s : s.slice(0, 80) + \"…\";\r\n }\r\n\r\n /**\r\n * Semantic search: embed the query, rank indexed nodes by cosine, post-filter by\r\n * under/type/tag, return top-k. `freshness: \"wait\"` flushes the reindexer first;\r\n * default `best-effort` searches what's indexed and reports `staleCount`.\r\n */\r\n async search(queryText: string, opts: SearchOpts = {}): Promise<SearchResult> {\r\n if (opts.freshness === \"wait\") await this.reindex();\r\n const k = opts.k ?? 8;\r\n const [queryVec] = await this.embedding.embed([queryText]);\r\n const ranked = await this.vectors.search(queryVec, await this.vectors.size());\r\n const results: SearchHit[] = [];\r\n for (const hit of ranked) {\r\n if (results.length >= k) break;\r\n // Skip logically-removed entries that haven't been physically flushed yet.\r\n if (this.pendingRemoval.has(hit.nodeId)) continue;\r\n const node = this.tree.get(hit.nodeId);\r\n if (!node) continue;\r\n const path = this.addressing.pathOf(node.id);\r\n if (opts.under !== undefined && !isWithin(path, opts.under)) continue;\r\n if (opts.type !== undefined && node.type !== opts.type) continue;\r\n if (opts.tag !== undefined && !(node.tags?.includes(opts.tag) ?? false)) continue;\r\n results.push({\r\n id: node.id,\r\n path,\r\n type: node.type,\r\n score: hit.score,\r\n snippet: this.snippetOf(this.tree.toJson(node.id)),\r\n });\r\n }\r\n return { results, staleCount: this.staleCount() };\r\n }\r\n}\r\n","import type { NodeId } from \"./types\";\r\n\r\nexport interface VectorIndexEntry {\r\n nodeId: NodeId;\r\n vector: number[];\r\n}\r\n\r\nexport interface VectorHit {\r\n nodeId: NodeId;\r\n score: number;\r\n}\r\n\r\n/** Stores per-node vectors and ranks by similarity. Async so DB-backed adapters\r\n * (pgvector, sqlite-vec) can implement it; the in-memory default is sync inside. */\r\nexport interface VectorIndexPort {\r\n upsert(entries: VectorIndexEntry[]): Promise<void>;\r\n remove(nodeId: NodeId): Promise<void>;\r\n search(query: number[], k: number): Promise<VectorHit[]>;\r\n has(nodeId: NodeId): Promise<boolean>;\r\n size(): Promise<number>;\r\n entries(): Promise<VectorIndexEntry[]>;\r\n}\r\n\r\n/** Unit-normalize into a Float32Array; zero-norm vectors stay all-zeros\r\n * (their dot with anything is 0 — matches cosine's zero-magnitude behavior). */\r\nfunction normalize(v: ArrayLike<number>): Float32Array {\r\n const out = new Float32Array(v.length);\r\n let n = 0;\r\n for (let i = 0; i < v.length; i++) n += v[i] * v[i];\r\n if (n === 0) return out;\r\n const inv = 1 / Math.sqrt(n);\r\n for (let i = 0; i < v.length; i++) out[i] = v[i] * inv;\r\n return out;\r\n}\r\n\r\nfunction dot(a: Float32Array, b: Float32Array): number {\r\n const len = Math.min(a.length, b.length);\r\n let d = 0;\r\n for (let i = 0; i < len; i++) d += a[i] * b[i];\r\n return d;\r\n}\r\n\r\n/** In-memory brute-force index. Vectors are stored as Float32Arrays (raw for\r\n * `entries()`, unit-normalized for search) so `search` is a plain dot product\r\n * — the cosine of two normalized vectors. Correct and simple at current scale. */\r\nexport class MemoryVectorIndex implements VectorIndexPort {\r\n private readonly vectors = new Map<NodeId, { raw: Float32Array; unit: Float32Array }>();\r\n\r\n async upsert(entries: VectorIndexEntry[]): Promise<void> {\r\n for (const e of entries) {\r\n this.vectors.set(e.nodeId, { raw: Float32Array.from(e.vector), unit: normalize(e.vector) });\r\n }\r\n }\r\n\r\n async remove(nodeId: NodeId): Promise<void> {\r\n this.vectors.delete(nodeId);\r\n }\r\n\r\n async has(nodeId: NodeId): Promise<boolean> {\r\n return this.vectors.has(nodeId);\r\n }\r\n\r\n async size(): Promise<number> {\r\n return this.vectors.size;\r\n }\r\n\r\n async search(query: number[], k: number): Promise<VectorHit[]> {\r\n const q = normalize(query);\r\n const hits: VectorHit[] = [];\r\n for (const [nodeId, { unit }] of this.vectors) {\r\n hits.push({ nodeId, score: dot(q, unit) });\r\n }\r\n hits.sort((a, b) => b.score - a.score);\r\n return hits.slice(0, k);\r\n }\r\n\r\n async entries(): Promise<VectorIndexEntry[]> {\r\n return [...this.vectors].map(([nodeId, { raw }]) => ({ nodeId, vector: Array.from(raw) }));\r\n }\r\n}\r\n","import type { ArbNode, NodeId } from \"./types\";\r\nimport { ArtifactTree, type TreeDeps } from \"./artifact-tree\";\r\nimport { EventLog, type MutationEvent } from \"./event-log\";\r\nimport type { VectorIndexPort, VectorIndexEntry } from \"./vector-index-port\";\r\n\r\n/** A JSON-serializable snapshot of an entire artifact: tree + event-log + vectors.\r\n * v2 adds `baseSeq` (the event-log compaction floor); v1 files restore with floor 0. */\r\nexport interface StoredArtifact {\r\n version: 1 | 2;\r\n rootId: NodeId;\r\n nodes: ArbNode[];\r\n events: MutationEvent[];\r\n /** Absolute seq of the oldest retained event (compaction floor). Absent in v1 → 0. */\r\n baseSeq?: number;\r\n vectors: VectorIndexEntry[];\r\n}\r\n\r\n/** Persists/loads a StoredArtifact. Adapters: MemoryStorage, FileStorage (and DB-backed later). */\r\nexport interface StoragePort {\r\n save(artifact: StoredArtifact): Promise<void>;\r\n load(): Promise<StoredArtifact | null>;\r\n}\r\n\r\n/** Dump the live components into a StoredArtifact (v2). */\r\nexport async function serializeArtifact(\r\n tree: ArtifactTree,\r\n log: EventLog,\r\n vectors: VectorIndexPort,\r\n): Promise<StoredArtifact> {\r\n return {\r\n version: 2,\r\n rootId: tree.rootIdValue(),\r\n nodes: tree.allNodes(),\r\n events: [...log.entries()],\r\n baseSeq: log.baseSeqValue(),\r\n vectors: await vectors.entries(),\r\n };\r\n}\r\n\r\n/** Rebuild a fresh tree + log from a StoredArtifact, and upsert its vectors into `vectors`. */\r\nexport async function restoreArtifact(\r\n stored: StoredArtifact,\r\n deps: TreeDeps,\r\n vectors: VectorIndexPort,\r\n): Promise<{ tree: ArtifactTree; log: EventLog }> {\r\n const tree = ArtifactTree.fromStored(stored.nodes, stored.rootId, deps);\r\n const log = EventLog.fromStored(stored.events, stored.baseSeq ?? 0);\r\n await vectors.upsert(stored.vectors);\r\n return { tree, log };\r\n}\r\n\r\n/** In-memory StoragePort: holds a deep-cloned bundle. */\r\nexport class MemoryStorage implements StoragePort {\r\n private stored: StoredArtifact | null = null;\r\n\r\n async save(artifact: StoredArtifact): Promise<void> {\r\n this.stored = structuredClone(artifact);\r\n }\r\n\r\n async load(): Promise<StoredArtifact | null> {\r\n return this.stored ? structuredClone(this.stored) : null;\r\n }\r\n}\r\n","import { readFile, writeFile, rename } from \"node:fs/promises\";\r\nimport type { StoredArtifact, StoragePort } from \"./storage\";\r\n\r\nfunction isStoredArtifact(v: unknown): v is StoredArtifact {\r\n if (typeof v !== \"object\" || v === null) return false;\r\n const a = v as Record<string, unknown>;\r\n return (\r\n (a[\"version\"] === 1 || a[\"version\"] === 2) &&\r\n typeof a[\"rootId\"] === \"string\" &&\r\n Array.isArray(a[\"nodes\"]) &&\r\n Array.isArray(a[\"events\"]) &&\r\n Array.isArray(a[\"vectors\"])\r\n );\r\n}\r\n\r\n/**\r\n * File-backed StoragePort: one JSON file per artifact. `load` returns null if the\r\n * file is absent. Saves are atomic (write tmp, then rename) so a crash mid-write\r\n * never corrupts an existing artifact; loads validate the parsed shape.\r\n */\r\nexport class FileStorage implements StoragePort {\r\n constructor(private readonly path: string) {}\r\n\r\n async save(artifact: StoredArtifact): Promise<void> {\r\n const tmp = this.path + \".tmp\";\r\n await writeFile(tmp, JSON.stringify(artifact), \"utf8\");\r\n await rename(tmp, this.path);\r\n }\r\n\r\n async load(): Promise<StoredArtifact | null> {\r\n let text: string;\r\n try {\r\n text = await readFile(this.path, \"utf8\");\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return null;\r\n throw err;\r\n }\r\n let parsed: unknown;\r\n try {\r\n parsed = JSON.parse(text);\r\n } catch (err) {\r\n const detail = err instanceof Error ? err.message : String(err);\r\n throw new Error(`FileStorage: corrupt artifact file ${this.path}: ${detail}`);\r\n }\r\n if (!isStoredArtifact(parsed)) {\r\n throw new Error(`FileStorage: invalid artifact file ${this.path} (unrecognized shape)`);\r\n }\r\n return parsed;\r\n }\r\n}\r\n","import type { Json } from \"./types\";\r\nimport { parsePointer } from \"./jsonpointer\";\r\n\r\n/** Read the value at a JSON Pointer, or undefined if any segment is missing. */\r\nexport function getAtPath(value: Json, pointer: string): Json | undefined {\r\n const segs = parsePointer(pointer);\r\n let cur: Json | undefined = value;\r\n for (const seg of segs) {\r\n if (Array.isArray(cur)) {\r\n const i = Number(seg);\r\n cur = Number.isInteger(i) && i >= 0 && i < cur.length ? cur[i] : undefined;\r\n } else if (cur !== null && typeof cur === \"object\") {\r\n cur = seg in cur ? (cur as Record<string, Json>)[seg] : undefined;\r\n } else {\r\n return undefined;\r\n }\r\n if (cur === undefined) return undefined;\r\n }\r\n return cur;\r\n}\r\n\r\n/** Navigate (within `root`) to the container holding the pointer's last segment. */\r\nfunction navParent(root: Json, pointer: string): { parent: Json; key: string } | undefined {\r\n const segs = parsePointer(pointer);\r\n if (segs.length === 0) return undefined;\r\n let cur: Json | undefined = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const seg = segs[i];\r\n if (Array.isArray(cur)) cur = cur[Number(seg)];\r\n else if (cur !== null && typeof cur === \"object\") cur = (cur as Record<string, Json>)[seg];\r\n else return undefined;\r\n if (cur === undefined || cur === null) return undefined;\r\n }\r\n return { parent: cur, key: segs[segs.length - 1] };\r\n}\r\n\r\n/** In-place variant of setAtPath: mutates `value` (root pointer returns `newVal`). */\r\nexport function setAtPathMut(value: Json, pointer: string, newVal: Json): Json {\r\n if (pointer === \"\") return newVal;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent[Number(pk.key)] = newVal;\r\n else (pk.parent as Record<string, Json>)[pk.key] = newVal;\r\n return value;\r\n}\r\n\r\n/** In-place variant of removeAtPath: mutates `value` (root pointer returns null). */\r\nexport function removeAtPathMut(value: Json, pointer: string): Json {\r\n if (pointer === \"\") return null;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 1);\r\n else delete (pk.parent as Record<string, Json>)[pk.key];\r\n return value;\r\n}\r\n\r\n/** In-place variant of insertAtPath: mutates `value` (root pointer returns `val`). */\r\nexport function insertAtPathMut(value: Json, pointer: string, val: Json): Json {\r\n if (pointer === \"\") return val;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 0, val);\r\n else (pk.parent as Record<string, Json>)[pk.key] = val;\r\n return value;\r\n}\r\n\r\n/** Return a copy of `value` with the value at `pointer` replaced (root → returns `newVal`). */\r\nexport function setAtPath(value: Json, pointer: string, newVal: Json): Json {\r\n return setAtPathMut(structuredClone(value), pointer, newVal);\r\n}\r\n\r\n/** Return a copy of `value` with the element at `pointer` removed (object delete / array splice). */\r\nexport function removeAtPath(value: Json, pointer: string): Json {\r\n return removeAtPathMut(structuredClone(value), pointer);\r\n}\r\n\r\n/** Return a copy of `value` with `val` inserted at `pointer` (object set / array splice-in). */\r\nexport function insertAtPath(value: Json, pointer: string, val: Json): Json {\r\n return insertAtPathMut(structuredClone(value), pointer, val);\r\n}\r\n","import type { Json } from \"./types\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { Addressing } from \"./addressing\";\r\nimport type { EventLog, MutationEvent } from \"./event-log\";\r\nimport type { Mutator } from \"./mutator\";\r\nimport { type Ref, InvalidOpError } from \"./errors\";\r\nimport { getAtPath, setAtPathMut, removeAtPathMut, insertAtPathMut } from \"./json-edit\";\r\n\r\n/** Undo a single event on a JSON value IN PLACE (the caller owns `value` — it is the\r\n * single upfront clone made by `reconstructValueAt`). The spliced-in `before` values\r\n * are still cloned (M14): they protect the LOG from mutation through the output. */\r\nfunction reverseApplyValue(value: Json, e: MutationEvent): Json {\r\n switch (e.kind) {\r\n case \"set\":\r\n return e.path === undefined ? value : setAtPathMut(value, e.path, structuredClone(e.before ?? null));\r\n case \"insert\":\r\n return e.path === undefined ? value : removeAtPathMut(value, e.path);\r\n case \"remove\":\r\n return e.path === undefined ? value : insertAtPathMut(value, e.path, structuredClone(e.before ?? null));\r\n case \"move\": {\r\n if (e.toPath === undefined || e.fromPath === undefined) return value;\r\n const moved = getAtPath(value, e.toPath) ?? null;\r\n const withoutMoved = removeAtPathMut(value, e.toPath);\r\n return insertAtPathMut(withoutMoved, e.fromPath, moved);\r\n }\r\n }\r\n}\r\n\r\n/** Value-level time-travel over the reversible event-log. */\r\nexport class Replay {\r\n constructor(\r\n private readonly tree: ArtifactTree,\r\n private readonly log: EventLog,\r\n ) {}\r\n\r\n /** The whole artifact's JSON value as of `version` (0 = initial, log.length = current).\r\n * Throws if `version` is below the compaction floor (that history was dropped). */\r\n reconstructValueAt(version: number): Json {\r\n const total = this.log.length();\r\n const floor = this.log.baseSeqValue();\r\n if (version < floor) {\r\n throw new InvalidOpError(`cannot reconstruct version ${version}: history before ${floor} was compacted`);\r\n }\r\n const target = Math.min(version, total);\r\n let value: Json = structuredClone(this.tree.toJson());\r\n for (let seq = total - 1; seq >= target; seq--) {\r\n value = reverseApplyValue(value, this.log.at(seq)!);\r\n }\r\n return value;\r\n }\r\n\r\n /** The value at JSON Pointer `path` as of `version`, or undefined if absent then. */\r\n getAt(path: string, version: number): Json | undefined {\r\n return getAtPath(this.reconstructValueAt(version), path);\r\n }\r\n\r\n /** The mutations applied between version `vA` (inclusive) and `vB` (exclusive).\r\n * Events compacted away are not included. */\r\n diff(vA: number, vB: number): MutationEvent[] {\r\n return this.log.since(vA).filter((e) => e.seq < vB);\r\n }\r\n\r\n /** The node's {type, tags} as of `version`, by scanning later events on its path.\r\n * Move-aware: if the version-`version` occupant was moved away, follow it to its\r\n * new path and keep scanning — its type/tags travel with it. If the scan exhausts\r\n * on a FOLLOWED path, the occupant is the live node there — read it directly\r\n * (\"keep current\" would read whatever now sits at the original path).\r\n * type: string | null (untyped/absent) | undefined (unknown — keep current).\r\n * tags: string[] ([] = untagged) | undefined (unknown/pre-M14 — keep current).\r\n * Limitation (same as pre-M14): array-index paths can mis-resolve across sibling\r\n * index shifts; exact for object paths. */\r\n private stateAt(\r\n path: string,\r\n version: number,\r\n addressing: Addressing,\r\n ): { type: string | null | undefined; tags: string[] | undefined } {\r\n const total = this.log.length();\r\n let p = path;\r\n for (let seq = Math.max(version, this.log.baseSeqValue()); seq < total; seq++) {\r\n const e = this.log.at(seq)!;\r\n if (e.kind === \"move\") {\r\n if (e.fromPath === p) {\r\n p = e.toPath ?? p; // occupant moved away — follow it\r\n continue;\r\n }\r\n if (e.toPath === p) return { type: null, tags: [] }; // something ELSE moved in → vacant at `version`\r\n continue;\r\n }\r\n if (e.path !== p) continue;\r\n if (e.kind === \"set\" || e.kind === \"remove\") {\r\n return {\r\n type: e.nodeTypeBefore === undefined ? undefined : e.nodeTypeBefore,\r\n tags: e.tagsBefore, // absent (pre-M14) → undefined = keep current\r\n };\r\n }\r\n if (e.kind === \"insert\") return { type: null, tags: [] }; // node did not exist at `version`\r\n }\r\n if (p !== path) {\r\n // Followed through moves and nothing later touched the occupant: it is the\r\n // live node at `p` — its type/tags are the version-`version` answer.\r\n const live = addressing.byPath(p);\r\n return { type: live?.type ?? null, tags: live?.tags ?? [] };\r\n }\r\n return { type: undefined, tags: undefined }; // untouched since `version` — keep current\r\n }\r\n\r\n /** Restore the node at `ref` to its value, type, AND tags as of `toVersion`, as a new live mutation. */\r\n revert(mutator: Mutator, addressing: Addressing, ref: Ref, toVersion: number): void {\r\n const path = \"id\" in ref ? addressing.pathOf(ref.id) : ref.path;\r\n const past = this.getAt(path, toVersion);\r\n const { type, tags } = this.stateAt(path, toVersion, addressing);\r\n const opts: { type?: string | null; tags?: string[] } = {};\r\n if (type !== undefined) opts.type = type;\r\n if (tags !== undefined) opts.tags = tags;\r\n mutator.set({ path }, past ?? null, opts);\r\n }\r\n}\r\n","import type { Json, NodeId } from \"./types\";\r\nimport { ArtifactTree, type TreeDeps } from \"./artifact-tree\";\r\nimport { Addressing } from \"./addressing\";\r\nimport { EventLog, type MutationEvent } from \"./event-log\";\r\nimport { Mutator } from \"./mutator\";\r\nimport type { VectorIndexPort } from \"./vector-index-port\";\r\nimport { serializeArtifact, restoreArtifact } from \"./storage\";\r\nimport type { DeltaStoragePort } from \"./delta-storage\";\r\nimport { InvalidOpError } from \"./errors\";\r\n\r\n/** The JSON-Pointer of the parent container of `pointer` (\"\" = root). Pointer\r\n * separators are literal \"/\"; an in-key \"/\" is escaped \"~1\", so lastIndexOf is safe. */\r\nfunction parentPointer(pointer: string): string {\r\n const i = pointer.lastIndexOf(\"/\");\r\n return i <= 0 ? \"\" : pointer.slice(0, i);\r\n}\r\n\r\n/**\r\n * Re-apply ONE recorded event FORWARD onto a live tree via the `Mutator`, addressed by\r\n * the event's stable path(s). The inverse of replay's `reverseApplyValue`: set→`after`,\r\n * insert→insert `after`, remove→remove, move→to. Goes through the Mutator so\r\n * decomposition, typing (via `e.nodeType`), and the index hooks run exactly as in normal\r\n * operation. Node ids for touched subtrees are regenerated; replay/revert are path-addressed and\r\n * unaffected, but id-addressed views (e.g. toolset `history`, which filters by targetId)\r\n * may not see a regenerated node's pre-restore history. Malformed/pre-M7 events (missing\r\n * paths) are skipped.\r\n */\r\nexport function applyEventForward(mutator: Mutator, e: MutationEvent): void {\r\n switch (e.kind) {\r\n case \"set\": {\r\n if (e.path === undefined) return;\r\n const opts: { type?: string | null; tags?: string[] } = {};\r\n if (e.nodeType !== undefined) opts.type = e.nodeType;\r\n if (e.tags !== undefined) opts.tags = e.tags;\r\n mutator.set({ path: e.path }, e.after ?? null, opts);\r\n return;\r\n }\r\n case \"insert\": {\r\n if (e.path === undefined || e.key === null) return;\r\n const opts: { type?: string | null; tags?: string[] } = {};\r\n if (e.nodeType !== undefined) opts.type = e.nodeType;\r\n if (e.tags !== undefined) opts.tags = e.tags;\r\n mutator.insert({ path: parentPointer(e.path) }, e.key, e.after ?? null, opts);\r\n return;\r\n }\r\n case \"remove\":\r\n if (e.path === undefined) return;\r\n mutator.remove({ path: e.path });\r\n return;\r\n case \"move\":\r\n if (e.fromPath === undefined || e.toPath === undefined || !e.to || e.to.key === null) return;\r\n mutator.move({ path: e.fromPath }, { path: parentPointer(e.toPath) }, e.to.key);\r\n return;\r\n }\r\n}\r\n\r\n/** Forward-apply a sequence of events, in order. */\r\nexport function replayForward(mutator: Mutator, events: readonly MutationEvent[]): void {\r\n for (const e of events) applyEventForward(mutator, e);\r\n}\r\n\r\n/**\r\n * Append every event newer than `sinceSeq` to the journal (the cheap, common save).\r\n * Returns the new high-water seq to pass next time. No-op if nothing is new.\r\n * Throws if events in `[sinceSeq, baseSeq)` were compacted away before being journaled\r\n * (that history is unrecoverable) — compact only right before `persistCheckpoint`.\r\n */\r\nexport async function persistDelta(store: DeltaStoragePort, log: EventLog, sinceSeq: number): Promise<number> {\r\n if (sinceSeq < log.baseSeqValue()) {\r\n throw new InvalidOpError(\r\n `persistDelta: events [${sinceSeq}, ${log.baseSeqValue()}) were compacted before being journaled`,\r\n );\r\n }\r\n const fresh = log.since(sinceSeq);\r\n if (fresh.length > 0) await store.appendEvents(fresh);\r\n return log.length();\r\n}\r\n\r\n/**\r\n * Write a full checkpoint (replacing the prior one and clearing the journal) and return\r\n * its high-water seq. Pair with M12 `log.compactTo(...)` BEFORE calling to keep the\r\n * checkpoint's embedded event window small.\r\n */\r\nexport async function persistCheckpoint(\r\n store: DeltaStoragePort,\r\n tree: ArtifactTree,\r\n log: EventLog,\r\n vectors: VectorIndexPort,\r\n): Promise<number> {\r\n await store.writeCheckpoint(await serializeArtifact(tree, log, vectors));\r\n return log.length();\r\n}\r\n\r\n/**\r\n * Restore a tree + log from a checkpoint plus its journaled deltas. Returns null if no\r\n * checkpoint has been written yet. Forward-replays the journal through a `Mutator` so node\r\n * TYPES are preserved (via each event's `nodeType`) and UNCHANGED nodes keep their ids and\r\n * checkpoint vectors; touched nodes are re-decomposed and marked `embedding.state: \"stale\"`\r\n * for the consumer's `SemanticIndex` reindex, and removed/orphaned nodes' vectors are\r\n * dropped. `vectors` should be a fresh index (the checkpoint's vectors are upserted into it).\r\n * Restore must use the same `decompose` decision as the original run (journal-touched nodes\r\n * are re-decomposed); replay does not re-validate.\r\n */\r\nexport async function restoreFromDelta(\r\n store: DeltaStoragePort,\r\n deps: TreeDeps,\r\n vectors: VectorIndexPort,\r\n): Promise<{ tree: ArtifactTree; log: EventLog } | null> {\r\n const { checkpoint, journal } = await store.loadDelta();\r\n if (!checkpoint) return null;\r\n // The journal must continue exactly where the checkpoint ends — a gap means events\r\n // were lost (torn journal line, or compaction before journaling); replaying past a\r\n // gap would silently produce a wrong tree, so fail loudly instead.\r\n const checkpointVersion = (checkpoint.baseSeq ?? 0) + checkpoint.events.length;\r\n for (let i = 0; i < journal.length; i++) {\r\n if (journal[i].seq !== checkpointVersion + i) {\r\n throw new InvalidOpError(\r\n `restoreFromDelta: journal not contiguous with checkpoint (expected seq ${checkpointVersion + i}, got ${journal[i].seq})`,\r\n );\r\n }\r\n }\r\n // Guard the id generator: `fromStored` preserves the checkpoint's node ids, but\r\n // `deps.idGen` starts fresh, so ids minted while replaying the journal could collide\r\n // with restored ids (a collision silently overwrites a live node in the node map and\r\n // corrupts the parent chain into a cycle — `pathOf` then never terminates). Skip any\r\n // id already in use; deterministic generators (SeqIdGen) simply advance past them.\r\n const usedIds = new Set(checkpoint.nodes.map((n) => n.id));\r\n const guardedDeps: TreeDeps = {\r\n ...deps,\r\n idGen: {\r\n next: () => {\r\n let id = deps.idGen.next();\r\n while (usedIds.has(id)) id = deps.idGen.next();\r\n usedIds.add(id);\r\n return id;\r\n },\r\n },\r\n };\r\n const { tree } = await restoreArtifact(checkpoint, guardedDeps, vectors);\r\n const addressing = new Addressing(tree);\r\n const replayLog = new EventLog(); // throwaway — the faithful log is rebuilt below\r\n // Mutator hooks are synchronous but the vector port is async — queue removals\r\n // during replay and flush them (awaited) afterwards, so a DB-backed index never\r\n // gets a fire-and-forget delete.\r\n const removedIds: NodeId[] = [];\r\n const mutator = new Mutator(tree, addressing, replayLog, {\r\n clock: deps.clock,\r\n onChange: (node) => {\r\n node.meta.embedding = { state: \"stale\" };\r\n },\r\n onRemove: (id) => {\r\n removedIds.push(id);\r\n },\r\n });\r\n replayForward(mutator, journal);\r\n for (const id of removedIds) await vectors.remove(id);\r\n const log = EventLog.fromStored([...checkpoint.events, ...journal], checkpoint.baseSeq ?? 0);\r\n return { tree, log };\r\n}\r\n","import { readFile, writeFile, appendFile } from \"node:fs/promises\";\r\nimport type { MutationEvent } from \"./event-log\";\r\nimport type { StoredArtifact } from \"./storage\";\r\nimport { FileStorage } from \"./file-storage\";\r\n\r\n/** A checkpoint snapshot plus the events journaled after it. */\r\nexport interface DeltaBundle {\r\n checkpoint: StoredArtifact | null;\r\n journal: MutationEvent[];\r\n}\r\n\r\n/**\r\n * Append-oriented persistence: a periodic full **checkpoint** + an appendable **journal**\r\n * of events after it. `appendEvents` is O(new events) — the per-save win over `StoragePort`,\r\n * which rewrites the whole artifact. Restore = checkpoint + forward-replayed journal\r\n * (see `restoreFromDelta`). Opt-in and independent of `StoragePort`.\r\n */\r\nexport interface DeltaStoragePort {\r\n /** Replace the checkpoint and clear the journal (the new checkpoint already embeds\r\n * every event up to its version). */\r\n writeCheckpoint(artifact: StoredArtifact): Promise<void>;\r\n /** Append events to the journal (O(events)). */\r\n appendEvents(events: readonly MutationEvent[]): Promise<void>;\r\n /** The current checkpoint (or null) plus journaled events with `seq >=` the checkpoint\r\n * version — stale pre-checkpoint events are filtered, making writeCheckpoint+clear\r\n * crash-safe. */\r\n loadDelta(): Promise<DeltaBundle>;\r\n}\r\n\r\n/** The next-seq a checkpoint covers (absolute): baseSeq + embedded event count. */\r\nfunction checkpointVersion(c: StoredArtifact | null): number {\r\n return c ? (c.baseSeq ?? 0) + c.events.length : 0;\r\n}\r\n\r\n/** In-memory DeltaStoragePort (deep-clones on the boundary). */\r\nexport class MemoryDeltaStorage implements DeltaStoragePort {\r\n private checkpoint: StoredArtifact | null = null;\r\n private journal: MutationEvent[] = [];\r\n\r\n async writeCheckpoint(artifact: StoredArtifact): Promise<void> {\r\n this.checkpoint = structuredClone(artifact);\r\n this.journal = [];\r\n }\r\n\r\n async appendEvents(events: readonly MutationEvent[]): Promise<void> {\r\n for (const e of events) this.journal.push(structuredClone(e));\r\n }\r\n\r\n async loadDelta(): Promise<DeltaBundle> {\r\n const v = checkpointVersion(this.checkpoint);\r\n return {\r\n checkpoint: this.checkpoint ? structuredClone(this.checkpoint) : null,\r\n journal: this.journal.filter((e) => e.seq >= v).map((e) => structuredClone(e)),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * File-backed DeltaStoragePort: the checkpoint is a JSON file (atomic + validated, via\r\n * `FileStorage`); the journal is an append-only NDJSON file (one event per line).\r\n * `writeCheckpoint` clears the journal; a torn final journal line (crash mid-append) is\r\n * treated as a truncated tail and ignored.\r\n */\r\nexport class FileDeltaStorage implements DeltaStoragePort {\r\n private readonly checkpointStore: FileStorage;\r\n\r\n constructor(\r\n checkpointPath: string,\r\n private readonly journalPath: string,\r\n ) {\r\n this.checkpointStore = new FileStorage(checkpointPath);\r\n }\r\n\r\n async writeCheckpoint(artifact: StoredArtifact): Promise<void> {\r\n await this.checkpointStore.save(artifact);\r\n await writeFile(this.journalPath, \"\", \"utf8\");\r\n }\r\n\r\n async appendEvents(events: readonly MutationEvent[]): Promise<void> {\r\n if (events.length === 0) return;\r\n // The leading \"\\n\" isolates any torn tail left by a crash mid-append: new events\r\n // always start on a fresh line, and blank lines are skipped on load.\r\n const lines = \"\\n\" + events.map((e) => JSON.stringify(e)).join(\"\\n\") + \"\\n\";\r\n await appendFile(this.journalPath, lines, \"utf8\");\r\n }\r\n\r\n async loadDelta(): Promise<DeltaBundle> {\r\n const checkpoint = await this.checkpointStore.load();\r\n const v = checkpointVersion(checkpoint);\r\n let text = \"\";\r\n try {\r\n text = await readFile(this.journalPath, \"utf8\");\r\n } catch (err) {\r\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\r\n }\r\n const journal: MutationEvent[] = [];\r\n for (const line of text.split(\"\\n\")) {\r\n if (!line) continue;\r\n try {\r\n journal.push(JSON.parse(line) as MutationEvent);\r\n } catch {\r\n continue; // torn/garbage line from a crash mid-append — skip it; restore validates contiguity\r\n }\r\n }\r\n return { checkpoint, journal: journal.filter((e) => e.seq >= v) };\r\n }\r\n}\r\n","import type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { Addressing } from \"./addressing\";\r\nimport type { EventLog, MutationEvent } from \"./event-log\";\r\nimport type { Mutator } from \"./mutator\";\r\nimport type { SemanticIndex } from \"./semantic-index\";\r\nimport {\r\n Navigator,\r\n type DescribeOpts,\r\n type DescribeResult,\r\n type GetOpts,\r\n type GetResult,\r\n type FindSelector,\r\n type FindOpts,\r\n type FindResult,\r\n} from \"./navigator\";\r\nimport type { SearchOpts, SearchResult } from \"./semantic-index\";\r\nimport { type Ref, ArborError, ScopeViolationError, InvalidOpError, NodeNotFoundError } from \"./errors\";\r\nimport { isWithin } from \"./jsonpointer\";\r\nimport type { Json, NodeId } from \"./types\";\r\n\r\n/** Every toolset call returns this — errors are structured, never thrown across the agent boundary. */\r\nexport type ToolResult<T> = { ok: true; value: T } | { ok: false; error: { code: string; message: string } };\r\n\r\nexport type PatchOp =\r\n | { op: \"set\"; value: Json; ifVersion?: number }\r\n | { op: \"insert\"; key: string | number; value: Json; ifVersion?: number }\r\n | { op: \"remove\"; ifVersion?: number }\r\n | { op: \"move\"; to: Ref; key: string | number; ifVersion?: number };\r\n\r\nexport interface ToolsetDeps {\r\n tree: ArtifactTree;\r\n addressing: Addressing;\r\n log: EventLog;\r\n mutator: Mutator;\r\n index?: SemanticIndex;\r\n}\r\n\r\nexport interface ToolsetBinding {\r\n owner?: string;\r\n /** JSON Pointer prefix: writes must be at or under it (enforced by the Mutator). */\r\n writeScope?: string;\r\n /** JSON Pointer prefix: reads are confined to it. */\r\n readScope?: string;\r\n}\r\n\r\nexport interface PatchResult {\r\n id: NodeId;\r\n path: string;\r\n /** The affected node's version AFTER the op (remove: the parent's). Feed into the next ifVersion. */\r\n version: number;\r\n}\r\n\r\nexport interface Toolset {\r\n describe(ref?: Ref, opts?: DescribeOpts): Promise<ToolResult<DescribeResult>>;\r\n get(ref: Ref, opts?: GetOpts): Promise<ToolResult<GetResult>>;\r\n find(selector: FindSelector, opts?: FindOpts): Promise<ToolResult<FindResult>>;\r\n search(query: string, opts?: SearchOpts): Promise<ToolResult<SearchResult>>;\r\n patch(ref: Ref, op: PatchOp): Promise<ToolResult<PatchResult>>;\r\n history(ref?: Ref, opts?: { limit?: number }): Promise<ToolResult<MutationEvent[]>>;\r\n}\r\n\r\n/** An event is within scope if any of its recorded paths is within scope. */\r\nfunction eventWithinScope(e: MutationEvent, scope: string): boolean {\r\n if (e.path !== undefined && isWithin(e.path, scope)) return true;\r\n if (e.toPath !== undefined && isWithin(e.toPath, scope)) return true;\r\n if (e.fromPath !== undefined && isWithin(e.fromPath, scope)) return true;\r\n return false;\r\n}\r\n\r\n/** Run a tool body, converting thrown errors into a structured ToolResult. */\r\nasync function run<T>(fn: () => T | Promise<T>): Promise<ToolResult<T>> {\r\n try {\r\n return { ok: true, value: await fn() };\r\n } catch (e) {\r\n if (e instanceof ArborError) return { ok: false, error: { code: e.code, message: e.message } };\r\n const message = e instanceof Error ? e.message : String(e);\r\n return { ok: false, error: { code: \"ERROR\", message } };\r\n }\r\n}\r\n\r\n/** A scoped, agent-facing bundle of tools returning structured results. */\r\nexport function makeToolset(deps: ToolsetDeps, binding: ToolsetBinding = {}): Toolset {\r\n const { tree, addressing } = deps;\r\n const navigator = new Navigator(tree, addressing);\r\n\r\n return {\r\n describe: (ref, opts) =>\r\n run(() => {\r\n const target: Ref = ref ?? (binding.readScope !== undefined ? { path: binding.readScope } : { path: \"\" });\r\n const r = navigator.describe(target, opts);\r\n if (!isWithin(r.node.path, binding.readScope)) {\r\n throw new ScopeViolationError(r.node.path, binding.readScope!);\r\n }\r\n return r;\r\n }),\r\n\r\n get: (ref, opts) =>\r\n run(() => {\r\n const r = navigator.get(ref, opts);\r\n if (!isWithin(r.path, binding.readScope)) {\r\n throw new ScopeViolationError(r.path, binding.readScope!);\r\n }\r\n // Deep-clone the WHOLE result: `content` (and `meta`) come from the live\r\n // tree by reference; handing them across the agent boundary would let a\r\n // caller mutate the artifact without an event, bypassing write-scope.\r\n return structuredClone(r);\r\n }),\r\n\r\n find: (selector, opts) =>\r\n run(() => {\r\n if (binding.readScope !== undefined && opts?.within !== undefined && !isWithin(opts.within, binding.readScope)) {\r\n throw new ScopeViolationError(opts.within, binding.readScope);\r\n }\r\n return navigator.find(selector, { ...opts, within: opts?.within ?? binding.readScope });\r\n }),\r\n\r\n search: (query, opts = {}) =>\r\n run(async () => {\r\n if (!deps.index) throw new InvalidOpError(\"no semantic index configured for this toolset\");\r\n if (binding.readScope !== undefined && opts.under !== undefined && !isWithin(opts.under, binding.readScope)) {\r\n throw new ScopeViolationError(opts.under, binding.readScope);\r\n }\r\n const under = opts.under ?? binding.readScope;\r\n return deps.index.search(query, { ...opts, under });\r\n }),\r\n\r\n patch: (ref, op) =>\r\n run<PatchResult>(() => {\r\n const common = { owner: binding.owner, writeScope: binding.writeScope, ifVersion: op.ifVersion };\r\n const resolve = (r: Ref) => {\r\n const node = \"id\" in r ? addressing.byId(r.id) : addressing.byPath(r.path);\r\n if (!node) throw new NodeNotFoundError(r);\r\n return node;\r\n };\r\n switch (op.op) {\r\n case \"set\": {\r\n deps.mutator.set(ref, op.value, common);\r\n const node = resolve(ref);\r\n return { id: node.id, path: addressing.pathOf(node.id), version: node.meta.version };\r\n }\r\n case \"insert\": {\r\n const id = deps.mutator.insert(ref, op.key, op.value, common);\r\n const node = tree.get(id)!;\r\n return { id, path: addressing.pathOf(id), version: node.meta.version };\r\n }\r\n case \"remove\": {\r\n const node = resolve(ref);\r\n const removed = { id: node.id, path: addressing.pathOf(node.id) };\r\n const parentId = node.parentId;\r\n deps.mutator.remove(ref, common);\r\n const parent = parentId !== null ? tree.get(parentId) : undefined;\r\n return { id: removed.id, path: removed.path, version: parent?.meta.version ?? 0 };\r\n }\r\n case \"move\": {\r\n const node = resolve(ref);\r\n deps.mutator.move(ref, op.to, op.key, common);\r\n return { id: node.id, path: addressing.pathOf(node.id), version: node.meta.version };\r\n }\r\n }\r\n }),\r\n\r\n history: (ref, opts = {}) =>\r\n run(() => {\r\n let events = [...deps.log.entries()];\r\n if (ref !== undefined) {\r\n const node = \"id\" in ref ? addressing.byId(ref.id) : addressing.byPath(ref.path);\r\n if (!node) throw new NodeNotFoundError(ref);\r\n const path = addressing.pathOf(node.id);\r\n if (!isWithin(path, binding.readScope)) throw new ScopeViolationError(path, binding.readScope!);\r\n const id = node.id;\r\n events = events.filter((e) => e.targetId === id);\r\n } else if (binding.readScope !== undefined) {\r\n const scope = binding.readScope;\r\n events = events.filter((e) => eventWithinScope(e, scope));\r\n }\r\n return structuredClone(opts.limit !== undefined ? events.slice(-opts.limit) : events);\r\n }),\r\n };\r\n}\r\n","// AG-UI adapter — expose the artifact tree + event log as AG-UI shared-state\r\n// events (STATE_SNAPSHOT / STATE_DELTA with RFC 6902 JSON Patch ops). Zero-dep:\r\n// these are plain objects shaped like AG-UI events, no AG-UI SDK required.\r\nimport type { Json } from \"./types\";\r\nimport type { ArtifactTree } from \"./artifact-tree\";\r\nimport type { EventLog, MutationEvent } from \"./event-log\";\r\nimport { InvalidOpError } from \"./errors\";\r\n\r\n/** RFC 6902 operation (the subset Arbor emits). */\r\nexport type JsonPatchOp =\r\n | { op: \"replace\" | \"add\"; path: string; value: Json }\r\n | { op: \"remove\"; path: string }\r\n | { op: \"move\"; from: string; path: string };\r\n\r\nexport interface AgUiStateSnapshot {\r\n type: \"STATE_SNAPSHOT\";\r\n snapshot: Json;\r\n}\r\n\r\nexport interface AgUiStateDelta {\r\n type: \"STATE_DELTA\";\r\n delta: JsonPatchOp[];\r\n}\r\n\r\n/** One mutation event as an RFC 6902 op, or null for pre-M7 events without paths. */\r\nexport function toJsonPatch(e: MutationEvent): JsonPatchOp | null {\r\n switch (e.kind) {\r\n case \"set\":\r\n return e.path === undefined ? null : { op: \"replace\", path: e.path, value: e.after ?? null };\r\n case \"insert\":\r\n return e.path === undefined ? null : { op: \"add\", path: e.path, value: e.after ?? null };\r\n case \"remove\":\r\n return e.path === undefined ? null : { op: \"remove\", path: e.path };\r\n case \"move\":\r\n return e.fromPath === undefined || e.toPath === undefined\r\n ? null\r\n : { op: \"move\", from: e.fromPath, path: e.toPath };\r\n }\r\n}\r\n\r\n/** The full current state as an AG-UI STATE_SNAPSHOT event. */\r\nexport function snapshotEvent(tree: ArtifactTree): AgUiStateSnapshot {\r\n return { type: \"STATE_SNAPSHOT\", snapshot: tree.toJson() };\r\n}\r\n\r\n/** Retained events with seq >= sinceSeq as ONE AG-UI STATE_DELTA event (pathless\r\n * pre-M7 events are skipped). Returns the delta plus the next since-cursor.\r\n *\r\n * Throws InvalidOpError when `sinceSeq` is below the log's compaction floor:\r\n * the events in [sinceSeq, baseSeq) are gone, and applying a gapped delta would\r\n * silently diverge the client. On this error the caller must re-send a fresh\r\n * `snapshotEvent` (and resume deltas from the current version) instead. */\r\nexport function deltaSince(log: EventLog, sinceSeq: number): { event: AgUiStateDelta; nextSeq: number } {\r\n if (sinceSeq < log.baseSeqValue()) {\r\n throw new InvalidOpError(\r\n `deltaSince: events [${sinceSeq}, ${log.baseSeqValue()}) were compacted away — send a fresh STATE_SNAPSHOT instead`,\r\n );\r\n }\r\n const delta: JsonPatchOp[] = [];\r\n for (const e of log.since(sinceSeq)) {\r\n const op = toJsonPatch(e);\r\n if (op) delta.push(op);\r\n }\r\n return { event: { type: \"STATE_DELTA\", delta }, nextSeq: log.length() };\r\n}\r\n","import type { Json } from \"./types\";\r\nimport { ArtifactTree, type TreeDeps } from \"./artifact-tree\";\r\nimport { Addressing } from \"./addressing\";\r\nimport { EventLog } from \"./event-log\";\r\nimport { Mutator, type MutatorDeps } from \"./mutator\";\r\nimport { Replay } from \"./replay\";\r\nimport { SemanticIndex } from \"./semantic-index\";\r\nimport { makeToolset, type Toolset, type ToolsetBinding } from \"./toolset\";\r\nimport type { TypeRegistry } from \"./type-registry\";\r\nimport { makeRegistryValidator } from \"./registry-validator\";\r\nimport { typeAwareDecision } from \"./type-aware-decision\";\r\nimport { sizeBasedDecision, type DecomposeDecision } from \"./decompose\";\r\nimport { UuidIdGen, type IdGen } from \"./ids\";\r\nimport { SystemClock, type Clock } from \"./clock\";\r\nimport type { EmbeddingPort } from \"./embedding-port\";\r\nimport { MemoryVectorIndex, type VectorIndexPort } from \"./vector-index-port\";\r\nimport { serializeArtifact, restoreArtifact, type StoragePort } from \"./storage\";\r\nimport { persistCheckpoint, persistDelta, restoreFromDelta } from \"./delta\";\r\nimport type { DeltaStoragePort } from \"./delta-storage\";\r\nimport { InvalidOpError } from \"./errors\";\r\n\r\n/** Everything `createArbor`/`restoreArbor` need. All optional — sensible defaults. */\r\nexport interface ArborOpts {\r\n /** Initial JSON for a fresh artifact (default {}). Ignored by restoreArbor. */\r\n initial?: Json;\r\n /** Node types: per-type validation, decompose override, embedText. */\r\n registry?: TypeRegistry;\r\n /** Base decompose policy (default sizeBasedDecision(200)); made type-aware when a registry is given. */\r\n decompose?: DecomposeDecision;\r\n idGen?: IdGen; // default UuidIdGen — deterministic gens are safe too (restore is guarded)\r\n clock?: Clock; // default SystemClock\r\n /** Enables the semantic index (vectors default to MemoryVectorIndex). */\r\n embedding?: EmbeddingPort;\r\n vectors?: VectorIndexPort;\r\n /** Whole-artifact persistence: enables save(); restoreArbor falls back to it. */\r\n storage?: StoragePort;\r\n /** Incremental persistence: enables saveDelta()/checkpoint(); restoreArbor prefers it. */\r\n delta?: DeltaStoragePort;\r\n}\r\n\r\n/** A fully wired artifact: the live components plus lifecycle helpers. */\r\nexport interface Arbor {\r\n readonly tree: ArtifactTree;\r\n readonly addressing: Addressing;\r\n readonly log: EventLog;\r\n readonly mutator: Mutator;\r\n readonly replay: Replay;\r\n /** Present iff `embedding` was configured. */\r\n readonly index?: SemanticIndex;\r\n readonly vectors: VectorIndexPort;\r\n /** A scoped agent-facing toolset over this artifact. */\r\n toolset(binding?: ToolsetBinding): Toolset;\r\n /** Whole-artifact snapshot to `storage`. */\r\n save(): Promise<void>;\r\n /** Append events since the last saveDelta/checkpoint to the delta journal. */\r\n saveDelta(): Promise<void>;\r\n /** Full snapshot to delta storage (clears the journal). `keepLast` first compacts\r\n * the log to a sliding window of that many events. */\r\n checkpoint(opts?: { keepLast?: number }): Promise<void>;\r\n}\r\n\r\nfunction buildDeps(opts: ArborOpts): TreeDeps {\r\n const base = opts.decompose ?? sizeBasedDecision(200);\r\n return {\r\n idGen: opts.idGen ?? new UuidIdGen(),\r\n clock: opts.clock ?? new SystemClock(),\r\n decision: opts.registry ? typeAwareDecision(base, opts.registry) : base,\r\n };\r\n}\r\n\r\n/** Wrap an idGen so it never mints an id already present in `used` (and records\r\n * what it mints) — restoring preserves stored node ids, so a deterministic\r\n * generator would otherwise collide and corrupt the node map. */\r\nfunction guardIdGen(idGen: IdGen, used: Set<string>): IdGen {\r\n return {\r\n next: () => {\r\n let id = idGen.next();\r\n while (used.has(id)) id = idGen.next();\r\n used.add(id);\r\n return id;\r\n },\r\n };\r\n}\r\n\r\nfunction assemble(\r\n opts: ArborOpts,\r\n tree: ArtifactTree,\r\n log: EventLog,\r\n vectors: VectorIndexPort,\r\n clock: Clock,\r\n hasCheckpoint: boolean,\r\n): Arbor {\r\n const addressing = new Addressing(tree);\r\n const index = opts.embedding\r\n ? new SemanticIndex(tree, addressing, opts.embedding, vectors, opts.registry)\r\n : undefined;\r\n const mdeps: MutatorDeps = { clock };\r\n if (opts.registry) mdeps.validate = makeRegistryValidator(opts.registry);\r\n if (index) Object.assign(mdeps, index.hooks());\r\n const mutator = new Mutator(tree, addressing, log, mdeps);\r\n const replay = new Replay(tree, log);\r\n let highWater = log.length(); // delta journal position (everything before is persisted/checkpointed)\r\n let checkpointed = hasCheckpoint;\r\n\r\n async function doCheckpoint(keepLast?: number): Promise<void> {\r\n if (!opts.delta) throw new InvalidOpError(\"checkpoint(): no delta storage configured\");\r\n if (keepLast !== undefined) log.compactTo(log.length() - keepLast);\r\n highWater = await persistCheckpoint(opts.delta, tree, log, vectors);\r\n checkpointed = true;\r\n }\r\n\r\n return {\r\n tree,\r\n addressing,\r\n log,\r\n mutator,\r\n replay,\r\n index,\r\n vectors,\r\n toolset: (binding) => makeToolset({ tree, addressing, log, mutator, index }, binding),\r\n save: async () => {\r\n if (!opts.storage) throw new InvalidOpError(\"save(): no storage configured\");\r\n await opts.storage.save(await serializeArtifact(tree, log, vectors));\r\n },\r\n saveDelta: async () => {\r\n if (!opts.delta) throw new InvalidOpError(\"saveDelta(): no delta storage configured\");\r\n if (!checkpointed) {\r\n // A journal with no checkpoint is unrestorable — snapshot instead.\r\n await doCheckpoint();\r\n return;\r\n }\r\n highWater = await persistDelta(opts.delta, log, highWater);\r\n },\r\n checkpoint: (o) => doCheckpoint(o?.keepLast),\r\n };\r\n}\r\n\r\n/** Build a fresh, fully wired artifact from `opts.initial` (default {}). */\r\nexport function createArbor(opts: ArborOpts = {}): Arbor {\r\n const deps = buildDeps(opts);\r\n const tree = ArtifactTree.fromJson(opts.initial ?? {}, deps);\r\n const log = new EventLog();\r\n const vectors = opts.vectors ?? new MemoryVectorIndex();\r\n const arbor = assemble(opts, tree, log, vectors, deps.clock, false);\r\n // Index the initial content: fromJson fires no hooks, so without this the\r\n // initial JSON would be unsearchable until first mutated.\r\n if (arbor.index) {\r\n for (const node of tree.allNodes()) arbor.index.onChange(node);\r\n }\r\n return arbor;\r\n}\r\n\r\n/**\r\n * Restore a fully wired artifact from persistence: prefers `delta` (checkpoint +\r\n * forward-replayed journal), falls back to `storage`, returns null when neither has\r\n * data. Owns the restore invariants: a fresh (or caller-provided) vector index is\r\n * upserted from the snapshot, the SemanticIndex is re-created (it re-seeds its stale\r\n * queue from node meta), and the idGen is guarded against collisions with restored\r\n * node ids. Use the SAME `decompose`/`registry` as the original run — journal-touched\r\n * nodes are re-decomposed on delta restore.\r\n */\r\nexport async function restoreArbor(opts: ArborOpts): Promise<Arbor | null> {\r\n const deps = buildDeps(opts);\r\n const vectors = opts.vectors ?? new MemoryVectorIndex();\r\n if (opts.delta) {\r\n const restored = await restoreFromDelta(opts.delta, deps, vectors); // guards its idGen internally\r\n if (restored) return assemble(opts, restored.tree, restored.log, vectors, deps.clock, true);\r\n }\r\n if (opts.storage) {\r\n const stored = await opts.storage.load();\r\n if (stored) {\r\n const guarded: TreeDeps = {\r\n ...deps,\r\n idGen: guardIdGen(deps.idGen, new Set(stored.nodes.map((n) => n.id))),\r\n };\r\n const { tree, log } = await restoreArtifact(stored, guarded, vectors);\r\n return assemble(opts, tree, log, vectors, deps.clock, false);\r\n }\r\n }\r\n return null;\r\n}\r\n"],"mappings":"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","names":["cid","checkpointVersion","readFile","writeFile","writeFile","readFile"]}
@@ -0,0 +1,18 @@
1
+ import { Json } from './types.js';
2
+
3
+ /** Read the value at a JSON Pointer, or undefined if any segment is missing. */
4
+ declare function getAtPath(value: Json, pointer: string): Json | undefined;
5
+ /** In-place variant of setAtPath: mutates `value` (root pointer returns `newVal`). */
6
+ declare function setAtPathMut(value: Json, pointer: string, newVal: Json): Json;
7
+ /** In-place variant of removeAtPath: mutates `value` (root pointer returns null). */
8
+ declare function removeAtPathMut(value: Json, pointer: string): Json;
9
+ /** In-place variant of insertAtPath: mutates `value` (root pointer returns `val`). */
10
+ declare function insertAtPathMut(value: Json, pointer: string, val: Json): Json;
11
+ /** Return a copy of `value` with the value at `pointer` replaced (root → returns `newVal`). */
12
+ declare function setAtPath(value: Json, pointer: string, newVal: Json): Json;
13
+ /** Return a copy of `value` with the element at `pointer` removed (object delete / array splice). */
14
+ declare function removeAtPath(value: Json, pointer: string): Json;
15
+ /** Return a copy of `value` with `val` inserted at `pointer` (object set / array splice-in). */
16
+ declare function insertAtPath(value: Json, pointer: string, val: Json): Json;
17
+
18
+ export { getAtPath, insertAtPath, insertAtPathMut, removeAtPath, removeAtPathMut, setAtPath, setAtPathMut };
@@ -0,0 +1,85 @@
1
+ // src/jsonpointer.ts
2
+ function decodeSegment(s) {
3
+ return s.replace(/~1/g, "/").replace(/~0/g, "~");
4
+ }
5
+ function parsePointer(pointer) {
6
+ if (pointer === "") return [];
7
+ if (!pointer.startsWith("/")) {
8
+ throw new Error(`Invalid JSON Pointer (must be "" or start with "/"): ${pointer}`);
9
+ }
10
+ return pointer.slice(1).split("/").map(decodeSegment);
11
+ }
12
+
13
+ // src/json-edit.ts
14
+ function getAtPath(value, pointer) {
15
+ const segs = parsePointer(pointer);
16
+ let cur = value;
17
+ for (const seg of segs) {
18
+ if (Array.isArray(cur)) {
19
+ const i = Number(seg);
20
+ cur = Number.isInteger(i) && i >= 0 && i < cur.length ? cur[i] : void 0;
21
+ } else if (cur !== null && typeof cur === "object") {
22
+ cur = seg in cur ? cur[seg] : void 0;
23
+ } else {
24
+ return void 0;
25
+ }
26
+ if (cur === void 0) return void 0;
27
+ }
28
+ return cur;
29
+ }
30
+ function navParent(root, pointer) {
31
+ const segs = parsePointer(pointer);
32
+ if (segs.length === 0) return void 0;
33
+ let cur = root;
34
+ for (let i = 0; i < segs.length - 1; i++) {
35
+ const seg = segs[i];
36
+ if (Array.isArray(cur)) cur = cur[Number(seg)];
37
+ else if (cur !== null && typeof cur === "object") cur = cur[seg];
38
+ else return void 0;
39
+ if (cur === void 0 || cur === null) return void 0;
40
+ }
41
+ return { parent: cur, key: segs[segs.length - 1] };
42
+ }
43
+ function setAtPathMut(value, pointer, newVal) {
44
+ if (pointer === "") return newVal;
45
+ const pk = navParent(value, pointer);
46
+ if (!pk || pk.parent === null || typeof pk.parent !== "object") return value;
47
+ if (Array.isArray(pk.parent)) pk.parent[Number(pk.key)] = newVal;
48
+ else pk.parent[pk.key] = newVal;
49
+ return value;
50
+ }
51
+ function removeAtPathMut(value, pointer) {
52
+ if (pointer === "") return null;
53
+ const pk = navParent(value, pointer);
54
+ if (!pk || pk.parent === null || typeof pk.parent !== "object") return value;
55
+ if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 1);
56
+ else delete pk.parent[pk.key];
57
+ return value;
58
+ }
59
+ function insertAtPathMut(value, pointer, val) {
60
+ if (pointer === "") return val;
61
+ const pk = navParent(value, pointer);
62
+ if (!pk || pk.parent === null || typeof pk.parent !== "object") return value;
63
+ if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 0, val);
64
+ else pk.parent[pk.key] = val;
65
+ return value;
66
+ }
67
+ function setAtPath(value, pointer, newVal) {
68
+ return setAtPathMut(structuredClone(value), pointer, newVal);
69
+ }
70
+ function removeAtPath(value, pointer) {
71
+ return removeAtPathMut(structuredClone(value), pointer);
72
+ }
73
+ function insertAtPath(value, pointer, val) {
74
+ return insertAtPathMut(structuredClone(value), pointer, val);
75
+ }
76
+ export {
77
+ getAtPath,
78
+ insertAtPath,
79
+ insertAtPathMut,
80
+ removeAtPath,
81
+ removeAtPathMut,
82
+ setAtPath,
83
+ setAtPathMut
84
+ };
85
+ //# sourceMappingURL=json-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jsonpointer.ts","../src/json-edit.ts"],"sourcesContent":["/** Escape a single reference token per RFC 6901: ~ -> ~0, / -> ~1. */\r\nexport function encodeSegment(s: string): string {\r\n return s.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\r\n}\r\n\r\n/** Unescape a single reference token per RFC 6901: ~1 -> /, then ~0 -> ~. */\r\nexport function decodeSegment(s: string): string {\r\n return s.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\r\n}\r\n\r\n/** Build a JSON Pointer string. Empty segment list => \"\" (root). */\r\nexport function buildPointer(segments: ReadonlyArray<string | number>): string {\r\n if (segments.length === 0) return \"\";\r\n return \"/\" + segments.map((s) => encodeSegment(String(s))).join(\"/\");\r\n}\r\n\r\n/** Append one child key to a parent pointer, escaping the key exactly as `buildPointer` does. */\r\nexport function appendPointer(parent: string, key: string | number): string {\r\n return parent + \"/\" + encodeSegment(String(key));\r\n}\r\n\r\n/** True when `path` is at or under `scope` (JSON Pointer prefix). Undefined scope = everywhere. */\r\nexport function isWithin(path: string, scope: string | undefined): boolean {\r\n return scope === undefined || path === scope || path.startsWith(scope + \"/\");\r\n}\r\n\r\n/** Parse a JSON Pointer into decoded segments. \"\" => [] (root). */\r\nexport function parsePointer(pointer: string): string[] {\r\n if (pointer === \"\") return [];\r\n if (!pointer.startsWith(\"/\")) {\r\n throw new Error(`Invalid JSON Pointer (must be \"\" or start with \"/\"): ${pointer}`);\r\n }\r\n return pointer.slice(1).split(\"/\").map(decodeSegment);\r\n}\r\n","import type { Json } from \"./types\";\r\nimport { parsePointer } from \"./jsonpointer\";\r\n\r\n/** Read the value at a JSON Pointer, or undefined if any segment is missing. */\r\nexport function getAtPath(value: Json, pointer: string): Json | undefined {\r\n const segs = parsePointer(pointer);\r\n let cur: Json | undefined = value;\r\n for (const seg of segs) {\r\n if (Array.isArray(cur)) {\r\n const i = Number(seg);\r\n cur = Number.isInteger(i) && i >= 0 && i < cur.length ? cur[i] : undefined;\r\n } else if (cur !== null && typeof cur === \"object\") {\r\n cur = seg in cur ? (cur as Record<string, Json>)[seg] : undefined;\r\n } else {\r\n return undefined;\r\n }\r\n if (cur === undefined) return undefined;\r\n }\r\n return cur;\r\n}\r\n\r\n/** Navigate (within `root`) to the container holding the pointer's last segment. */\r\nfunction navParent(root: Json, pointer: string): { parent: Json; key: string } | undefined {\r\n const segs = parsePointer(pointer);\r\n if (segs.length === 0) return undefined;\r\n let cur: Json | undefined = root;\r\n for (let i = 0; i < segs.length - 1; i++) {\r\n const seg = segs[i];\r\n if (Array.isArray(cur)) cur = cur[Number(seg)];\r\n else if (cur !== null && typeof cur === \"object\") cur = (cur as Record<string, Json>)[seg];\r\n else return undefined;\r\n if (cur === undefined || cur === null) return undefined;\r\n }\r\n return { parent: cur, key: segs[segs.length - 1] };\r\n}\r\n\r\n/** In-place variant of setAtPath: mutates `value` (root pointer returns `newVal`). */\r\nexport function setAtPathMut(value: Json, pointer: string, newVal: Json): Json {\r\n if (pointer === \"\") return newVal;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent[Number(pk.key)] = newVal;\r\n else (pk.parent as Record<string, Json>)[pk.key] = newVal;\r\n return value;\r\n}\r\n\r\n/** In-place variant of removeAtPath: mutates `value` (root pointer returns null). */\r\nexport function removeAtPathMut(value: Json, pointer: string): Json {\r\n if (pointer === \"\") return null;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 1);\r\n else delete (pk.parent as Record<string, Json>)[pk.key];\r\n return value;\r\n}\r\n\r\n/** In-place variant of insertAtPath: mutates `value` (root pointer returns `val`). */\r\nexport function insertAtPathMut(value: Json, pointer: string, val: Json): Json {\r\n if (pointer === \"\") return val;\r\n const pk = navParent(value, pointer);\r\n if (!pk || pk.parent === null || typeof pk.parent !== \"object\") return value;\r\n if (Array.isArray(pk.parent)) pk.parent.splice(Number(pk.key), 0, val);\r\n else (pk.parent as Record<string, Json>)[pk.key] = val;\r\n return value;\r\n}\r\n\r\n/** Return a copy of `value` with the value at `pointer` replaced (root → returns `newVal`). */\r\nexport function setAtPath(value: Json, pointer: string, newVal: Json): Json {\r\n return setAtPathMut(structuredClone(value), pointer, newVal);\r\n}\r\n\r\n/** Return a copy of `value` with the element at `pointer` removed (object delete / array splice). */\r\nexport function removeAtPath(value: Json, pointer: string): Json {\r\n return removeAtPathMut(structuredClone(value), pointer);\r\n}\r\n\r\n/** Return a copy of `value` with `val` inserted at `pointer` (object set / array splice-in). */\r\nexport function insertAtPath(value: Json, pointer: string, val: Json): Json {\r\n return insertAtPathMut(structuredClone(value), pointer, val);\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,14 @@
1
+ /** Escape a single reference token per RFC 6901: ~ -> ~0, / -> ~1. */
2
+ declare function encodeSegment(s: string): string;
3
+ /** Unescape a single reference token per RFC 6901: ~1 -> /, then ~0 -> ~. */
4
+ declare function decodeSegment(s: string): string;
5
+ /** Build a JSON Pointer string. Empty segment list => "" (root). */
6
+ declare function buildPointer(segments: ReadonlyArray<string | number>): string;
7
+ /** Append one child key to a parent pointer, escaping the key exactly as `buildPointer` does. */
8
+ declare function appendPointer(parent: string, key: string | number): string;
9
+ /** True when `path` is at or under `scope` (JSON Pointer prefix). Undefined scope = everywhere. */
10
+ declare function isWithin(path: string, scope: string | undefined): boolean;
11
+ /** Parse a JSON Pointer into decoded segments. "" => [] (root). */
12
+ declare function parsePointer(pointer: string): string[];
13
+
14
+ export { appendPointer, buildPointer, decodeSegment, encodeSegment, isWithin, parsePointer };
@@ -0,0 +1,33 @@
1
+ // src/jsonpointer.ts
2
+ function encodeSegment(s) {
3
+ return s.replace(/~/g, "~0").replace(/\//g, "~1");
4
+ }
5
+ function decodeSegment(s) {
6
+ return s.replace(/~1/g, "/").replace(/~0/g, "~");
7
+ }
8
+ function buildPointer(segments) {
9
+ if (segments.length === 0) return "";
10
+ return "/" + segments.map((s) => encodeSegment(String(s))).join("/");
11
+ }
12
+ function appendPointer(parent, key) {
13
+ return parent + "/" + encodeSegment(String(key));
14
+ }
15
+ function isWithin(path, scope) {
16
+ return scope === void 0 || path === scope || path.startsWith(scope + "/");
17
+ }
18
+ function parsePointer(pointer) {
19
+ if (pointer === "") return [];
20
+ if (!pointer.startsWith("/")) {
21
+ throw new Error(`Invalid JSON Pointer (must be "" or start with "/"): ${pointer}`);
22
+ }
23
+ return pointer.slice(1).split("/").map(decodeSegment);
24
+ }
25
+ export {
26
+ appendPointer,
27
+ buildPointer,
28
+ decodeSegment,
29
+ encodeSegment,
30
+ isWithin,
31
+ parsePointer
32
+ };
33
+ //# sourceMappingURL=jsonpointer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/jsonpointer.ts"],"sourcesContent":["/** Escape a single reference token per RFC 6901: ~ -> ~0, / -> ~1. */\r\nexport function encodeSegment(s: string): string {\r\n return s.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\r\n}\r\n\r\n/** Unescape a single reference token per RFC 6901: ~1 -> /, then ~0 -> ~. */\r\nexport function decodeSegment(s: string): string {\r\n return s.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\r\n}\r\n\r\n/** Build a JSON Pointer string. Empty segment list => \"\" (root). */\r\nexport function buildPointer(segments: ReadonlyArray<string | number>): string {\r\n if (segments.length === 0) return \"\";\r\n return \"/\" + segments.map((s) => encodeSegment(String(s))).join(\"/\");\r\n}\r\n\r\n/** Append one child key to a parent pointer, escaping the key exactly as `buildPointer` does. */\r\nexport function appendPointer(parent: string, key: string | number): string {\r\n return parent + \"/\" + encodeSegment(String(key));\r\n}\r\n\r\n/** True when `path` is at or under `scope` (JSON Pointer prefix). Undefined scope = everywhere. */\r\nexport function isWithin(path: string, scope: string | undefined): boolean {\r\n return scope === undefined || path === scope || path.startsWith(scope + \"/\");\r\n}\r\n\r\n/** Parse a JSON Pointer into decoded segments. \"\" => [] (root). */\r\nexport function parsePointer(pointer: string): string[] {\r\n if (pointer === \"\") return [];\r\n if (!pointer.startsWith(\"/\")) {\r\n throw new Error(`Invalid JSON Pointer (must be \"\" or start with \"/\"): ${pointer}`);\r\n }\r\n return pointer.slice(1).split(\"/\").map(decodeSegment);\r\n}\r\n"],"mappings":";AACO,SAAS,cAAc,GAAmB;AAC/C,SAAO,EAAE,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AAClD;AAGO,SAAS,cAAc,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG;AACjD;AAGO,SAAS,aAAa,UAAkD;AAC7E,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SAAO,MAAM,SAAS,IAAI,CAAC,MAAM,cAAc,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG;AACrE;AAGO,SAAS,cAAc,QAAgB,KAA8B;AAC1E,SAAO,SAAS,MAAM,cAAc,OAAO,GAAG,CAAC;AACjD;AAGO,SAAS,SAAS,MAAc,OAAoC;AACzE,SAAO,UAAU,UAAa,SAAS,SAAS,KAAK,WAAW,QAAQ,GAAG;AAC7E;AAGO,SAAS,aAAa,SAA2B;AACtD,MAAI,YAAY,GAAI,QAAO,CAAC;AAC5B,MAAI,CAAC,QAAQ,WAAW,GAAG,GAAG;AAC5B,UAAM,IAAI,MAAM,wDAAwD,OAAO,EAAE;AAAA,EACnF;AACA,SAAO,QAAQ,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,aAAa;AACtD;","names":[]}
@@ -0,0 +1,59 @@
1
+ import { ArbNode, Json, NodeId } from './types.js';
2
+ import { Clock } from './clock.js';
3
+ import { ArtifactTree } from './artifact-tree.js';
4
+ import { Addressing } from './addressing.js';
5
+ import { EventLog, OpKind } from './event-log.js';
6
+ import { Ref } from './errors.js';
7
+ import './ids.js';
8
+ import './decompose.js';
9
+
10
+ /** Optional validation hook. Throws to reject a mutation. M3 plugs Zod in here. */
11
+ type Validator = (input: {
12
+ node: ArbNode | null;
13
+ proposed: Json;
14
+ type?: string;
15
+ op: OpKind;
16
+ }) => void;
17
+ interface MutatorDeps {
18
+ clock: Clock;
19
+ validate?: Validator;
20
+ /** Called after a node's content changes (set/insert) — e.g. to mark a semantic index stale. */
21
+ onChange?: (node: ArbNode) => void;
22
+ /** Called after a node is removed — e.g. to drop it from a semantic index. */
23
+ onRemove?: (nodeId: NodeId) => void;
24
+ /** Called at transaction start; the returned snapshot is passed to `onTxRestore` on rollback. */
25
+ onTxSnapshot?: () => unknown;
26
+ /** Called on transaction rollback with the snapshot from `onTxSnapshot`. */
27
+ onTxRestore?: (snapshot: unknown) => void;
28
+ }
29
+ interface MutateOpts {
30
+ owner?: string;
31
+ /** JSON Pointer prefix; the target must be at or under it. */
32
+ writeScope?: string;
33
+ /** Optimistic concurrency: reject unless the target's current version equals this. */
34
+ ifVersion?: number;
35
+ /** Register/override the node's type (drives validation and the decompose override).
36
+ * `null` explicitly CLEARS the type (validation is skipped) — used by type-aware revert. */
37
+ type?: string | null;
38
+ /** Replace the node's tags (identity labels for exact `find` by tag). */
39
+ tags?: string[];
40
+ }
41
+ declare class Mutator {
42
+ private readonly tree;
43
+ private readonly addressing;
44
+ private readonly log;
45
+ private readonly deps;
46
+ constructor(tree: ArtifactTree, addressing: Addressing, log: EventLog, deps: MutatorDeps);
47
+ private resolve;
48
+ private checkScope;
49
+ private checkVersion;
50
+ private bump;
51
+ set(ref: Ref, value: Json, opts?: MutateOpts): void;
52
+ insert(parentRef: Ref, keyOrIndex: string | number, value: Json, opts?: MutateOpts): NodeId;
53
+ remove(ref: Ref, opts?: MutateOpts): void;
54
+ move(ref: Ref, toParentRef: Ref, keyOrIndex: string | number, opts?: MutateOpts): void;
55
+ /** Run `fn` atomically: if it throws, the tree, log, and any hooked index state are restored. */
56
+ transaction(fn: () => void): void;
57
+ }
58
+
59
+ export { type MutateOpts, Mutator, type MutatorDeps, type Validator };