fix(desktop): the automation editor is drawn from Settings' own rows, every pick a Settings picker on the window's menu and every yes or no a switch
Summary
Dean asked for a full UI audit of the automation editor (Settings › Experimental › Automations › an automation), with every control matched to its counterpart elsewhere in the app. The audit, with renders of each element, is at https://stage-w2237.conductor.show/.
What didn't match:
- Five native
<select>s: GitHub event, time zone, weekday, minute, and agent. Each opens the OS menu rather than the window's menu-surface, which is the GitHub-event picker Dean flagged. - Four
Segmentedcontrols: trigger type, frequency (five wide), runs land in, and owner. Settings keeps Segmented for a short scale of one value (Effort, Context, Role); every Settings pop-up is thePickerRowchip and menu. - A native checkbox where the app uses its Switch.
- A hand-built label-column form where the rest of the app uses Settings rows.
- The model chip in its toolbar look and the repository chip as a pill.
- A time field off the chips' height and corner.
- A 20/650 title, where Settings' page title is 22/700.
- An owner line drawn as a hand-made pill.
- No Experimental badge or Send feedback, though the list page has both.
- Two labels ending in "…".
What this changes, with shared components only:
- Every pick-one is the Settings picker.
PickerRowandSelectRowcover Type, Repeats, Event, Time zone (searched), Runs land in, Agent and Owner.Pickercovers the weekday and the minute, beside the time.Pickeris the chip and menu pulled out ofPickerRowso a row can stand it next to another control;PickerRowis now that plus the row. - Archive successful runs is a
SwitchRow.SwitchRow'sonChangemay now answervoid, asSelectRow's already may, since a draft's switch can't be refused. - The model and repository chips keep their own menus and take the field look: a new
lookprop onAgentModelChip, andCHIP_PLACE.FIELDonRepositoryChip. - The form is laid out as a Settings page.
SettingsGroupcards (Trigger, Task, Runs, Sharing) hold Settings rows, and a problem stands under its row as a Settings refusal does. The task's textarea is its card. The bespokeFormRowand.automation-form-*/-schedule/-select/-checkCSS are deleted. - The title matches the Settings page title. The owner line is plain muted text with the glyph and name.
- The toolbar wears Experimental and Send feedback. "Saving…" becomes "Saving", and the agent list's "Reading…" becomes a "Loading agents" spinner inside the menu.
- The editor's pickers grow from Settings' 200px to show their whole value. "Pull request opened or updated" is never cut short.
- Webhooks: rebased onto #2805, so the webhook section has an Address row and a Secret row. The Secret row shows New secret, or the secret just made, shown once (read-only, Copy, Done), with the row kept out of the screen recording (
ph-no-capture) and keyed by the secret, so one secret's "Copied" is never shown for the next (Devin). - A saved agent the workspace no longer lists stays first in the Agent menu, while the repository is still the one it was saved on, so a different pick can be taken back (Devin).
- In a narrow window the rows wrap as a wrapping Settings row does, and the pickers and time field shrink to fit, so nothing runs past the card (Devin).
- Behaviour is unchanged: the same draft model, saves, Escape handling and validation.
Rebased onto #2833, so the editor keeps #2833's centred --reading-width measure. The rows take their height from Settings' --settings-row-height.
For #2780 (GitHub-trigger settings). Build those controls from these same rows in the Trigger card:
- each yes or no (Skip drafts, Include forks, each sender, each moment) as a
SwitchRow; - any pick-one as a
SelectRoworPickerRow.
Renders
These are from main's real CSS (the desktop build's styles.css) with the real AutomationsPage on a stubbed host, in Chrome on Linux. Inter stands in for SF Pro.
| Before | After | |
|---|---|---|
| Schedule · light | ![]() | ![]() |
| Schedule · dark | ![]() | ![]() |
| GitHub event · light | ![]() | ![]() |
| GitHub event · dark | ![]() | ![]() |
| Webhook (saved) · light | ![]() | ![]() |
| Webhook (saved) · dark | ![]() | ![]() |
| Same agent · light | ![]() | ![]() |
| Same agent · dark | ![]() | ![]() |
| New, in a shared workspace (Owner) · light | ![]() | ![]() |
| New, in a shared workspace (Owner) · dark | ![]() | ![]() |
Pickers open (after). Before, these were native selects that opened the OS menu.
| Light | Dark | |
|---|---|---|
| GitHub event | ![]() | ![]() |
| Time zone, searched | ![]() | ![]() |
| Agent | ![]() | ![]() |
| Model | ![]() | ![]() |
Evidence
./scripts/check.sh: passes locally (lint, knip, discarded-effect, typecheck, test).pnpm check:affected: passes.automations-page.test.ts: 43 pass (main has 39).- New: an automation's page says it is an experiment, and its Send feedback is about Automations. This fails without the change; the editor had neither.
- New: a saved agent the workspace's list no longer holds can be picked again after another pick; it is not offered once the repository changes; a new secret shown after one was copied is not said to be copied. Each fails without its fix.
- Updated: #2805's two secret tests now pick Webhook and Schedule from the Type picker.
- Updated to drive the new controls, asserting the same behaviour:
- the Owner row;
- the GitHub trigger's sentence and event, now read off the Type picker's detail and the Event picker;
- Escape after a Repeats change;
- the repository chip;
- Archive successful runs, now a switch;
- Same agent picked from the Agent menu;
- a new GitHub automation;
- a webhook not yet saved.
Invariants
-
./scripts/check.shgreen. (CI) - JSON Schema goldens unchanged.
- Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
- Gateway envelope goldens unchanged.
- No new
astype assertion. - No
Effect.runPromise/runSync/runForkoutside the edges. - No new raw async primitives.
- No dropped Effect, Stream, or Layer.
- Test count: +4 (39 → 43 in
automations-page.test.ts). - Hand-rolled form controls deleted (
FormRow, its CSS, the native selects and the checkbox). - No
CLAUDE.md/AGENTS.mdsentence names a changed part. -
PRIVACY.mdunchanged. Session replay still masks every word, and no new way of drawing words is added. - Package deps unchanged.
- Barrel/door rule: the renderer imports
EXPERIMENTfrom@luke/settings, asautomations-page.tsxalready does.
Notes
- Mac: this is a UI PR, and CI could not verify the Mac UI. No capture was taken on a Mac. The renders above are Chrome on Linux.
- On a Mac, the time field types or steps with the arrows. Its native clock is hidden because that picker is the engine's, not the window's menu.
🤖 Generated with Claude Code



























