f115c982bc
Tier 1 — pre-step skip conditions: when: <remote shell expr> skip unless expr exits 0 creates: <remote path> skip if path already exists removes: <remote path> skip if path is already absent Any of the three saying "skip" marks the step `skipped` and moves on. Evaluated under bash -c on the remote so `!`, `[[`, pipes etc. behave consistently regardless of the default remote shell. Tier 2 — post-step change detection: changed_when: <remote shell expr> Evaluated after a successful step. Exit 0 → step counts as `changed` (default). Exit != 0 → `ok` (ran, nothing actually different). Without this field, successful steps default to `changed`, matching Ansible's shell/command defaults. Useful on verify steps: `changed_when: "false"` reports them as `ok` since they only attest. Status model moved from pass/fail to four states: ok / changed / failed / skipped Summary reports each count; overall outcome is CHANGED if any step changed, OK if none did, FAILED on any non-skipped failure. Rerunnable smoke: playbooks/elway-smoke.yaml now proves it. On a clean target the cold run reports 4 changed, 3 ok. Rerunning with the same vars reports 2 skipped / 2 changed (upload + log-record have no idempotency hooks and are always `changed`). Overriding --var greeting=... re-runs the gated step exactly as intended. Doc block at the top of the script updated with the new schema fields and state machine.