@@ -157,102 +157,68 @@ def delivery_spend_allowed(
157157 )
158158
159159
160+ def action_selection_context (payload : Mapping [str , Any ]) -> dict [str , Any ]:
161+ """Transport bounded current facts; TypeScript owns every admission decision."""
162+ fields = ("ok" , "should_run" , "effective_action" , "normal_delivery_allowed" , "recovery_delivery_allowed" ,
163+ "self_repair_allowed" , "capability_repair_allowed" , "workspace_repair_allowed" , "safe_bypass_allowed" ,
164+ "actionable_by_codex" , "spend_allowed_now" , "spend_after_validation" )
165+ result = {key : payload [key ] for key in fields if key in payload }
166+ for field , keys in (
167+ ("selected_todo" , ("todo_id" , "selection_binding" )),
168+ ("autonomous_replan_obligation" , ("selection_binding" ,)),
169+ ("action_selection_qualification" , ("state" , "requested_todo_id" , "recovery_action" )),
170+ ):
171+ raw = payload .get (field )
172+ if isinstance (raw , Mapping ):
173+ result [field ] = {key : raw [key ] for key in keys if key in raw }
174+ if field == "selected_todo" :
175+ result [field ]["todo_id" ] = normalize_todo_id (raw .get ("todo_id" ))
176+ if field == "action_selection_qualification" and isinstance (raw .get ("selected_todo" ), Mapping ):
177+ result [field ]["selected_todo" ] = {"todo_id" : normalize_todo_id (raw ["selected_todo" ].get ("todo_id" ))}
178+ return result
179+
180+
181+ def _selection_projection (method : str , payload : Mapping [str , Any ], * ,
182+ agent_must_attempt : bool , agent_delivery_allowed : bool | None ,
183+ requested_todo_id : str | None = None ) -> dict [str , Any ]:
184+ from ..effect_runtime import effect_runtime_result
185+
186+ request = {"packet" : action_selection_context (payload ), "agent_must_attempt" : agent_must_attempt ,
187+ "agent_delivery_allowed" : agent_delivery_allowed }
188+ if requested_todo_id is not None :
189+ request ["requested_todo_id" ] = requested_todo_id
190+ result = effect_runtime_result (method , request )
191+ if not isinstance (result , dict ):
192+ raise TypeError ("typed action selection returned an invalid projection" )
193+ return result
194+
195+
160196def current_action_selection_admission (
161197 payload : Mapping [str , Any ], * , requested_todo_id : str ,
162- agent_must_attempt : bool , agent_delivery_refused : bool ,
198+ agent_must_attempt : bool , agent_delivery_allowed : bool | None ,
163199) -> tuple [str | None , bool ]:
164- """Read current obligation admission, including repair and monitor positives."""
165- selected_todo = payload .get ("selected_todo" )
166- selected_todo_id = (
167- normalize_todo_id (selected_todo .get ("todo_id" ))
168- if isinstance (selected_todo , Mapping )
169- else None
170- )
171- qualification_value = payload .get ("action_selection_qualification" )
172- qualification : Mapping [str , object ] = (
173- qualification_value if isinstance (qualification_value , Mapping ) else {}
174- )
175- if selected_todo_id is None and str (qualification .get ("state" ) or "" ) == (
176- "qualified"
177- ):
178- # An unsettled-host-turn recovery decision carries no top-level
179- # `selected_todo`: its qualification names the Todo that prior Turn
180- # has to settle, and binding the guard to that Todo is the documented
181- # closeout path rather than a conflict with the projection.
182- qualification_selected = qualification .get ("selected_todo" )
183- selected_todo_id = (
184- normalize_todo_id (qualification_selected .get ("todo_id" ))
185- if isinstance (qualification_selected , Mapping )
186- else None
187- )
188- selection_binding = (
189- selected_todo .get ("selection_binding" )
190- if isinstance (selected_todo , Mapping )
191- else None
192- )
193- execution_obligation_value = payload .get ("execution_obligation" )
194- execution_obligation : Mapping [str , object ] = (
195- execution_obligation_value
196- if isinstance (execution_obligation_value , Mapping )
197- else {}
198- )
199- pending_selection_delivery_qualified = (
200- selection_binding == "pending_action_selection"
201- and payload .get ("normal_delivery_allowed" ) is True
202- )
203- pending_selection_workspace_repair_qualified = (
204- selection_binding == "pending_action_selection"
205- and payload .get ("workspace_repair_allowed" ) is True
206- and payload .get ("effective_action" ) == EffectiveAction .AGENT_WORKSPACE_REPAIR .value
207- and execution_obligation .get ("kind" ) == "agent_workspace_repair"
208- and execution_obligation .get ("must_attempt_work" ) is True
209- and agent_must_attempt
210- and agent_delivery_refused
211- )
212- exact_current_obligation_qualified = (
213- selection_binding != "pending_action_selection"
214- and execution_obligation .get ("must_attempt_work" ) is True
215- and agent_must_attempt
216- )
217- if (
218- selected_todo_id == requested_todo_id
219- and payload .get ("ok" ) is True
220- and payload .get ("should_run" ) is True
221- and (
222- pending_selection_delivery_qualified
223- or pending_selection_workspace_repair_qualified
224- or exact_current_obligation_qualified
225- )
226- ):
227- return selected_todo_id , True
228-
229- return selected_todo_id , False
200+ result = _selection_projection ("work_item.action_selection.admission.project" , payload ,
201+ requested_todo_id = requested_todo_id , agent_must_attempt = agent_must_attempt ,
202+ agent_delivery_allowed = agent_delivery_allowed )
203+ selected , admitted = result .get ("selected_todo_id" ), result .get ("admitted" )
204+ if (selected is not None and not isinstance (selected , str )) or type (admitted ) is not bool :
205+ raise TypeError ("typed action selection returned invalid admission facts" )
206+ return selected , admitted
230207
231208
232209def action_selection_needs_recovery (
233210 payload : Mapping [str , Any ], * , agent_must_attempt : bool = False ,
234- agent_delivery_refused : bool = False ,
211+ agent_delivery_allowed : bool | None = None ,
235212) -> bool :
236- """Read the typed qualifier's result without reimplementing admission."""
237- qualification = payload .get ("action_selection_qualification" )
238- if not isinstance (qualification , Mapping ) or qualification .get ("state" ) not in {"deferred" , "rejected" }:
213+ # No selected-request input means there is no recovery projection to read.
214+ if not isinstance (payload .get ("action_selection_qualification" ), Mapping ):
239215 return False
240- # A committed binding is reconciled by the receipt owner, not by pending
241- # selection recovery. Preserve the same exemption as CLI preflight.
242- selected = payload .get ("selected_todo" )
243- replan = payload .get ("autonomous_replan_obligation" )
244- if any (isinstance (value , Mapping ) and value .get ("selection_binding" ) == "heartbeat_receipt"
245- for value in (selected , replan )):
246- return False
247- _ , admitted = current_action_selection_admission (
248- payload , requested_todo_id = str (qualification .get ("requested_todo_id" ) or "" ),
249- agent_must_attempt = agent_must_attempt , agent_delivery_refused = agent_delivery_refused ,
250- )
251- if admitted :
252- return False
253- if qualification .get ("recovery_action" ) != "reenter_guard_without_selection" :
254- raise RuntimeError ("rejected action selection omitted its typed recovery action" )
255- return True
216+ result = _selection_projection ("work_item.action_selection.recovery.project" , payload ,
217+ agent_must_attempt = agent_must_attempt , agent_delivery_allowed = agent_delivery_allowed )
218+ required = result .get ("required" )
219+ if type (required ) is not bool :
220+ raise TypeError ("typed action selection returned an invalid recovery decision" )
221+ return required
256222
257223
258224def action_selection_recovery_fields (
0 commit comments