1 import Base 2 import ./ordinary_condition_composition.bend as Comp 3 import ordinary_app_recipe.bend as Tree 4 import ordinary_app_schema.bend as App 5 import ordinary_app_composer.bend as Build 6 import ordinary_app_registration_fields.bend as Records 7 import ordinary_app_observation_data.bend as DTO 8 import ordinary_schema.bend as Schema 9 import world.bend as W 10 import system.bend as Sys 11 import schedule.bend as Sch 12 import schedule_provision.bend as SP 13 # Plan is ordinary operational input; only enabled snapshots lower its description. 14 # Detached schedule step plus its declared provisioning requirements. 15 # Description order follows the operational plan, including explicit barriers. 16 type PlannedStep is Data: 17 PlannedStep{step:Sch.Step,requirements:List<&2,SP.Requirement>} 18 # Detached enabled-debug view of an application and its selected schedule. 19 # Contains observations and metadata, not affine owners or a restorable save. 20 type Description is Data: 21 Description{application:App.Description,namespace:U32,name:String,steps:List<&2,PlannedStep>} 22 # An application with an explicit validated schedule and its retained owners. 23 # This lower-level layer requires dispatch/condition/provision callbacks on run; 24 # ordinary-app-run derives those callbacks from existing registrations. 25 type Application -> W.World & DTO.Observation,-fold:H -> H & List<&2,Records.Fields>> is Type: 26 Application{app:App.Application,plan:SP.Plan,namespace:U32,name:String,steps:List<&2,Sch.Step>,needs:List<&2,SP.Requirement>} 27 # Schedule attachment returns Attached with the scheduled owner or Invalid 28 # with the original application owner. Refusal does not discard the application. 29 type Attachment<-Original:Type,-Scheduled:Type> is Type: 30 Attached{app:Scheduled} 31 Invalid{app:Original} 32 # Outcome retaining the affine application in every branch. Finished carries 33 # schedule observations; Failed also carries the system/condition error; 34 # Rejected denotes schedule refusal; Missing lists unavailable requirements. 35 # Failed execution can retain earlier committed systems; it is not whole-run rollback. 36 type RunResult<-A:Type,-S:Data,-Error:Data> is Type: 37 Finished{app:A,observations:List<&2,Sch.Observation>} 38 Failed{app:A,error:Error,observations:List<&2,Sch.Observation>} 39 Rejected{app:A} 40 Missing{app:A,requirements:List<&2,SP.Requirement>} 41 def planned(~S:Data,plan:SP.Plan) -> List<&2,PlannedStep>: 42 match plan: 43 case SP.Empty{}:[] 44 case SP.Entry{step,needs}:[PlannedStep{step,needs}] 45 case SP.Sequence{left,right}:List.append(&2,PlannedStep,planned(~S,left),planned(~S,right)) 46 def ids(registrations:List<&2,W.RegistrationMeta>) -> List<&2,U32>: 47 match registrations: 48 case []:[] 49 case W.RegistrationMeta{id,_,_} <> rest:id <> ids(rest) 50 def catalog(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World) -> W.World & (U32 & List<&2,U32>): 51 match world: 52 case W.World{+namespace,allocator,store,resource,events,pending,+registrations,nextSystemId,clock}:(W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock},(namespace,ids(registrations))) 53 def built(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,schema:Schema.Schema,world:W.World,recipe:Tree.Recipe,Rows,observe>,debug:Bool,+plan:SP.Plan,result:SP.Build) -> Attachment,Application>: 54 match result: 55 case SP.Invalid{owners}:Invalid{App.Application{schema,Build.Registered{world,owners,recipe,debug}}} 56 case SP.Built{SP.Provisioned{Sch.Schedule{namespace,name,steps,owners},needs}}:Attached{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs}} 57 def cataloged(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,schema:Schema.Schema,owners:H,recipe:Tree.Recipe,Rows,observe>,debug:Bool,+plan:SP.Plan,name:String,result:W.World & (U32 & List<&2,U32>)) -> Attachment,Application>: 58 match result: 59 case (world,(namespace,known)):built(~S,~C,~R,~E,~H,~Rows,~observe,~fold,schema,world,recipe,debug,plan,SP.build(~S,~C,~R,~E,~H,namespace,name,plan,known,owners)) 60 # Attach an explicit operational plan to an application, validating steps 61 # against its current registration catalog. Returns Attached or Invalid with 62 # the original owner. Does not execute bodies or flush pending commands. 63 # Prefer ordinary-app-run.attach for a plan derived from registrations. 64 def attach(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,app:App.Application,name:String,plan:SP.Plan) -> Attachment,Application>: 65 match app: 66 case App.Application{schema,Build.Registered{world,owners,recipe,debug}}:cataloged(~S,~C,~R,~E,~H,~Rows,~observe,~fold,schema,owners,recipe,debug,plan,name,catalog(~S,~C,~R,~E,world)) 67 # Return the scheduled application with debug toggled; preserve its world, 68 # plan and invocation owners. This call does not run or inspect any system. 69 def enabled(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,value:Application,flag:Bool) -> Application: 70 match value: 71 case Application{app,plan,namespace,name,steps,needs}:Application{App.enabled(~S,~C,~R,~E,~H,~Rows,~observe,~fold,app,flag),plan,namespace,name,steps,needs} 72 def observed(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,+plan:SP.Plan,+namespace:U32,+name:String,steps:List<&2,Sch.Step>,needs:List<&2,SP.Requirement>,result:App.Application & Maybe<&2,App.Description>) -> Application & Maybe<&2,Description>: 73 match result: 74 case (app,None{}):(Application{app,plan,namespace,name,steps,needs},None{}) 75 case (app,Some{view}):(Application{app,plan,namespace,name,steps,needs},Some{Description{view,namespace,name,planned(~S,plan)}}) 76 # Return the retained application and an optional detached debug description. 77 # Disabled debug yields None. Enabled observation describes the operational 78 # plan without running it or consuming system lifecycle/event cursors. 79 # Example: examples/scheduled-health/registration.bend uses ordinary-app-run.snapshot. 80 def snapshot(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,value:Application) -> Application & Maybe<&2,Description>: 81 match value: 82 case Application{app,plan,namespace,name,steps,needs}:observed(~S,~C,~R,~E,~H,~Rows,~observe,~fold,plan,namespace,name,steps,needs,App.snapshot(~S,~C,~R,~E,~H,~Rows,~observe,~fold,app)) 83 def executed(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~Error:Data,schema:Schema.Schema,recipe:Tree.Recipe,Rows,observe>,debug:Bool,plan:SP.Plan,needs:List<&2,SP.Requirement>,result:Sch.RunResult) -> RunResult,S,Error>: 84 match result: 85 case Sch.Finished{Sch.Schedule{namespace,name,steps,owners},world,observations}:Finished{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},observations} 86 case Sch.Failed{Sch.Schedule{namespace,name,steps,owners},world,error,observations}:Failed{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},error,observations} 87 case Sch.Rejected{Sch.Schedule{namespace,name,steps,owners},world}:Rejected{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs}} 88 def provisioned(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~Error:Data,schema:Schema.Schema,recipe:Tree.Recipe,Rows,observe>,debug:Bool,plan:SP.Plan,result:SP.ProvisionResult) -> RunResult,S,Error>: 89 match result: 90 case SP.Missing{SP.Provisioned{Sch.Schedule{namespace,name,steps,owners},needs},world,missing}:Missing{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},missing} 91 case SP.Executed{result,needs}:executed(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~Error,schema,recipe,debug,plan,needs,result) 92 # Advanced execution of an explicit schedule with supplied callbacks. Checks 93 # provisioned requirements before steps; all result variants retain the App. 94 # Systems execute in plan order; only explicit barriers apply deferred work. 95 # dispatch/condition/provision are trusted world-threading callbacks; arbitrary 96 # callback mutations or host IO are not automatically transactional. Prefer 97 # ordinary-app-run.run for registration-derived ordinary execution. 98 def run(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~Error:Data,~dispatch:H -> W.World -> U32 -> H & Sys.Outcome,Error,Unit>,~condition:W.World -> U32 -> W.World & Bool,~provision:W.World -> W.World & List<&2,SP.Requirement>,value:Application) -> RunResult,S,Error>: 99 match value: 100 case Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs}:provisioned(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~Error,schema,recipe,debug,plan,SP.run(~S,~C,~R,~E,~H,~Error,~dispatch,~condition,~provision,SP.Provisioned{Sch.Schedule{namespace,name,steps,owners},needs},world)) 101 102 # Stateful guards are retained beside the same ordinary App, not in its resources. 103 # Scheduled application retaining affine condition bindings beside system 104 # owners, outside resource storage. Guard state is returned with the App, 105 # including skip/failure; it is not reset by rolling back a system transaction. 106 type ConditionedApplication -> W.World & DTO.Observation,-fold:H -> H & List<&2,Records.Fields>,B:Type,-select:B -> W.World -> U32 -> Comp.Evaluation,B>> is Type: 107 ConditionedApplication{app:Application,bindings:Comp.Bindings,B,select>} 108 # Guard attachment returns ConditionsAttached or ConditionsInvalid. 109 # Refusal returns both the original application and the condition bindings, 110 # preserving their separate affine owners for retry or disposal. 111 type ConditionAttachment<-Original:Type,-Guards:Type,-Scheduled:Type> is Type: 112 ConditionsAttached{app:Scheduled} 113 ConditionsInvalid{app:Original,bindings:Guards} 114 # Detached debug description of the underlying application plus ordered 115 # condition-binding descriptions; contains no live condition owners. 116 type ConditionDescription is Data: 117 ConditionDescription{original:Description,bindings:List<&2,Comp.BindingDescription>} 118 def conditions_attached(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,schema:Schema.Schema,world:W.World,recipe:Tree.Recipe,Rows,observe>,debug:Bool,plan:SP.Plan,needs:List<&2,SP.Requirement>,result:Comp.Attachment) -> ConditionAttachment,Comp.Bindings,B,select>,ConditionedApplication>: 119 match result: 120 case Comp.Attached{Sch.Schedule{namespace,name,steps,(owners,bindings)}}:ConditionsAttached{ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings}} 121 case Comp.AttachmentRejected{Sch.Schedule{namespace,name,steps,owners},bindings}:ConditionsInvalid{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings} 122 # Attach typed condition owners by actual scheduled system ID. Duplicate 123 # bindings and targets absent from the schedule refuse attachment; refusal 124 # returns both App and bindings. Does not evaluate guards or run system bodies. 125 # A scheduled system with no binding is unconditional, not implicitly skipped. 126 def attach_conditions(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,value:Application,bindings:Comp.Bindings,B,select>) -> ConditionAttachment,Comp.Bindings,B,select>,ConditionedApplication>: 127 match value: 128 case Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs}:conditions_attached(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~B,~select,schema,world,recipe,debug,plan,needs,Comp.attach(~S,~C,~R,~E,~H,~B,~select,Sch.Schedule{namespace,name,steps,owners},bindings)) 129 # Toggle debug while retaining the same scheduled App and condition owners. 130 # Does not evaluate or reset condition state. 131 def enabled_conditions(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,value:ConditionedApplication,flag:Bool) -> ConditionedApplication: 132 match value: 133 case ConditionedApplication{app,bindings}:ConditionedApplication{enabled(~S,~C,~R,~E,~H,~Rows,~observe,~fold,app,flag),bindings} 134 def conditions_snapshot_present(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,app:Application,view:Description,bindings:Comp.Bindings,B,select>) -> ConditionedApplication & Maybe<&2,ConditionDescription>: 135 match bindings: 136 case Comp.Bindings{owner,+facts}:(ConditionedApplication{app,Comp.Bindings{owner,facts}},Some{ConditionDescription{view,facts}}) 137 def conditions_snapshot_returned(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,bindings:Comp.Bindings,B,select>,observed:Application & Maybe<&2,Description>) -> ConditionedApplication & Maybe<&2,ConditionDescription>: 138 match observed: 139 case (app,None{}):(ConditionedApplication{app,bindings},None{}) 140 case (app,Some{view}):conditions_snapshot_present(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~B,~select,app,view,bindings) 141 # Return the conditioned App with detached descriptions only when enabled. 142 # Neither guard evaluation nor system execution is performed; affine binding 143 # owners and registered visibility cursors are retained. 144 def snapshot_conditions(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,value:ConditionedApplication) -> ConditionedApplication & Maybe<&2,ConditionDescription>: 145 match value: 146 case ConditionedApplication{app,bindings}:conditions_snapshot_returned(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~B,~select,bindings,snapshot(~S,~C,~R,~E,~H,~Rows,~observe,~fold,app)) 147 def conditions_executed(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,~BodyError:Data,~dispatch:H -> W.World -> U32 -> H & Sys.Outcome,BodyError,Unit>,schema:Schema.Schema,recipe:Tree.Recipe,Rows,observe>,debug:Bool,plan:SP.Plan,needs:List<&2,SP.Requirement>,result:Sch.RunResult,B,select>,Comp.Error>) -> RunResult,S,Comp.Error>: 148 match result: 149 case Sch.Finished{Sch.Schedule{namespace,name,steps,(owners,bindings)},world,observations}:Finished{ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings},observations} 150 case Sch.Failed{Sch.Schedule{namespace,name,steps,(owners,bindings)},world,error,observations}:Failed{ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings},error,observations} 151 case Sch.Rejected{Sch.Schedule{namespace,name,steps,(owners,bindings)},world}:Rejected{ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings}} 152 def conditions_provisioned(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,~BodyError:Data,~dispatch:H -> W.World -> U32 -> H & Sys.Outcome,BodyError,Unit>,schema:Schema.Schema,recipe:Tree.Recipe,Rows,observe>,debug:Bool,plan:SP.Plan,result:SP.ProvisionResult,B,select>,Comp.Error>) -> RunResult,S,Comp.Error>: 153 match result: 154 case SP.Missing{SP.Provisioned{Sch.Schedule{namespace,name,steps,(owners,bindings)},needs},world,missing}:Missing{ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings},missing} 155 case SP.Executed{result,needs}:conditions_executed(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~B,~select,~BodyError,~dispatch,schema,recipe,debug,plan,needs,result) 156 # Execute with retained typed guard bindings and explicit provisioning. 157 # False skips the body; unavailable/rejected conditions stop with their typed 158 # error. Earlier successful steps and returned guard state remain retained. 159 # No binding means unconditional execution; barriers alone apply deferred work. 160 # Every RunResult branch returns the conditioned application owner. 161 def run_conditions(~S:Data,~C:Type,~R:Type,~E:Data,~H:Type,~Rows:Data,~observe:W.World -> W.World & DTO.Observation,~fold:H -> H & List<&2,Records.Fields>,~B:Type,~select:B -> W.World -> U32 -> Comp.Evaluation,B>,~BodyError:Data,~dispatch:H -> W.World -> U32 -> H & Sys.Outcome,BodyError,Unit>,~provision:W.World -> W.World & List<&2,SP.Requirement>,value:ConditionedApplication) -> RunResult,S,Comp.Error>: 162 match value: 163 case ConditionedApplication{Application{App.Application{schema,Build.Registered{world,owners,recipe,debug}},plan,namespace,name,steps,needs},bindings}:conditions_provisioned(~S,~C,~R,~E,~H,~Rows,~observe,~fold,~B,~select,~BodyError,~dispatch,schema,recipe,debug,plan,Comp.run_provisioned(~S,~C,~R,~E,~H,~B,~select,~BodyError,~dispatch,~provision,SP.Provisioned{Sch.Schedule{namespace,name,steps,(owners,bindings)},needs},world))