Krikri::ConditionalEvaluator::UndefinedVariableError
Raised only when raise_undefined is true (currently: task-level
when: via Executor#when_passes?, which already wraps this whole
call in a rescue that converts it into a real failed-task result -
see WhenEvaluationError there) and evaluating the condition reaches
a BARE or DOTTED variable reference (the same REGEX_BARE_VAR_REF-
shaped grammar VariableSubstitutor's own strict: module-arg check
already covers, see its UndefinedVariableError) that resolves to
nothing. Deliberately as narrowly scoped as that existing check:
only a direct lookup reaching evaluate_value's own "not found" exit
raises - a filter/function chain (foo | default(...), lookup(...),
any is <test>) still falls back to the lenient "undefined" sentinel
regardless, since this hand-rolled evaluator's own syntax-coverage
gaps already produce that same sentinel for reasons unrelated to the
variable genuinely being undefined - conflating the two would turn
an evaluator limitation into a spurious task failure (see
UndefinedVariableError's own comment in variable_substitutor.cr for
the identical reasoning applied there first).
Found live via round172's buluma.git_tag (Rocky 9.6): when: git_remote != '' and git_remote != None with git_remote genuinely
undefined (no default, never set). Real Ansible raises ("'git_remote'
is undefined") and fails the task (failed=1); this evaluator's
lenient nil != ''/nil != None comparisons both resolved truthy
instead, evaluating the whole when: as satisfied - the exact
"changes final task-pass/fail state" trigger KNOWN_MISSING.md called
for revisiting this with. raise_undefined is a separate flag from
strict above (which checks the FINAL result's own type, for
changed_when:/failed_when: - unrelated to whether an intermediate
operand was undefined) - the two are independent because
changed_when:/failed_when: deliberately still get the lenient
undefined-operand handling here (not touched by this fix).