It's quite finicky to reproduce. In the code below, if you replace (> x 0) with (>= x 0) it works as expected.
When the breakpoint is hit, you can see in the Scope panel that a is marked as dirty but b is not and still has the previous value.
I would expect that (not= x b) is never triggered because x + 10 - 10 should be equal to x.
(def x (r/atom 0))
(def a (r/reaction (+ @x 10)))
(def b (r/reaction (- @a 10)))
(defn f [x' b']
(let [x @x']
(if (> x 0)
(let [b @b']
(when (not= x b)
(js-debugger))
(+ x b))
x)))
(def z (r/reaction (f x b)))
(defn app []
[:span (str @z " ")
[:button {:on-click #(swap! x inc)} "INC"]])