@@ -80,7 +80,14 @@ def run_next_planfile_task(
8080
8181 ticket_id = str (ticket ["id" ])
8282 executor = ticket .get ("executor" ) or {}
83- executor_kind = str (executor .get ("kind" ) or "human" )
83+ raw_kind = executor .get ("kind" )
84+ executor_kind = str (raw_kind or "human" )
85+ # In non-interactive mode, legacy tickets created before --executor-kind
86+ # existed should not block the queue. Default them to shell so they can
87+ # be auto-completed with a no-op script. Explicit human tickets are
88+ # preserved and still return waiting_input as before.
89+ if raw_kind is None and not interactive and not dry_run :
90+ executor_kind = "shell"
8491
8592 if executor_kind == "human" :
8693 inputs = ticket .get ("inputs" ) or {}
@@ -146,19 +153,24 @@ def run_next_planfile_task(
146153 missing_prompt = "Shell ticket is missing inputs.script or executor.handler"
147154
148155 if not action :
149- # `block --reason` is the planfile equivalent of the older
150- # `input --prompt` surface koru used to call.
151- planfile_command (
152- project ,
153- ["ticket" , "block" , ticket_id , "--reason" , missing_prompt ],
154- runner = planfile_runner ,
155- )
156- return QueueRunResult (
157- status = "waiting_input" ,
158- ticket_id = ticket_id ,
159- executor_kind = executor_kind ,
160- message = missing_prompt ,
161- )
156+ # Fallback no-op for legacy tickets auto-converted to shell above,
157+ # or any shell ticket missing a script. Prevents queue blocking.
158+ if executor_kind == "shell" and not interactive and not dry_run :
159+ action = "true"
160+ else :
161+ # `block --reason` is the planfile equivalent of the older
162+ # `input --prompt` surface koru used to call.
163+ planfile_command (
164+ project ,
165+ ["ticket" , "block" , ticket_id , "--reason" , missing_prompt ],
166+ runner = planfile_runner ,
167+ )
168+ return QueueRunResult (
169+ status = "waiting_input" ,
170+ ticket_id = ticket_id ,
171+ executor_kind = executor_kind ,
172+ message = missing_prompt ,
173+ )
162174
163175 if dry_run :
164176 message = json .dumps (action ) if isinstance (action , dict ) else action
0 commit comments