diff --git a/Seqaid/Config.hs b/Seqaid/Config.hs
--- a/Seqaid/Config.hs
+++ b/Seqaid/Config.hs
@@ -49,7 +49,7 @@
 --
 -- More documentation is pending, but for additional explanations
 -- about this particular example, please refer to
--- <http://www.fremissant.net/seqaid/seqaid.html#using this document>.
+-- <http://www.fremissant.net/seqaid#using this document>.
 
   module Seqaid.Config where
 
diff --git a/Seqaid/Demo.hs b/Seqaid/Demo.hs
--- a/Seqaid/Demo.hs
+++ b/Seqaid/Demo.hs
@@ -16,10 +16,22 @@
 -- <http://hackage.haskell.org/package/deepseq-bounded deepseq-bounded>
 -- for more information about this methodology.
 
+#ifdef mingw32_HOST_OS
+#define USE_DOS 0
+#else
+#if IS_WINDOWS
+#define USE_DOS 1
+#else
+#define USE_DOS 0
+#endif
+#endif
+
   module Main ( main ) where
 --module Seqaid.Demo ( main ) where
 
   import System.Environment ( getArgs )
+  import System.IO ( hGetContents, hClose )
+  import Control.Exception ( evaluate )
   import qualified System.IO.Temp as T
   import qualified System.Directory as D
   import System.Process
@@ -29,61 +41,122 @@
   import Data.Version
   import Data.List ( intercalate )
 
-  leaky_version = (intercalate "." $ map show $ take 3 $ versionBranch version) ++ ".0"
---leaky_version = "0.1.6.0"  -- XXX need a better way!!....
+#if USE_DOS
+  -- Not using the constraint, because requires performing regex
+  -- on the output of a system command.  I'd like to provide the
+  -- demo for non-mingw32 Windows users, but I have no means of
+  -- testing that (or mingw32 for that matter).  Hopefully what's
+  -- here works (presuming there's even such a thing as Haskell
+  -- on Windows without mingw32).
+  leaky_hard_version_windows
+   = (intercalate "." $ map show $ take 3 $ versionBranch version) ++ ".0"
+-- = "0.1.6.0"  -- XXX need a better way!!....
+#else
+  leaky_constraint
+   = let vlo = take 3 $ versionBranch version
+         vhi = take 2 vlo ++ [1 + last vlo]
+     in    "'leaky >= "
+        ++ (intercalate "." $ map show vlo)
+        ++ " && < "
+        ++ (intercalate "." $ map show vhi)
+        ++ "'"
+#endif
 
   main :: IO ExitCode
   main = do
 --          putStrLn $ leaky_version
 --          error "DEVEXIT"
             args <- getArgs
+
             if args /= ["demo"]
             then do
               putStrLn "seqaid: \"seqaid demo\" is the only supported invocation at this time."
               return $ ExitFailure 1
             else do
+
               tdir <- T.createTempDirectory "." "leaky_"
--- XXX Note that "cabal get" already extracts the tarball for you.
--- XXX Note mingw32 still uses bash.
-              let dos_str = concat
-                   [ "@echo off\n"
-                   , "cabal get leaky-" ++ leaky_version ++ "\n"
-                   , "cd leaky-" ++ leaky_version ++ "\n"
-                   , "cabal configure\n"
-                   , "cabal build\n"
-                   , "cabal run 234\n"
-                   , "echo.\n"
-                   , "echo \"(Please see " ++ tdir ++ "/leaky-" ++ leaky_version ++ "/README for the interpretation.)\"\n"
-                   , "echo.\n"
-                   ]
+              D.setCurrentDirectory tdir
 
-              let nix_str = concat
-                   [ "#!/bin/bash\nset -e\n" ++ ""
-                   , "cabal get leaky-" ++ leaky_version ++ "\n"
-                   , "cd leaky-" ++ leaky_version ++ "\n"
-                   , "cabal configure\n"
-                   , "cabal build\n"
-                   , "cabal run 234\n"
-                   , "echo\n"
-                   , "echo \"(Please see " ++ tdir ++ "/leaky-" ++ leaky_version ++ "/README for the interpretation.)\"\n"
-                   , "echo\n"
+#if ! USE_DOS
+
+              -- Find the most recent available version of package leaky
+              -- which satisfies the constraint computed above.  (We use
+              -- cabal-install to do this for us.)
+              let command_to_resolve_constraint_for_get
+                   =    "#!/bin/bash\nset -e\n"
+                     ++ "cabal install leaky --dry-run --constraint="
+                     ++ leaky_constraint
+                     ++ " | tail -1"
+--                   ++ " | grep -e '^leaky-'"
+                     ++ " | sed -e 's/\\([^ ][^ ]*\\)\\($|..*\\)/\\1/'"
+                     ++ "\n"  -- so file ends with EOL (good practice)
+
+              writeFile "seqaidresolveleaky.sh" command_to_resolve_constraint_for_get
+              p <- D.getPermissions "seqaidresolveleaky.sh"
+              D.setPermissions
+                 "seqaidresolveleaky.sh" p { D.executable = True }
+              -- not sure how to handle exit status this way
+              (_, Just hout, _, _)
+                <- createProcess (proc "seqaidresolveleaky.sh" [])
+                                   { std_out = CreatePipe }
+              resolved <- hGetContents hout
+              evaluate $ length resolved  -- force reading of whole file!
+              hClose hout
+
+#endif
+
+#if USE_DOS
+
+-- XXX Note that "cabal get" already extracts the tarball for you.
+-- XXX Note mingw32 uses bash (not DOS/CMD).
+              let dos_str = intercalate "\n"
+                   [ "@echo off"
+                   , "cabal get leaky-" ++ leaky_hard_version_windows
+                   , "cd leaky-" ++ leaky_hard_version_windows
+                   , "cabal configure"
+                   , "cabal build"
+                   , "cabal run 234"
+                   , "echo."
+                   , "echo \"(Please see " ++ tdir ++ "/leaky-" ++ leaky_hard_version_windows ++ "/README for the interpretation.)\""
+                   , "echo."
+                   , ""  -- so file ends with EOL (good practice)
                    ]
 
-#ifdef mingw32_HOST_OS
-              let seqaid_init_bash = nix_str
 #else
-#if IS_WINDOWS
-              let seqaid_init_bash = dos_str
+
+              let nix_str = intercalate "\n"
+                   [ "#!/bin/bash\nset -e"
+#if 1
+                   , "cabal get " ++ resolved
+                   , "cd " ++ resolved
 #else
-              let seqaid_init_bash = nix_str
+                   , "cabal get leaky --constraint \"" ++ leaky_constraint ++ "\""  -- sadly not
+                   , "cd leaky-*"
 #endif
+                   , "cabal configure"
+                   , "cabal build"
+                   , "cabal run 234"
+                   , "echo"
+                   , "echo \"(Please see " ++ tdir ++ "/" ++ resolved ++ "/README for the interpretation.)\""
+--                 , "echo \"(Please see " ++ tdir ++ "/*" ++ "/README for the interpretation.)\""
+                   , "echo"
+                   , ""  -- so file ends with EOL (good practice)
+                   ]
+
 #endif
 
-              D.setCurrentDirectory tdir
-              writeFile "seqaidinit.sh" seqaid_init_bash
-              p <- D.getPermissions "seqaidinit.sh"
-              D.setPermissions "seqaidinit.sh" (p { D.executable = True })
-              st <- system "./seqaidinit.sh"
+#if USE_DOS
+              let seqaid_init_script_contents = dos_str
+              let seqaid_init_script_name = "seqaidinit.bat"
+#else
+              let seqaid_init_script_contents = nix_str
+              let seqaid_init_script_name = "seqaidinit.sh"
+#endif
+
+              writeFile seqaid_init_script_name seqaid_init_script_contents
+              p <- D.getPermissions seqaid_init_script_name
+              D.setPermissions seqaid_init_script_name p { D.executable = True }
+              st <- system $ "./" ++ seqaid_init_script_name
               case st of
                 ExitSuccess -> return ExitSuccess
                 ExitFailure n -> do
diff --git a/Seqaid/Global.hs b/Seqaid/Global.hs
--- a/Seqaid/Global.hs
+++ b/Seqaid/Global.hs
@@ -8,21 +8,6 @@
 
   {-# LANGUAGE CPP #-}
 
--- Later: This (now) has no effect when new grammar is in effect.
--- This is temporary, so seqaid demo output remains compatible
--- with the documentation already written around it.  (The new
--- shrinkPat has more finesse, but you have to run the demo
--- longer to see the heap stabilise -- the demonstration is
--- not nearly as effective.  Also, the patterns have a lot
--- of #'s in them which looks noisy and confusing, although
--- it's natural enough.)  We could attempt vertical alignment
--- since flanking whitespace is now supported, and that would
--- do more than anything to improve the presentation...
--- However, with DEMO_MODE off, one would definitely prefer
--- the new shrinkPat.  This comment will probably be
--- as writ on water...
-#define USE_OLD_SHRINK_PAT 0
-
 -- XXX Should scour the code for "max_depth" etc. -- all those
 -- names which are specific to this DEMO_MODE hack!... And get
 -- them into CPP guards. And get something sane in the OTHER
@@ -41,7 +26,7 @@
 --
 -- Maintainer  :  Andrew Seniuk <rasfar@gmail.com>
 -- Stability   :  provisional
--- Portability :  GHC
+-- Portability :  GHC (uses global IORefs)
 --
 -- Collects 'IORef's used by the seqaid runtime.
 --
@@ -206,102 +191,16 @@
   fixed_pat_sequence
    = let shrink_pat
           | deepseq_bounded_flag__new_improved_pattern_grammar  = shrinkPat
-#if USE_OLD_SHRINK_PAT
-          | otherwise  = shrinkPat_old
-#else
           | otherwise  = shrinkPat
-#endif
      in    ( map (\i -> compilePat ('*':show i)) [0,1..8] )
         ++ ( reverse $ condenseEq shrink_pat fixed_pat )
 
--- [Debugging notes for recent changes to deepseq-bounded.]
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 0 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 1 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 3 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 7 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 12 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 13 Int\n()\n"
--- leaky: DeepSeqBounded_PingException "NFDataP: PING: 14 Int\n()\n"
--- This is what we see. If wait (only see 0 repeating for a while).
--- (And the system grinds to a crawl, although it appears to be
--- a stable crawl.)
------
--- See cotemp (20150111130916) 000-readme for the labelling of the tree...
--- This mystery is largely solved. As for "slowdown" well, it's no
--- wonder if we're trying to print something for every one of the
--- gizillion exceptions, but if it was a quick stats update or something,
--- might actually be fine at full speed...
--- Speaking of "speed", a threadDelay-type attribute would be useful...
--- Too useful not to do it! (Except that threadDelay is known to be
--- a bit flakey...). (But you gotta try...)
-#if 1
   fixed_pat
    | deepseq_bounded_flag__new_improved_pattern_grammar
       = setPatternPatNodeUniqueIDs 0 $
---        compilePat "=>cab((!(!)(((^!).!(!))))!(^!(!)))"
---        compilePat "=>cab((!(!)(((+!).!(!))))!(+!(!)))"
---        compilePat "((!(!)(((+^/!).!(!))))!(!(!)))"
---        compilePat "((!(!)(((+^!).!(!))))!(!(!)))"
---        compilePat "+^(+^(+^!+^(+^/!)+^/(+^/(+^/(+^/!)+^/.+^/!+^/(+^/!))))+^/!+^/(+^/!+^/(+^/!)))"
---        compilePat "+^/(+^/(+^/!+^/(+^/!)+^/(+^/(+^/(+^/!)+^/.+^/!+^/(+^/!))))+^/!+^/(+^/!+^/(+^/!)))"
---        compilePat "+^(+^(+^!+^(+^!)+^(+^(+^(+^!)+^.+^!+^(+^!))))+^!+^(+^!+^(+^!)))"
---        compilePat "((!(!)+(+(+(+!).!(!))))!(!(!)))"  -- yes, it works (if you wait a wee bit) -- trying the full-blanket-+'d one again!!!
---        compilePat "((!(!)(((+!).!(!))))!+(!(!)))"  -- 
---        compilePat "((!(!)((+(+!).!(!))))!(!(!)))"  -- ACTUALLY WORKS -- at FIRST you see only TC, then after the next stats line you see "4 TC / 3 Int" (or maybe the other way around, but I think this is the order...)
---        compilePat "((!(!)(((+!).!(!))))!(!(!)))"  -- still works
--- XXX Oh, I see what happened: I made !(!) -> . at some point,
--- as part of testing, and this got propagated and forgotten,
--- and changed back . -> ! (instead of !(!)) -- but this is
--- harmless actually?!!!
---        compilePat "((!(!)(((+^!)+^/.!(!))))!(!(!)))"
---        compilePat "((!+^/.(((!)+^/.!(!))))!(!(!)))"  -- nothing.
---        compilePat "+(+(+!+(+!)+(+(+(+!).!(!))))!(!(!)))"   -- XXX XXX
---        compilePat "(+(!+.(+((!)+.!(!))))!(!(!)))"
-----      compilePat "((!(!)((+.(!)+.+!(!))))!(!(!)))"
------     compilePat "+(+(+!+!+(+(+(+!).!(!))))!(!(!)))"      -- XXX XXX
---        compilePat "+(+(+!+(+!)+(+(+(+!).!(!))))!(!(!)))"   -- XXX XXX
---        compilePat "((+!^(!)(+((!).+^!/^(+^!))))!(!(!)))"  -- yep
---        compilePat "((+!^(!)(+((!).+^!^(+^!))))!(!(!)))"  -- all working
- --       compilePat "((!(+^/.)(((!)+^/.!+^/.)))!(!(!)))"  -- nothing
---        compilePat "((!(/.)(((!)/.!/.)))!(!(!)))"  -- nothing
----       compilePat "((!/.(((!)/.!(!))))!(!(!)))"  -- nope, neither calls handleAttrs (incididentally, this leaks noticeably and monotonically, while the one with just . on the Blob, if not technically leak-free [? it seems to accumulate heap and then periodically discharge it, notwithstanding our frequent performGC calls...], at least not exhibiting net growth over longrunning...)  This is a better test at the moment as the first . is of simple base nullary type Int.
---        compilePat "((!(!)(((!)/.!(!))))!(!(!)))"  -- the problem with this test is that the .'d node is of unusual type Blob, which has hack NFData instances etc...
----       compilePat "((!+.(((!)+.+!(!))))+!(!(+!)))"
----       compilePat "((+!+.((+(+!)+.!(!))))+!(!(+!)))"
----       compilePat "((!+.(((!)+.!(!))))!(!(!)))"
----       compilePat "((!.(((!)+.!(!))))!(!(!)))"
----       compilePat "((!.(((!)+.!(!))))!(!(!)))"
---        compilePat "((!(!)(((!)+.!(!))))!(!(!)))"
---        compilePat "+(+(+!+(+!)+(+(+(+!)+.+!+(+!))))+!+(+!+(+!)))"  -- this is working now for generic nodes, but NOT for any of the others; so we see it for exactly the OTHER 9 nodes not among the 8 listed below! ch!... [later: fixed GNFDataP]
---        compilePat "^(^(^!^(^!)^(^(^(^!)^.^!^(^!))))^!^(^!^(^!)))"  -- AMAZINGLY WORKS!!! See IDs 0 1 3 7 12 13 14
---        compilePat "((!(!)(((^!).!(!))))!(!(!)))"  -- works
---        compilePat "((!(!)(((!).^!(!))))!(!(!)))"  -- NO WORKY: FREEZES (same)
-#if 0
--- (Reproducible serious bug!)
---        compilePat "((!(!)(((!).+!(!))))!(!(!)))"  -- NO WORKY: FREEZES
-                                                     -- AFTER "trc msg.":
----  P  (( ()((() + ()))) ( ()))              duty       918272    8720160  TA
----  P  ((!(!)(((!) +!(!))))!(!(!)))          duty      1660356    2185992  TA
----  P  ((!(!)(((!) +!(!))))!(!(!)))          duty      2348988    2244528  TA
----  P  ((!(!)(((!) +!(!))))!(!(!)))          duty      3037620    2240528  TA
----  P  ((!(!)(((!) +!(!))))!(!(!)))          duty      3693484    2207760  TA
---- trc msg.
---- ^C
-#endif
---        compilePat "((!(!)(((!)+.!(!))))!(!(!)))"  -- NO WORKY
---        compilePat "((!(!)(((+!).!(+!))))!(!(!)))"  -- works! "(TRACE: 3 Int) (TRACE: 7 Int)" repeating
---        compilePat "((!(!)(((!).!(+!))))!(!(!)))"  -- works! "(TRACE: 7 Int)"
---        compilePat "((!(!)(((!)+^/.!(!))))!(!(!)))"  -- no worky!
---        compilePat "(+^/(!(!)(((!).!(!))))!(!(!)))"  -- no worky
---        compilePat "(+(!(!)(((!).!(!))))!(!(!)))"  -- no worky
---        compilePat "(+(!(!)(((+!).!(!))))!(!(!)))"
---        compilePat "((!(!)(((+!).!(!))))!(!(!)))"  -- works! "(TRACE: 3 Int)"
           compilePat "((!(!)(((!).!(!))))!(!(!)))"
    | otherwise
       = compilePat ".{.{..{.}.{.{.{.}#..{.}}}}..{..{.}}}"
-#else
-  fixed_pat = compilePat ".{.{..{.}.{.{.{.}#..{.}}}}..{..{.}}}"
-#endif
 
 -------------------------------------------------------------------------------
 
diff --git a/Seqaid/Optim.hs b/Seqaid/Optim.hs
--- a/Seqaid/Optim.hs
+++ b/Seqaid/Optim.hs
@@ -1,69 +1,6 @@
 
 -------------------------------------------------------------------------------
 
--- Plans
---
--- Try to make the optimiser pure.
---
--- For simplicity, let's assume a steady-state program; this will
--- still be useful with minimal change if need to respond adaptively...
---
--- If you can afford the sum-of-products weighting coefficients,
--- you can get pretty flexible objective functions out of the
--- three main quantities of interest (that I can think of):
---
---   (1) Time.
---       The amount of time elapsed since last checkpoint
---       should preferably not increase.
---
---   (2) Heap size.
---       The size of the live heap since last checkpoint
---       should preferably not increase.
---
---   (3) Bytes allocated (this frame).
---       The amount of GC activity since last checkpoint
---       should preferably not increase.
---
--- Any of these, taken individually (i.e. extremes of the l.c.)
--- would be interesting and useful, but it seems reasonable
--- to expect a non-trivial blend of two, or all, to be
--- most "meta-performant" (best convergence rates).  Or who knows!
---
--- Need to experiment.
---
--- I don't yet have code in place measuring (1); only (2) and (3).
-
--------------------------------------------------------------------------------
-
--- The specific strategy for this next round at least:
--- Two-phase optimisation:
---
---   (1) N-phase : sweep forcen n=0,1,... until either:
---        - gets too costly in Time [once can measure that...]; or
---        - achieve dramatic improvement in objective function (at n' say)
---
---   (2) P-phase : begin with mkPatN n'
---        - forcep . (mkPatN n) = forcen n
---       Then call erodePat (with weighting of choice).
---       keep doing this, accepting steps only if performance
---       improves (rel. to your objective criterion).  Eventually
---       no improvement will be made for a long time -- this is
---       taken as an "approximation to global optimum", and a
---       fresh pass through the P-phase can be used to try
---       additional stochastic trials.
---
--- Also, in principle, you might be better to start mkPatN at
--- an n' higher than the very lowest which plugged leak.
--- This seems a bit unlikely, but I don't know why not...
--- That you might arrive at a better global optimum
--- if you allow some "surplus forcing" at one or more points.
---
--- These are the nagging questions that I'm not sure about,
--- and expect to learn more as begin testing and seqaid on
--- a corpus of programs.
-
--------------------------------------------------------------------------------
-
   {-  OPTIONS_GHC -O2 #-}
 
   {-# LANGUAGE CPP #-}
@@ -100,11 +37,6 @@
 
     optimIO ,
 
-    optim ,
-
-    optim_N_phase ,
-    optim_P_phase ,
-
   ) where
 
 -------------------------------------------------------------------------------
@@ -132,6 +64,10 @@
 
 --import Debug.Trace ( trace )
 
+#if SAI_FORK
+  import Seqaid.Optim_sai
+#endif
+
 -------------------------------------------------------------------------------
 
   import Seqaid.Global ( depth_ioref                  )
@@ -182,132 +118,21 @@
   -- which also takes care of the IORef stuff...
 
 -------------------------------------------------------------------------------
-
-  -- XXX Why is depth global, but patterns is per-site?...
-  -----
-  -- This needs to read the (most recently cached) GHC.Stats data.
-  -- If N-phase, needs to affect the depth_ioref.
-  -- If P-phase, needs to affect the patterns_ioref.
-  -- It could actually have type IO (), but might like to
-  -- return some pertinent information as well.
-  optimIO :: IO ()
---optimIO :: IO (Int,Int,Pattern,SeqNode,Int64,Int64,Int64,Int64,Int64)
-  optimIO = do
-
--- XXX Based on a clone of run_IO_SM.
-
-#if 0
-
-    stats_query_idx <- do
-                        sqi <- readIORef stats_query_idx_ioref
-                        return sqi
-    depth <- do
-              d <- readIORef depth_ioref
-              return d
-#if 0
--- XXX a code fragment expected to be useful (see seqaidDispatch where clause)
-    tmp = stats_query_idx-(2+max_depth)
-    pat' | tmp < length fixed_pat_sequence
-            = fixed_pat_sequence!!tmp
-         | otherwise
-            = last fixed_pat_sequence
-#endif
-#if NFDATAN_ONLY
-#error "NFDATAN_ONLY is not valid at this time."
-#else
-#if 1
-    pat <- do
-#if 1 || DEMO_MODE
-            let tmp = stats_query_idx
---          let tmp = stats_query_idx-(2+max_depth)
-            let p | tmp < length fixed_pat_sequence
-                     = fixed_pat_sequence!!tmp
-                  | otherwise
-                     = last fixed_pat_sequence
-#if 0
-            H.insert ht sid_hash p
-#endif
-            return p
-#else
-            ht <- readIORef patterns_ioref
-            let sid_hash = thd3 sid
-            mp <- H.lookup ht sid_hash
-            if isNothing mp
-            then do
-              let p = compilePat "#"
-              H.insert ht sid_hash p
-              return p
-            else do
-              return $ fromJust mp
-#endif
-#else
--- XXX wrong and never tested, obviously
-    pat = patterns_ioref!(fst3 sid)
-#endif
-#endif
-
-#endif
-
-    i <- do
-          ii <- readIORef counter_ioref
-          modifyIORef' counter_ioref (1+)
-          return ii
-    ba <- readIORef bytes_allocated_ioref
-    cbu <- readIORef current_bytes_used_ioref
-
-#if 0
-
-#if 0
-    if stats_query_idx >= max_depth && i >= t
-    then do
-      let j = stats_query_idx - max_depth
-      writeIORef pattern_ioref (fixed_pat_sequence!!j)
-      return ()
-    else return ()
-#endif
-    if depth <= max_depth && i >= t
-    then do
-#if 1
-      modifyIORef' depth_ioref (1+)
-#else
--- XXX need Data instances...
---    writeIORef pattern_ioref (mkPatN depth x)
-#endif
-      return ()
-    else return ()
-
-#endif
-
---- !_ <- return x  -- magic! thank you!!
-
---  return (stats_query_idx,depth,pat,snk,i,t,size,cbu,t')
-    return ()
-
--------------------------------------------------------------------------------
-
-  optim :: ()
-  optim = ()
-
--------------------------------------------------------------------------------
-
-  optim_N_phase :: ()
-  optim_N_phase = ()
-
--------------------------------------------------------------------------------
-
-  optim_P_phase :: ()
-  optim_P_phase = ()
-
--------------------------------------------------------------------------------
-
+  -- | This is for internal use only.
+  --
+  -- /The seemingly redundant superclass constraints are necessary/
+  -- /due to some weirdness in the TH or Core code (I forget the/
+  -- /details); should try to get rid of them in case it's/
+  -- /since become possible.../
+{--}
   -- Okay!
   -- Now it is time to use the hash values
-
+{--}
   -- XXX This is simply the collected unsafePerformIO calls
   -- that were initially scattered throughout seqaidDispatch.
   -- It happened to behave the same as that did, without change;
   -- but a once-over reorganising the logic slightly would be good...
-
+{--}
   -- is this pragma necessary? does it even make sense with IO?...
   {-# NOINLINE run_IO_SM #-}
 #if SEQABLE_ONLY
@@ -344,11 +169,11 @@
 #endif
 
 #if SEQABLE_ONLY
-    let pat = compilePat "#"  -- just whatever
+    let pat = emptyPat
 #else
 #if NFDATAN_ONLY
 --- #error "NFDATA_ONLY is not valid at this time."
-    let pat = compilePat "#"  -- just whatever
+    let pat = emptyPat
 #else
     pat <- do
 #if 1 || DEMO_MODE
@@ -370,7 +195,7 @@
             mp <- H.lookup ht sid_hash
             if isNothing mp
             then do
-              let p = compilePat "#"
+              let p = emptyPat
               H.insert ht sid_hash p
               return p
             else do
@@ -448,6 +273,13 @@
 
     return (stats_query_idx,depth,pat,snk,i,t,size,cbu,t')
 --  return ()
+
+-------------------------------------------------------------------------------
+
+#if ! SAI_FORK
+  optimIO :: IO ()
+  optimIO = return ()
+#endif
 
 -------------------------------------------------------------------------------
 
diff --git a/Seqaid/Prepro.hs b/Seqaid/Prepro.hs
--- a/Seqaid/Prepro.hs
+++ b/Seqaid/Prepro.hs
@@ -26,6 +26,12 @@
 -- Portability :  GHC
 --
 -- Seqaid preprocessor, run via GHC -F.
+-- In order to use seqaid there is some configuration required,
+-- both in your project .cabal file, and in a seqaid.config file.
+-- Refer to the project
+-- <http://www.fremissant.net/seqaid#using homepage>
+-- (also distributed locally in the HTML directory of the seqaid package)
+-- for more details.
 
   module Main where
 --module Seqaid.Prepro where
@@ -378,6 +384,8 @@
 
         -- (3) Inject the Seqaid.TH import statement:
         -- Later: And also some type imports (for omnitypic wrapper injection).
+-- XXX Later: Why is this #if 1 here??... If figure out that it should
+-- be here, please leave a comment as to why!
 #if 1
         let go2 s = indent ++ "import Seqaid.TH\n" ++ omni_imports ++ s
 #else
@@ -575,7 +583,11 @@
           [ ghcopts'
           , "--make "
           , "-c "
+#if USE_CPPHS
           , "-pgmPcpphs -optP--cpp"
+#else
+--        , "-cpp"  -- (see comments in the seqaid.cabal file)
+#endif
           , "" ++ nowneeded
           , "-fplugin-opt=Seqaid.Plugin:prepro=" ++ modname
           , "-fplugin-opt=Seqaid.Plugin:" ++ omni_types_pname
diff --git a/Seqaid/Runtime.hs b/Seqaid/Runtime.hs
--- a/Seqaid/Runtime.hs
+++ b/Seqaid/Runtime.hs
@@ -21,6 +21,11 @@
 -- Portability :  GHC (unsafePerformIO)
 --
 -- This module is for seqaid internal use.
+--
+-- /The seemingly redundant superclass constraints are necessary/
+-- /due to some weirdness in the TH or Core code (I forget the/
+-- /details); should try to get rid of them in case it's/
+-- /since become possible.../
 
   module Seqaid.Runtime (
 
diff --git a/changelog.txt b/changelog.txt
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,9 +1,20 @@
 
+0.2.1.0 -> 0.2.1.1
+ - added a non-manual USE_CPPHS flag to seqaid.cabal, which should
+   in principle allow the client build system to try cpphs first, and
+   if that build fails, then try again with a native cpp if there's
+   one in the path (which is usually the case)
+    - this auto-toggle works for me with GHC 7.8.4 and Cabal 1.22.0.0
+    - what is the oldest version of cabal-install that this
+      auto-toggling will happen in?...
+ - improvements in platform-dependent handling in Demo.hs
+ - and also in choice of leaky version in Demo.hs
+
 0.2.0.0 -> 0.2.1.0
  - realised I should be using Manual: True in all my .cabal flags,
    or else the constraint solver is free to toggle them!!
 
-0.1.7.0 -> 0.2.0.0
+** 0.1.7.0 -> 0.2.0.0
  - deepseq-bounded had a major version bump
  - fixed cpphs missing dependency (Seqaid lib, and seqaid and seqaidpp exe's)
  - more...
diff --git a/dist/setup-config b/dist/setup-config
new file mode 100644
Binary files /dev/null and b/dist/setup-config differ
diff --git a/seqaid.cabal b/seqaid.cabal
--- a/seqaid.cabal
+++ b/seqaid.cabal
@@ -2,7 +2,7 @@
 -------------------------------------------------------------------------------
 
 name:                seqaid
-version:             0.2.1.0
+version:             0.2.1.1
 synopsis:            Dynamic strictness control, including space leak repair
 license:             BSD3
 license-file:        LICENSE
@@ -12,9 +12,10 @@
 bug-reports:         http://fremissant.net/seqaid/trac
 ---bug-reports:         Andrew Seniuk <rasfar@gmail.com>
 category:            Compiler Plugin
+--hackage-tags:        parallel, leak, space, strictness, forcing, diagnostic, remedial, auto-instrumentation, instrumentation, tools, bsd3, ghc-plugin, program, library
 build-type:          Simple
 stability:           provisional, nascent
-cabal-version:       >= 1.16
+cabal-version:       >= 1.18
 
 -- NOTE: Version of GHC /must/ be >= 7.8, due to need to use TH >= 2.9.
 -- Could possibly relax to TH >= 2.8 (which would include GHC 7.6.*),
@@ -24,7 +25,7 @@
 --tested-with:         GHC==7.8.*, GHC==7.10.1  -- illegal syntax (Cabal 1.20)
 --tested-with:         GHC==7.6.3, GHC==7.8.1, GHC==7.8.3, GHC==7.8.4
 
-description:         Seqaid is a GHC plugin for non-invasive auto-instrumentation of dynamic strictness (and parallelism) control, shortly to include optimisation for automated space leak relief using minimal strictification. [The optimiser is still in development however.]
+description:         Seqaid is a GHC plugin providing non-invasive auto-instrumentation of Haskell projects, for dynamic strictness (and parallelism) control. This will soon include optimisation for automated space leak relief using minimal strictification. [The optimiser is still in development however.]
                      .
                      Refer to the seqaid <http://www.fremissant.net/seqaid homepage> for more information.
                      .
@@ -62,6 +63,12 @@
   Default: False
   Manual: True
 
+Flag SAI_FORK
+  Description: .
+--Default: True
+  Default: False
+  Manual: True
+
 Flag TRY_INJECT_NOINLINE_ON_REQUESTED_BINDS
   Description: If we can prevent inlining of injected binds (without requiring user edits), that would probably be a good trade-off in terms of lost optimiser opportunities in exchange for assurance that the bind won't be inlined. This didn't work, and is a poor solution anyway.
 --Default: True
@@ -132,6 +139,15 @@
 --Default: False
   Manual: True
 
+-- This does indeed work for me (it is auto-toggled when cpphs is unavailable).
+-- Default to False, since it seems more likely there's a native cpp, than
+-- that a cpphs installation works smoothly.
+Flag USE_CPPHS
+  Description: Non-manual flag to allow the build system to try cpphs first, and if that fails, then to try system-wide cpp (typically GNU). I've actually toggled the default, so the build system will try for a system-wide cpp first, and failing that, will try to use cpphs, installing it if necessary. I prefer cpp. I am not getting my most invaluable -Wundef option with cpphs using -optP-Wundef -optP--cpp in my ghc-options. Does cpphs implement it? Not sure...
+  Default: False
+--Default: True
+  Manual: False
+
 -------------------------------------------------------------------------------
 
 library {
@@ -154,6 +170,8 @@
     , Seqaid.TH_710
     , Seqaid.TH_extra_710
 
+  other-modules:
+
   -- These are the dependencies of modulespection which, at this
   -- time (20150106), are not (otherwise) also dependencies of seqaid.
   -- Later: Really? I thought temporary was... (Oh! only of seqaid exe.)
@@ -174,8 +192,14 @@
 
   build-depends:
       base == 4.*
-    , cpphs >= 1.14
 
+  -- We don't really depend on the cpphs /library/, but installing
+  -- the library also installs the cpphs executable, so in case
+  -- build-tools doesn't nab it, this ought to!
+  if flag(USE_CPPHS)
+     build-depends:
+         cpphs >= 1.14
+
   if flag(GHC_710)
      build-depends:
          ghc == 7.10.*
@@ -258,7 +282,6 @@
 --  , deepseq == 1.3.0.2
 
   ghc-options: -optP-Wundef -fno-warn-overlapping-patterns
-  ghc-options: -pgmPcpphs -optP--cpp
   ghc-options:                  -funbox-strict-fields -fwarn-tabs
 --ghc-options:        -Wall -O2 -funbox-strict-fields -fwarn-tabs
 
@@ -275,9 +298,27 @@
   -- http://stackoverflow.com/questions/2549167/cpp-extension-and-multiline-literals-in-haskell
   -- I prefer string gaps to unlines [ l1, l2, ... ] b/c then lines
   -- can start at the left margin!
---ghc-options:        -pgmP cpphs -optP--cpp
---ghc-options: -cpp
+  if flag(USE_CPPHS)
+     -- Which is most portable, a space after the P or not???
+     -- See the comment on the other branch of this Cabal "condition".
+     ghc-options: -pgmPcpphs -optP--cpp
+--else
+--   -- This is no longer needed, but SINCE WHEN?? i.e. for
+--   -- which versions of GHC (and perhaps cabal-install)?...
+--   -- Without a reasonable means to answer this question
+--   -- (short of tracking down and scouring changelogs
+--   -- in reverse chronological order), the conscientious
+--   -- programmer has no recourse but to try to cover
+--   -- all the bases.
+--   --   But since recent cabal-install screams loudly about it,
+--   -- better comment it out.
+--   ghc-options: -cpp
 
+  if flag(SAI_FORK)
+     cpp-options: -DSAI_FORK=1
+  else
+     cpp-options: -DSAI_FORK=0
+
   if flag(SEQABLE_ONLY)
      cpp-options: -DSEQABLE_ONLY=1
   else
@@ -335,14 +376,13 @@
 
   default-extensions: CPP
   default-language:   Haskell2010
+
 }
 
 -------------------------------------------------------------------------------
 
--- XXX Note that the flags in library section are NOT present here.
--- (Which is fine so long as the executable's code doesn't try to use them;
--- and will get a warning anyhow if it does.)
 executable seqaid {
+
 -- It seems you cannot put the seqaid Main module in Seqaid.Main namespace?
   hs-source-dirs:     .
   main-is:            Seqaid/Demo.hs
@@ -351,19 +391,28 @@
 
   build-depends:
       base == 4.*
-    , cpphs >= 1.14
     , temporary == 1.2.*
     , directory == 1.2.*
 -- Finally needed to drop to 1.* for testing GHC 7.6.3!
     , process == 1.*
 --  , process == 1.2.*
+
+  -- We don't really depend on the cpphs /library/, but installing
+  -- the library also installs the cpphs executable, so in case
+  -- build-tools doesn't nab it, this ought to!
+  if flag(USE_CPPHS)
+     build-depends:
+         cpphs >= 1.14
+
   ghc-options:                  -funbox-strict-fields -fwarn-tabs -threaded
 --ghc-options:        -Wall -O2 -funbox-strict-fields -fwarn-tabs -threaded
 
   ghc-options: -optP-Wundef -fno-warn-overlapping-patterns
   -- [See comments in the library part above.]
-  ghc-options: -pgmP cpphs -optP--cpp
---ghc-options: -cpp
+  if flag(USE_CPPHS)
+     ghc-options: -pgmPcpphs -optP--cpp
+--else
+--   ghc-options: -cpp
 
 -- Test #ifdef mingw32_HOST_OS instead! (it's built-in to GHC)
 ------
@@ -372,26 +421,24 @@
 -- to that by executing a Cmnd batch script.
 --
 -- And, if it /is/ MinGW, then it's the same bash script as run on *nix...
-if os(windows)
-   cpp-options: -DIS_WINDOWS=1
-else
-   cpp-options: -DIS_WINDOWS=0
+  if os(windows)
+     cpp-options: -DIS_WINDOWS=1
+  else
+     cpp-options: -DIS_WINDOWS=0
 
   default-extensions: CPP
   default-language:   Haskell2010
+
 }
 
 -------------------------------------------------------------------------------
 
--- XXX Note that the flags in library section are NOT present here.
--- (Which is fine so long as the executable's code doesn't try to use them;
--- and will get a warning anyhow if it does.)
 executable seqaidpp {
+
   hs-source-dirs:     .
   main-is:            Seqaid/Prepro.hs
   build-depends:
       base == 4.*
-    , cpphs >= 1.14
     , regex-base <= 0.93.2
     , regex-pcre <= 0.94.4
 -- (process may still be uncommented b/c using to debug...)
@@ -404,10 +451,24 @@
     , Cabal >= 1.10
 --  , Cabal >= 1.18
 
+  -- We don't really depend on the cpphs /library/, but installing
+  -- the library also installs the cpphs executable, so in case
+  -- build-tools doesn't nab it, this ought to!
+  if flag(USE_CPPHS)
+     build-depends:
+         cpphs >= 1.14
+
   ghc-options: -optP-Wundef -fno-warn-overlapping-patterns
   -- [See comments in the library part above.]
-  ghc-options: -pgmP cpphs -optP--cpp
---ghc-options: -cpp
+  if flag(USE_CPPHS)
+     ghc-options: -pgmPcpphs -optP--cpp
+--else
+--   ghc-options: -cpp
+
+  if flag(USE_CPPHS)
+     cpp-options: -DUSE_CPPHS=1
+  else
+     cpp-options: -DUSE_CPPHS=0
 
   if flag(TRY_INJECT_NOINLINE_ON_REQUESTED_BINDS)
      cpp-options: -DTRY_INJECT_NOINLINE_ON_REQUESTED_BINDS=1
