           (dotimes [i (alength output-kinds)]
             (.get-or-create-index kn (aget output-kinds i) (aget output-names i) (into-array (filter #(not (nil? %)) (aget output-fields i)))))
 
-          (Flow. solver output-kinds output-names output-fields))))))
+          (aset rule-id->flow rule-id
+                (Flow. solver output-kinds output-names output-fields)))))
+
+    rule-id->flow))
 
 ;; TESTS
 

                                                                                             #js ["make-str" "constant" "js" "\"edge \" + xx + \" \" + yy"]
                                                                                             #js ["know-str" "variable" "name" "zz"]])

(.run (nth (compile kn) 2) kn)

(.get-or-create-index kn "know" "str-edge" #js ["name"])


;; NOTE can't handle missing keys yet - requires a schema
(defn compile [kn]
  (let [rule-id->flow #js {}
        clauses (.keys (.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|know|remember|forget" "clause-id" "name"]))
        fields (.keys (.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"]))
        rule-id->clauses (atom (into {} (for [[k vs] (group-by #(nth % 0) clauses)] [k (set (map vec vs))])))
        clause-id->fields (atom (into {} (for [[k vs] (group-by #(nth % 0) fields)] [k (set (map vec vs))])))]
