Five empty chips for parameters nobody sets on most nodes took more room than
the prompt. The group now shows as a single control saying how many of its
settings are set, and opens the whole object in one dialog.
The write-back reuses the object round trip rather than the array one, so an
optional numeric cleared in the modal removes the key instead of persisting 0 -
otherwise the provider default would be unreachable, which is the bug fixed
yesterday for the inline editor. Clearing everything drops the object entirely,
so a saved flow never carries an empty husk that implies a choice was made.
A temperature of 0 counts towards the badge: it is the repeatable setting, not
an absence, and a collapsed control must never hide a value.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Implements the frontend side of the control-flow engine's Fase 4-5
backend extension: presentation-only swimlanes for grouping nodes by
actor/responsibility, and a new IOType.JSON for structured input/
output descriptors. Both are additive/optional fields, backward
compatible with existing flows.
Swimlanes:
- Model: FlowLane (id, name, description, order, color), FlowData.lanes,
and an optional laneId on every block/container.
- Lane management (add/rename/reorder/color/delete) in a new "Lanes"
section of the title toolbar, mirroring the existing Global Inputs
editor. Deleting a lane clears laneId on any node that referenced it,
avoiding an immediate NODE_LANE_NOT_FOUND validation error.
- Real visual swimlanes on the rete.js canvas: horizontal color-coded
bands with labels that pan/zoom together with the nodes, backed by a
transform layer kept in sync with the area's live transform.
- Drag-to-reassign: moving a node updates its laneId based on the drop
Y position, but only for genuine pointer drags — programmatic moves
(initial load, clone, server-side node regeneration) are excluded via
the existing programmatic-translation tracking, so loading a flow
never silently reassigns lanes.
- A small lane badge on the node header confirms the current
assignment after a drag.
- The readonly/execution-view diff and patch logic now accounts for
laneId and lanes so live updates are detected correctly.
Also fixes a data-loss bug found while wiring this up: exportGraph()
rebuilt each node and the top-level FlowData as explicit object
literals that never carried laneId/lanes through, and flowFromApi()
never normalized lanes coming back from the backend — both would have
silently dropped the field on save/reload, the same class of bug fixed
earlier for biasAnnotations.
JSON IO type:
- Global input type picker now offers JSON alongside TEXT/FILE.
- Behavioral probe editor: JSON-typed mock outputs default to {} and
use the JSON textarea editor instead of a plain text input.
- portSelectableKinds (generic-node) includes JSON among the concrete
types offered wherever a port's kind is ANY.
Verified with the full suite (253/253, 21 new tests) and a live
end-to-end browser check: created two lanes, dragged a node from the
unassigned area into a lane (confirmed via the node's lane badge),
saved, and reopened the saved flow with the lane assignment intact.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
generic-node's "Delete node?" popup used its own slightly different
red shades (border #fca5a5, gradient background, text #881337)
instead of the #7f1d1d/#fecaca/#fff1f2 combination that its own
warning tooltip and container-node's identical delete-confirm popup
already use consistently. Aligned it to that shared combination.
Investigated the header color difference between generic-node (blue)
and container-node (teal) that an earlier audit flagged as an
inconsistency: task-step-node.css shows the header gradient is a
deliberate per-node-type identity color (blue = automatic, orange =
human-interaction, per its .llm-node--human .llm-header rule), so
container-node's teal is consistent with that scheme, not a bug — left
unchanged. The port badge colors (input/output/dependency) were
already identical between generic-node and container-node.
Verified with the full suite (232/232) and a live browser check of
the delete-confirm popup.
Co-Authored-By: Claude Sonnet 5 <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>