 (.get-or-create-index kn "know" "foo" #js ["x" "y"])
 
 (.get-or-create-index kn "know" "bar" #js ["z"])
+
+(.get-or-create-index kn "know" "frip" #js ["x" "w"])
 )


;; FLOWS

(deftype Flow [solver output-kinds output-names output-fields]
  Object
  (run [this kn rule->dirty? kind->name->rules]
       (.reset solver)
       (let [facts&vals (.elems solver)]
         (dotimes [i (alength output-kinds)]
           (let [kind (aget output-kinds i)
                 name (aget output-names i)
                 fields (aget output-fields i)]
             (when (true? (.update-facts kn kind name fields facts&vals))
               (let [dirtied-rules (aget kind->name->rules kind name)]
                 (dotimes [j (alength dirtied-rules)]
                   (aset rule->dirty? (aget dirtied-rules j) true)))))))))

(deftype Flows [rules rule->flow rule->dirty? kind->name->rules name->transient?]
  Object

              ;; make solver
              solver (btree/solver num-vars (into-array constraints))

              ;; make sinks
              sinks (into-array
                     (for [[_ clause-type clause-id name] clauses
                           :when (not= clause-type "when")]
                       (sink-of rule-id clause-type clause-id name var->ix)))]

          (swap! rule->flow assoc rule-id (SolverFlow. solver sinks)))))

    ;; set up state for outputs
    (doseq [[rule flow] @rule->flow
            sink (.-sinks flow)]
      (let [kind (.-kind sink)
            name (.-name sink)
            fields (.-fields sink)
            filtered-fields (into-array (filter #(not (nil? %)) fields))
            transient? (identical? kind "know")]
        ;; TODO get transient? from schema instead
        (assert (not= (not transient?) (get @name->transient? name)) name)
        (swap! name->transient? assoc name transient?)
        (swap! kind->name->rules update-in [kind name] #(or % #{}))
        (.ensure-index kn "know" name filtered-fields)
        (when (false? transient?)
          (.ensure-index kn "forget" name filtered-fields)
          (.ensure-index kn "remember" name filtered-fields))))

    ;; TODO stratify
    (Flows. (clj->js (map first @rule->flow)) (clj->js @rule->flow) #js {} (clj->js @kind->name->rules) (clj->js @name->transient?))))
