feat: amber container for filter/idempotent gate state + red pulse on failed badge
When a filter processor rejects a message (filterMatched=false) or an idempotent consumer detects a duplicate (duplicateMessage=true), the compound container turns amber (header, border, body tint). Also adds red pulsing rings on the failed processor badge (same SMIL pattern as the teal hasTraceData pulse). Backend: ProcessorNode gains filterMatched/duplicateMessage fields, threaded from ProcessorExecution JSON path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,12 @@ export function CompoundNode({
|
||||
onNodeClick, onNodeDoubleClick, onNodeEnter, onNodeLeave,
|
||||
};
|
||||
|
||||
// Gate state: filter rejected or idempotent duplicate → amber container
|
||||
const ownState = node.id ? executionOverlay?.get(node.id) : undefined;
|
||||
const isGated = ownState?.filterMatched === false || ownState?.duplicateMessage === true;
|
||||
const GATE_COLOR = '#D97706'; // amber-600
|
||||
const effectiveColor = isGated ? GATE_COLOR : color;
|
||||
|
||||
// _TRY_BODY / _CB_MAIN: transparent wrapper — no header, no border, just layout
|
||||
if (node.type === '_TRY_BODY' || node.type === '_CB_MAIN') {
|
||||
return (
|
||||
@@ -118,7 +124,8 @@ export function CompoundNode({
|
||||
);
|
||||
}
|
||||
|
||||
// Default compound rendering (DO_TRY, EIP_CHOICE, etc.)
|
||||
// Default compound rendering (DO_TRY, EIP_CHOICE, EIP_FILTER, EIP_IDEMPOTENT_CONSUMER, etc.)
|
||||
const containerFill = isGated ? '#FFFBEB' : 'white'; // amber-50 tint when gated
|
||||
return (
|
||||
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
|
||||
{/* Container body */}
|
||||
@@ -128,14 +135,14 @@ export function CompoundNode({
|
||||
width={w}
|
||||
height={h}
|
||||
rx={CORNER_RADIUS}
|
||||
fill="white"
|
||||
stroke={color}
|
||||
strokeWidth={1.5}
|
||||
fill={containerFill}
|
||||
stroke={effectiveColor}
|
||||
strokeWidth={isGated ? 2 : 1.5}
|
||||
/>
|
||||
|
||||
{/* Colored header bar */}
|
||||
<rect x={0} y={0} width={w} height={HEADER_HEIGHT} rx={CORNER_RADIUS} fill={color} />
|
||||
<rect x={CORNER_RADIUS} y={CORNER_RADIUS} width={w - CORNER_RADIUS * 2} height={HEADER_HEIGHT - CORNER_RADIUS} fill={color} />
|
||||
<rect x={0} y={0} width={w} height={HEADER_HEIGHT} rx={CORNER_RADIUS} fill={effectiveColor} />
|
||||
<rect x={CORNER_RADIUS} y={CORNER_RADIUS} width={w - CORNER_RADIUS * 2} height={HEADER_HEIGHT - CORNER_RADIUS} fill={effectiveColor} />
|
||||
|
||||
{/* Header icon (left-aligned) */}
|
||||
<g transform={`translate(6, ${HEADER_HEIGHT / 2 - 5}) scale(0.417)`}>
|
||||
|
||||
Reference in New Issue
Block a user