1 import Base 2 import ./change_tick.bend as Tick 3 import ./trace_facts.bend as TraceFacts 4 import ./world.bend as W 5 import ./registration.bend as Reg 6 7 # Closed runner index is erased; the runtime registration owner remains affine. 8 # System completion retains World on both branches. Success also owns 9 # Output; failure carries only Error, so affine body outputs are not returned 10 # by this type. Rollback is performed by the chosen runner, not this constructor. 11 type Outcome is Type: 12 Succeeded{world: World,output: Output} 13 Failed{world: World,error: Error} 14 # Affine registration owner with runtime namespace, actual registration ID, 15 # metadata and lifecycle cursor. The erased runner binds argument/result types; 16 # raw construction is trusted administration, not a way to confer gameplay access. 17 type Registry -> Args -> Outcome,Error,Output>> is Type: 18 Registry{namespace: U32,id: U32,name: String,access: List<&2,String>,cursor: Maybe<&2,Tick.Tick>} 19 # Registered returns World and the new Registry; RegistrationFailed returns 20 # World without a registration owner. Registration does not invoke the runner. 21 type RegistrationResult -> Args -> Outcome,Error,Output>> is Type: 22 Registered{world: W.World,registry: Registry} 23 RegistrationFailed{world: W.World} 24 # Completed retains Registry and a runner Outcome. RegistrationRejected 25 # retains Registry, World and original Args without invoking the runner. 26 # Rejection is distinct from a body failure that has consumed Args. 27 type RunResult -> Args -> Outcome,Error,Output>> is Type: 28 Completed{registry: Registry,outcome: Outcome,Error,Output>} 29 RegistrationRejected{registry: Registry,world: W.World,args: Args} 30 31 def register_meta(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,world: W.World,result: W.Registration,+namespace: U32,+name: String,+access: List<&2,String>) -> RegistrationResult: 32 match result: 33 case W.RegistrationRejected{_}: RegistrationFailed{world} 34 case W.Registered{id}: Registered{world,Registry{namespace,id,name,access,None{}}} 35 36 def register_join(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registered: W.World & W.Registration,+namespace: U32,+name: String,+access: List<&2,String>) -> RegistrationResult: 37 (world,result) = registered 38 register_meta(~S,~C,~R,~E,~Args,~Error,~Output,~runner,world,result,namespace,name,access) 39 40 def register_namespace(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,named: W.World & U32,+name: String,+access: List<&2,String>) -> RegistrationResult: 41 (world,+namespace) = named 42 register_join(~S,~C,~R,~E,~Args,~Error,~Output,~runner,W.register(~S,~C,~R,~E,world,name,access),namespace,name,access) 43 44 # Register the closed runner in this World with name/access metadata. 45 # Returns Registered or RegistrationFailed, retaining World on either path. 46 # Raw access strings are metadata; actual body capabilities come from its 47 # declared runner. Prefer ordinary-system or App registration for derived access. 48 def register(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,world: W.World,+name: String,+access: List<&2,String>) -> RegistrationResult: 49 register_namespace(~S,~C,~R,~E,~Args,~Error,~Output,~runner,W.namespace(~S,~C,~R,~E,world),name,access) 50 51 def complete(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,outcome: Outcome,Error,Output>) -> RunResult: 52 Completed{registry,outcome} 53 54 # Leave the captured scope on either executed outcome; never rewind time. 55 def leave_outcome(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,outcome:Outcome,Error,Output>) -> Outcome,Error,Output>: 56 match outcome: 57 case Succeeded{world,output}:Succeeded{W.leave_run(~S,~C,~R,~E,world),output} 58 case Failed{world,error}:Failed{W.leave_run(~S,~C,~R,~E,world),error} 59 60 def executed_registry(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,registry:Registry,tick:Tick.Tick) -> Registry: 61 match registry: 62 case Registry{namespace,id,name,access,_}:Registry{namespace,id,name,access,Some{tick}} 63 64 def run_entered(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,registry:Registry,args:Args,entered:W.World & Tick.Tick) -> RunResult: 65 (world,tick)=entered 66 complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner,executed_registry(~S,~C,~R,~E,~Args,~Error,~Output,~runner,registry,tick),leave_outcome(~S,~C,~R,~E,~Args,~Error,~Output,~runner,runner(world,args))) 67 68 def run_checked(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,allowed: Bool,registry: Registry,world: W.World,args: Args) -> RunResult: 69 match allowed: 70 case False{}: RegistrationRejected{registry,world,args} 71 case True{}: run_entered(~S,~C,~R,~E,~Args,~Error,~Output,~runner,registry,args,W.enter_run(~S,~C,~R,~E,world)) 72 73 def run_metadata(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,checked: W.World & Bool,args: Args) -> RunResult: 74 (world,allowed) = checked 75 run_checked(~S,~C,~R,~E,~Args,~Error,~Output,~runner,allowed,registry,world,args) 76 77 def run_namespace_checked(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,allowed: Bool,registry: Registry,world: W.World,args: Args) -> RunResult: 78 match allowed registry: 79 case False{} registry: RegistrationRejected{registry,world,args} 80 case True{} Registry{+namespace,+id,+name,+access,+cursor}: run_metadata(~S,~C,~R,~E,~Args,~Error,~Output,~runner,Registry{namespace,id,name,access,cursor},W.registration_matches(~S,~C,~R,~E,world,id,name,access),args) 81 82 def run_namespace_value(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,world: W.World,+actual: U32,args: Args) -> RunResult: 83 match registry: 84 case Registry{+namespace,+id,+name,+access,+cursor}: run_namespace_checked(~S,~C,~R,~E,~Args,~Error,~Output,~runner,U32.is_eq(namespace,actual),Registry{namespace,id,name,access,cursor},world,args) 85 86 def run_namespace(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,named: W.World & U32,args: Args) -> RunResult: 87 (world,+actual) = named 88 run_namespace_value(~S,~C,~R,~E,~Args,~Error,~Output,~runner,registry,world,actual,args) 89 90 # Validate runtime namespace and live registration metadata, then invoke 91 # the runner. Rejection returns original Args, World and Registry unchanged 92 # in ownership; completed failure returns only the runner Error/World. 93 # Every admitted execution captures this_run and records it on success or error. 94 # Rejection leaves time/cursor unchanged. Runner defines rollback behavior. 95 def run(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,world: W.World,args: Args) -> RunResult: 96 run_namespace(~S,~C,~R,~E,~Args,~Error,~Output,~runner,registry,W.namespace(~S,~C,~R,~E,world),args) 97 98 # Return Registry and its current lifecycle cursor, without advancing it 99 # or reading any component/event stream. 100 def cursor(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry) -> Registry & Maybe<&2,Tick.Tick>: 101 match registry: 102 case Registry{+namespace,+id,+name,+access,+cursor}: (Registry{namespace,id,name,access,cursor},cursor) 103 104 # Instance identity is observed without consuming the registration owner. 105 # Return Registry and its actual registration ID without consuming the owner. 106 # IDs must still be validated with namespace/live metadata before execution. 107 def identity(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry) -> Registry & U32: 108 match registry: 109 case Registry{namespace,+id,name,access,cursor}: (Registry{namespace,id,name,access,cursor},id) 110 111 # Rejected disposal returns the registration; accepted disposal consumes it. 112 # Disposed returns World and consumes this registration owner. 113 # DisposalRejected returns World and Registry for retry or explicit recovery. 114 # This type introduces no user-payload finalizer or capture-disposal callback. 115 type Disposal -> Args -> Outcome,Error,Output>> is Type: 116 Disposed{world: W.World} 117 DisposalRejected{world: W.World,registry: Registry} 118 119 def dispose_returned(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,observed: W.World & Bool) -> Disposal: 120 match observed: 121 case (world,True{}): Disposed{world} 122 case (world,False{}): DisposalRejected{world,registry} 123 124 # Remove a registration only when its namespace/ID/name/access still match. 125 # Success consumes Registry; refusal returns it with World. Does not dispose 126 # unrelated retained Local/capture owners or invent implicit finalizers. 127 def dispose(~S: Data,~C: Type,~R: Type,~E: Data,~Args: Type,~Error: Data,~Output: Type,~runner: W.World -> Args -> Outcome,Error,Output>,registry: Registry,world: W.World) -> Disposal: 128 match registry: 129 case Registry{+namespace,+id,+name,+access,cursor}: dispose_returned(~S,~C,~R,~E,~Args,~Error,~Output,~runner,Registry{namespace,id,name,access,cursor},Reg.remove(~S,~C,~R,~E,world,namespace,id,name,access)) 130 131 # Trusted canonical runner transport. Registration is checked before the body. 132 def observed_outcome_with(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,result:Outcome,Error,Output> & TraceFacts.State) -> RunResult & TraceFacts.State: 133 match result: 134 case (outcome,trace):(finish(registry,leave_outcome(~S,~C,~R,~E,~Args,~Error,~Output,~runner,outcome)),trace) 135 def observed_entered(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,trace:TraceFacts.State,args:Args,entered:W.World & Tick.Tick) -> RunResult & TraceFacts.State: 136 (world,tick)=entered 137 observed_outcome_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~finish,executed_registry(~S,~C,~R,~E,~Args,~Error,~Output,~runner,registry,tick),observed(trace,world,args)) 138 def observed_checked_with(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,trace:TraceFacts.State,checked:W.World & Bool,args:Args) -> RunResult & TraceFacts.State: 139 match checked: 140 case (world,False{}):(RegistrationRejected{registry,world,args},trace) 141 case (world,True{}):observed_entered(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~finish,registry,trace,args,W.enter_run(~S,~C,~R,~E,world)) 142 def observed_namespace_checked_with(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,trace:TraceFacts.State,world:W.World,args:Args,allowed:Bool) -> RunResult & TraceFacts.State: 143 match registry allowed: 144 case registry False{}:(RegistrationRejected{registry,world,args},trace) 145 case Registry{+namespace,+id,+name,+access,+cursor} True{}:observed_checked_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~finish,Registry{namespace,id,name,access,cursor},trace,W.registration_matches(~S,~C,~R,~E,world,id,name,access),args) 146 def observed_named_with(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,trace:TraceFacts.State,named:W.World & U32,args:Args) -> RunResult & TraceFacts.State: 147 match registry named: 148 case Registry{+namespace,+id,+name,+access,+cursor}, (world,actual):observed_namespace_checked_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~finish,Registry{namespace,id,name,access,cursor},trace,world,args,U32.is_eq(namespace,actual)) 149 # Trusted transport for an observed runner and custom completion policy. 150 # Validates registration before invoking observed; refusal returns original 151 # Args/owners and trace. finish receives the executed cursor; raw callbacks must 152 # preserve their relationship to runner and its transaction contract. 153 def run_observed_with(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,~finish:Registry -> Outcome,Error,Output> -> RunResult,registry:Registry,trace:TraceFacts.State,world:W.World,args:Args) -> RunResult & TraceFacts.State: 154 observed_named_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~finish,registry,trace,W.namespace(~S,~C,~R,~E,world),args) 155 156 def observed_outcome(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,registry:Registry,result:Outcome,Error,Output> & TraceFacts.State) -> RunResult & TraceFacts.State: 157 observed_outcome_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner),registry,result) 158 def observed_checked(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,registry:Registry,trace:TraceFacts.State,checked:W.World & Bool,args:Args) -> RunResult & TraceFacts.State: 159 observed_checked_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner),registry,trace,checked,args) 160 def observed_namespace_checked(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,registry:Registry,trace:TraceFacts.State,world:W.World,args:Args,allowed:Bool) -> RunResult & TraceFacts.State: 161 observed_namespace_checked_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner),registry,trace,world,args,allowed) 162 def observed_named(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,registry:Registry,trace:TraceFacts.State,named:W.World & U32,args:Args) -> RunResult & TraceFacts.State: 163 observed_named_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner),registry,trace,named,args) 164 # Observed execution captures and records this_run on success or failure. 165 # Refusal preserves Args, time, cursor and trace. 166 # Returned facts describe execution, not additional ECS work to apply. 167 def run_observed(~S:Data,~C:Type,~R:Type,~E:Data,~Args:Type,~Error:Data,~Output:Type,~runner:W.World -> Args -> Outcome,Error,Output>,~observed:TraceFacts.State -> W.World -> Args -> Outcome,Error,Output> & TraceFacts.State,registry:Registry,trace:TraceFacts.State,world:W.World,args:Args) -> RunResult & TraceFacts.State: 168 run_observed_with(~S,~C,~R,~E,~Args,~Error,~Output,~runner,~observed,~complete(~S,~C,~R,~E,~Args,~Error,~Output,~runner),registry,trace,world,args)