Krikri::TaskDebugger
debugger: - drop into an interactive prompt when a task reaches the
configured condition (always / never / on_failed / on_skipped /
on_unreachable).
Real Ansible's debugger reads from stdin even when it is NOT a terminal, unlike vars_prompt (verified against ansible-core 2.19.4: piping "c" continues the run; closing stdin yields "User interrupted execution" and exit 99). Both are reproduced.
Commands: p/print, r/redo, c/continue, q/quit, u/update_task, EOF,
and ASSIGNMENT to task.args[...] / task_vars[...].
Real Ansible implements assignment by exec-ing the typed line as
Python against a live scope dict, which this engine has no equivalent
of. What it does instead is parse the two assignment SHAPES that make
the debugger useful - task.args['x'] = <literal> and
task_vars['y'] = <literal> - and apply them to the real task/vars,
so the documented workflow (fix a wrong argument, r, watch it pass)
works. Arbitrary Python beyond that shape is still refused rather
than silently ignored: an unparseable assignment says so.
The interaction between the two, verified against real ansible-core 2.19.4 rather than assumed, is subtle and reproduced exactly:
task.args[...] = vtakes effect on the very nextr.task_vars[...] = vdoes NOT, on its own, change the task's arguments - a redo right after it re-runs the ORIGINAL command (real Ansible's task object is already templated by then). Onlyu/update_taskre-templates the task from the updated vars, which is exactly what real Ansible's owndo_update_task("Recreate the task from task._ds, and template with updated task_vars") does.
Constants
Exit code real Ansible uses when the debugger is left by EOF or quit - its generic "user interrupted execution" code.
An assignment shape this understands: task.args['key'] = value or
task_vars['key'] = value, with either quote style, and with or
without the brackets' surrounding whitespace.
Class methods
Runs the prompt loop. Returns whether the caller should re-run the task; quitting or EOF exits the process, as real Ansible does.
task is mutated in place for task.args[...] = assignments (its
params are this engine's equivalent - the raw, pre-substitution
module arguments). var_overrides is the caller's own hash for
task_vars[...] = assignments: entries land in it only once
u/update_task promotes them, so the caller can merge it into
the vars context it builds for a redo and get real Ansible's
semantics for free.