@@ -303,7 +303,7 @@ def dispatch_once(self, task_id: str) -> bool:
303303 self ._requeue_task (task_id , reason = "no_selection" )
304304 return False
305305
306- # 5.5. Plan task merge: coalesce sibling merge candidates onto this worker
306+ # Plan task merge: coalesce sibling merge candidates onto this worker
307307 merged_children : list [str ] = []
308308 if self ._task_merge_enabled and self ._task_merge_max_batch_size > 1 :
309309 merged_children = self ._runtime .plan_merge (
@@ -341,11 +341,21 @@ def dispatch_once(self, task_id: str) -> bool:
341341 self ._fail_task (task_id , str (exc ), payload = {"error" : str (exc )})
342342 return True
343343
344- # 6.5. Conditional execution: skip dispatch if condition not met
344+ # Re-validate resolved task spec
345+ try :
346+ rendered_task .spec .validate_dispatchable ()
347+ except ValueError as exc :
348+ self ._runtime .release_merge (task_id )
349+ self ._fail_task (
350+ task_id , "spec_validation_failed" , payload = {"error" : str (exc )}
351+ )
352+ return True
353+
354+ # Conditional execution: skip dispatch if condition not met
345355 if self ._evaluate_condition_skip (task_id , rendered_task , record ):
346356 return True
347357
348- # 6.6. Resolve merged-child rendered payloads
358+ # Resolve merged-child rendered payloads
349359 rendered_children : list [MergedChildTaskStrict ] | None = None
350360 if record .merged_children :
351361 rendered_children = []
0 commit comments