Mirrors the existing block-side bias impact feature onto containers,
reusing the same descriptor, form and error handling as the backend
integration doc specifies, rather than duplicating them:
- FlowContainer now carries biasAnnotations, matching FlowBlock.
- ContainersService/ContainersCallService gained
retrieveBiasCapabilities/retrieveBiasCapabilitiesForInstance,
backed by GET/POST /containers/types/{type}/bias-capabilities.
- bias-annotations and behavioral-probe-editor now accept FlowNode
instead of FlowBlock only; the probe editor dispatches capability
lookups to BlocksService or ContainersService based on nodeFamily,
so container annotations reuse the exact same shared components
and UI instead of a second, parallel implementation.
- container-node gained the bias badge, the bias-annotations panel,
and preserves annotations across recreateContainer() the same way
generic-node already does across block regeneration.
- task-execution-viewer's bias-rerun candidate list now includes
containers with executable probes, not just blocks.
Also fixes a real data-loss bug found while wiring this up:
rete-editor's exportGraph explicitly stripped bias annotations from
containers on every flow save, silently discarding anything entered
through the new panel.
Verified with the full suite (238/238, 6 new tests) and a live
end-to-end browser check: an annotation added to a container only
offered INPUT_TRANSFORMATION/OUTPUT_TRANSFORMATION (per the fake
container capabilities), and survived a save + reopen of the saved
flow, proving the exportGraph fix actually round-trips the data.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The bias annotation editor rendered its dimming backdrop as a plain
position:fixed div. Since it sits inside a node card that rete.js
positions with a CSS transform for pan/zoom, that transform becomes
the containing block for fixed descendants, so the backdrop was
confined to the node's own box instead of covering the page.
Switch to a native <dialog> shown via showModal(), which promotes it
to the browser's top layer regardless of ancestor transforms, and use
::backdrop for the dimming overlay. showModal() is guarded because
jsdom does not implement it, so unit tests keep working.
Confirmed both by unit tests and a live browser check: the backdrop's
bounding rect now spans the full viewport instead of the node's box.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>