neutron product · PD003 · ux feedback addendum · round 2 · 2026-08-05

Round 2: the drag must track, the ask must be one box

Second owner walk of the live workflows surface, same day. Eight things bit — every one a surface behaviour, none a governance defect. This page records what was hit, what actually caused it, and the fix that was decided; every fix is now specified against a studied reference rather than invented.

addendum actioning round 2 of the live-surface review findings 8 + 2 additions references n8n · dify · langflow · flowise decisions D1–D8 · D-icons approved tracking #424 #425 #426 #427
01 · What you hit

Eight findings, eight causes — and two additions

Each row is what you said, what the code turned out to be doing, and what was decided. The figures below draw them, at the fidelity a builder can work from.

Reference-backed as of this revision. n8n, Dify, Langflow and Flowise were cloned under forks/ and read; each mechanism below is lifted from one of them and carries its decision id (D1–D8, D-icons). The approved wireframes v2 are the visual ground truth — where this page and a wireframe disagree, the wireframe wins. Two additions joined the original eight: node kind icons (§02) and contextual run actions (§07).

You saidVerified causeDecided fix
1 “The drag doesn't track — the box only lands when I let go.” GovernedCanvas is a controlled React Flow: it passes nodes down and handles only onNodeDragStop. With no onNodesChange, React Flow's intermediate positions are dropped, so nothing re-renders until the drop. Apply position changes live via applyNodeChanges — the library's own idiom for controlled graphs (§02) bug
2 “Why is there already a trigger box when I make a new one?” starterGraph() seeds a trigger_1 cron card into every new workflow, so the canvas opens with a decision already made for you. Empty canvas + n8n's two dashed squares — + Add first step or ✦ Build with AI — nothing placed until you choose (§03) gap
3 “The wiring feels complex.” Port-drag exists, but ports are 10px and give no hover feedback — undiscoverable. Beneath the canvas sits a second, redundant from/to/label dropdown form, so wiring looks like paperwork. Port-drag becomes the only mechanism: kind-coloured handles that grow on hover, green/red target feedback mid-drag, a kind picker when the wire lands on empty canvas, fat edge hit paths, click-select + Delete. The dropdown form is deleted (§03) gap
4 “‘Build with agent' opens this big chat panel — I just want a box you click where you can type what you want.” Round 1 specified an in-section assistant slide-over; shipped, it reads as a whole second app opening over the work. A one-line inline AI box (“Describe the workflow you want…”). What opens is a ~400px docked panel that squeezes the canvas, never an overlay (§04) redesign
5 The agent answered as the whole platform, not as a workflow builder. Builder turns go through plain /api/chat with zero workflow framing — no role, no NEP context, no graph. The generic assistant persona is exactly what you get. A workflow-builder turn lane that injects scoped context server-side: role, NEP-0006 summary, the open workflow's graph, propose via workflow_upsert; proposals preview on the canvas with N/M badges (§04) bug
6 “Why is the whole list of workflows at the bottom of the page I'm already inside?” Detail views render the all-workflows list below their own content — a leftover from the single-panel layout, now redundant with the sidebar. Removed from every detail view. The list lives in the sidebar and the list state only (§05) gap
7 “Where do I see the runs?” GET /api/workflows/:id/runs already returns run history; the governed detail view only ever renders the latest run, so history has no door. A Runs section per governed workflow — status · when · duration · the failure's own error text — whose rows load into the run view that already exists (§05) small
8 “The runs should light up.” Run status is a subtle border tint; the only motion on the page is the parked-approval pulse. A running workflow looks identical to a finished one at a glance. Grey-out then light-up: spinner + accent border on the running node, marching dash on the active edge, green on completed, slow amber ring on a parked gate, auto-pan, and Run now auto-follows its run (§06) small
+ Addition, from the study: a graph of grey boxes is unreadable at a glance. Node kind is small-caps text only; nothing distinguishes a Slack post from a cron trigger except reading it. A coloured kind icon chip on every node, brand icons on mapped capability tools, status as spinner / ✓ / ✕ in the head (§02) addition
+ Addition, from the study: watching a run and acting on it are the same moment. A run in flight cannot be stopped from where you watch it, and a finished run cannot be repeated. Stop welded to the running pill, Re-run on terminal runs, decide-in-place for parked ones (§07) addition
02 · The node card

Every node says what it is, in colour

Addition, from the study. Today a node is a grey box whose kind you read in small caps. Every node now carries a kind icon chip — one saturated hue per kind, white glyph, Dify's chip anatomy — so a graph is legible at a glance. A capability node whose tool maps to a known service shows that service's icon instead; unknown tools keep the kind chip, so something always renders. D-icons

Status rides in two channels that never collide: an icon in the head (spinner · ✓ · ✕) and the border tint. Selection outranks status — a selected node always shows its selection ring.

trigger capability agent turn approval notify branch
Node anatomy the six kinds, plus every status a node can wear
trigger
Mon 09:000 0 9 * * 1
capability
list issuesunknown tool → kind chip
S capability
post to #digestmapped tool → brand icon
agent turn
Scout drafts the digestspinner in the head
approval · parked
Owner reviewslow amber ring, 4.5s
branch
weekend?true / false ports
notify
#Marketingcompleted — green border
capability
list issueshover → the actual error text
agent turn
selected while runningselection ring wins
03 · The canvas

It tracks, it starts empty, it wires by hand

Findings 1–3 are one story: the canvas answers late, decides for you, and offers two ways to do the same thing. The fix is the opposite of each.

the interaction being fixed surface being removed idle node
Workflows /new workflow draft · nothing published Cancel Publish

Palette · drag onto canvas

Triggerstart
Capabilitytool
Agent turnllm
Approvalgate

Nothing is pre-placed. The publish rule is unchanged — the server still requires exactly one trigger; it just stops being pre-decided for you.

Add first step or Build with AI
2 adds and selects the trigger 4 focuses the AI box below
Workflows /weekly-outreach-digest editing · v3 unpublished Cancel Publish v3

Wiring · one mechanism

drag port → portonly way
12px dot30px hit
hovergrows + glows
valid targetgreen
invalid targetred
drop on canvaskind picker
edge15px hit path

Ports take their node's kind colour. Cycles and self-connections are refused as you drag, not at publish. There is no second way to connect two nodes.

trigger · cron
Mon 09:000 0 9 * * 1
agent turn
Scout drafts the digestmoving with the cursor
agent turn
was hereold position
approval
Owner reviewrole: admin · 1h timeout
notify
#Marketing“digest ready”
+ capability · agent
approval · notify · branch
1 every frame renders — applyNodeChanges 3 fat hit path — click selects, ⌫ removes 3 green = valid drop · red = invalid 3 drop on empty canvas → pick a kind, wired at the drop point
✕ removed from under the canvas
from ▾to ▾label ▾Connect

A second wiring path that duplicated the ports and made the graph feel like a form. With handles that announce themselves, it has no job left.

04 · Asking for it

One box, and an agent that knows it builds workflows

Findings 4 and 5 are the same request from two sides: make asking small, and make the answer be about workflows. The box is one line on the surface you're already on. What opens afterwards is a docked panel, ~400px, that squeezes the canvas rather than covering it — n8n's grid column, never an overlay. Close it and the thread survives. D4

Workflows engine healthy Import from n8n New workflow
Describe the workflow you want… Ask

No panel opens on click — it is a text input. On submit, the builder turn starts and the thread panel slides in to show that turn, then the proposal arrives as the same gated workflow_upsert approval card as always.

Governed workflows · 3
weekly-outreach-digest v2 live · draft v3 4 runs parked 2h · waiting on owner Open
agent-authored-acceptance v1 live 2 runs completed 08:31 · 10s Open
Workflows /weekly-outreach-digest proposal pending · not applied Close panel

Steps

trigger
weekend?new
draftchanged

The panel took its width from the canvas — the graph shrank, nothing is hidden behind it.

trigger
Mon 09:00
N
branch
weekend?
M
agent turn
draftprompt changed
5 proposal renders on the canvas — N new, M modified

Workflow builder · docked

Proposal: skip weekends 2 nodes · 1 new, 1 changed

Parked at the gate. Approving lands it disabled — arming stays a separate human action.

Approve Deny
~400px · squeezes, never covers

The proposal is a preview, not a mutation: the live graph is untouched until the card is approved, so you judge the picture instead of a text summary. D5

what the agent said · live, 2026-08-05 “I'm Neutron Core—the primary assistant…”

That is the correct answer to a question nobody asked. The turn carried no workflow framing at all, so it introduced the platform. The builder lane fixes the input, not the model:

you type“email me a digest of new issues every Monday”
builder laneinjects role · NEP-0006 summary · the open graph · stay-on-workflows
turnsame chat engine, same seat, same audit
proposesworkflow_upsert → approval card
exists today the new lane unchanged governance

Nothing about the gate moves. The lane is context, not authority: an agent that knows it is building a workflow still cannot publish one without the card.

05 · The detail view

Lose the list at the bottom, gain the runs

Findings 6 and 7 trade places. The all-workflows list leaves the detail view — you are already inside one, and the sidebar has the rest. In its place goes the thing you actually asked for: the history the API has been returning all along, one row per run — status dot, when, duration, and a failure's own error text in the row rather than one click away. D6 · D7

Workflows /weekly-outreach-digest v2 live · enabled Edit Run now

Sidebar · the list lives here

weekly-outreach-digest
agent-authored-acceptance
human-editor-acceptance

Exactly one place to change which workflow you are looking at. The detail view no longer repeats it below the fold.

Runs · 6
running started 2m ago ← viewing above Open run
waiting today 09:00 2h 14m parked at approval “owner review” Open run
completed Mon 09:00 38s 4 steps · approved by you Open run
completed 28 Jul 09:00 41s 4 steps Open run
failed 21 Jul 09:00 6s capability denied · list_issues Open run
completed 14 Jul 09:00 36s 4 steps Open run

Rows come from GET /api/workflows/:id/runs — already shipped. Clicking one loads the existing run view; no new run surface is invented.

06 · Live runs

A running workflow should look like one

Finding 8, now specified against the references. At run start the whole graph greys to about 70% and then lights up node by node (Dify's model), so “what is happening right now” is the only thing at full strength. The executing node carries a spinner in its head plus an accent border; the edge feeding it runs a marching dash; finished nodes and their edges settle green with a ✓; a parked approval wears the slow amber ring from §02. The view auto-pans to the active node, and Run now follows the run it started. D8

One correction from the study worth recording: n8n's visible “spinner” is a rotating ring, and its actual spinner component is dead code. The spinner drawn here is Dify's — the clearer cue, and the one we are copying.

executing now — spinner + accent border done — green, ✓ parked — slow amber ring not reached — dimmed to 70%
weekly-outreach-digest /run 8c31f0a2 running · 6s ■ Stop Runs

Steps

trigger✓ 09:00:00
issues✓ 1.2s
draft
gatequeued

Run now navigated here by itself, and the canvas panned to the running node — the run you started is the run you are watching.

trigger
Mon 09:00fired on time
capability
list issues14 items · 1.2s
agent
draftstreaming… 6s
approval
Owner reviewnot reached
notify
#Marketingnot reached
8 done: green border, ✓, settled edge 8 spinner + accent border · edge marches 8 everything unreached sits at 70%

Motion is status, not decoration: only the executing node and the edge feeding it move. Everything honours prefers-reduced-motion — with motion off, the same states read as solid colour, a static ring, and a still dash.

07 · Actions

The action lives where the state is

Addition, from the study. Watching a run and acting on it are the same moment, so the controls ride the status rather than sitting in a toolbar: Stop is welded to the running pill (Dify), Re-run appears on a run that has finished or failed, and a parked run is decided in place — the inspector approve/deny already specified as round 1 acceptance item 5, not a second mechanism. Each control exists only in the state it applies to, so there are no dead buttons; if the engine has no cancel path for Stop, that path gets built rather than faked.

state → running · 41s ■ Stop completed · 38s ↻ Re-run parked · 2h 14m ✋ decide in place
running Stop cancels the run and marks it cancelled — the same terminal state a timeout produces, never a hidden kill.
completed / failed Re-run starts a new run of the published version — history keeps both, and the new run auto-follows exactly like Run now.
parked Approve / Deny in the run inspector — the same durable approval row the inbox and WhatsApp card carry (round 1, item 5).
08 · Acceptance

What a live walk has to observe

Each line is one observation a spec-verifier can make on the deployed surface, in order, in a single session. Items 1–8 are the findings; 9 and 10 are the additions.

1
A node dragged across the canvas follows the cursor continuously — its position updates during the drag, not on release — and the dropped position survives publish and reload.
2
Creating a workflow opens a canvas with zero nodes and exactly two dashed squares, “+ Add first step” and “✦ Build with AI”; the first adds one trigger and leaves it selected, the second focuses the AI box; publishing with no trigger is still refused by the server.
3
Wiring works only by dragging port to port: a port grows on hover and carries its node's kind colour, valid targets answer green and invalid ones red during the drag, dropping on empty canvas offers a kind picker that lands the node already wired, an edge can be selected by clicking near (not exactly on) the line, and Delete removes it. The from/to/label form is absent from the DOM.
4
The workflows surface shows a one-line “Describe the workflow you want…” input; submitting starts a turn and opens a docked panel roughly 400px wide that narrows the canvas rather than covering it — no canvas content sits underneath it — and closing the panel keeps the thread.
5
A builder turn answers as a workflow builder, never introducing itself as the platform, and proposes through workflow_upsert; opened from a workflow its reply reflects that workflow's actual graph; a pending proposal renders on the canvas with N badges on new nodes and M on modified ones while the live graph stays unchanged until the card is approved.
6
No detail view (governed workflow, run, or schedule) renders the all-workflows list anywhere on the page; switching workflows happens from the sidebar.
7
A governed workflow page lists its runs with a status dot, when, and duration, and a failed run shows its own error text in the row; clicking any row loads that run into the run view above.
8
Starting a run dims the whole graph and then lights nodes as they execute: the running node shows a spinner in its head plus an accent border, the edge feeding it marches, completed nodes turn green with ✓, a parked approval wears a slowly rotating amber ring, unreached nodes stay dimmed, the view pans to the active node, and “Run now” lands on the run it started. With prefers-reduced-motion set, every one of those states is still distinguishable without animation.
9
A running run offers Stop attached to its status pill and stopping it produces a cancelled terminal state; a finished or failed run offers Re-run, which starts a new run that the view follows; a parked run is approved or denied in the run inspector (round 1, item 5). No control appears in a state it cannot act on.
10
Every node on the canvas carries a kind icon chip whose colour differs per kind across all six kinds; a capability node bound to a mapped service shows that service's icon while an unmapped tool still shows the kind chip; a failed node shows ✕ and reveals its error text on hover; and a selected node keeps its selection ring while running.