The Contract State Machine
The Contract State Machine: each transition is a capability whose guard is not an if-statement but an enum predicate on its declared contract (new this round). An illegal transition doesn't fail - it never types-checks in the first place, and the violation names the states that WOULD have been legal.
Developer Experience
Round 4
Piotr Solnica
exit 0
bundle exec ruby examples/state_machine.rb
a real captured run
CONTRACT STATE MACHINE: order ord-7 begins in 'cart' deliver XX cannot deliver from 'cart' (legal from: shipped) - state violated place -> now 'placed' place XX cannot place from 'placed' (legal from: cart) - state violated ship -> now 'shipped' cancel XX cannot cancel from 'shipped' (legal from: cart, placed) - state violated deliver -> now 'delivered' journey: cart -> placed -> shipped -> delivered the machine has no case statement and no runtime transition table: each event's contract declares its legal source states as an enum, and the validator enforces the topology. illegal moves are type errors with the legal alternatives in the message.
source
# frozen_string_literal: true # The Contract State Machine: each transition is a capability whose # guard is not an if-statement but an enum predicate on its declared # contract (new this round). An illegal transition doesn't fail - it # never types-checks in the first place, and the violation names the # states that WOULD have been legal. # # bundle exec ruby examples/state_machine.rb # # Runs offline. Watch "deliver" bounce off a cart-state order. require class="s">"bundler/setup" require class="s">"agentic" # from: is the transition guard, expressed as a contract enum TRANSITIONS = { class="s">"place" => {from: %w[cart], to: class="s">"placed"}, class="s">"ship" => {from: %w[placed], to: class="s">"shipped"}, class="s">"deliver" => {from: %w[shipped], to: class="s">"delivered"}, class="s">"cancel" => {from: %w[cart placed], to: class="s">"canceled"} }.freeze TRANSITIONS.each do |event, rule| spec = Agentic:class="y">:CapabilitySpecification.new( name: event, description: class="s">"Transition an order via #{event}", version: class="s">"1.0.0", inputs: { order_id: {type: class="s">"string", required: true, non_empty: true}, state: {type: class="s">"string", required: true, enum: rule[class="y">:from]} }, outputs: {state: {type: class="s">"string", required: true, enum: [rule[class="y">:to]]}} ) Agentic.register_capability(spec, Agentic:class="y">:CapabilityProvider.new( capability: spec, implementation: ->(inputs) { {state: rule[class="y">:to]} } )) end # The machine: current state + registry lookup. No case statement, # no transition table at runtime - the contracts ARE the table. class Order attr_reader class="y">:id, class="y">:state, class="y">:history def initialize(id) @id = id @state = class="s">"cart" @history = [class="s">"cart"] end def fire(event) provider = Agentic:class="y">:AgentCapabilityRegistry.instance.get_provider(event) or return [class="y">:unknown_event, event] result = provider.execute(order_id: @id, state: @state) @state = result[class="y">:state] @history << @state [class="y">:ok, @state] rescue Agentic:class="y">:Errors:class="y">:ValidationError => e # The violation now carries the contract's expectation - no # side-channel lookup into the transition table needed allowed = e.expectations.dig(class="y">:state, class="y">:enum) || [] [class="y">:illegal, class="s">"cannot #{event} from '#{@state}' (legal from: #{allowed.join(", class="s">")}) - #{e.violations.keys.join(", class="s">")} violated"] end end order = Order.new(class="s">"ord-7") SCRIPT = %w[deliver place place ship cancel deliver].freeze puts class="s">"CONTRACT STATE MACHINE: order #{order.id} begins in 'cart'" puts SCRIPT.each do |event| verdict, detail = order.fire(event) case verdict when class="y">:ok then puts format(class="s">" %-8s -> now '%s'", event, detail) when class="y">:illegal then puts format(class="s">" %-8s XX %s", event, detail) when class="y">:unknown_event then puts format(class="s">" %-8s ?? no such transition", event) end end puts puts class="s">"journey: #{order.history.join(" -> class="s">")}" puts puts class="s">"the machine has no case statement and no runtime transition table:" puts class="s">"each event's contract declares its legal source states as an enum," puts class="s">"and the validator enforces the topology. illegal moves are type" puts class="s">"errors with the legal alternatives in the message."