     (recur cf (if (cf f arg1) f arg1) r)
     arg1))
 
-(defn max-status [& stats] (apply max-compare better-status? (cons +worst-status+ stats) ))
-(defn min-status [& stats] (apply max-compare (complement better-status?) (cons +best-status+ stats)))
-
-(def zero-status (Status. 0 :solved))
-(defn add-statuses [s1 s2]
-  (Status. (+ (:max-reward s1)
+(defn max-summary [& stats] (apply max-compare better-summary? (cons +worst-summary+ stats) ))
+(defn min-summary [& stats] (apply max-compare (complement better-summary?) (cons +best-summary+ stats)))
+
+(def zero-summary (SimpleSummary. 0 :solved []))
+(defn add-summaries [s1 s2]
+  (SimpleSummary. (+ (:max-reward s1)
               (:max-reward s2))
-           (min-key status-val (:status s1) (:status s2))))
-
-(defn viable-status? [status]
-  (> (:max-reward status) is/neg-inf))
-
-(defn refinable-status? [stat min-reward]
+           (min-key status-val (:status s1) (:status s2))
+           (when (and (= (:status s1) :solved) (= (:status s2) :solved))
+             (concat (:opt-sol s1) (:opt-sol s2)))))
+
+
+(defn viable-summary? [summary]
+  (> (:max-reward summary) is/neg-inf))
+
+(defn refinable-summary? [stat min-reward]
   (and (= (:status stat) :live)
        (>= (:max-reward stat) min-reward)))
 
+(defn summary-solution [stat]
+  (when (= (:status stat) :solved)
+    (:opt-sol stat)))
+
+
 (defn next-min-reward [stat min-reward]
   (min min-reward (:max-reward stat)))
 
 
-(defn assert-unrefinable [status min-reward]
-  (assert (not (refinable-status? status min-reward)))
-  status)
-
-
-(defmacro unrefinable-status-or [stat min-reward form]
-  `(let [stat# ~stat]
-     (if (refinable-status? stat# ~min-reward)
-       ~form
-       stat#)))
-
-(defn max-thing-status-and-next [status-fn & things]
+
+(defn max-thing-summary-and-next [summary-fn & things]
   (if (empty? things)
-    [nil +worst-status+ +worst-status+]
+    [nil +worst-summary+ +worst-summary+]
     (loop [best-thing (first things)
-           best-status (status-fn (first things))
-           next-best-status +worst-status+
+           best-summary (summary-fn (first things))
+           next-best-summary +worst-summary+
            more-things (rest things)]
       (if-let [[next-thing & even-more-things] (seq more-things)]
-        (let [next-status (status-fn next-thing)]
-          (if (better-status? next-status best-status)
-            (recur next-thing next-status best-status even-more-things)
-            (recur best-thing best-status (max-status next-status next-best-status) even-more-things)))))))
-
-(defn one-operation-on-best [status-fn1 s1 op1 status-fn2 s2 op2 min-reward default]
-  (let [[best1 status1 ns1] (max-thing-status-and-next status-fn1 s1)
-        [best2 status2 ns2] (max-thing-status-and-next status-fn2 s2)
-        best-status     (max-status status1 status2)]
-    (if (not (refinable-status? best-status min-reward))
+        (let [next-summary (summary-fn next-thing)]
+          (if (better-summary? next-summary best-summary)
+            (recur next-thing next-summary best-summary even-more-things)
+            (recur best-thing best-summary (max-summary next-summary next-best-summary) even-more-things)))))))
+
+(defn one-operation-on-best [summary-fn1 s1 op1 summary-fn2 s2 op2 min-reward default]
+  (let [[best1 summary1 ns1] (max-thing-summary-and-next summary-fn1 s1)
+        [best2 summary2 ns2] (max-thing-summary-and-next summary-fn2 s2)
+        best-summary     (max-summary summary1 summary2)]
+    (if (not (refinable-summary? best-summary min-reward))
       default
-      (if (better-status? status2 status1)
-        (op2 best2 (next-min-reward (max-status ns2 status1) min-reward))
-        (op1 best1 (next-min-reward (max-status ns1 status2) min-reward))))))
-
-(defn operate-on-best [status-fn1 seq-fn1 op1 status-fn2 seq-fn2 op2 init next-fn min-reward]
+      (if (better-summary? summary2 summary1)
+        (op2 best2 (next-min-reward (max-summary ns2 summary1) min-reward))
+        (op1 best1 (next-min-reward (max-summary ns1 summary2) min-reward))))))
+
+(defn operate-on-best [summary-fn1 seq-fn1 op1 summary-fn2 seq-fn2 op2 init next-fn min-reward]
   (last
    (util/iterate-while
-    #(when-let [x (one-operation-on-best status-fn1 (seq-fn1 %) op1 status-fn2 (seq-fn2 %) op2 min-reward nil)]
+    #(when-let [x (one-operation-on-best summary-fn1 (seq-fn1 %) op1 summary-fn2 (seq-fn2 %) op2 min-reward nil)]
        (next-fn x))
     init)))
 

  "Returns a plan by propagating changes starting at the last node in prefix through remaining-nodes.
   Returns nil if the plan becomes infeasible, otherwise a plan."
  [input-constraint input-set prefix-nodes remaining-nodes set-changed?]
  (when-let [[[_ out-set out-status] out-nodes]
             (map-state
              update-pn-input
              (cons set-changed? (plan-node-output-set-and-status (last prefix-nodes))))]
    (Plan. input-constraint input-set (concat prefix-nodes out-nodes) out-set out-status)))

;; Need some meta-level basis to choose what to do...
;; For now, just pick a node at random, try to refine it, then try to split on its output.
(defn expand-plan [plan min-reward]
  (let [{:keys [input-constraint input-set plan-nodes output-set status]} plan
        [pre-nodes [ref-node & post-nodes]] (split-at (rand-int (count plan-nodes)) plan-nodes)
        [pre-set pre-status]  (if (seq pre-nodes) (plan-node-output-set-and-status (last pre-nodes)) [input-set zero-status])
        sub-min-reward (- min-reward
                          (- (:max-reward status)
                             (- (:max-reward (:out-status ref-node)) (:max-reward pre-status))))]
    (filter identity
            (for [next-pn (split-pn-output (refine-pn ref-node pre-status sub-min-reward) pre-set pre-status sub-min-reward)]
              (propagate-plan-changes input-constraint input-set (concat pre-nodes [next-pn]) post-nodes)))))



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Output Set Nodes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Dependencies on pointers
(declare full-osp-summary refine-osp! add-plans-osp! make-child-osp )

(defrecord OutputSetNode    [plans child-pointers])

(defn make-initial-output-set-node [init-set action opt-reward]
  (OutputSetNode.
   (lazy-seq (for [[constraint ref] (angelic/immediate-refinements-set action init-set)]
               (make-initial-plan init-set constraint ref)))
   (make-live-summary opt-reward)
   +worst-summary+
   nil))



(defn osn-plan-summary [osn] (apply max-summary (map :summary (:plans osn))))
(defn osn-child-summary [osn ecs] (apply max-summary (map full-osp-summary (remove ecs (:child-pointers osn)))))
(defn osn-summary [osn ecs] (max-summary (osn-plan-summary osn) (osn-child-summary osn ecs)))

(def osn-child-pointers :child-pointers)
(defn osn-add-plans [osn plans] (update-in osn [:plans] concat plans))

;; osn/osp
(defn merge-children
