                                          ha
                                          Infinity
                                          (required-transitions ha)))
+        #_(println "New required transitions" (transition-intervals has
+                                                                    ha
+                                                                    Infinity
+                                                                    (required-transitions ha)))
         ; calculate intervals when optional guards will be satisfied up to and including the upcoming required guard, if any
         opts (transition-intervals has
                                    ha

      ; we prioritize the first-defined optional transition. this policy could change later, e.g. to be an error.
      (first opts))))

(defn ha-dependencies [_ha] #{})

(defn follow-transitions [has transitions]
  (let [t (first (:interval (first transitions)))
        _ (assert (every? #(= t (first (:interval %))) transitions) "All transitions must have same start time")
        ; simultaneously transition all the HAs that can transition.
        transitioned-has (map (fn [{id :id {target :target update :update} :transition}]
                                (enter-state has (update (get has id)) target t))
                              transitions)
        transitioned-ids (into #{} (map :id transitioned-has))

        reenter-has (map #(let [ha (get has %)]
                           (enter-state has ha (:state ha) t))
                         deps)]
    #_(println "next transitions" #_reenter-has (transition-intervals has
                                                                  (second reenter-has)
                                                                  Infinity
                                                                  (required-transitions (second reenter-has))))
    (merge has (zipmap (map :id reenter-has) reenter-has))))

(defn update-scene [scene now inputs]
