diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,3 @@
+0.32.0.8
+
+  * update versions of depended-upon packages
diff --git a/current-versions.txt b/current-versions.txt
--- a/current-versions.txt
+++ b/current-versions.txt
@@ -1,7 +1,7 @@
 This package was tested to work with these dependency
 versions and compiler version.
 These are the default versions fetched by cabal install.
-Tested as of: 2014-03-08 16:59:06.573315 UTC
+Tested as of: 2014-04-16 17:16:55.729949 UTC
 Path to compiler: ghc-7.6.3
 Compiler description: 7.6.3
 
@@ -32,40 +32,52 @@
     time-1.4.0.1
     unix-2.6.0.1
 
-/home/massysett/penny/sunlight-15431/db:
+/home/massysett/penny/sunlight-10948/db:
     MonadRandom-0.1.13
     QuickCheck-2.6
-    action-permutations-0.0.0.0
+    action-permutations-0.0.0.1
     anonymous-sums-0.4.0.0
+    ansi-terminal-0.6.1.1
+    ansi-wl-pprint-0.6.7.1
+    async-2.0.1.5
     base-unicode-symbols-0.2.2.4
+    bifunctors-4.1.1
     cereal-0.4.0.1
-    comonad-4.0
+    comonad-4.0.1
     contravariant-0.4.4
-    distributive-0.4
+    distributive-0.4.3.1
     either-4.1.1
     hashable-1.2.1.0
     haskell-lexer-1.0
-    matchers-0.14.0.2
+    matchers-0.18.0.0
     monad-control-0.3.2.3
-    mtl-2.1.2
-    multiarg-0.24.0.4
+    mtl-2.1.3.1
+    multiarg-0.26.0.0
     nats-0.1.2
     ofx-0.4.0.2
+    optparse-applicative-0.8.0.1
     parsec-3.1.5
-    penny-0.32.0.6
-    prednote-0.18.0.4
+    penny-0.32.0.8
+    prednote-0.22.0.2
     pretty-show-1.6.7
-    rainbow-0.12.0.0
+    rainbow-0.14.0.0
+    rainbox-0.4.0.2
     random-1.0.1.1
     random-shuffle-0.0.4
-    semigroupoids-4.0
-    semigroups-0.12.2
+    regex-base-0.93.2
+    regex-tdfa-1.2.0
+    semigroupoids-4.0.1
+    semigroups-0.13.0.1
     split-0.2.2
-    tagged-0.7
+    stm-2.4.3
+    tagged-0.7.1
+    tasty-0.8.0.4
+    tasty-quickcheck-0.8
     terminfo-0.4.0.0
     text-1.1.0.1
     transformers-0.3.0.0
     transformers-base-0.4.1
     transformers-compat-0.1.1.1
-    unordered-containers-0.2.3.3
+    unbounded-delays-0.1.0.7
+    unordered-containers-0.2.4.0
 
diff --git a/lib/Penny/Cabin/Balance/Convert/Chunker.hs b/lib/Penny/Cabin/Balance/Convert/Chunker.hs
--- a/lib/Penny/Cabin/Balance/Convert/Chunker.hs
+++ b/lib/Penny/Cabin/Balance/Convert/Chunker.hs
@@ -60,7 +60,7 @@
   -> Columns PreSpec
   -> Columns R.Width
 maxWidthPerColumn w p = f <$> w <*> p where
-  f old new = max old (R.Width . X.length . Rb.text . bits $ new)
+  f old new = max old (R.Width . sum . map X.length . Rb.text . bits $ new)
 
 -- | Changes a single set of Columns to a set of ColumnSpec of the
 -- given width.
@@ -193,7 +193,8 @@
     eo = E.fromVisibleNum vn
     lbl = E.Other
     ca = PreSpec R.LeftJustify (lbl, eo)
-         (E.getEvenOddLabelValue lbl eo chgrs . Rb.Chunk mempty $ txt)
+         (E.getEvenOddLabelValue lbl eo chgrs . Rb.Chunk mempty . (:[])
+            $ txt)
     cd = PreSpec R.LeftJustify (lbl, eo)
          (E.getEvenOddLabelValue lbl eo chgrs mempty)
     cq = cd
@@ -208,7 +209,7 @@
     applyFmt = E.getEvenOddLabelValue lbl eo chgrs
     eo = E.fromVisibleNum vn
     lbl = E.Other
-    ca = PreSpec R.LeftJustify (lbl, eo) (applyFmt (Rb.Chunk mempty txt))
+    ca = PreSpec R.LeftJustify (lbl, eo) (applyFmt (Rb.Chunk mempty [txt]))
       where
         txt = X.append indents acctTxt
         indents = X.replicate (indentAmount * max 0 i)
@@ -232,7 +233,7 @@
       L.Zero -> Nothing
       L.NonZero c -> Just $ L.colDrCr c
     qtFmt = E.getEvenOddLabelValue lbl eo chgrs
-    chkQt = qtFmt $ Rb.Chunk mempty t
+    chkQt = qtFmt $ Rb.Chunk mempty [t]
     (lbl, t) = case bl of
       L.Zero -> (E.Zero, X.pack "--")
       L.NonZero (L.Column dc qt) -> (E.dcToLbl dc, fmt qt)
diff --git a/lib/Penny/Cabin/Balance/Convert/ChunkerPct.hs b/lib/Penny/Cabin/Balance/Convert/ChunkerPct.hs
--- a/lib/Penny/Cabin/Balance/Convert/ChunkerPct.hs
+++ b/lib/Penny/Cabin/Balance/Convert/ChunkerPct.hs
@@ -61,7 +61,7 @@
   -> Columns PreSpec
   -> Columns R.Width
 maxWidthPerColumn w p = f <$> w <*> p where
-  f old new = max old (R.Width . X.length . Rb.text . bits $ new)
+  f old new = max old (R.Width . sum . map X.length . Rb.text . bits $ new)
 
 -- | Changes a single set of Columns to a set of ColumnSpec of the
 -- given width.
@@ -206,7 +206,7 @@
     eo = E.fromVisibleNum vn
     lbl = E.Other
     ca = PreSpec R.LeftJustify (lbl, eo)
-         (E.getEvenOddLabelValue lbl eo chgrs . Rb.Chunk mempty $ txt)
+         (E.getEvenOddLabelValue lbl eo chgrs . Rb.Chunk mempty $ [txt])
     cd = PreSpec R.LeftJustify (lbl, eo)
          (E.getEvenOddLabelValue lbl eo chgrs mempty)
     cq = cd
@@ -221,7 +221,7 @@
     applyFmt = E.getEvenOddLabelValue lbl eo chgrs
     eo = E.fromVisibleNum vn
     lbl = E.Other
-    ca = PreSpec R.LeftJustify (lbl, eo) (applyFmt (Rb.Chunk mempty txt))
+    ca = PreSpec R.LeftJustify (lbl, eo) (applyFmt (Rb.Chunk mempty [txt]))
       where
         txt = X.append indents acctTxt
         indents = X.replicate (indentAmount * max 0 i)
@@ -242,7 +242,7 @@
     eo = E.fromVisibleNum vn
     chkDc = E.bottomLineToDrCr (fmap pctDrCr pct) eo chgrs
     qtFmt = E.getEvenOddLabelValue lbl eo chgrs
-    chkQt = qtFmt $ Rb.Chunk mempty t
+    chkQt = qtFmt $ Rb.Chunk mempty [t]
     (lbl, t) = case pct of
       Nothing -> (E.Zero, X.pack "--")
       Just (Percent dc qt) ->
diff --git a/lib/Penny/Cabin/Balance/MultiCommodity/Chunker.hs b/lib/Penny/Cabin/Balance/MultiCommodity/Chunker.hs
--- a/lib/Penny/Cabin/Balance/MultiCommodity/Chunker.hs
+++ b/lib/Penny/Cabin/Balance/MultiCommodity/Chunker.hs
@@ -63,7 +63,7 @@
   -> Columns R.Width
 maxWidthPerColumn w p = f <$> w <*> p where
   f old new = max old ( safeMaximum (R.Width 0)
-                        . map (R.Width . X.length . Rb.text)
+                        . map (R.Width . sum . map X.length . Rb.text)
                         . bits $ new)
   safeMaximum d ls = if null ls then d else maximum ls
 
@@ -179,7 +179,7 @@
     lbl = E.Other
     eo = E.fromVisibleNum vn
     applyFmt = E.getEvenOddLabelValue lbl eo chgrs
-    ca = PreSpec R.LeftJustify (lbl, eo) [applyFmt $ Rb.Chunk mempty txt]
+    ca = PreSpec R.LeftJustify (lbl, eo) [applyFmt $ Rb.Chunk mempty [txt]]
       where
         txt = X.append indents acctTxt
         indents = X.replicate (indentAmount * max 0 i)
diff --git a/lib/Penny/Cabin/Interface.hs b/lib/Penny/Cabin/Interface.hs
--- a/lib/Penny/Cabin/Interface.hs
+++ b/lib/Penny/Cabin/Interface.hs
@@ -4,9 +4,9 @@
 
 import qualified Data.Prednote.Expressions as Exp
 import qualified Penny.Cabin.Scheme as S
+import qualified Data.Prednote as Pd
 import qualified Data.Text as X
 import Text.Matchers (CaseSensitive)
-import qualified Text.Matchers as TM
 import qualified System.Console.MultiArg as MA
 import qualified System.Console.Rainbow as R
 
@@ -64,7 +64,7 @@
   -- case sensitivity (this may have been changed in the filtering
   -- options)
 
-  -> (CaseSensitive -> X.Text -> Either X.Text TM.Matcher)
+  -> (CaseSensitive -> X.Text -> Either X.Text (Pd.Predbox X.Text))
   -- ^ Result from previous parsers indicating the matcher factory the
   -- user wishes to use
 
diff --git a/lib/Penny/Cabin/Posts.hs b/lib/Penny/Cabin/Posts.hs
--- a/lib/Penny/Cabin/Posts.hs
+++ b/lib/Penny/Cabin/Posts.hs
@@ -71,8 +71,7 @@
 import qualified Penny.Lincoln.Queries as Q
 import qualified Penny.Liberty as Ly
 import qualified Penny.Shield as Sh
-import qualified Data.Prednote.Expressions as Exp
-import qualified Data.Prednote.Pdct as Pe
+import qualified Data.Prednote as Pd
 import qualified System.Console.Rainbow as Rb
 
 import Data.List (intersperse)
@@ -88,7 +87,7 @@
 postsReport
   :: E.Changers
   -> CO.ShowZeroBalances
-  -> (Pe.Pdct (Ly.LibertyMeta, L.Posting))
+  -> (Pd.Predbox (Ly.LibertyMeta, L.Posting))
   -- ^ Removes posts from the report if applying this function to the
   -- post returns False. Posts removed still affect the running
   -- balance.
@@ -129,7 +128,7 @@
   -> CaseSensitive
   -> L.Factory
   -> E.Changers
-  -> Exp.ExprDesc
+  -> Pd.ExprDesc
   -> ([L.Transaction] -> [(Ly.LibertyMeta, L.Posting)])
   -> [Either String (P.State -> Either X.Text P.State)]
   -> Either X.Text I.ArgsAndReport
@@ -161,7 +160,7 @@
                  ++ rptChks
       return chks
 
-indentAmt :: Pe.IndentAmt
+indentAmt :: Pd.IndentAmt
 indentAmt = 4
 
 blankLine :: Rb.Chunk
@@ -169,18 +168,18 @@
 
 showExpression
   :: P.ShowExpression
-  -> Pe.Pdct ((Ly.LibertyMeta, L.Posting))
+  -> Pd.Predbox ((Ly.LibertyMeta, L.Posting))
   -> [Rb.Chunk]
 showExpression (P.ShowExpression b) pdct =
   if not b then [] else info : blankLine : (chks ++ [blankLine])
   where
     info = "Postings filter expression:\n"
-    chks = Pe.showPdct indentAmt 0 pdct
+    chks = Pd.showPredbox indentAmt 0 pdct
 
 showVerboseFilter
   :: (L.Amount L.Qty -> X.Text)
   -> P.VerboseFilter
-  -> Pe.Pdct (Ly.LibertyMeta, L.Posting)
+  -> Pd.Predbox (Ly.LibertyMeta, L.Posting)
   -> [(Ly.LibertyMeta, L.Posting)]
   -> [Rb.Chunk]
 showVerboseFilter fmt (P.VerboseFilter b) pdct bs =
@@ -188,7 +187,7 @@
   where
     chks =
       fst
-      $ Pe.verboseFilter ((L.display fmt) . snd) indentAmt False pdct bs
+      $ Pd.verboseFilter ((L.display fmt) . snd) indentAmt False pdct bs
     info = "Postings report filter:\n"
 
 defaultOptions
@@ -209,13 +208,13 @@
 type Error = X.Text
 
 getPredicate
-  :: Exp.ExprDesc
-  -> [Exp.Token ((Ly.LibertyMeta, L.Posting))]
-  -> Either Error (Pe.Pdct ((Ly.LibertyMeta, L.Posting)))
+  :: Pd.ExprDesc
+  -> [Pd.Token ((Ly.LibertyMeta, L.Posting))]
+  -> Either Error (Pd.Predbox ((Ly.LibertyMeta, L.Posting)))
 getPredicate d ts =
   case ts of
-    [] -> return $ Pe.always
-    _ -> Exp.parseExpression d ts
+    [] -> return $ Pd.always
+    _ -> Pd.parseExpression d ts
 
 
 -- | All the information to configure the postings report if the
@@ -281,7 +280,7 @@
 newParseState ::
   CaseSensitive
   -> L.Factory
-  -> Exp.ExprDesc
+  -> Pd.ExprDesc
   -> ZincOpts
   -> P.State
 newParseState cs fty expr o = P.State
diff --git a/lib/Penny/Cabin/Posts/Allocated.hs b/lib/Penny/Cabin/Posts/Allocated.hs
--- a/lib/Penny/Cabin/Posts/Allocated.hs
+++ b/lib/Penny/Cabin/Posts/Allocated.hs
@@ -342,6 +342,7 @@
                 toBit (TF.Words seqTxts) =
                   md
                   . Rb.Chunk mempty
+                  . (:[])
                   . X.unwords
                   . Fdbl.toList
                   $ seqTxts
@@ -376,6 +377,7 @@
         (TF.Words shortened) = TF.shorten shortest target ws
         sq = [ md
                . Rb.Chunk mempty
+               . (:[])
                . X.concat
                . intersperse (X.singleton ':')
                . Fdbl.toList
diff --git a/lib/Penny/Cabin/Posts/BottomRows.hs b/lib/Penny/Cabin/Posts/BottomRows.hs
--- a/lib/Penny/Cabin/Posts/BottomRows.hs
+++ b/lib/Penny/Cabin/Posts/BottomRows.hs
@@ -329,7 +329,7 @@
     . snd
     $ info
   md = E.getEvenOddLabelValue E.Other eo ch
-  toBit (TF.Words ws) = md . Rb.Chunk mempty $ t where
+  toBit (TF.Words ws) = md . Rb.Chunk mempty . (:[]) $ t where
     t = X.concat . intersperse (X.singleton ' ') . Fdbl.toList $ ws
 
 
@@ -347,7 +347,7 @@
        . L.unMemo
        $ m
   md = E.getEvenOddLabelValue lbl eo ch
-  toBit (TF.Words ws) = md . Rb.Chunk mempty
+  toBit (TF.Words ws) = md . Rb.Chunk mempty . (:[])
                         $ (X.unwords . Fdbl.toList $ ws)
 
 
@@ -377,7 +377,7 @@
   ts = (E.Other, eo)
   cell = R.ColumnSpec R.LeftJustify w ts cs
   md = E.getEvenOddLabelValue E.Other eo ch
-  toBit n = md . Rb.Chunk mempty
+  toBit n = md . Rb.Chunk mempty . (:[])
             . X.drop (max 0 (X.length n - width)) $ n
   cs = case Q.filename . snd $ info of
     Nothing -> []
diff --git a/lib/Penny/Cabin/Posts/Growers.hs b/lib/Penny/Cabin/Posts/Growers.hs
--- a/lib/Penny/Cabin/Posts/Growers.hs
+++ b/lib/Penny/Cabin/Posts/Growers.hs
@@ -63,7 +63,7 @@
 widestLine (PreSpec _ _ bs) =
   case bs of
     [] -> 0
-    xs -> maximum . map (X.length . Rb.text) $ xs
+    xs -> maximum . map (sum . map X.length . Rb.text) $ xs
 
 data PreSpec = PreSpec {
   _justification :: R.Justification
@@ -83,7 +83,7 @@
   let eo = E.fromVisibleNum . M.visibleNum . fst $ b
       j = R.LeftJustify
       md = E.getEvenOddLabelValue lbl eo chgrs
-      ck = [md $ Rb.Chunk mempty t]
+      ck = [md $ Rb.Chunk mempty [t]]
   in PreSpec j (lbl, eo) ck
 
 
@@ -234,7 +234,7 @@
     L.Credit -> E.Credit
   eo = E.fromVisibleNum . M.visibleNum . fst $ i
   md = E.getEvenOddLabelValue lbl eo chgrs
-  bit = md $ Rb.Chunk mempty t
+  bit = md $ Rb.Chunk mempty [t]
 
 
 getPostingDrCr :: E.Changers -> (M.PostMeta, L.Posting) -> PreSpec
diff --git a/lib/Penny/Cabin/Posts/Meta.hs b/lib/Penny/Cabin/Posts/Meta.hs
--- a/lib/Penny/Cabin/Posts/Meta.hs
+++ b/lib/Penny/Cabin/Posts/Meta.hs
@@ -11,7 +11,7 @@
 import qualified Penny.Liberty as Ly
 import qualified Penny.Cabin.Meta as M
 import qualified Penny.Cabin.Options as CO
-import qualified Data.Prednote.Pdct as Pe
+import qualified Data.Prednote as Pe
 import Data.Monoid (mempty, mappend)
 
 data PostMeta = PostMeta
@@ -43,7 +43,7 @@
 -- the VisibleNum.
 toBoxList
   :: CO.ShowZeroBalances
-  -> Pe.Pdct (Ly.LibertyMeta, L.Posting)
+  -> Pe.Predbox (Ly.LibertyMeta, L.Posting)
   -- ^ Removes posts from the report if applying this function to the
   -- post returns a value other than Just True. Posts removed still
   -- affect the running balance.
@@ -58,7 +58,7 @@
 toBoxList szb pdct pff
   = addMetadata
   . Ly.processPostFilters pff
-  . filter (Pe.rBool . flip Pe.evaluate pdct . snd)
+  . filter (Pe.rBool . Pe.evaluate pdct . snd)
   . addBalances szb
 
 addBalances
diff --git a/lib/Penny/Cabin/Posts/Parser.hs b/lib/Penny/Cabin/Posts/Parser.hs
--- a/lib/Penny/Cabin/Posts/Parser.hs
+++ b/lib/Penny/Cabin/Posts/Parser.hs
@@ -11,6 +11,7 @@
 import Control.Applicative ((<$>), pure, (<*>),
                             Applicative)
 import Data.Char (toLower)
+import Data.Functor.Contravariant (contramap)
 import qualified Data.Foldable as Fdbl
 import Data.Monoid ((<>))
 import Data.Text (Text)
@@ -24,7 +25,7 @@
 import qualified Penny.Cabin.Options as CO
 import qualified Penny.Liberty as Ly
 import qualified Data.Prednote.Expressions as Exp
-import qualified Data.Prednote.Pdct as Pt
+import qualified Data.Prednote as Pt
 import qualified Penny.Lincoln as L
 import qualified Penny.Shield as S
 import qualified Text.Matchers as M
@@ -82,7 +83,7 @@
       let cs = sensitive st
           fty = factory st
       g <- lyFn cs fty
-      let g' = Pt.boxPdct snd g
+      let g' = contramap snd g
           ts' = tokens st ++ [Exp.operand g']
       return $ st { tokens = ts' }
 
diff --git a/lib/Penny/Cabin/Row.hs b/lib/Penny/Cabin/Row.hs
--- a/lib/Penny/Cabin/Row.hs
+++ b/lib/Penny/Cabin/Row.hs
@@ -77,8 +77,8 @@
   -> JustifiedCell
 justify (Width w) j l eo chgrs pc = JustifiedCell (left, right)
   where
-    origWidth = X.length . R.text $ pc
-    pad = E.getEvenOddLabelValue l eo chgrs . R.Chunk mempty $ t
+    origWidth = sum . map X.length . R.text $ pc
+    pad = E.getEvenOddLabelValue l eo chgrs . R.Chunk mempty $ [t]
     t = X.replicate (max 0 (w - origWidth)) (X.singleton ' ')
     (left, right) = case j of
       LeftJustify -> (pc, pad)
@@ -116,7 +116,7 @@
   toPaddedColumn (JustifiedColumn cs (Width w) (lbl, eo)) =
     let l = length cs
         nPads = max 0 $ h - l
-        pad = E.getEvenOddLabelValue lbl eo chgrs . R.Chunk mempty $ t
+        pad = E.getEvenOddLabelValue lbl eo chgrs . R.Chunk mempty $ [t]
         t = X.replicate w (X.singleton ' ')
         pads = replicate nPads $ JustifiedCell (mempty, pad)
     in cs ++ pads
diff --git a/lib/Penny/Cabin/Scheme.hs b/lib/Penny/Cabin/Scheme.hs
--- a/lib/Penny/Cabin/Scheme.hs
+++ b/lib/Penny/Cabin/Scheme.hs
@@ -107,7 +107,7 @@
   -> R.Chunk
 bottomLineToCmdty chgrs eo (cy, bl) = md c
   where
-    c = R.Chunk mempty . L.unCommodity $ cy
+    c = R.Chunk mempty . (:[]) . L.unCommodity $ cy
     lbl = case bl of
       L.Zero -> Zero
       L.NonZero (L.Column clmDrCr _) -> dcToLbl clmDrCr
@@ -132,7 +132,7 @@
   -> EvenOdd
   -> (L.Commodity, L.BottomLine)
   -> R.Chunk
-bottomLineToQty chgrs getTxt eo (cy, bl) = md (R.Chunk mempty t)
+bottomLineToQty chgrs getTxt eo (cy, bl) = md (R.Chunk mempty [t])
   where
     (lbl, t) = case bl of
       L.Zero -> (Zero, X.pack "--")
diff --git a/lib/Penny/Liberty.hs b/lib/Penny/Liberty.hs
--- a/lib/Penny/Liberty.hs
+++ b/lib/Penny/Liberty.hs
@@ -70,7 +70,7 @@
 import qualified Penny.Lincoln.Predicates as P
 import qualified Penny.Lincoln.Queries as Q
 import qualified Penny.Lincoln.Predicates.Siblings as PS
-import qualified Data.Prednote.Pdct as E
+import qualified Data.Prednote as E
 import qualified Penny.Lincoln as L
 import qualified System.Console.Rainbow as C
 import qualified Data.Prednote.Expressions as X
@@ -110,7 +110,7 @@
 parsePredicate
   :: X.ExprDesc
   -> [X.Token a]
-  -> Either Error (E.Pdct a)
+  -> Either Error (E.Predbox a)
 parsePredicate d ls = case ls of
   [] -> return E.always
   _ -> X.parseExpression d ls
@@ -178,7 +178,7 @@
 type MatcherFactory
   = CaseSensitive
   -> Text
-  -> Either Text TM.Matcher
+  -> Either Text (E.Predbox Text)
 
 newtype ListLength = ListLength { unListLength :: Int }
                      deriving (Eq, Ord, Show)
@@ -212,7 +212,7 @@
   :: String
   -> CaseSensitive
   -> MatcherFactory
-  -> Either Error TM.Matcher
+  -> Either Error (E.Predbox Text)
 
 getMatcher s cs f
   = either (Left . mkError) Right
@@ -226,8 +226,8 @@
 -- the string given is invalid.
 parseComparer
   :: String
-  -> (Ordering -> E.Pdct a)
-  -> Either InputError (E.Pdct a)
+  -> (Ordering -> E.Predbox a)
+  -> Either InputError (E.Predbox a)
 parseComparer s f
   = maybe (Left . MA.ErrorMsg $ "bad comparer")
           Right $ E.parseComparer (pack s) f
@@ -243,7 +243,7 @@
   where
     err msg = MA.ErrorMsg $ "bad date - " <> show msg
 
-type Operand = E.Pdct L.Posting
+type Operand = E.Predbox L.Posting
 
 -- | OptSpec for a date.
 date :: OptSpec Operand
@@ -286,7 +286,7 @@
   -> Maybe Char
   -- ^ Short option, if included
 
-  -> (TM.Matcher -> P.LPdct)
+  -> (E.Predbox Text -> P.LPdct)
   -- ^ When applied to a Matcher, this function returns a predicate.
 
   -> OptSpec ( CaseSensitive
@@ -423,10 +423,10 @@
   :: String
   -- ^ Name of the command line option, such as @global-posting@
 
-  -> (Int -> Ordering -> E.Pdct L.Posting)
+  -> (Int -> Ordering -> E.Predbox L.Posting)
   -- ^ Function that returns a Pdct for forward serial
 
-  -> (Int -> Ordering -> E.Pdct L.Posting)
+  -> (Int -> Ordering -> E.Predbox L.Posting)
   -- ^ Function that returns a Pdct for reverse serial
 
   -> ( OptSpec Operand
diff --git a/lib/Penny/Lincoln/Matchers.hs b/lib/Penny/Lincoln/Matchers.hs
--- a/lib/Penny/Lincoln/Matchers.hs
+++ b/lib/Penny/Lincoln/Matchers.hs
@@ -4,6 +4,7 @@
 
 import qualified Data.Text as X
 import qualified Text.Matchers as MT
+import qualified Data.Prednote as P
 
 -- | A function that makes Matchers.
 type Factory
@@ -14,7 +15,7 @@
   -- ^ The pattern to use when testing for a match. For example, this
   -- might be a regular expression, or simply the text to be matched.
 
-  -> Either X.Text MT.Matcher
+  -> Either X.Text (P.Predbox X.Text)
   -- ^ Sometimes producing a matcher might fail; for example, the user
   -- might have supplied a bad pattern. If so, an exception is
-  -- returned. On success, a Matcher is returned.
+  -- returned. On success, a matcher is returned.
diff --git a/lib/Penny/Lincoln/Predicates.hs b/lib/Penny/Lincoln/Predicates.hs
--- a/lib/Penny/Lincoln/Predicates.hs
+++ b/lib/Penny/Lincoln/Predicates.hs
@@ -49,44 +49,47 @@
 import qualified Penny.Lincoln.Queries as Q
 import Penny.Lincoln.Ents (Posting)
 import qualified Penny.Lincoln.Ents as E
-import qualified Text.Matchers as M
-import qualified Data.Prednote.Pdct as P
+import qualified Data.Prednote as P
 import Penny.Lincoln.Serial (forward, backward)
 
-type LPdct = P.Pdct Posting
+type LPdct = P.Predbox Posting
 
-type MakePdct = M.Matcher -> LPdct
+type MakePdct = P.Predbox Text -> LPdct
 
 -- * Matching helpers
+
+eval :: P.Predbox a -> a -> Bool
+eval pb = P.rBool . P.evaluate pb
+
 match
   :: HasText a
   => Text
   -- ^ Description of this field
   -> (Posting -> a)
   -- ^ Function that returns the field being matched
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-match t f m = P.operand desc pd
+match t f m = P.predicate desc pd
   where
     desc = makeDesc t m
-    pd = M.match m . text . f
+    pd = eval m . text . f
 
 matchMaybe
   :: HasText a
   => Text
   -- ^ Description of this field
   -> (Posting -> Maybe a)
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchMaybe t f m = P.operand desc pd
+matchMaybe t f m = P.predicate desc pd
   where
     desc = makeDesc t m
-    pd = maybe False (M.match m . text) . f
+    pd = maybe False (eval m . text) . f
 
-makeDesc :: Text -> M.Matcher -> Text
+makeDesc :: Text -> P.Predbox Text -> Text
 makeDesc t m
   = "subject: " <> t
-  <> " matcher: " <> M.matchDesc m
+  <> " matcher: " <> P.pLabel m
 
 -- | Does the given matcher match any of the elements of the Texts in
 -- a HasTextList?
@@ -94,12 +97,12 @@
   :: HasTextList a
   => Text
   -> (Posting -> a)
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchAny t f m = P.operand desc pd
+matchAny t f m = P.predicate desc pd
   where
     desc = makeDesc t m
-    pd = any (M.match m) . textList . f
+    pd = any (eval m) . textList . f
 
 -- | Does the given matcher match the text that is at the given
 -- element of a HasTextList? If the HasTextList does not have a
@@ -109,28 +112,28 @@
   => Int
   -> Text
   -> (Posting -> a)
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchLevel l d f m = P.operand desc pd
+matchLevel l d f m = P.predicate desc pd
   where
     desc = makeDesc ("level " <> X.pack (show l) <> " of " <> d) m
     pd pf = let ts = textList (f pf)
             in if l < 0 || l >= length ts
                then False
-               else M.match m (ts !! l)
+               else eval m (ts !! l)
 
 -- | Does the matcher match the text of the memo? Joins each line of
 -- the memo with a space.
 matchMemo
   :: Text
   -> (Posting -> Maybe B.Memo)
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchMemo t f m = P.operand desc pd
+matchMemo t f m = P.predicate desc pd
   where
     desc = makeDesc t m
     pd = maybe False doMatch . f
-    doMatch = M.match m
+    doMatch = eval m
               . X.intercalate (X.singleton ' ')
               . B.unMemo
 
@@ -141,7 +144,7 @@
   -> Text
   -- ^ Label
   -> (Posting -> a)
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
 matchDelimited sep lbl f m = match lbl f' m
   where
@@ -181,7 +184,7 @@
 
 
 drCr :: B.DrCr -> LPdct
-drCr dc = P.operand desc pd
+drCr dc = P.predicate desc pd
   where
     desc = "entry is a " <> s
     s = case dc of { B.Debit -> "debit"; B.Credit -> "credit" }
@@ -193,30 +196,30 @@
 credit :: LPdct
 credit = drCr B.Credit
 
-commodity :: M.Matcher -> LPdct
+commodity :: P.Predbox Text -> LPdct
 commodity = match "commodity" Q.commodity
 
-account :: M.Matcher -> LPdct
+account :: P.Predbox Text -> LPdct
 account = matchDelimited ":" "account" Q.account
 
-accountLevel :: Int -> M.Matcher -> LPdct
+accountLevel :: Int -> P.Predbox Text -> LPdct
 accountLevel i = matchLevel i "account" Q.account
 
-accountAny :: M.Matcher -> LPdct
+accountAny :: P.Predbox Text -> LPdct
 accountAny = matchAny "any sub-account" Q.account
 
-tag :: M.Matcher -> LPdct
+tag :: P.Predbox Text -> LPdct
 tag = matchAny "any tag" Q.tags
 
 -- | True if a posting is reconciled; that is, its flag is exactly
 -- @R@.
 reconciled :: LPdct
-reconciled = P.operand d p
+reconciled = P.predicate d p
   where
     d = "posting flag is exactly \"R\" (is reconciled)"
     p = maybe False ((== X.singleton 'R') . B.unFlag) . Q.flag
 
-filename :: M.Matcher -> LPdct
+filename :: P.Predbox Text -> LPdct
 filename = matchMaybe "filename" Q.filename
 
 -- | Makes Pdct based on comparisons against a particular serial.
@@ -235,9 +238,9 @@
   -- ^ The Pdct returned will be True if the item has a serial
   -- and @compare ser rhs@ returns this Ordering; False otherwise.
 
-  -> P.Pdct a
+  -> P.Predbox a
 
-serialPdct name getSer i o = P.operand n f
+serialPdct name getSer i o = P.predicate n f
   where
     n = "serial " <> name <> " is " <> descCmp <> " "
         <> X.pack (show i)
@@ -248,7 +251,7 @@
     f = fromMaybe False . fmap (\ser -> compare ser i == o)
         . getSer
 
-type MakeSerialPdct = Int -> Ordering -> P.Pdct Posting
+type MakeSerialPdct = Int -> Ordering -> P.Predbox Posting
 
 fwdGlobalPosting :: MakeSerialPdct
 fwdGlobalPosting =
diff --git a/lib/Penny/Lincoln/Predicates/Siblings.hs b/lib/Penny/Lincoln/Predicates/Siblings.hs
--- a/lib/Penny/Lincoln/Predicates/Siblings.hs
+++ b/lib/Penny/Lincoln/Predicates/Siblings.hs
@@ -48,45 +48,48 @@
 import Penny.Lincoln.HasText (HasText, text, HasTextList, textList)
 import qualified Penny.Lincoln.Queries.Siblings as Q
 import Penny.Lincoln.Ents (Posting)
-import qualified Text.Matchers as M
-import qualified Data.Prednote.Pdct as P
+import qualified Data.Prednote as P
 
-type LPdct = P.Pdct Posting
+type LPdct = P.Predbox Posting
 
-type MakePdct = M.Matcher -> LPdct
+type MakePdct = P.Predbox Text -> LPdct
 
 -- * Matching helpers
+
+eval :: P.Predbox a -> a -> Bool
+eval pb = P.rBool . P.evaluate pb
+
 match
   :: HasText a
   => Text
   -- ^ Description of this field
   -> (Posting -> [a])
   -- ^ Function that returns the field being matched
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-match t f m = P.operand desc pd
+match t f m = P.predicate desc pd
   where
     desc = makeDesc t m
-    pd = any (M.match m) . map text . f
+    pd = any (eval m) . map text . f
 
 matchMaybe
   :: HasText a
   => Text
   -- ^ Description of this field
   -> (Posting -> [Maybe a])
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchMaybe t f m = P.operand desc pd
+matchMaybe t f m = P.predicate desc pd
   where
     desc = makeDesc t m
     pd = any (== (Just True))
-         . map (fmap (M.match m . text))
+         . map (fmap (eval m . text))
          . f
 
-makeDesc :: Text -> M.Matcher -> Text
+makeDesc :: Text -> P.Predbox Text -> Text
 makeDesc t m
   = "subject: " <> t <> " (any sibling posting) matcher: "
-  <> M.matchDesc m
+  <> P.pLabel m
 
 -- | Does the given matcher match any of the elements of the Texts in
 -- a HasTextList?
@@ -94,12 +97,12 @@
   :: HasTextList a
   => Text
   -> (Posting -> [a])
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchAny t f m = P.operand desc pd
+matchAny t f m = P.predicate desc pd
   where
     desc = makeDesc t m
-    pd = any (any (M.match m)) . map textList . f
+    pd = any (any (eval m)) . map textList . f
 
 -- | Does the given matcher match the text that is at the given
 -- element of a HasTextList? If the HasTextList does not have a
@@ -109,14 +112,14 @@
   => Int
   -> Text
   -> (Posting -> [a])
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchLevel l d f m = P.operand desc pd
+matchLevel l d f m = P.predicate desc pd
   where
     desc = makeDesc ("level " <> X.pack (show l) <> " of " <> d) m
     pd pf = let doMatch list = if l < 0 || l >= length list
                                then False
-                               else M.match m (list !! l)
+                               else eval m (list !! l)
             in any doMatch . map textList . f $ pf
 
 -- | Does the matcher match the text of the memo? Joins each line of
@@ -124,13 +127,13 @@
 matchMemo
   :: Text
   -> (Posting -> [Maybe B.Memo])
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
-matchMemo t f m = P.operand desc pd
+matchMemo t f m = P.predicate desc pd
   where
     desc = makeDesc t m
     pd = any (maybe False doMatch) . f
-    doMatch = M.match m
+    doMatch = eval m
               . X.intercalate (X.singleton ' ')
               . B.unMemo
 
@@ -141,7 +144,7 @@
   -> Text
   -- ^ Label
   -> (Posting -> [a])
-  -> M.Matcher
+  -> P.Predbox Text
   -> LPdct
 matchDelimited sep lbl f m = match lbl f' m
   where
@@ -164,7 +167,7 @@
 -- | A Pdct that returns True if @compare subject qty@ returns the
 -- given Ordering.
 qty :: Ordering -> B.Qty -> LPdct
-qty o q = P.operand desc pd
+qty o q = P.predicate desc pd
   where
     desc = "quantity of any sibling is " <> dd <> " " <> X.pack (show q)
     dd = case o of
@@ -188,7 +191,7 @@
   | otherwise = Nothing
 
 drCr :: B.DrCr -> LPdct
-drCr dc = P.operand desc pd
+drCr dc = P.predicate desc pd
   where
     desc = "entry of any sibling is a " <> s
     s = case dc of { B.Debit -> "debit"; B.Credit -> "credit" }
@@ -200,25 +203,25 @@
 credit :: LPdct
 credit = drCr B.Credit
 
-commodity :: M.Matcher -> LPdct
+commodity :: P.Predbox Text -> LPdct
 commodity = match "commodity" Q.commodity
 
-account :: M.Matcher -> LPdct
+account :: P.Predbox Text -> LPdct
 account = matchDelimited ":" "account" Q.account
 
-accountLevel :: Int -> M.Matcher -> LPdct
+accountLevel :: Int -> P.Predbox Text -> LPdct
 accountLevel i = matchLevel i "account" Q.account
 
-accountAny :: M.Matcher -> LPdct
+accountAny :: P.Predbox Text -> LPdct
 accountAny = matchAny "any sub-account" Q.account
 
-tag :: M.Matcher -> LPdct
+tag :: P.Predbox Text -> LPdct
 tag = matchAny "any tag" Q.tags
 
 -- | True if a posting is reconciled; that is, its flag is exactly
 -- @R@.
 reconciled :: LPdct
-reconciled = P.operand d p
+reconciled = P.predicate d p
   where
     d = "posting flag is exactly \"R\" (is reconciled)"
     p = any (maybe False ((== X.singleton 'R') . B.unFlag))
@@ -246,9 +249,9 @@
   -- item has a srerial and @compare@ does not return this Ordering;
   -- Nothing if the item does not have a serial.
 
-  -> P.Pdct E.Posting
+  -> P.Predbox E.Posting
 
-serialPdct name getSer i o = P.operand n f
+serialPdct name getSer i o = P.predicate n f
   where
     n = "serial " <> name <> " is " <> descCmp <> " "
         <> X.pack (show i)
@@ -264,7 +267,7 @@
         . second E.tailEnts
         . E.unPosting
 
-type MakeSerialPdct = Int -> Ordering -> P.Pdct Posting
+type MakeSerialPdct = Int -> Ordering -> P.Predbox Posting
 
 fwdGlobalPosting :: MakeSerialPdct
 fwdGlobalPosting =
diff --git a/lib/Penny/Wheat.hs b/lib/Penny/Wheat.hs
--- a/lib/Penny/Wheat.hs
+++ b/lib/Penny/Wheat.hs
@@ -40,8 +40,7 @@
 import qualified Data.Sums as Su
 
 import qualified Data.Version as V
-import qualified Data.Prednote.Test as TT
-import qualified Data.Prednote.Pdct as Pe
+import qualified Data.Prednote as Pd
 import qualified System.Console.Rainbow as Rb
 import qualified System.Console.MultiArg as MA
 import System.Locale (defaultTimeLocale)
@@ -76,20 +75,20 @@
     -- of lines, wich each line not terminated by a newline
     -- character. It is displayed at the end of the online help.
 
-  , tests :: [Time.UTCTime -> TT.Test L.Posting]
+  , tests :: [Time.UTCTime -> Pd.Test L.Posting]
     -- ^ The actual tests to run. The UTCTime is the @base time@. Each
     -- test may decide what to do with the base time--for example, the
     -- test might say that all postings have to have a date on or
     -- before that date. Or the test might just ignore the base time.
 
-  , indentAmt :: Pe.IndentAmt
+  , indentAmt :: Pd.IndentAmt
     -- ^ How many spaces to indent each level in a tree of tests.
 
-  , verbosity :: Maybe TT.TestVerbosity
+  , verbosity :: Maybe Pd.TestVerbosity
     -- ^ If Just, use this verbosity. If Nothing, use the default
     -- verbosity provided by the tests themselves.
 
-  , testPred :: TT.Name -> Bool
+  , testPred :: Pd.Name -> Bool
     -- ^ Test names are filtered with this function; a test is only
     -- run if this function returns True.
 
@@ -114,11 +113,11 @@
   Left e -> Left (MA.ErrorMsg $ "could not parse date: " ++ show e)
   Right g -> return . L.toUTC $ g
 
-parseRegexp :: String -> Either MA.InputError (TT.Name -> Bool)
+parseRegexp :: String -> Either MA.InputError (Pd.Name -> Bool)
 parseRegexp s = case M.pcre M.Sensitive (X.pack s) of
   Left e -> Left . MA.ErrorMsg $
     "could not parse regular expression: " ++ X.unpack e
-  Right m -> return . M.match $ m
+  Right m -> return (\n -> Pd.rBool (Pd.evaluate m n))
 
 allOpts :: [MA.OptSpec (WheatConf -> WheatConf)]
 allOpts =
@@ -173,7 +172,7 @@
   items <- Cop.open args
   let pstgs = getItems items
       formatter = formatQty conf items
-  let tsts = filter ((testPred conf) . TT.testName)
+  let tsts = filter ((testPred conf) . Pd.testName)
              . map ($ (L.toUTC . S.currentTime $ rt))
              . tests
              $ conf
@@ -190,16 +189,16 @@
   -> WheatConf
   -> [L.Posting]
   -> Rb.Term
-  -> TT.Test L.Posting
+  -> Pd.Test L.Posting
   -> IO Bool
 runTest fmt c ps term test = do
-  let rslt = TT.evalTest test ps
-      cks = TT.showResult (indentAmt c) (L.display fmt)
-                          (verbosity c) rslt
+  let rslt = Pd.evalTest test ps
+      cks = Pd.showTestResult (indentAmt c) (L.display fmt)
+                              (verbosity c) rslt
   Rb.putChunks term cks
-  if stopOnFail c && not (TT.resultPass rslt)
+  if stopOnFail c && not (Pd.resultPass rslt)
     then Exit.exitFailure
-    else return (TT.resultPass rslt)
+    else return (Pd.resultPass rslt)
 
 getItems :: [Cop.LedgerItem] -> [L.Posting]
 getItems
@@ -213,19 +212,19 @@
 
 -- | Passes only if each posting is True.
 eachPostingMustBeTrue
-  :: TT.Name
-  -> Pe.Pdct L.Posting
-  -> TT.Test L.Posting
-eachPostingMustBeTrue n pd = TT.eachSubjectMustBeTrue pd n
+  :: Pd.Name
+  -> Pd.Predbox L.Posting
+  -> Pd.Test L.Posting
+eachPostingMustBeTrue n pd = Pd.eachSubjectMustBeTrue pd n
 
 -- | Passes if at least a particular number of postings is True.
 atLeastNPostings
   :: Int
   -- ^ The number of postings that must be true for the test to pass
-  -> TT.Name
-  -> Pe.Pdct L.Posting
-  -> TT.Test L.Posting
-atLeastNPostings i n pd = TT.nSubjectsMustBeTrue pd n i
+  -> Pd.Name
+  -> Pd.Predbox L.Posting
+  -> Pd.Test L.Posting
+atLeastNPostings i n pd = Pd.nSubjectsMustBeTrue pd n i
 
 --
 -- Help
diff --git a/lib/Penny/Zinc.hs b/lib/Penny/Zinc.hs
--- a/lib/Penny/Zinc.hs
+++ b/lib/Penny/Zinc.hs
@@ -16,7 +16,7 @@
 import qualified Penny.Copper as C
 import qualified Penny.Liberty as Ly
 import qualified Data.Prednote.Expressions as X
-import qualified Data.Prednote.Pdct as Pe
+import qualified Data.Prednote as Pe
 import qualified Penny.Lincoln as L
 import qualified Penny.Lincoln.Queries as Q
 import qualified Penny.Shield as S
@@ -200,7 +200,7 @@
      else mconcat exSpecs
 
 type Factory = M.CaseSensitive
-             -> Text -> Either Text M.Matcher
+             -> Text -> Either Text (Pe.Predbox Text)
 
 makeToken
   :: OptResult
@@ -324,7 +324,7 @@
 
   , foColorToFile :: ColorToFile
   , foExprDesc :: X.ExprDesc
-  , foPredicate :: Pe.Pdct L.Posting
+  , foPredicate :: Pe.Predbox L.Posting
   , foShowExpression :: ShowExpression
   , foVerboseFilter :: VerboseFilter
   }
@@ -405,13 +405,13 @@
 showFilterExpression
   :: ([R.Chunk] -> IO ())
   -> ShowExpression
-  -> Pe.Pdct L.Posting
+  -> Pe.Predbox L.Posting
   -> IO ()
 showFilterExpression ptr (ShowExpression se) pdct =
   if not se
   then return ()
   else ptr $ info : blankLine :
-             (Pe.showPdct indentAmt 0 pdct ++ [blankLine])
+             (Pe.showPredbox indentAmt 0 pdct ++ [blankLine])
   where
     info = "Posting filter expression:\n"
 
diff --git a/minimum-versions.txt b/minimum-versions.txt
--- a/minimum-versions.txt
+++ b/minimum-versions.txt
@@ -1,11 +1,11 @@
 This package was tested to work with these dependency
 versions and compiler version.
 These are the minimum versions given in the .cabal file.
-Tested as of: 2014-03-08 16:59:06.573315 UTC
+Tested as of: 2014-04-16 17:16:55.729949 UTC
 Path to compiler: ghc-7.4.1
 Compiler description: 7.4.1
 
-/opt/ghc/7.4.1/lib/ghc-7.4.1/package.conf.d:
+/var/lib/ghc/package.conf.d:
     Cabal-1.14.0
     array-0.4.0.0
     base-4.5.0.0
@@ -33,34 +33,44 @@
     time-1.4
     unix-2.5.1.0
 
-/home/massysett/penny/sunlight-15431/db:
+/home/massysett/penny/sunlight-10948/db:
     MonadRandom-0.1.13
-    QuickCheck-2.5
+    QuickCheck-2.6
     action-permutations-0.0.0.0
     anonymous-sums-0.4.0.0
+    ansi-terminal-0.6.1.1
+    ansi-wl-pprint-0.6.7.1
+    async-2.0.1.5
     cereal-0.3.5.2
     comonad-3.1
-    contravariant-0.4.4
+    contravariant-0.2.0.1
     either-3.4.1
     haskell-lexer-1.0
-    matchers-0.14.0.2
-    mtl-2.1.2
+    matchers-0.18.0.0
+    mtl-2.1.3.1
     multiarg-0.24.0.4
     nats-0.1.2
     ofx-0.4.0.2
+    optparse-applicative-0.8.0.1
     parsec-3.1.3
-    penny-0.32.0.6
-    prednote-0.18.0.4
+    penny-0.32.0.8
+    prednote-0.22.0.2
     pretty-show-1.5
-    rainbow-0.12.0.0
+    rainbow-0.14.0.0
+    rainbox-0.4.0.2
     random-1.0.0.0
     random-shuffle-0.0.4
+    regex-base-0.93.2
+    regex-tdfa-1.2.0
     semigroupoids-3.1
     semigroups-0.9.2
     split-0.2.2
-    tagged-0.7
+    stm-2.4.3
+    tagged-0.7.1
+    tasty-0.8.0.4
+    tasty-quickcheck-0.8
     terminfo-0.4.0.0
-    text-0.11.2.0
+    text-0.11.3.1
     transformers-0.3.0.0
-    transformers-compat-0.1.1.1
+    unbounded-delays-0.1.0.7
 
diff --git a/penny.cabal b/penny.cabal
--- a/penny.cabal
+++ b/penny.cabal
@@ -3,8 +3,8 @@
 -- penny.cabal for you.
 
 Name: penny
-Version: 0.32.0.6
-Cabal-version: >=1.8
+Version: 0.32.0.8
+Cabal-version: >=1.14
 Build-Type: Simple
 License: BSD3
 Copyright: 2012-2014 Omari Norman.
@@ -15,6 +15,7 @@
 bug-reports: omari@smileystation.com
 Category: Console, Finance
 License-File: LICENSE
+tested-with: GHC ==7.4.1, GHC ==7.6.3
 
 synopsis: Extensible double-entry accounting system
 
@@ -39,6 +40,7 @@
   , current-versions.txt
   , minimum-versions.txt
   , penny.cabal.m4
+  , changelog
 
 source-repository head
   type: git
@@ -47,37 +49,39 @@
 Library
 
   Build-depends:
-      base >= 4.5.0.0 && < 5
+      base >= 4.5.0.0 && < 4.7
 
     -- Do not try to put comments on same line as data; Cabal does
     -- not allow this.
 
     -- Package                  Version
-    , bytestring                >= 0.9.2.1
-    , containers                >= 0.4.2.1
-    , old-locale                >= 1.0.0.4
-    , parsec                    >= 3.1.3
-    , split                     >= 0.2.2
-    , text                      >= 0.11.2.0
-    , time                      >= 1.4
+    , bytestring                >= 0.9.2.1              && < 0.11
+    , containers                >= 0.4.2.1              && < 0.6
+    , old-locale                >= 1.0.0.4              && < 1.1
+    , parsec                    >= 3.1.3                  && < 3.2
+    , split                     >= 0.2.2                   && < 0.3
+    , text                      >= 0.11.3.1                    && < 1.2
+    , time                      >= 1.4                    && < 1.5
     , transformers              >= 0.3.0.0
 
     -- Omari packages
     -- Package                  Version
     , anonymous-sums            >= 0.4.0.0
-    , matchers                  >= 0.14.0.2                && < 0.15.0.0
-    , multiarg                  >= 0.24.0.4                && < 0.25.0.0
-    , ofx                       >= 0.4.0.2
-    , prednote                  >= 0.18.0.4                && < 0.19.0.0
-    , rainbow                   >= 0.12.0.0
+    , matchers                  >= 0.18.0.0                && < 0.19
+    , multiarg                  >= 0.24.0.4                && < 0.27.0.0
+    , ofx                       >= 0.4.0.2                     && < 0.5
+    , prednote                  >= 0.22.0.2                && < 0.23
+    , rainbow                   >= 0.14.0.0                 && < 0.15.0.0
+    , rainbox                   >= 0.4.0.2                 && < 0.5
 
     -- Other packages
     -- Package                  Version
-    , action-permutations       == 0.0.0.0
-    , cereal                    >= 0.3.5.2
-    , either                    >= 3.4.1
-    , pretty-show               >= 1.5
-    , semigroups                >= 0.9.2
+    , action-permutations       >= 0.0.0.0     && < 0.0.0.2
+    , cereal                    >= 0.3.5.2                  && < 0.5
+    , contravariant             >= 0.2.0.1           && < 0.5
+    , either                    >= 3.4.1                  && < 4.2
+    , pretty-show               >= 1.5             && < 1.7
+    , semigroups                >= 0.9.2              && < 0.14
 
   Exposed-modules:
       Penny
@@ -166,6 +170,7 @@
   ghc-options: -Wall
   if flag(debug)
     ghc-options: -auto-all -caf-all
+  default-language: Haskell2010
 
 Test-Suite penny-test
   type: exitcode-stdio-1.0
@@ -178,26 +183,27 @@
     , Copper.Render
     , Lincoln
   hs-source-dirs: tests
+  default-language: Haskell2010
 
   -- For details on why penny is a dependency here, see
   -- http://stackoverflow.com/questions/6711151
 
   build-depends:
-      penny           == 0.32.0.6
-    , base            >= 4.5.0.0 && < 5
+      penny           == 0.32.0.8
+    , base            >= 4.5.0.0                              && < 4.7
 
     -- Packages I maintain
-    , multiarg        >= 0.24.0.4                          && < 0.25.0.0
-    , anonymous-sums  >= 0.4.0.0
+    , multiarg        >= 0.24.0.4                          && < 0.27.0.0
+    , anonymous-sums  >= 0.4.0.0                    && < 0.5
 
     -- Other packages
-    , QuickCheck      >= 2.5
-    , random-shuffle  >= 0.0.4
-    , parsec          >= 3.1.3
-    , semigroups      >= 0.9.2
-    , text            >= 0.11.2.0
-    , time            >= 1.4
-    , transformers    >= 0.3.0.0
+    , QuickCheck      >= 2.6                        && < 2.7
+    , random-shuffle  == 0.0.4
+    , parsec          >= 3.1.3                            && < 3.2
+    , semigroups      >= 0.9.2                        && < 0.14
+    , text            >= 0.11.3.1                              && < 1.2
+    , time            >= 1.4                              && < 1.5
+    , transformers    >= 0.3.0.0                      && < 0.4
 
   ghc-options: -Wall
 
@@ -207,23 +213,24 @@
       Copper.Gen.Parsers
     , Copper.Gen.Terminals
   hs-source-dirs: tests
+  default-language: Haskell2010
 
   if flag(build-gibberish)
     build-depends:
-          penny           == 0.32.0.6
-        , base            >= 4.5.0.0 && < 5
+          penny           == 0.32.0.8
+        , base            >= 4.5.0.0                          && < 4.7
 
         -- Packages I maintain
-        , multiarg        >= 0.24.0.4                      && < 0.25.0.0
+        , multiarg        >= 0.24.0.4                      && < 0.27.0.0
 
         -- Other packages
-        , QuickCheck      >= 2.5
-        , random-shuffle  >= 0.0.4
-        , random          >= 1.0.0.0
-        , semigroups      >= 0.9.2
-        , text            >= 0.11.2.0
-        , time            >= 1.4
-        , transformers    >= 0.3.0.0
+        , QuickCheck      >= 2.6                    && < 2.7
+        , random-shuffle  == 0.0.4
+        , random          >= 1.0.0.0                        && < 1.1
+        , semigroups      >= 0.9.2                    && < 0.14
+        , text            >= 0.11.3.1                          && < 1.2
+        , time            >= 1.4                          && < 1.5
+        , transformers    >= 0.3.0.0                  && < 0.4
 
   else
     buildable: False
@@ -236,13 +243,14 @@
 
 Executable penny
   Build-depends:
-      penny ==0.32.0.6
-    , base >= 4.5.0.0 && < 5
+      penny ==0.32.0.8
+    , base >= 4.5.0.0                                         && < 4.7
 
   hs-source-dirs: bin
   Main-is: penny-main.hs
   Other-modules: Paths_penny
   GHC-Options: -Wall
+  default-language: Haskell2010
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
 
@@ -255,12 +263,13 @@
 
 Executable penny-selloff
   Build-depends:
-      penny == 0.32.0.6
-    , base >= 4.5.0.0 && < 5
+      penny == 0.32.0.8
+    , base >= 4.5.0.0                                         && < 4.7
 
   other-modules: Paths_penny
   hs-source-dirs: bin
   Main-is: penny-selloff.hs
+  default-language: Haskell2010
   GHC-Options: -Wall
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
@@ -274,13 +283,14 @@
 
 Executable penny-diff
   Build-depends:
-      penny == 0.32.0.6
-    , base >= 4.5.0.0 && < 5
+      penny == 0.32.0.8
+    , base >= 4.5.0.0                                         && < 4.7
 
   hs-source-dirs: bin
   Main-is: penny-diff.hs
   Other-modules: Paths_penny
   GHC-Options: -Wall
+  default-language: Haskell2010
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
 
@@ -293,13 +303,14 @@
 
 Executable penny-reprint
   Build-depends:
-      penny == 0.32.0.6
-    , base >= 4.5.0.0 && < 5
+      penny == 0.32.0.8
+    , base >= 4.5.0.0                                         && < 4.7
 
   hs-source-dirs: bin
   main-is: penny-reprint.hs
   Other-modules: Paths_penny
   ghc-options: -Wall
+  default-language: Haskell2010
   if ! flag(build-reprint)
     buildable: False
 
@@ -309,11 +320,12 @@
 
 Executable penny-reconcile
   Build-depends:
-      penny == 0.32.0.6
-    , base >= 4.5.0.0 && < 5
+      penny == 0.32.0.8
+    , base >= 4.5.0.0                                         && < 4.7
 
   hs-source-dirs: bin
   main-is: penny-reconcile.hs
+  default-language: Haskell2010
   Other-modules: Paths_penny
   ghc-options: -Wall
   if ! flag(build-reconcile)
diff --git a/penny.cabal.m4 b/penny.cabal.m4
--- a/penny.cabal.m4
+++ b/penny.cabal.m4
@@ -4,7 +4,7 @@
 
 Name: penny
 Version: pv_penny
-Cabal-version: >=1.8
+Cabal-version: >=1.14
 Build-Type: Simple
 License: BSD3
 Copyright: 2012-2014 Omari Norman.
@@ -15,6 +15,7 @@
 bug-reports: omari@smileystation.com
 Category: Console, Finance
 License-File: LICENSE
+tested-with: GHC ==7.4.1, GHC ==7.6.3
 
 synopsis: Extensible double-entry accounting system
 
@@ -39,6 +40,7 @@
   , current-versions.txt
   , minimum-versions.txt
   , penny.cabal.m4
+  , changelog
 
 source-repository head
   type: git
@@ -53,13 +55,13 @@
     -- not allow this.
 
     -- Package                  Version
-    , bytestring                >= pv_bytestring
-    , containers                >= pv_containers
-    , old-locale                >= pv_old_locale
-    , parsec                    >= pv_parsec
-    , split                     >= pv_split
-    , text                      >= pv_text
-    , time                      >= pv_time
+    , bytestring                >= pv_bytestring              && < pv_bytestring_max
+    , containers                >= pv_containers              && < pv_containers_max
+    , old-locale                >= pv_old_locale              && < pv_old_locale_max
+    , parsec                    >= pv_parsec                  && < pv_parsec_max
+    , split                     >= pv_split                   && < pv_split_max
+    , text                      >= pv_text                    && < pv_text_max
+    , time                      >= pv_time                    && < pv_time_max
     , transformers              >= pv_transformers
 
     -- Omari packages
@@ -67,17 +69,19 @@
     , anonymous-sums            >= pv_anonymous_sums
     , matchers                  >= pv_matchers                && < pv_matchers_max
     , multiarg                  >= pv_multiarg                && < pv_multiarg_max
-    , ofx                       >= pv_ofx
+    , ofx                       >= pv_ofx                     && < pv_ofx_max
     , prednote                  >= pv_prednote                && < pv_prednote_max
-    , rainbow                   >= pv_rainbow
+    , rainbow                   >= pv_rainbow                 && < pv_rainbow_max
+    , rainbox                   >= pv_rainbox                 && < pv_rainbox_max
 
     -- Other packages
     -- Package                  Version
-    , action-permutations       == pv_action_permutations
-    , cereal                    >= pv_cereal
-    , either                    >= pv_either
-    , pretty-show               >= pv_pretty_show
-    , semigroups                >= pv_semigroups
+    , action-permutations       >= pv_action_permutations     && < pv_action_permutations_max
+    , cereal                    >= pv_cereal                  && < pv_cereal_max
+    , contravariant             >= pv_contravariant           && < pv_contravariant_max
+    , either                    >= pv_either                  && < pv_either_max
+    , pretty-show               >= pv_pretty_show             && < pv_pretty_show_max
+    , semigroups                >= pv_semigroups              && < pv_semigroups_max
 
   Exposed-modules:
       Penny
@@ -166,6 +170,7 @@
   ghc-options: -Wall
   if flag(debug)
     ghc-options: -auto-all -caf-all
+  default-language: Haskell2010
 
 Test-Suite penny-test
   type: exitcode-stdio-1.0
@@ -178,26 +183,27 @@
     , Copper.Render
     , Lincoln
   hs-source-dirs: tests
+  default-language: Haskell2010
 
   -- For details on why penny is a dependency here, see
   -- http://stackoverflow.com/questions/6711151
 
   build-depends:
       penny           == pv_penny
-    , base            >= pv_base && < pv_base_max
+    , base            >= pv_base                              && < pv_base_max
 
     -- Packages I maintain
     , multiarg        >= pv_multiarg                          && < pv_multiarg_max
-    , anonymous-sums  >= pv_anonymous_sums
+    , anonymous-sums  >= pv_anonymous_sums                    && < pv_anonymous_sums_max
 
     -- Other packages
-    , QuickCheck      >= pv_QuickCheck
-    , random-shuffle  >= pv_random_shuffle
-    , parsec          >= pv_parsec
-    , semigroups      >= pv_semigroups
-    , text            >= pv_text
-    , time            >= pv_time
-    , transformers    >= pv_transformers
+    , QuickCheck      >= pv_QuickCheck                        && < pv_QuickCheck_max
+    , random-shuffle  == pv_random_shuffle
+    , parsec          >= pv_parsec                            && < pv_parsec_max
+    , semigroups      >= pv_semigroups                        && < pv_semigroups_max
+    , text            >= pv_text                              && < pv_text_max
+    , time            >= pv_time                              && < pv_time_max
+    , transformers    >= pv_transformers                      && < pv_transformers_max
 
   ghc-options: -Wall
 
@@ -207,23 +213,24 @@
       Copper.Gen.Parsers
     , Copper.Gen.Terminals
   hs-source-dirs: tests
+  default-language: Haskell2010
 
   if flag(build-gibberish)
     build-depends:
           penny           == pv_penny
-        , base            >= pv_base && < pv_base_max
+        , base            >= pv_base                          && < pv_base_max
 
         -- Packages I maintain
         , multiarg        >= pv_multiarg                      && < pv_multiarg_max
 
         -- Other packages
-        , QuickCheck      >= pv_QuickCheck
-        , random-shuffle  >= pv_random_shuffle
-        , random          >= pv_random
-        , semigroups      >= pv_semigroups
-        , text            >= pv_text
-        , time            >= pv_time
-        , transformers    >= pv_transformers
+        , QuickCheck      >= pv_QuickCheck                    && < pv_QuickCheck_max
+        , random-shuffle  == pv_random_shuffle
+        , random          >= pv_random                        && < pv_random_max
+        , semigroups      >= pv_semigroups                    && < pv_semigroups_max
+        , text            >= pv_text                          && < pv_text_max
+        , time            >= pv_time                          && < pv_time_max
+        , transformers    >= pv_transformers                  && < pv_transformers_max
 
   else
     buildable: False
@@ -237,12 +244,13 @@
 Executable penny
   Build-depends:
       penny ==pv_penny
-    , base >= pv_base && < pv_base_max
+    , base >= pv_base                                         && < pv_base_max
 
   hs-source-dirs: bin
   Main-is: penny-main.hs
   Other-modules: Paths_penny
   GHC-Options: -Wall
+  default-language: Haskell2010
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
 
@@ -256,11 +264,12 @@
 Executable penny-selloff
   Build-depends:
       penny == pv_penny
-    , base >= pv_base && < pv_base_max
+    , base >= pv_base                                         && < pv_base_max
 
   other-modules: Paths_penny
   hs-source-dirs: bin
   Main-is: penny-selloff.hs
+  default-language: Haskell2010
   GHC-Options: -Wall
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
@@ -275,12 +284,13 @@
 Executable penny-diff
   Build-depends:
       penny == pv_penny
-    , base >= pv_base && < pv_base_max
+    , base >= pv_base                                         && < pv_base_max
 
   hs-source-dirs: bin
   Main-is: penny-diff.hs
   Other-modules: Paths_penny
   GHC-Options: -Wall
+  default-language: Haskell2010
   if flag(debug)
     GHC-Options: -rtsopts -auto-all -caf-all
 
@@ -294,12 +304,13 @@
 Executable penny-reprint
   Build-depends:
       penny == pv_penny
-    , base >= pv_base && < pv_base_max
+    , base >= pv_base                                         && < pv_base_max
 
   hs-source-dirs: bin
   main-is: penny-reprint.hs
   Other-modules: Paths_penny
   ghc-options: -Wall
+  default-language: Haskell2010
   if ! flag(build-reprint)
     buildable: False
 
@@ -310,10 +321,11 @@
 Executable penny-reconcile
   Build-depends:
       penny == pv_penny
-    , base >= pv_base && < pv_base_max
+    , base >= pv_base                                         && < pv_base_max
 
   hs-source-dirs: bin
   main-is: penny-reconcile.hs
+  default-language: Haskell2010
   Other-modules: Paths_penny
   ghc-options: -Wall
   if ! flag(build-reconcile)
diff --git a/versions.m4 b/versions.m4
--- a/versions.m4
+++ b/versions.m4
@@ -1,39 +1,37 @@
 divert(-1)
 
 # Penny version
-define(`pv_penny', `0.32.0.6')
+define(`pv_penny', `0.32.0.8')
 
 # Haskell Platform
-define(`pv_base', `4.5.0.0')
-define(`pv_base_max', `5')
-define(`pv_bytestring', `0.9.2.1')
-define(`pv_containers', `0.4.2.1')
-define(`pv_old_locale', `1.0.0.4')
-define(`pv_parsec', `3.1.3')
-define(`pv_QuickCheck', `2.5')
-define(`pv_split', `0.2.2')
-define(`pv_text', `0.11.2.0')
-define(`pv_time', `1.4')
-define(`pv_transformers', `0.3.0.0')
+define(`pv_base', `4.5.0.0')                      define(`pv_base_max', `4.7')
+define(`pv_bytestring', `0.9.2.1')                define(`pv_bytestring_max', `0.11')
+define(`pv_containers', `0.4.2.1')                define(`pv_containers_max', `0.6')
+define(`pv_old_locale', `1.0.0.4')                define(`pv_old_locale_max', `1.1')
+define(`pv_parsec', `3.1.3')                      define(`pv_parsec_max', `3.2')
+define(`pv_QuickCheck', `2.6')                    define(`pv_QuickCheck_max', `2.7')
+define(`pv_split', `0.2.2')                       define(`pv_split_max', `0.3')
+define(`pv_text', `0.11.3.1')                     define(`pv_text_max', `1.2')
+define(`pv_time', `1.4')                          define(`pv_time_max', `1.5')
+define(`pv_transformers', `0.3.0.0')              define(`pv_transformers_max', `0.4')
 
 # Packages I maintain
-define(`pv_anonymous_sums', `0.4.0.0')
-define(`pv_matchers', `0.14.0.2')
-define(`pv_matchers_max', `0.15.0.0')
-define(`pv_multiarg', `0.24.0.4')
-define(`pv_multiarg_max', `0.25.0.0')
-define(`pv_ofx', `0.4.0.2')
-define(`pv_prednote', `0.18.0.4')
-define(`pv_prednote_max', `0.19.0.0')
-define(`pv_rainbow', `0.12.0.0')
+define(`pv_anonymous_sums', `0.4.0.0')            define(`pv_anonymous_sums_max', `0.5')
+define(`pv_matchers', `0.18.0.0')                 define(`pv_matchers_max', `0.19')
+define(`pv_multiarg', `0.24.0.4')                 define(`pv_multiarg_max', `0.27.0.0')
+define(`pv_ofx', `0.4.0.2')                       define(`pv_ofx_max', `0.5')
+define(`pv_prednote', `0.22.0.2')                 define(`pv_prednote_max', `0.23')
+define(`pv_rainbow', `0.14.0.0')                  define(`pv_rainbow_max', `0.15.0.0')
+define(`pv_rainbox', `0.4.0.2')                   define(`pv_rainbox_max', `0.5')
 
 # Other packages
-define(`pv_action_permutations', `0.0.0.0')
-define(`pv_cereal', `0.3.5.2')
-define(`pv_either', `3.4.1')
-define(`pv_pretty_show', `1.5')
-define(`pv_random', `1.0.0.0')
+define(`pv_contravariant', `0.2.0.1')             define(`pv_contravariant_max', `0.5')
+define(`pv_action_permutations', `0.0.0.0')       define(`pv_action_permutations_max', `0.0.0.2')
+define(`pv_cereal', `0.3.5.2')                    define(`pv_cereal_max', `0.5')
+define(`pv_either', `3.4.1')                      define(`pv_either_max', `4.2')
+define(`pv_pretty_show', `1.5')                   define(`pv_pretty_show_max', `1.7')
+define(`pv_random', `1.0.0.0')                    define(`pv_random_max', `1.1')
 define(`pv_random_shuffle', `0.0.4')
-define(`pv_semigroups', `0.9.2')
+define(`pv_semigroups', `0.9.2')                  define(`pv_semigroups_max', `0.14')
 
 divert(1)dnl
