 
 ;;;; Node tree
 
-(defn normalize-kind [node]
+(defn process-down [node f ctx]
+  (let [{:keys [node ctx]} (f node ctx)]
+    (-> node
+        (update :children
+                (fn [children]
+                  (mapv #(process-down % f ctx) children))))))
+
+(defn normalize-kind [node _]
   (letfn [(normalize [kind]
             (let [aliases {"project" ["project"]
                            "requirement" ["requirement" "req" "r"]

                    (build-node name-segment data)))]
    (let [tree (reduce build-step root data)]
      (-> tree
          (normalize-kind)
          (inject-name [])
          (inject-parent nil)))))

(defn flatten-tree [node]
  (letfn [(collect-step [m node]

                               ffirst)
                          kind)]
              res))]
    {:node (if (contains? node "kind")
             (update node "kind" normalize)
             node)}))

(defn inject-name [node parent-segments]
  (let [segments (if (nil? (:name node))
                   parent-segments
                   (conj parent-segments (:name node)))]
    {:node (assoc node :name (str/join "/" segments))
     :ctx segments}))

(defn inject-parent [node ctx]
  (let [parent ctx]
    {:node (assoc node :parent (or (:parent node)
                                   (:name parent)))
     :ctx (if (contains? node "kind") node parent)}))

(defn build-tree [root data]
  (letfn [(build-node [name-segment data]
