   (vertex-for-id [_ id])
   (vertices [_])
   (add-edge! [_ src dest f opts]))
+
+(defprotocol IWatchable
+  (add-watch! [_ type id f])
+  (remove-watch! [_ type id]))
 
 (defprotocol IGraphExecutor
   (execute! [_])

  (let [ctx       (merge default-async-context-opts opts)
        bus       (vec (repeatedly (:bus-size ctx) chan))
        ctx       (assoc ctx :bus bus :result (or (:result ctx) (chan)))
        processor (:processor ctx)
        c-thresh  (:collect-thresh ctx)
        s-thresh  (:signal-thresh ctx)
        max-ops   (:max-ops ctx)
        max-t     (:timeout ctx)
        result    (:result ctx)]
    (reify
      #?@(:clj
           [clojure.lang.IDeref

               #(-> %
                    (update ::uncollected conj sig)
                    (assoc-in [::signal-map src] sig)))
        (debug id " ignoring unchanged signal: " (pr-str sig))))
    _))

#?(:clj
