Quickstart: Do Dispatch Open-Op Lifecycle
Verify the mission end-to-end in a scratch spec-kitty project:
# 1. Dispatch — Op opens, does NOT close
spec-kitty do "fix the flaky retry test" --json | tee /tmp/do.json
# expect: "status": "open", a close_contract object, and kitty-ops/<id>.jsonl
# containing exactly one started event (no completed event)
ID=$(jq -r .invocation_id /tmp/do.json)
# 2. Doctor sees the orphan
spec-kitty doctor ops --json # expect: <id> listed, exit 1
# 3. Agent closes with a real outcome
spec-kitty profile-invocation complete --invocation-id "$ID" --outcome done
# expect: completed event with outcome=done, closed_by=agent;
# auto-commit "op(<profile>): <action> [<id8>]" in git log
# 4. Double close is refused
spec-kitty profile-invocation complete --invocation-id "$ID" --outcome done
# expect: AlreadyClosedError, exit 1
# 5. Stale sweep
spec-kitty do "another task" --json # leave open
spec-kitty doctor ops --close-stale --threshold 0 --json
# expect: swept=1, outcome=abandoned, closed_by=doctor_sweep, auto-committed
# 6. Session presence (Claude Code project)
spec-kitty session-start
# with an open Op present: orientation lists it with the close command
# 7. Migration idempotency (repo with legacy kitty-ops records)
spec-kitty upgrade # runs op-record schema v2 migration
spec-kitty upgrade # second run: no changes (idempotent)
Test suite anchors: tests/specify_cli/invocation/cli/test_do.py (open-Op dispatch), tests/specify_cli/invocation/test_doctor_ops.py (sweep), tests/upgrade/ (migration), tests/specify_cli/invocation/test_propagator*.py (envelope v2).