Quickstart — WP Lane FSM
Exercise the FSM (single authority)
from specify_cli.status.models import Lane
from specify_cli.status.wp_state import wp_state_for
from specify_cli.status.transition_context import TransitionContext
s = wp_state_for(Lane.GENESIS)
s.current_lane # Lane.GENESIS
s.may_transition_to(Lane.PLANNED) # True (structural edge)
s.may_transition_to(Lane.CLAIMED) # False (must seed first)
# Full transition — edge + guard + force decided by the State object (DM-01KTH03G)
ctx = TransitionContext(actor="claude", ...)
s.transition_to(Lane.PLANNED, ctx) # -> PlannedState ; raises InvalidTransitionError on reject
validate_transition(from, to, ctx) now delegates to the state and returns (ok, error_message) — identical results to before, one owner.
Verify the invariants
# I1 single source: derived matrix == states' edges; no parallel transition table
PYTHONPATH=src python3 -c "from specify_cli.status.transitions import ALLOWED_TRANSITIONS; print(len(ALLOWED_TRANSITIONS))"
# I2 genesis non-display: absent from CANONICAL_LANES and from a materialized summary
PYTHONPATH=src python3 -c "from specify_cli.status_lanes import CANONICAL_LANES; print('genesis' in CANONICAL_LANES)" # False
# Targeted suites (NOT the full suite — it is slow)
python -m pytest tests/status/ tests/specify_cli/status/ -q
python -m pytest tests/specify_cli/coordination/ tests/sync/ -q
Validate the mission's acceptance
genesis → plannedseed persists and survivesfinalize-tasks(no clobber).- An unseeded
implementfails with "run finalize-tasks" and leaves no worktree. - A genesis seed produces a contract-valid SaaS payload (post
spec_kitty_eventsbump). ruff+mypyclean on touched modules; existing transition/guard suites green (behavior preserved).