diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -118,3 +118,25 @@
 ### Conditionals
 - [ ] Conditional breakpoints     (breakpoint is hit only if condition is satisfied)
 - [ ] Hit conditional breakpoints (stop after N number of hits)
+
+# Building from source
+
+To build `ghc-debug-adapter`:
+```
+cabal build -w /path/to/recent/ghc exe:ghc-debug-adapter
+```
+
+To build the VSCode extension
+```
+cd vscode-extension
+nix-build
+```
+
+## Testing
+
+```
+cd test/integration-tests
+nix-shell
+make GHC=/path/to/recent/ghc \
+     DEBUGGER=$(cd ../.. && cabal list-bin -w /path/to/recent/ghc exe:ghc-debug-adapter)
+```
diff --git a/ghc-debugger.cabal b/ghc-debugger.cabal
--- a/ghc-debugger.cabal
+++ b/ghc-debugger.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ghc-debugger
-version:            0.2.0.0
+version:            0.3.0.0
 synopsis:
     A step-through machine-interface debugger for GHC Haskell
 
diff --git a/ghc-debugger/GHC/Debugger/Breakpoint.hs b/ghc-debugger/GHC/Debugger/Breakpoint.hs
--- a/ghc-debugger/GHC/Debugger/Breakpoint.hs
+++ b/ghc-debugger/GHC/Debugger/Breakpoint.hs
@@ -96,7 +96,7 @@
               , sourceSpan = realSrcSpanToSourceSpan spn
               , breakId = bid
               }
-      case findBreakForBind fun_str modBreaks of
+      case maybe [] (findBreakForBind fun_str) modBreaks of
         []  -> do
           liftIO $ logOutput logger (text $ "No breakpoint found by name " ++ function ++ ". Ignoring...")
           return BreakNotFound
diff --git a/ghc-debugger/GHC/Debugger/Runtime.hs b/ghc-debugger/GHC/Debugger/Runtime.hs
--- a/ghc-debugger/GHC/Debugger/Runtime.hs
+++ b/ghc-debugger/GHC/Debugger/Runtime.hs
@@ -56,7 +56,7 @@
                 PositionalIndex ix -> subTerms !! (ix-1)
                 LabeledField fl    ->
                   case L.findIndex (== fl) (map flSelector $ dataConFieldLabels dc) of
-                    Just ix -> subTerms !! (ix-1)
+                    Just ix -> subTerms !! ix
                     Nothing -> error "Couldn't find labeled field in dataConFieldLabels"
               NewtypeWrap{wrapped_term} ->
                 wrapped_term -- regardless of PathFragment
diff --git a/ghc-debugger/GHC/Debugger/Stopped.hs b/ghc-debugger/GHC/Debugger/Stopped.hs
--- a/ghc-debugger/GHC/Debugger/Stopped.hs
+++ b/ghc-debugger/GHC/Debugger/Stopped.hs
@@ -176,13 +176,8 @@
                 -- It is a "lazy" DAP variable: our reply can ONLY include
                 -- this single variable.
 
-                let ty = GHCI.termType term
-                term' <- if isBoringTy ty
-                            then deepseqTerm term -- deepseq boring types like String, because it is more helpful to print them whole than their structure.
-                            else seqTerm term
-                -- update cache with the forced term right away instead of invalidating it.
-                -- TODO: is this the best place to have this update? what's the better abstraction?
-                asks termCache >>= \r -> liftIO $ modifyIORef' r (insertTermCache key term')
+                term' <- forceTerm key term
+
                 vi <- termToVarInfo key term'
 
                 return (Left vi)
diff --git a/ghc-debugger/GHC/Debugger/Stopped/Variables.hs b/ghc-debugger/GHC/Debugger/Stopped/Variables.hs
--- a/ghc-debugger/GHC/Debugger/Stopped/Variables.hs
+++ b/ghc-debugger/GHC/Debugger/Stopped/Variables.hs
@@ -3,7 +3,10 @@
    TypeApplications, ScopedTypeVariables, BangPatterns #-}
 module GHC.Debugger.Stopped.Variables where
 
+import Data.IORef
 import Control.Monad
+import Control.Monad.Reader
+import Control.Monad.IO.Class
 
 import GHC
 import GHC.Types.FieldLabel
@@ -17,6 +20,7 @@
 import GHC.Debugger.Interface.Messages
 import GHC.Debugger.Runtime
 import GHC.Debugger.Runtime.Term.Key
+import GHC.Debugger.Runtime.Term.Cache
 import GHC.Debugger.Utils
 
 -- | 'TyThing' to 'VarInfo'. The 'Bool' argument indicates whether to force the
@@ -69,14 +73,19 @@
 
 -- | Construct a 'VarInfo' from the given 'Name' of the variable and the 'Term' it binds
 termToVarInfo :: TermKey -> Term -> Debugger VarInfo
-termToVarInfo key term = do
+termToVarInfo key term0 = do
   -- Make a VarInfo for a term
   let
     isThunk
-     | Suspension{} <- term = True
+     | Suspension{} <- term0 = True
      | otherwise = False
-    ty = GHCI.termType term
+    ty = GHCI.termType term0
 
+  term <- if not isThunk && isBoringTy ty
+            then forceTerm key term0 -- make sure that if it's an evaluated boring term then it is /fully/ evaluated.
+            else pure term0
+
+  let
     -- We scrape the subterms to display as the var's value. The structure is
     -- displayed in the editor itself by expanding the variable sub-fields
     termHead t
@@ -96,12 +105,12 @@
   -- We only want to return @SpecificVariable@ (which allows expansion) for
   -- values with sub-fields or thunks.
   varRef <- do
-    if GHCI.isFullyEvaluatedTerm term
+    if GHCI.isFullyEvaluatedTerm term ||
        -- Even if it is already evaluated, we do want to display a
        -- structure as long if it is not a "boring type" (one that does not
        -- provide useful information from being expanded)
        -- (e.g. consider how awkward it is to expand Char# 10 and I# 20)
-       && (isBoringTy ty || not (hasDirectSubTerms term))
+       (not isThunk && (isBoringTy ty || not (hasDirectSubTerms term)))
      then do
         return NoVariables
      else do
@@ -117,3 +126,16 @@
       RefWrap{}      -> True
       Term{subTerms} -> not $ null subTerms
 
+-- | Forces a term to WHNF in the general case, or to NF in the case of 'isBoringTy'.
+-- The term is updated at the given key.
+forceTerm :: TermKey -> Term -> Debugger Term
+forceTerm key term = do
+  let ty = GHCI.termType term
+  term' <- if isBoringTy ty
+              -- deepseq boring types like String, because it is more helpful
+              -- to print them whole than their structure.
+              then deepseqTerm term
+              else seqTerm term
+  -- update cache with the forced term right away instead of invalidating it.
+  asks termCache >>= \r -> liftIO $ modifyIORef' r (insertTermCache key term')
+  return term'
