diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,22 @@
 
 ## Unreleased
 
+## 0.2.0.3 — 2026-08-29
+
+### Changed
+
+- Every library dependency now carries a PVP upper bound: `aeson`, `bytestring`,
+  `effectful`. `cabal check` reported these under `missing-upper-bounds`.
+  Without one, a future breaking release of a dependency enters a consumer's
+  build plan unchecked — which is the failure the bound exists to prevent.
+
+  Each bound admits the version this package is built and tested against and
+  stops below the next major.
+
+  `aeson` stops at `<2.3` rather than `<2.4`: baikai-openai 0.5 constrains it to
+  `^>=2.2`, so aeson 2.3 is not reachable for this cohort and a wider bound
+  would assert compatibility that cannot be exercised here.
+
 ## 0.2.0.2 — 2026-08-07
 
 ### Changed
diff --git a/shikumi-compile.cabal b/shikumi-compile.cabal
--- a/shikumi-compile.cabal
+++ b/shikumi-compile.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.4
 name:            shikumi-compile
-version:         0.2.0.2
+version:         0.2.0.3
 synopsis:        The compiler layer for shikumi LM programs (EP-9)
 category:        AI
 description:
@@ -48,10 +48,10 @@
     Shikumi.Compile.ZeroShot
 
   build-depends:
-    , aeson
+    , aeson         >=2.2      && <2.3
     , base          >=4.20     && <5
-    , bytestring
-    , effectful
+    , bytestring    >=0.11     && <0.13
+    , effectful     >=2.5      && <2.7
     , generic-lens  >=2.2      && <2.4
     , lens          ^>=5.3
     , shikumi       ^>=0.3.0.0
@@ -69,7 +69,7 @@
 
   build-depends:
     , aeson
-    , baikai           >=0.5      && <0.6
+    , baikai           >=0.6      && <0.7
     , base
     , bytestring
     , effectful
diff --git a/test/Test/Fixtures.hs b/test/Test/Fixtures.hs
--- a/test/Test/Fixtures.hs
+++ b/test/Test/Fixtures.hs
@@ -34,8 +34,8 @@
 import Baikai
   ( AssistantContent (..),
     Response,
-    _Response,
-    _TextContent,
+    emptyResponse,
+    emptyTextContent,
   )
 import Control.Lens ((&), (.~))
 import Data.Aeson (FromJSON, ToJSON)
@@ -112,7 +112,7 @@
 -- | An assistant 'Response' carrying @t@ as its single text block.
 mkResponse :: Text -> Response
 mkResponse t =
-  _Response & #message . #content .~ V.singleton (AssistantText (_TextContent & #text .~ t))
+  emptyResponse & #message . #content .~ V.singleton (AssistantText (emptyTextContent & #text .~ t))
 
 -- | Decodes as an @Answer@ under the fallback adapter.
 answerResponse :: Response
