Add runtime and commitment state machines

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 11:41:40 -04:00
parent 0a934bf061
commit de40fe73c7
2 changed files with 169 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
// Package statemachine holds the pure runtime and commitment transition
// functions ported from the Rust implementation. No I/O, no shared state.
package statemachine
import (
"fmt"
"antidrift/internal/domain"
)
// RuntimeAction enumerates runtime transitions. Activate's policy acceptance
// and admin-override exit targets from the Rust enum are flattened into
// distinct actions so the action type stays a simple value.
type RuntimeAction string
const (
EnterPlanning RuntimeAction = "enter_planning"
CancelOrTimeout RuntimeAction = "cancel_or_timeout"
ActivateAccepted RuntimeAction = "activate_accepted"
ActivateRejected RuntimeAction = "activate_rejected"
StartTransition RuntimeAction = "start_transition"
CompleteForReview RuntimeAction = "complete_for_review"
SevereViolation RuntimeAction = "severe_violation"
ReturnToActive RuntimeAction = "return_to_active"
SwitchTask RuntimeAction = "switch_task"
EndTransitionForReview RuntimeAction = "end_transition_for_review"
ContinuePlanning RuntimeAction = "continue_planning"
EndWorkPeriod RuntimeAction = "end_work_period"
EnterAdminOverride RuntimeAction = "enter_admin_override"
ExitAdminOverrideToLocked RuntimeAction = "exit_admin_override_to_locked"
ExitAdminOverrideToPlanning RuntimeAction = "exit_admin_override_to_planning"
)
type CommitmentAction string
const (
CommitmentActivate CommitmentAction = "activate"
PauseForTransition CommitmentAction = "pause_for_transition"
ReturnFromPause CommitmentAction = "return_from_pause"
Complete CommitmentAction = "complete"
Abandon CommitmentAction = "abandon"
Violate CommitmentAction = "violate"
RecoverExplicitly CommitmentAction = "recover_explicitly"
)
// IllegalTransitionError reports a rejected transition.
type IllegalTransitionError struct {
From string
Action string
}
func (e IllegalTransitionError) Error() string {
return fmt.Sprintf("illegal transition from %s via %s", e.From, e.Action)
}
// PolicyRejectedError reports an activation attempted with an unaccepted policy.
type PolicyRejectedError struct{}
func (PolicyRejectedError) Error() string { return "policy was rejected" }
func TransitionRuntime(current domain.RuntimeState, action RuntimeAction) (domain.RuntimeState, error) {
type key struct {
s domain.RuntimeState
a RuntimeAction
}
table := map[key]domain.RuntimeState{
{domain.RuntimeLocked, EnterPlanning}: domain.RuntimePlanning,
{domain.RuntimePlanning, ActivateAccepted}: domain.RuntimeActive,
{domain.RuntimePlanning, CancelOrTimeout}: domain.RuntimeLocked,
{domain.RuntimeActive, StartTransition}: domain.RuntimeTransition,
{domain.RuntimeActive, CompleteForReview}: domain.RuntimeReview,
{domain.RuntimeActive, SevereViolation}: domain.RuntimeLocked,
{domain.RuntimeTransition, ReturnToActive}: domain.RuntimeActive,
{domain.RuntimeTransition, SwitchTask}: domain.RuntimePlanning,
{domain.RuntimeTransition, EndTransitionForReview}: domain.RuntimeReview,
{domain.RuntimeTransition, CancelOrTimeout}: domain.RuntimeLocked,
{domain.RuntimeReview, ContinuePlanning}: domain.RuntimePlanning,
{domain.RuntimeReview, EndWorkPeriod}: domain.RuntimeLocked,
{domain.RuntimeAdminOverride, ExitAdminOverrideToLocked}: domain.RuntimeLocked,
{domain.RuntimeAdminOverride, ExitAdminOverrideToPlanning}: domain.RuntimePlanning,
}
if action == ActivateRejected && current == domain.RuntimePlanning {
return current, PolicyRejectedError{}
}
if action == EnterAdminOverride {
return domain.RuntimeAdminOverride, nil
}
if next, ok := table[key{current, action}]; ok {
return next, nil
}
return current, IllegalTransitionError{From: string(current), Action: string(action)}
}
func TransitionCommitment(current domain.CommitmentState, action CommitmentAction) (domain.CommitmentState, error) {
type key struct {
s domain.CommitmentState
a CommitmentAction
}
table := map[key]domain.CommitmentState{
{domain.CommitmentDraft, CommitmentActivate}: domain.CommitmentActive,
{domain.CommitmentActive, PauseForTransition}: domain.CommitmentPaused,
{domain.CommitmentPaused, ReturnFromPause}: domain.CommitmentActive,
{domain.CommitmentActive, Complete}: domain.CommitmentCompleted,
{domain.CommitmentActive, Abandon}: domain.CommitmentAbandoned,
{domain.CommitmentActive, Violate}: domain.CommitmentViolated,
{domain.CommitmentPaused, Abandon}: domain.CommitmentAbandoned,
{domain.CommitmentViolated, RecoverExplicitly}: domain.CommitmentActive,
{domain.CommitmentViolated, Abandon}: domain.CommitmentAbandoned,
}
if next, ok := table[key{current, action}]; ok {
return next, nil
}
return current, IllegalTransitionError{From: string(current), Action: string(action)}
}