diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Changelog
 
+## [0.3.0.1] - 2021-11-21
+
+### Changed
+
+* Compatibility with `GHC >= 9.8`
+
 ## [0.3.0.0] - 2021-11-21
 
 ### Changed
diff --git a/genvalidity-mergeful.cabal b/genvalidity-mergeful.cabal
--- a/genvalidity-mergeful.cabal
+++ b/genvalidity-mergeful.cabal
@@ -1,24 +1,38 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.35.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 218b3a60cb86fcedf2942fea48c5ee2dc351c552cd48ca944629761753bfc87b
+-- hash: 394bb132a6d5e5a2cd9ef618e33cf81ac04d73a31dbd27e092e4fb732170f2af
 
 name:           genvalidity-mergeful
-version:        0.3.0.0
+version:        0.3.0.1
 description:    Please see the README on GitHub at <https://github.com/NorfairKing/mergeful#readme>
 homepage:       https://github.com/NorfairKing/mergeful#readme
 bug-reports:    https://github.com/NorfairKing/mergeful/issues
 author:         Tom Sydney Kerckhove
 maintainer:     syd@cs-syd.eu
-copyright:      Copyright: (c) 2019-2021 Tom Sydney Kerckhove
+copyright:      Copyright: (c) 2019-2023 Tom Sydney Kerckhove
 license:        MIT
 license-file:   LICENSE
 build-type:     Simple
 extra-source-files:
     CHANGELOG.md
+    test_resources/collection/client-addition.txt
+    test_resources/collection/client-id.txt
+    test_resources/collection/client-store.txt
+    test_resources/collection/request.txt
+    test_resources/collection/response.txt
+    test_resources/collection/server-store.txt
+    test_resources/item/client.txt
+    test_resources/item/request.txt
+    test_resources/item/response.txt
+    test_resources/item/server.txt
+    test_resources/value/client.txt
+    test_resources/value/request.txt
+    test_resources/value/response.txt
+    test_resources/value/server.txt
 
 source-repository head
   type: git
@@ -57,19 +71,24 @@
   hs-source-dirs:
       test
   ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-tool-depends:
+      sydtest-discover:sydtest-discover
   build-depends:
       QuickCheck
+    , autodocodec
+    , autodocodec-yaml
     , base <5
     , containers
-    , genvalidity-hspec
-    , genvalidity-hspec-aeson
     , genvalidity-mergeful
+    , genvalidity-sydtest
+    , genvalidity-sydtest-aeson
     , genvalidity-uuid
-    , hspec
     , mergeful
     , mtl
     , pretty-show
     , random
+    , safe-coloured-text
+    , sydtest
     , time
     , uuid
   default-language: Haskell2010
diff --git a/test/Data/Mergeful/CollectionSpec.hs b/test/Data/Mergeful/CollectionSpec.hs
--- a/test/Data/Mergeful/CollectionSpec.hs
+++ b/test/Data/Mergeful/CollectionSpec.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE RankNTypes #-}
@@ -10,7 +11,11 @@
   )
 where
 
+import Autodocodec
+import Autodocodec.Yaml
+import Control.Monad
 import Control.Monad.State
+import Data.Data
 import Data.Functor.Identity
 import Data.GenValidity.Mergeful ()
 import Data.GenValidity.Mergeful.Item ()
@@ -20,31 +25,52 @@
 import Data.Mergeful
 import qualified Data.Set as S
 import Data.UUID
+import Data.Word
 import GHC.Generics (Generic)
 import System.Random
-import Test.Hspec
-import Test.Hspec.QuickCheck
 import Test.QuickCheck
-import Test.Validity
-import Test.Validity.Aeson
-import Text.Show.Pretty
+import Test.Syd hiding (Timed (..))
+import Test.Syd.Validity
+import Test.Syd.Validity.Aeson
+import Test.Syd.Validity.Utils
+import Text.Colour
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
 
 spec :: Spec
 spec = modifyMaxShrinks (min 0) $ do
-  genValidSpec @ClientId
-  jsonSpec @ClientId
-  genValidSpec @(ClientStore ClientId Int Int)
-  jsonSpec @(ClientStore ClientId Int Int)
-  genValidSpec @(ServerStore Int Int)
-  jsonSpec @(ServerStore Int Int)
-  genValidSpec @(SyncRequest ClientId Int Int)
-  jsonSpec @(SyncRequest ClientId Int Int)
-  genValidSpec @(ClientAddition Int)
-  jsonSpec @(ClientAddition Int)
-  genValidSpec @(SyncResponse ClientId Int Int)
-  jsonSpec @(SyncResponse ClientId Int Int)
+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec
+      yamlSchemaSpec filePath = do
+        it ("outputs the same schema as before for " <> nameOf @a) $
+          pureGoldenTextFile
+            ("test_resources/collection/" <> filePath <> ".txt")
+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)
+
+  describe "ClientId" $ do
+    genValidSpec @ClientId
+    jsonSpec @ClientId
+    yamlSchemaSpec @ClientId "client-id"
+  describe "ClientStore" $ do
+    genValidSpec @(ClientStore ClientId Word8 Word8)
+    jsonSpec @(ClientStore ClientId Word8 Word8)
+    yamlSchemaSpec @(ClientStore ClientId Word8 Word8) "client-store"
+  describe "ServerStore" $ do
+    genValidSpec @(ServerStore Word8 Word8)
+    jsonSpec @(ServerStore Word8 Word8)
+    yamlSchemaSpec @(ServerStore Word8 Word8) "server-store"
+  describe "SyncRequest" $ do
+    genValidSpec @(SyncRequest ClientId Word8 Word8)
+    jsonSpec @(SyncRequest ClientId Word8 Word8)
+    yamlSchemaSpec @(SyncRequest ClientId Word8 Word8) "request"
+  describe "ClientAddition" $ do
+    genValidSpec @(ClientAddition Word8)
+    jsonSpec @(ClientAddition Word8)
+    yamlSchemaSpec @(ClientAddition Word8) "client-addition"
+  describe "SyncResponse" $ do
+    genValidSpec @(SyncResponse ClientId Word8 Word8)
+    jsonSpec @(SyncResponse ClientId Word8 Word8)
+    yamlSchemaSpec @(SyncResponse ClientId Word8 Word8) "response"
+
   describe "initialClientStore" $
     it "is valid" $
       shouldBeValid $
@@ -722,20 +748,20 @@
                         not (S.null syncResponseConflictsServerDeleted)
                       ]
                   )
-                  $ expectationFailure $
-                    unlines
-                      [ "There was a difference between mergeFunc1 and mergeFunc2 that was somehow unrelated to the conflicts:",
-                        "syncResponseConflicts:",
-                        ppShow syncResponseConflicts,
-                        "syncResponseConflictsClientDeleted:",
-                        ppShow syncResponseConflictsClientDeleted,
-                        "syncResponseConflictsServerDeleted:",
-                        ppShow syncResponseConflictsServerDeleted,
-                        "client store after mergeFunc1:",
-                        ppShow cstoreA,
-                        "client store after mergeFunc2:",
-                        ppShow cstoreB
-                      ]
+                  $ expectationFailure
+                  $ unlines
+                    [ "There was a difference between mergeFunc1 and mergeFunc2 that was somehow unrelated to the conflicts:",
+                      "syncResponseConflicts:",
+                      ppShow syncResponseConflicts,
+                      "syncResponseConflictsClientDeleted:",
+                      ppShow syncResponseConflictsClientDeleted,
+                      "syncResponseConflictsServerDeleted:",
+                      ppShow syncResponseConflictsServerDeleted,
+                      "client store after mergeFunc1:",
+                      ppShow cstoreA,
+                      "client store after mergeFunc2:",
+                      ppShow cstoreB
+                    ]
 
 newtype D m a = D
   { unD :: StateT StdGen m a
diff --git a/test/Data/Mergeful/ItemSpec.hs b/test/Data/Mergeful/ItemSpec.hs
--- a/test/Data/Mergeful/ItemSpec.hs
+++ b/test/Data/Mergeful/ItemSpec.hs
@@ -1,4 +1,6 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
 {-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
 
 module Data.Mergeful.ItemSpec
@@ -6,13 +8,19 @@
   )
 where
 
+import Autodocodec
+import Autodocodec.Yaml
+import Data.Data
 import Data.GenValidity.Mergeful.Item ()
 import Data.Mergeful.Item
 import Data.Mergeful.Timed
-import Test.Hspec
+import Data.Word
 import Test.QuickCheck
-import Test.Validity
-import Test.Validity.Aeson
+import Test.Syd hiding (Timed (..))
+import Test.Syd.Validity
+import Test.Syd.Validity.Aeson
+import Test.Syd.Validity.Utils
+import Text.Colour
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
 
@@ -23,14 +31,28 @@
 
 spec :: Spec
 spec = do
-  genValidSpec @(ClientItem Int)
-  jsonSpec @(ClientItem Int)
-  genValidSpec @(ServerItem Int)
-  jsonSpec @(ServerItem Int)
-  genValidSpec @(ItemSyncRequest Int)
-  jsonSpec @(ItemSyncRequest Int)
-  genValidSpec @(ItemSyncResponse Int)
-  jsonSpec @(ItemSyncResponse Int)
+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec
+      yamlSchemaSpec filePath = do
+        it ("outputs the same schema as before for " <> nameOf @a) $
+          pureGoldenTextFile
+            ("test_resources/item/" <> filePath <> ".txt")
+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)
+  describe "ClientItem" $ do
+    genValidSpec @(ClientItem Word8)
+    jsonSpec @(ClientItem Word8)
+    yamlSchemaSpec @(ClientItem Word8) "client"
+  describe "ServerItem" $ do
+    genValidSpec @(ServerItem Word8)
+    jsonSpec @(ServerItem Word8)
+    yamlSchemaSpec @(ServerItem Word8) "server"
+  describe "ItemSyncRequest" $ do
+    genValidSpec @(ItemSyncRequest Word8)
+    jsonSpec @(ItemSyncRequest Word8)
+    yamlSchemaSpec @(ItemSyncRequest Word8) "request"
+  describe "ItemSyncResponse" $ do
+    genValidSpec @(ItemSyncResponse Word8)
+    jsonSpec @(ItemSyncResponse Word8)
+    yamlSchemaSpec @(ItemSyncResponse Word8) "response"
   describe "makeItemSyncRequest" $
     it "produces valid requests" $
       producesValid (makeItemSyncRequest @Int)
@@ -133,24 +155,24 @@
                 resp `shouldBe` ItemSyncResponseConflict (Timed i st')
       it
         "notices a server-deleted-conflict if the client has a deleted item and server has a modified item"
-        $ forAllValid $
-          \i ->
-            forAllSubsequent $ \(st, st') -> do
-              let store1 = ServerFull (Timed i st')
-                  req = ItemSyncRequestDeletedLocally st
-              let (resp, store2) = processServerItemSync @Int store1 req
-              store2 `shouldBe` store1
-              resp `shouldBe` ItemSyncResponseConflictClientDeleted (Timed i st')
+        $ forAllValid
+        $ \i ->
+          forAllSubsequent $ \(st, st') -> do
+            let store1 = ServerFull (Timed i st')
+                req = ItemSyncRequestDeletedLocally st
+            let (resp, store2) = processServerItemSync @Int store1 req
+            store2 `shouldBe` store1
+            resp `shouldBe` ItemSyncResponseConflictClientDeleted (Timed i st')
       it
         "notices a server-deleted-conflict if the client has a modified item and server has no item"
-        $ forAllValid $
-          \i ->
-            forAllValid $ \st -> do
-              let store1 = ServerEmpty
-                  req = ItemSyncRequestKnownButChanged (Timed i st)
-              let (resp, store2) = processServerItemSync @Int store1 req
-              store2 `shouldBe` store1
-              resp `shouldBe` ItemSyncResponseConflictServerDeleted
+        $ forAllValid
+        $ \i ->
+          forAllValid $ \st -> do
+            let store1 = ServerEmpty
+                req = ItemSyncRequestKnownButChanged (Timed i st)
+            let (resp, store2) = processServerItemSync @Int store1 req
+            store2 `shouldBe` store1
+            resp `shouldBe` ItemSyncResponseConflictServerDeleted
   describe "syncing" $ do
     describe "fromServer" $ do
       syncingSpec @Int mergeFromServer
diff --git a/test/Data/Mergeful/TimedSpec.hs b/test/Data/Mergeful/TimedSpec.hs
--- a/test/Data/Mergeful/TimedSpec.hs
+++ b/test/Data/Mergeful/TimedSpec.hs
@@ -7,9 +7,9 @@
 
 import Data.GenValidity.Mergeful.Item ()
 import Data.Mergeful.Timed
-import Test.Hspec
-import Test.Validity
-import Test.Validity.Aeson
+import Test.Syd hiding (Timed (..))
+import Test.Syd.Validity
+import Test.Syd.Validity.Aeson
 
 spec :: Spec
 spec = do
diff --git a/test/Data/Mergeful/ValueSpec.hs b/test/Data/Mergeful/ValueSpec.hs
--- a/test/Data/Mergeful/ValueSpec.hs
+++ b/test/Data/Mergeful/ValueSpec.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE AllowAmbiguousTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeApplications #-}
 
 module Data.Mergeful.ValueSpec
@@ -5,13 +7,19 @@
   )
 where
 
+import Autodocodec
+import Autodocodec.Yaml
+import Data.Data
 import Data.GenValidity.Mergeful.Value ()
 import Data.Mergeful.Timed
 import Data.Mergeful.Value
-import Test.Hspec
+import Data.Word
 import Test.QuickCheck
-import Test.Validity
-import Test.Validity.Aeson
+import Test.Syd hiding (Timed (..))
+import Test.Syd.Validity
+import Test.Syd.Validity.Aeson
+import Test.Syd.Validity.Utils
+import Text.Colour
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
 
@@ -22,14 +30,30 @@
 
 spec :: Spec
 spec = do
-  genValidSpec @(ClientValue Int)
-  jsonSpec @(ClientValue Int)
-  genValidSpec @(ServerValue Int)
-  jsonSpec @(ServerValue Int)
-  genValidSpec @(ValueSyncRequest Int)
-  jsonSpec @(ValueSyncRequest Int)
-  genValidSpec @(ValueSyncResponse Int)
-  jsonSpec @(ValueSyncResponse Int)
+  let yamlSchemaSpec :: forall a. (Typeable a, GenValid a, HasCodec a) => FilePath -> Spec
+      yamlSchemaSpec filePath = do
+        it ("outputs the same schema as before for " <> nameOf @a) $
+          pureGoldenTextFile
+            ("test_resources/value/" <> filePath <> ".txt")
+            (renderChunksText With24BitColours $ schemaChunksViaCodec @a)
+
+  describe "ClientValue" $ do
+    genValidSpec @(ClientValue Word8)
+    jsonSpec @(ClientValue Word8)
+    yamlSchemaSpec @(ClientValue Word8) "client"
+  describe "ServerValue" $ do
+    genValidSpec @(ServerValue Word8)
+    jsonSpec @(ServerValue Word8)
+    yamlSchemaSpec @(ServerValue Word8) "server"
+  describe "ValueSyncRequest" $ do
+    genValidSpec @(ValueSyncRequest Word8)
+    jsonSpec @(ValueSyncRequest Word8)
+    yamlSchemaSpec @(ValueSyncRequest Word8) "request"
+  describe "ValueSyncResponse" $ do
+    genValidSpec @(ValueSyncResponse Word8)
+    jsonSpec @(ValueSyncResponse Word8)
+    yamlSchemaSpec @(ValueSyncResponse Word8) "response"
+
   describe "makeValueSyncRequest" $
     it "produces valid requests" $
       producesValid (makeValueSyncRequest @Int)
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,1 +1,1 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+{-# OPTIONS_GHC -F -pgmF sydtest-discover #-}
diff --git a/test_resources/collection/client-addition.txt b/test_resources/collection/client-addition.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/client-addition.txt
@@ -0,0 +1,8 @@
+# ClientAddition
+[37mid[m: # [31mrequired[m
+  # client-side identifier
+  [33m<number>[m # between [32m0[m and [32m255[m
+[37mtime[m: # [31mrequired[m
+  # server-side time
+  # Server time
+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
diff --git a/test_resources/collection/client-id.txt b/test_resources/collection/client-id.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/client-id.txt
@@ -0,0 +1,2 @@
+# ClientId
+[33m<number>[m # between [32m0[m and [32m18446744073709551615[m
diff --git a/test_resources/collection/client-store.txt b/test_resources/collection/client-store.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/client-store.txt
@@ -0,0 +1,36 @@
+# ClientStore
+[37madded[m: # [34moptional[m
+  # default: [35m{}[m
+  # added items
+  [37m<key>[m: 
+    [33m<number>[m # between [32m0[m and [32m255[m
+[37msynced[m: # [34moptional[m
+  # default: [35m{}[m
+  # synced items
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mchanged[m: # [34moptional[m
+  # default: [35m{}[m
+  # changed items
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mdeleted[m: # [34moptional[m
+  # default: [35m{}[m
+  # deleted items
+  [37m<key>[m: 
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
diff --git a/test_resources/collection/request.txt b/test_resources/collection/request.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/request.txt
@@ -0,0 +1,30 @@
+# SyncRequest
+[37madded[m: # [34moptional[m
+  # default: [35m{}[m
+  # new items
+  [37m<key>[m: 
+    [33m<number>[m # between [32m0[m and [32m255[m
+[37msynced[m: # [34moptional[m
+  # default: [35m{}[m
+  # known items
+  [37m<key>[m: 
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mchanged[m: # [34moptional[m
+  # default: [35m{}[m
+  # known but changed items
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mdeleted[m: # [34moptional[m
+  # default: [35m{}[m
+  # deleted items
+  [37m<key>[m: 
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
diff --git a/test_resources/collection/response.txt b/test_resources/collection/response.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/response.txt
@@ -0,0 +1,79 @@
+# SyncResponse
+[37mclient-added[m: # [34moptional[m
+  # default: [35m{}[m
+  # items added by the client
+  [37m<key>[m: 
+    # ClientAddition
+    [37mid[m: # [31mrequired[m
+      # client-side identifier
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # server-side time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mclient-changed[m: # [34moptional[m
+  # default: [35m{}[m
+  # items changed by the client
+  [37m<key>[m: 
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mclient-deleted[m: # [34moptional[m
+  # default: [35m[][m
+  # items deleted by the client
+  - [33m<number>[m # between [32m0[m and [32m255[m
+[37mserver-added[m: # [34moptional[m
+  # default: [35m{}[m
+  # items added by the server
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mserver-changed[m: # [34moptional[m
+  # default: [35m{}[m
+  # items changed by the server
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mserver-deleted[m: # [34moptional[m
+  # default: [35m[][m
+  # items deleted by the server
+  - [33m<number>[m # between [32m0[m and [32m255[m
+[37mconflict[m: # [34moptional[m
+  # default: [35m{}[m
+  # items that were changed simultaneously
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mconflict-client-deleted[m: # [34moptional[m
+  # default: [35m{}[m
+  # items that the server changed while the client deleted it
+  [37m<key>[m: 
+    # Timed
+    [37mvalue[m: # [31mrequired[m
+      # timed value
+      [33m<number>[m # between [32m0[m and [32m255[m
+    [37mtime[m: # [31mrequired[m
+      # timed time
+      # Server time
+      [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mconflict-server-deleted[m: # [34moptional[m
+  # default: [35m[][m
+  # items that the client changed while the server deleted it
+  - [33m<number>[m # between [32m0[m and [32m255[m
diff --git a/test_resources/collection/server-store.txt b/test_resources/collection/server-store.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/collection/server-store.txt
@@ -0,0 +1,9 @@
+[37m<key>[m: 
+  # Timed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
diff --git a/test_resources/item/client.txt b/test_resources/item/client.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/item/client.txt
@@ -0,0 +1,35 @@
+# ClientItem
+# [32mone of[m
+[ [37mtype[m: # [31mrequired[m
+    empty
+  <object>
+, [37mtype[m: # [31mrequired[m
+    added
+  [37mvalue[m: # [31mrequired[m
+    # item that was added, client-side
+    [33m<number>[m # between [32m0[m and [32m255[m
+, [37mtype[m: # [31mrequired[m
+    synced
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    changed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    deleted
+  [37mtime[m: # [31mrequired[m
+    # last time the server confirmed a change, from the client's perspective
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+]
diff --git a/test_resources/item/request.txt b/test_resources/item/request.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/item/request.txt
@@ -0,0 +1,32 @@
+# ItemSyncRequest
+# [32mone of[m
+[ [37mtype[m: # [31mrequired[m
+    empty
+  <object>
+, [37mtype[m: # [31mrequired[m
+    added
+  [37mvalue[m: # [31mrequired[m
+    # item that was added, client-side
+    [33m<number>[m # between [32m0[m and [32m255[m
+, [37mtype[m: # [31mrequired[m
+    synced
+  [37mtime[m: # [31mrequired[m
+    # last time the server confirmed a change, from the client's perspective
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    changed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    deleted
+  [37mtime[m: # [31mrequired[m
+    # last time the server confirmed a change, from the client's perspective
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+]
diff --git a/test_resources/item/response.txt b/test_resources/item/response.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/item/response.txt
@@ -0,0 +1,66 @@
+# ItemSyncResponse
+# [32mone of[m
+[ [37mtype[m: # [31mrequired[m
+    in-sync-empty
+  <object>
+, [37mtype[m: # [31mrequired[m
+    in-sync-full
+  <object>
+, [37mtype[m: # [31mrequired[m
+    client-added
+  [37mtime[m: # [31mrequired[m
+    # server's confirmation of the addition
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    client-changed
+  [37mtime[m: # [31mrequired[m
+    # server's confirmation of the addition
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    client-deleted
+  <object>
+, [37mtype[m: # [31mrequired[m
+    server-added
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    server-changed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    server-deleted
+  <object>
+, [37mtype[m: # [31mrequired[m
+    conflict
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    conflict-client-deleted
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    conflict-server-deleted
+  <object>
+]
diff --git a/test_resources/item/server.txt b/test_resources/item/server.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/item/server.txt
@@ -0,0 +1,11 @@
+# ServerItem
+# [32many of[m
+[ [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, <object>
+]
diff --git a/test_resources/value/client.txt b/test_resources/value/client.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/value/client.txt
@@ -0,0 +1,11 @@
+# ClientValue
+[37mvalue[m: # [31mrequired[m
+  # timed value
+  [33m<number>[m # between [32m0[m and [32m255[m
+[37mtime[m: # [31mrequired[m
+  # timed time
+  # Server time
+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+[37mchanged[m: # [31mrequired[m
+  # whether the value has changed, client-side
+  [33m<boolean>[m
diff --git a/test_resources/value/request.txt b/test_resources/value/request.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/value/request.txt
@@ -0,0 +1,18 @@
+# ValueSyncRequest
+# [32mone of[m
+[ [37mtype[m: # [31mrequired[m
+    synced
+  [37mtime[m: # [31mrequired[m
+    # time at which the server said the value was last synced
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    changed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+]
diff --git a/test_resources/value/response.txt b/test_resources/value/response.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/value/response.txt
@@ -0,0 +1,30 @@
+# ValueSyncResponse
+# [32mone of[m
+[ [37mtype[m: # [31mrequired[m
+    in-sync
+  <object>
+, [37mtype[m: # [31mrequired[m
+    client-changed
+  [37mtime[m: # [31mrequired[m
+    # server time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    server-changed
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+, [37mtype[m: # [31mrequired[m
+    conflict
+  [37mvalue[m: # [31mrequired[m
+    # timed value
+    [33m<number>[m # between [32m0[m and [32m255[m
+  [37mtime[m: # [31mrequired[m
+    # timed time
+    # Server time
+    [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
+]
diff --git a/test_resources/value/server.txt b/test_resources/value/server.txt
new file mode 100644
--- /dev/null
+++ b/test_resources/value/server.txt
@@ -0,0 +1,8 @@
+# ServerValue
+[37mvalue[m: # [31mrequired[m
+  # timed value
+  [33m<number>[m # between [32m0[m and [32m255[m
+[37mtime[m: # [31mrequired[m
+  # timed time
+  # Server time
+  [33m<number>[m # between [32m0[m and [32m18446744073709551615[m
