Skip to content

Preserve a live automation's active state on update - #7

Merged
jbedient-kizen merged 1 commit into
mainfrom
bug/automation-update-deactivates-without-asking
Aug 17, 2026
Merged

Preserve a live automation's active state on update#7
jbedient-kizen merged 1 commit into
mainfrom
bug/automation-update-deactivates-without-asking

Conversation

@jbedient-kizen

Copy link
Copy Markdown
Contributor

Problem

AutomationDef.active defaulted to False, so an update spec that said
nothing about active was indistinguishable from one that explicitly set
it to false. Combined with _build_automation_payload writing active
unconditionally and _merge_server_state letting the payload win, every
automations update from a spec that didn't mention active at all
silently deactivated a running automation — reported in First-Use Feedback
§7/§9 row #12. --dry-run didn't catch it either: the preview printed the
spec's value with no reference to what was live, so active=False read as
a target state, not a change.

Solution

Made active tri-state (bool | None, default None) and resolved the
None case in the planners, which already have live state in hand:
plan_create_automation resolves an omission to False (unchanged
default); plan_update_automation resolves it to whatever the live
automation currently is. The built PUT payload always carries an explicit
boolean either way. When a spec does explicitly flip a live automation,
the --dry-run preview now names it as a transition
(True → False (DEACTIVATES a live automation)) instead of a bare value.

translate.py, set_active/_patch_field, and the activate/deactivate
commands are untouched — they're the explicit path and were already
correct.

Testing

check.sh builder-cli --dir <worktree>, re-run fresh after the rebase onto
main at 9aaf7e0:

`AutomationDef.active` was `bool = False`, so an update spec that said
nothing about `active` was indistinguishable from one that explicitly
asked for `False` — every `automations update` from a spec omitting
the field silently deactivated a running automation, and `--dry-run`
didn't catch it because the preview printed the spec's value with no
reference to what was live.

Make `active` tri-state (`bool | None`, default `None`) and resolve
`None` in the planners, which already have the live state in hand:
`plan_create_automation` resolves an omission to `False`, matching
today's documented default; `plan_update_automation` resolves it to
whatever the live automation already is. The built payload still
always carries an explicit boolean. When a spec does explicitly flip a
live automation, the `--dry-run` preview now names it as a transition
("True → False (DEACTIVATES a live automation)") instead of a bare
value.

The plan's recommended approach was a `warnings: list[str]` channel on
PlanOperation, printed as its own line by _render_plan. Went with the
smaller-blast-radius option instead — embedding the transition string
in the existing preview cell — because PlanOperation is
`extra="forbid"` and plan JSON is a user-facing `--plan-file` artifact,
so a new required-shape field is a forward-compat break for anyone
applying a newer-CLI plan with an older CLI; the preview dict is
already `dict[str, Any]` and its only reader anywhere is
_render_plan's `f"{k}={v}"` join, so nothing else is affected. The
tradeoff: the transition string is quieter than a dedicated warning
line would be — at realistic terminal widths it sits mid-cell in a
wrapped row. Making it louder without the warnings channel isn't free
either: Rich markup in the string would leak into the JSON plan
artifact verbatim, and a generic " → " highlighter in the shared
renderer would flag ordinary field diffs across ten other planners
that already use that shape for non-warning transitions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jbedient-kizen
jbedient-kizen merged commit 5fcf310 into main Aug 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants