I think @d6u9d12e has put me on the trail of the answer.
On their advice, I ran which python and which jupyter-book. Python is coming from the virtual environment, but jupyter book is coming from where it's stored on the system.
Next, I edited pyproject.toml to add "jupyter-book==2.*" as a dependency, and running which jupyter book now pointed at the virtual environment.
Unfortunately, that's where my celebrations ended. When I tried to run jupyter book start book, I got this error:
⛔️ myst.yml Cannot (re)load site config. No configuration file found with "site" property.
Cannot (re)load site config. No configuration file found with "site" property.
Do you need to run myst init?
I ran myst init, and got command not found: myst.
Then I tried uv add myst, and got this quite verbose error message.
  × No solution found when resolving dependencies for split
  │ (python_full_version >= '3.14'):
  ╰─▶ Because only jupyter-book<2.dev0 is available and your project
      depends on jupyter-book>=2.dev0, we can conclude that your project's
      requirements are unsatisfiable.
      hint: `jupyter-book` was requested with a pre-release marker (e.g.,
      jupyter-book>=2.dev0), but pre-releases weren't enabled (try:
      `--prerelease=allow`)
  help: If you want to add the package regardless of the failed resolution,
        provide the `--frozen` flag to skip locking and syncing.
So I don't know quite what to do now. I could hammer away changing this and that, but I wouldn't really understand what's going on and that never works out well. If anyone has any further suggestions I would appreciate them.