Quickstart: Verify the Shared Package Boundary Cutover

Mission: shared-package-boundary-cutover-01KQ22DS

This document is the local-runnable verification recipe for the cutover. After the mission merges, anyone can follow these steps to prove on their own machine that the CLI's runtime is internal and that no spec-kitty-runtime install is required.


Prerequisites

  • Python 3.11+ (the CLI's documented minimum).
  • A clean shell with no VIRTUAL_ENV set.
  • git, uv (preferred) or pip + venv (fallback).

Step 1: Build the CLI wheel from source

cd /path/to/spec-kitty
uv build --wheel       # or: python -m build --wheel
ls dist/spec_kitty_cli-*.whl

You should see a single wheel file. Note its name — you will install it in a fresh environment in Step 3.

Step 2: Confirm the source tree has no vendored events

test ! -d src/specify_cli/spec_kitty_events && echo OK || echo "FAIL: vendored events tree still present"

Expected output: OK. If you see FAIL, the cutover regressed.

Step 3: Create a clean, isolated venv with no spec-kitty-runtime

mktemp -d -t cutover-verify
cd "$(mktemp -d -t cutover-verify)"
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip

# Confirm no spec-kitty-* packages are present yet
pip list | grep -i 'spec-kitty' || echo "OK: clean venv"

Step 4: Install the CLI from the wheel

pip install /path/to/spec-kitty/dist/spec_kitty_cli-*.whl

Step 5: Verify spec-kitty-runtime is NOT installed as a transitive dep

pip list | grep -i 'spec-kitty-runtime' && echo "FAIL: runtime got pulled in" || echo "OK: no runtime"

Expected output: OK: no runtime. The grep MUST return zero matches.

Step 6: Run spec-kitty next against a fixture mission

cp -r /path/to/spec-kitty/tests/fixtures/clean_install_fixture_mission ./fixture
cd fixture
git init -q
git add -A
git -c user.email=t@t -c user.name=t commit -q -m "fixture mission"

spec-kitty agent mission setup-plan --mission <fixture-handle> --json | jq .result
spec-kitty next --agent claude --mission <fixture-handle> --json | jq .result

Both calls should return "success". The second call advances the mission's runtime loop by one step and emits at least one StatusEvent in kitty-specs/<fixture-mission>/status.events.jsonl.

Step 7: Confirm CLI did not implicitly import spec_kitty_runtime

python -c "
import importlib, sys
import specify_cli  # triggers CLI module load
assert 'spec_kitty_runtime' not in sys.modules, sorted(k for k in sys.modules if 'runtime' in k.lower())
print('OK: spec_kitty_runtime not imported by CLI module load')
"

Expected output: OK: spec_kitty_runtime not imported by CLI module load.

Step 8: Verify events / tracker are consumed only via public PyPI imports

python -c "
import spec_kitty_events  # PyPI public surface
import spec_kitty_tracker  # PyPI public surface
print('events:', spec_kitty_events.__file__)
print('tracker:', spec_kitty_tracker.__file__)
"

The printed paths should be inside site-packages/ (the PyPI installs), not inside the CLI's source tree. If either path points inside specify_cli/, the cutover regressed.


What this verifies (mapped to spec acceptance criteria)

StepAcceptance criterion
1A1, A6 — wheel build path remains operational
2A4 (FR-003), NS-2 from data-model
3Setup for A1
4A1, A6
5A1, A2, A3 — proves spec-kitty-runtime is not installed
6A1, A6 — proves spec-kitty next works without runtime
7A3 — proves no production import of spec_kitty_runtime
8A4 — proves events / tracker consumed via PyPI

Troubleshooting

pip list shows spec-kitty-runtime after Step 4.

The CLI wheel pulled it as a transitive dependency. Inspect with pip show spec-kitty-runtime to find which package required it. If it is required by an unrelated package the user has installed locally, that is fine — the assertion that matters is "the CLI does not require it." Re-run Step 4 in a strictly isolated environment:

deactivate
rm -rf .venv
python -m venv .venv
source .venv/bin/activate
pip install /path/to/spec-kitty/dist/spec_kitty_cli-*.whl
pip list | grep -i 'spec-kitty-runtime'

If the assertion still fails, the cutover regressed. Open a P0 incident and re-run the architectural test:

pytest tests/architectural/test_shared_package_boundary.py -v

spec-kitty next fails with ModuleNotFoundError: No module named 'spec_kitty_runtime'.

The internalized runtime is missing or runtime_bridge.py was not cut over. This is a hard regression of the cutover. Re-run the architectural test and file a P0.

spec-kitty next fails with ModuleNotFoundError: No module named 'specify_cli.spec_kitty_events'.

Some consumer was missed during WP04; an old import path is still live. Re-run:

grep -rn "specify_cli.spec_kitty_events" src/

If anything matches in src/, that is the regression site.


CI counterpart

The clean-install verification job in .github/workflows/ci-quality.yml runs the equivalent of Steps 3..7 in a fresh container on every PR. If this quickstart fails locally but the CI job is green, your local environment is contaminated — the canonical answer is the CI job.