   (query-for-pattern
     [_ pattern] (@queries pattern)))
 
+(defrecord BasicTripleQuery [id acc result pattern]
+  #?@(:clj
+       [clojure.lang.IDeref (deref [_] (when result @result))]
+       :cljs
+       [IDeref (-deref [_] (when result @result))])
+  ITripleQuery
+  (raw-pattern
+    [_] pattern)
+  (result-vertex
+    [_] result)
+  f/IGraphComponent
+  (add-to-graph!
+    [_ g]
+    (let [{:keys [subj pred obj]} (triple-indices g)
+          acc  (f/add-vertex!
+                g {} {::f/collect-fn collect-select})
+          res  (f/add-vertex!
+                g nil
+                {::f/collect-fn       (aggregate-select g)
+                 ::f/score-collect-fn (score-collect-min-signal-vals 3)})
+          [s p o] pattern
+          this (assoc _ :acc acc :result res)]
+      (f/add-edge! g subj acc signal-index-select [0 s])
+      (f/add-edge! g pred acc signal-index-select [1 p])
+      (f/add-edge! g obj  acc signal-index-select [2 o])
+      (f/add-edge! g acc  res f/signal-forward nil)
+      (register-query! g this)))
+  (remove-from-graph!
+    [_ g]
+    (f/remove-vertex! g result)
+    (f/remove-vertex! g acc)
+    (assoc _ :acc nil :result nil)))
+
+(defrecord ParametricTripleQuery
+    [id sub-query result pattern]
+  #?@(:clj
+       [clojure.lang.IDeref (deref [_] (when result @result))]
+       :cljs
+       [IDeref (-deref [_] (when result @result))])
+  ITripleQuery
+  (raw-pattern
+    [_] (mapv #(if-not (qvar? %) %) pattern))
+  (result-vertex
+    [_] result)
+  f/IGraphComponent
+  (add-to-graph!
+    [_ g]
+    (let [[s p o]    pattern
+          vs?        (qvar? s), vp? (qvar? p), vo? (qvar? o)
+          vmap       (bind-translator vs? vp? vo? s p o)
+          verify     (triple-verifier s p o vs? vp? vo?)
+          res-tx     (comp (map #(if (verify %) (vmap %))) (filter identity))
+          collect-fn (f/collect-pure
+                      (fn [_ incoming]
+                        (if-let [res (seq (peek incoming))]
+                          (into #{} res-tx res)
+                          #{})))
+          q-pattern  (raw-pattern _)
+          sub-q      (or (query-for-pattern g q-pattern) (add-query! g id q-pattern))
+          res        (f/add-vertex! g nil {::f/collect-fn collect-fn})]
+      (f/add-edge! g (result-vertex sub-q) res f/signal-forward nil)
+      (assoc _ :sub-query sub-q :result res)))
+  (remove-from-graph!
+    [_ g]
+    (f/remove-vertex! g result)
+    (when (sole-user? (result-vertex sub-query) result)
+      (f/remove-from-graph! sub-query g))
+    (assoc _ :sub-query nil :result nil)))
+
+(defrecord TripleQueryJoin [id lhs rhs result]
+  #?@(:clj
+       [clojure.lang.IDeref (deref [_] (when result @result))]
+       :cljs
+       [IDeref (-deref [_] (when result @result))])
+  ITripleQuery
+  (raw-pattern
+    [_] nil)
+  (result-vertex
+    [_] result)
+  f/IGraphComponent
+  (add-to-graph!
+    [_ g]
+    (let [lhs-id (:id (result-vertex lhs))
+          rhs-id (:id (result-vertex rhs))
+          join   (f/add-vertex!
+                  g nil
+                  {::f/collect-fn
+                   (fn [vertex]
+                     (let [sig-map (::f/signal-map @(:state vertex))
+                           a (sig-map lhs-id)
+                           b (sig-map rhs-id)]
+                       (debug (:id vertex) :join-sets a b)
+                       (reset! (:value vertex) (set/join a b))))
+                   ::f/score-collect-fn
+                   score-collect-join})]
+      (f/add-edge! g (result-vertex lhs) join f/signal-forward nil)
+      (f/add-edge! g (result-vertex rhs) join f/signal-forward nil)
+      (assoc _ :result join)))
+  (remove-from-graph!
+    [_ g]
+    (f/remove-vertex! g result)
+    (when (sole-user? (result-vertex lhs) result)
+      (f/remove-from-graph! lhs g))
+    (when (sole-user? (result-vertex rhs) result)
+      (f/remove-from-graph! rhs g))))
+
+(defrecord TripleInferenceRule
+    [id query patterns production inf]
+  f/IGraphComponent
+  (add-to-graph!
+    [_ g]
+    (let [q   (apply add-query-join! g patterns)
+          inf (f/add-vertex!
+               g #{} {::f/collect-fn (collect-inference g production)})]
+      (f/add-edge! g (result-vertex q) inf f/signal-forward nil)
+      (assoc _ :query q :inf inf))))
+
 (defn triple-graph
   [g]
   (map->TripleGraph

       (debug :new-index val)
       val))))

(defn signal-index-select
  [vertex [idx sel]]
  [idx (if sel (@vertex sel [nil]) (->> @vertex vals (mapcat identity) (set)))])

(def collect-select
  (f/collect-pure
   (fn [val incoming]
     (let [val (reduce (fn [acc [idx res]] (assoc acc idx res)) val incoming)]
       ;;(debug :coll-select val incoming)
       val))))

(defn score-collect-min-signal-vals
  [num]
  (fn [vertex]
    (if (> num (count (vals (peek (::f/uncollected @(:state vertex)))))) 0 1)))

(defn score-collect-min-signals
  [num]
  (fn [vertex]
    (if (> num (count (::f/uncollected @(:state vertex)))) 0 1)))

(defn aggregate-select
  [g]
  (f/collect-pure
   (fn [_ incoming]

    :queries (atom {})
    :rules   (atom {})
    :g       g}))

(defn add-query!
  [g id pattern]
  (f/add-to-graph!
   (map->BasicTripleQuery {:id id :pattern pattern}) g))

(defn add-param-query!
  [g id pattern]
  (f/add-to-graph!
   (map->ParametricTripleQuery {:id id :pattern pattern}) g))

(defn add-join!
  ([g lhs rhs]
   (add-join! g (random-id) lhs rhs))
  ([g id lhs rhs]
   (f/add-to-graph!
    (map->TripleQueryJoin {:id id :lhs lhs :rhs rhs}) g)))

(defn add-query-join!
  [g a b & more]
  (reduce
   (fn [acc p]
     (add-join! g (random-id) acc (add-param-query! g (random-id) p)))
   (add-join!
    g (random-id)
    (add-param-query! g (random-id) a)
    (add-param-query! g (random-id) b))
   more))

(defn add-query-filter!
  [g q flt]
  (let [tx (comp (mapcat identity) (filter flt))
        fv (f/add-vertex!
            g nil
            {::f/collect-fn
             (f/collect-pure
              (fn [_ incoming] (sequence tx incoming)))})]
    (f/add-edge! g (result-vertex q) fv f/signal-forward nil)
    fv))

(defn add-rule!
  [g id query production]
  (f/add-to-graph!
   (map->TripleInferenceRule
    {:id id :patterns query :production production})
   g))

(defn add-counter!
  [g src]
