 
 ;; TODO - try a few different names here
 (defmethod problem-group-str :expound.problem/value-group [type spec-name val path problems opts]
-  ;; TODO - assert singleton
+  (s/assert ::singleton problems)
   (let [problem (first problems)
         subproblems (:problems problem)
-        {:keys [form in]} (problem-parts (first subproblems) opts)]
-    ;; TODO use better header
+        {:expound/keys [form in]} (first subproblems)]
     (format-err (-> subproblems first :expound.spec.problem/type header)
                 type
                 spec-name

                opts
                (expected-str type spec-name val path problems opts))))

;; TODO - use this wrapper more
;; TODO - rename
;; TODO - private
(defn problem-group-str-wrapper [problem opts]
  (let [{:keys [type spec-name in form]} (problem-parts problem opts)]
    (problem-group-str
     type
     spec-name
     form
     in
     [problem]
     opts)))

(defmethod expected-str :expound.problem/alt-group [type spec-name val path problems opts]
  (let [subproblems (:problems (first problems))]
    (string/join
     "\n\nor value\n\n"
     (for [problem subproblems]
       (let [{:keys [form in type]} (problem-parts problem opts)]
         (printer/format
          "%s\n\n%s"
          (value-str type spec-name form in [problem] opts)
          (expected-str2 spec-name [problem] opts)))))))

(defmethod problem-group-str :expound.problem/alt-group [_type spec-name val path problems opts]
  (s/assert ::singleton problems)

       form))
   groups))

(defn ^:private remove-vec [v x]
  (vec (remove #{x} v)))

(defn ^:private groups [problems]
