A storage was a block with a visual role that said "not a step", which
left resource-shaped exceptions scattered through the editor, the node
components, the palette and the execution view.
The flow now carries resources beside its blocks, and the canvas draws
them with a component of their own: no ports, no dependencies, one
handle for the steps that use it. What a step links is read from the
schema flag x-resource-ref, so the editor no longer knows the word
"storage" anywhere - a new kind of resource needs no code here.
The configuration form the two kinds of node share is now a component of
its own (app-node-parameters), so a resource is edited exactly as a
block while it is drawn differently.
Resource types come from /resources/types, and share the palette with
the blocks under the Resource kind.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A Storage node has a 'Used by' handle and a storage operation a 'Works
on' one; the link drawn between them, teal and dotted, is what sets the
operation's storageNode. It is neither a connection nor a dependency: it
carries no value and orders nothing, and loops leave it out. An
operation works on one node, so a new link replaces the old one, and
removing the link empties the field. On load the links are drawn back
from what each operation says.
Fields the schema marks x-ui-hidden are left out of every form and chip
- storageNode is set by the link, not typed - and kept in the
configuration.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A storage node comes from the server with the RESOURCE role. In the
editor it is drawn apart from the steps - dashed, teal, labelled
'Storage · not a step' - and its targets take a connection from every
step that writes there; a view parameter (<view>.<parameter>) still
takes one.
Its edges are left out when the editor works out which connections lead
back round a loop: a write followed by a read of the same node is not a
cycle, the same view the server takes.
The execution view draws the node from the flow, since it never has a
step, with no status of its own, so the reads and writes on its edges
still have somewhere to go.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every list parameter of a node now reads as its name and a count, and
opens on demand to its items; with none there is nothing to open, the
add button is the way in, and the "No items" line is gone. An item
added opens the list, so it is there to see.
The list is one shared component, app-node-list-field, rather than two
near-identical blocks in the block node and a third in the execution
view: the same list reads and behaves the same everywhere, and a
container that gains a list parameter takes the component as it is.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
In an execution, a step on its second round or later carries a Round N
badge. Answers to a person's question - decisions, evaluations, evidence,
revealing the reference - send the round of its loop the question was
opened on, fixed when the dialog opened rather than read at submit time,
so an answer to an old round's question is refused by the server instead
of being applied to a draft the person never saw.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Mechanical: three comment lines at the top of every .ts, .html and .css
under src, and nothing else. Split out from the licence commit so the
files that carry an actual change stay readable in the history, and kept
to its own commit because it moves the blame line on 390 files.
The short SPDX form rather than the full GNU notice - it is
machine-readable under REUSE, it satisfies the requirement to keep the
licence notice intact, and it points at LICENSE-ADDENDUM instead of
restating the attribution term in every file.
The template and stylesheet headers do not reach the bundle: Angular
discards template comments and the production build strips CSS ones. The
one in index.html survives, since that file is served as written, which is
no loss.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A step's error is regularly a provider payload or a stack, and a hover
tooltip could only ever clip it: there was no way to read past the first
few lines, let alone paste it into a bug report.
The badge now teases the failure - "Error executing" plus its first
line, clamped - and opens the whole text in a dialog where it keeps its
own line breaks, scrolls, stays selectable, and copies in one click.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
In the parent's execution graph a container's own status is WAITING_FOR_SUBFLOW,
so it took none of the in-progress styling and sat there inert for minutes while
its child ran. Combined with a tree that was not refreshing, a working run was
indistinguishable from a stuck one.
The card now pulses on the same rhythm as a running node, in indigo rather than
yellow because the work is a level down: the node is not computing, it is
waiting on a child, and that child is the thing worth opening. A badge names the
iteration in flight - __containerIterationIndex is new on the graph payload - so
the signal says what is happening and not merely that something is.
An errored container does not pulse: there the error is what matters.
Motion is now suppressed under prefers-reduced-motion, with the pulses settling
on their emphasised frame so the state survives without the animation. That
covers the two pre-existing pulses as well - adding a third blinking element is
the point where honouring the setting stops being optional.
Budgets: task-step-node.css went 122 bytes over, so the badge icon lost its spin
(the border pulse already carries "in progress"). The initial bundle is still
2.21 kB over its 1.75 MB budget, up from being just inside it - reported, not
raised.
497 frontend tests green; the new assertions fail with the class binding removed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Finishes the bias impact experiments plan (docs/bias-impact-experiments-plan.md
steps 7-12):
- Side-effect policy selector: reuse the .llm-warning visual language for the
external side-effects banner, add a REQUIRE_CONFIRMATION note.
- Full-flow compare ("Compare with baseline"): new bias-compare-dialog
(service + host) triggering compareBiasExecutions and opening the shared
report viewer; inline errors read from errors[].message/detail.
- Persisted reports: new bias-impact-report-list (list + detail in one view)
wired into a new "Bias impact reports" tab in task-execution-viewer;
404/403 on report detail show the same inline message on purpose.
- Canvas: annotation badge on generic-node (count, executable-probe
indicator, severity from the backend catalog); new
BiasComparisonViewStateService driving bias-active / downstream-changed /
routing-change highlighting on task-step-node and custom-connection, fed by
a highlightOnCanvas event from bias-impact-report-viewer wired in all three
places that render it; legend + "back to normal view" action in the canvas
toolbar.
- Fixed a bug where the bias variant context badge only rendered for
simulated executions.
- Fixed "Measure bias impact" to stay visible-but-disabled with an
explanatory tooltip while the baseline hasn't reached a final state,
instead of being hidden outright, per the §12 checklist.
- Added a Retry action to the compare dialog's error state for parity with
the report list.
- Added the end-to-end facade flow test (annotation -> capability -> isolated
experiment -> report) plus coverage for all new components/services.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>