                   node
                   (->> (::children node)
                        (map store!)
-                       (relink-children)
+                       (numbered-child-links)
                        (assoc node ::children)
                        (mdag/store-node! store nil)
                        (::node/data))))]

    data-type
      (mapcat
        (fn read-child
          [[child-link child-keys]]
          (let [child (graph/get-link! store node child-link)]
            (read-batch store child fields child-keys)))
        (assign-keys node record-keys))

    part/data-type
      (part/read-batch store node fields record-keys)


;; ## Update Functions

(defn- numbered-child-links
  "Write a vector of childen into numbered links."
  [children]
  (into []
        (map-indexed #(mdag/link (format "%03d" %1) %2))
        children))


(defn- index-children
  "Aggregates index node values from a sequence of child data."
  [children]
  (let [ckeys (into [] (map ::record/first-key) (rest children))
        links (numbered-child-links children)
        record-count (reduce + 0 (map ::record/count children))]
    {::keys ckeys
     ::children links
     ::record/count record-count
     ::record/first-key (::record/first-key (first children))
     ::record/last-key (::record/last-key (last children))}))


(defn- update-index-children!
  "Apply changes to a sequence of intermediate index nodes and redistribute the
  results to create a new sequence of valid indexes. Each input tuple should
  have the form `[index changes]`, and `carry` may be a forward-carried index
  subtree or partition that is **not** a direct descendant of the parent node.

  Returns a sequence of updated and valid (but unpersisted) index nodes, or a
  direct map of node data to carry forward."
  [store params carry inputs]
  ,,,)


(defn- update-index-node
  [store params carry [index changes]]
  (if (seq changes)
    (let [child-changes (map (juxt #(graph/get-link! store index (first %)) second)
                             (assign-records index changes))
          children (if (= 1 (::height index))
                     ; Update children as partitions.
                     (part/update-partitions! store params carry child-changes)
                     ; Update child index nodes.
                     (if (and (= data-type (:data/type carry))
                              (= (dec (::height index)) (::height carry)))
                       ; Adopt the carried index subtree by prepending it to the results.
                       (update-index-children! store params nil (cons [carry nil] child-changes))
                       ; No carry, or carry is not a direct child.
                       (update-index-children! store params carry child-changes)))]
      (if (sequential? children)
        (if (= 1 (count children))
          ; Orphaned child, return directly for carrying.
          (first children)
          ; Construct index node from partitions.
          ; FIXME: needs to break into multiple nodes on overflow
          [(merge index (index-children children))])
        ; Carried node, return for further carrying.
        children))
    ; No changes, return unchanged node.
    [index]))


(defn update-tree
