Skip to content

Document and enforce Turn state machine transitions (INV-5) #21

Closed

Description

@rororowyourboat

Context

From the system design audit, the Turn lifecycle has implicit but undocumented state transitions. The decider does not currently guard against all invalid transitions.

Current State

  • Turn states: running, interrupted, completed, error
  • No "resume" command exists (confirmed in decider.ts)
  • But the decider does not explicitly check for an already-active turn before thread.turn.start
  • Terminal states (interrupted, completed, error) are terminal by convention, not by guard

Design Decision (from spec)

INV-5: Turn states are terminal except running. No transition from interrupted/error back to running. Always start a new turn.

INV-4: At most one active Turn per Thread at any time.

Proposed Changes

  1. Add a guard in the decider for thread.turn.start that rejects if latestTurn.state === "running"
  2. Add explicit assertions or guards preventing any state transition from a terminal state
  3. Add unit tests covering all forbidden transitions:
    • interrupted -> running (must reject)
    • error -> running (must reject)
    • completed -> running (must reject)
    • running -> running (duplicate start, must reject)

Acceptance Criteria

  • Decider rejects thread.turn.start when a turn is already in running state
  • Forbidden transitions are tested
  • State machine diagram documented (see .plans/21-system-design-spec.md Section 5)

References

  • System Design Spec: .plans/21-system-design-spec.md Section 5 (Turn State Machine)
  • Audit finding: "Turn lifecycle has missing transitions and ambiguous terminal states"

Activity

  1. rororowyourboat commented on Apr 10, 2026

    @rororowyourboat
    OwnerAuthor

    Implemented in decider guards commit — turn.start guard rejects if latestTurn.state===running, state machine documented

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions