@coreason-ai/sensory-core 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+ // Copyright (c) 2026 CoReason, Inc
2
+ //
3
+ // This software is proprietary and dual-licensed
4
+ // Licensed under the Prosperity Public License 3.0 (the "License")
5
+ // A copy of the license is available at <https://prosperitylicense.com/versions/3.0.0>
6
+ // For details, see the LICENSE file
7
+ // Commercial use beyond a 30-day trial requires a separate license
8
+ //
9
+ // Source Code: <https://github.com/CoReason-AI/coreason-sensory-core>
10
+ import React, { useState, useEffect, useRef } from 'react';
11
+ import { motion, AnimatePresence } from 'framer-motion';
12
+ import { GlassBox } from './GlassBox';
13
+ /**
14
+ * Computes horizontal tree layout using post-order positioning.
15
+ */
16
+ function computeTreeLayout(node, depth = 0, layoutState = { nextLeafY: 0 }, xSpacing = 170, ySpacing = 65) {
17
+ const x = depth * xSpacing + 70;
18
+ if (!node.childSpeculations || node.childSpeculations.length === 0) {
19
+ const y = layoutState.nextLeafY * ySpacing + 60;
20
+ layoutState.nextLeafY += 1;
21
+ return {
22
+ tokenId: node.tokenId,
23
+ tokenValue: node.tokenValue,
24
+ logitProbability: node.logitProbability,
25
+ validationStatus: node.validationStatus,
26
+ x,
27
+ y,
28
+ children: [],
29
+ };
30
+ }
31
+ const children = node.childSpeculations.map((child) => computeTreeLayout(child, depth + 1, layoutState, xSpacing, ySpacing));
32
+ const sumY = children.reduce((sum, child) => sum + child.y, 0);
33
+ const y = sumY / children.length;
34
+ return {
35
+ tokenId: node.tokenId,
36
+ tokenValue: node.tokenValue,
37
+ logitProbability: node.logitProbability,
38
+ validationStatus: node.validationStatus,
39
+ x,
40
+ y,
41
+ children,
42
+ };
43
+ }
44
+ /**
45
+ * Traverses the computed layout tree to gather all node and connection information.
46
+ */
47
+ function collectLayoutEntities(node, accumulatedNodes = [], accumulatedEdges = []) {
48
+ accumulatedNodes.push(node);
49
+ for (const child of node.children) {
50
+ accumulatedEdges.push({
51
+ parentId: node.tokenId,
52
+ childId: child.tokenId,
53
+ x1: node.x,
54
+ y1: node.y,
55
+ x2: child.x,
56
+ y2: child.y,
57
+ status: child.validationStatus,
58
+ });
59
+ collectLayoutEntities(child, accumulatedNodes, accumulatedEdges);
60
+ }
61
+ return { nodes: accumulatedNodes, edges: accumulatedEdges };
62
+ }
63
+ /**
64
+ * SpeculativeTreeRenderer
65
+ *
66
+ * Target Persona: Systems Engineer / Operational Intelligencer
67
+ * Concept: System 1 / Speculative Decoding telemetry projection.
68
+ * Projects real-time speculative logit draft token proposals, visual decay,
69
+ * and target model validation status in a cybernetic tree diagram.
70
+ */
71
+ export const SpeculativeTreeRenderer = ({ tokenTree, onTokenFocus, className, }) => {
72
+ const [particles, setParticles] = useState([]);
73
+ const [hoveredToken, setHoveredToken] = useState(null);
74
+ // Track triggered rejections to prevent double-spawning particles
75
+ const processedRejectionsRef = useRef(new Set());
76
+ // Compute layout structures
77
+ const layoutRoot = computeTreeLayout(tokenTree);
78
+ const { nodes: layoutNodes, edges: layoutEdges } = collectLayoutEntities(layoutRoot);
79
+ // Determine viewport boundary limits
80
+ const maxX = Math.max(...layoutNodes.map((n) => n.x), 500) + 120;
81
+ const maxY = Math.max(...layoutNodes.map((n) => n.y), 250) + 80;
82
+ useEffect(() => {
83
+ const freshRejections = [];
84
+ // Identify nodes that became rejected and haven't spawned particles yet
85
+ const inspectForRejections = (n) => {
86
+ if (n.validationStatus === 'target_rejected' && !processedRejectionsRef.current.has(n.tokenId)) {
87
+ freshRejections.push(n);
88
+ }
89
+ n.children.forEach(inspectForRejections);
90
+ };
91
+ inspectForRejections(layoutRoot);
92
+ if (freshRejections.length > 0) {
93
+ const generatedParticles = [];
94
+ for (const rejNode of freshRejections) {
95
+ processedRejectionsRef.current.add(rejNode.tokenId);
96
+ // Spawn 8 disperse particles for decay animation
97
+ for (let i = 0; i < 8; i++) {
98
+ const angle = Math.random() * Math.PI * 2;
99
+ const speed = 25 + Math.random() * 40;
100
+ generatedParticles.push({
101
+ id: `${rejNode.tokenId}-particle-${i}-${Math.random()}`,
102
+ x: rejNode.x,
103
+ y: rejNode.y,
104
+ dx: Math.cos(angle) * speed,
105
+ dy: Math.sin(angle) * speed,
106
+ color: Math.random() > 0.4 ? '#ff4444' : '#ffaa00',
107
+ size: 2 + Math.random() * 3,
108
+ });
109
+ }
110
+ }
111
+ setParticles((prev) => [...prev, ...generatedParticles]);
112
+ // Clean up dissolved particles after 500ms
113
+ const cleanupTimer = setTimeout(() => {
114
+ setParticles((prev) => prev.filter((p) => !generatedParticles.includes(p)));
115
+ }, 500);
116
+ return () => clearTimeout(cleanupTimer);
117
+ }
118
+ }, [tokenTree, layoutRoot]);
119
+ const handleInteraction = (token) => {
120
+ if (onTokenFocus) {
121
+ onTokenFocus({
122
+ tokenId: token.tokenId,
123
+ tokenValue: token.tokenValue,
124
+ logitProbability: token.logitProbability,
125
+ validationStatus: token.validationStatus,
126
+ childSpeculations: [],
127
+ });
128
+ }
129
+ };
130
+ return (React.createElement(GlassBox, { className: className, variant: "black" },
131
+ React.createElement("div", { className: "flex flex-col space-y-3 font-mono" },
132
+ React.createElement("div", { className: "flex justify-between items-center border-b border-gray-800 pb-2" },
133
+ React.createElement("div", null,
134
+ React.createElement("h3", { className: "text-xs font-semibold text-white tracking-widest uppercase" }, "Speculative Telemetry"),
135
+ React.createElement("span", { className: "text-[9px] text-gray-500 uppercase" }, "System 1 Draft Proposals & Validation Decay")),
136
+ React.createElement("div", { className: "flex gap-3 text-[9px] uppercase tracking-wider" },
137
+ React.createElement("span", { className: "flex items-center gap-1" },
138
+ React.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-[var(--cr-accent-cyan)] shadow-[0_0_4px_var(--cr-accent-cyan)]" }),
139
+ "Validated"),
140
+ React.createElement("span", { className: "flex items-center gap-1" },
141
+ React.createElement("span", { className: "w-1.5 h-1.5 rounded-full border border-dashed border-gray-500" }),
142
+ "Draft Proposal"),
143
+ React.createElement("span", { className: "flex items-center gap-1" },
144
+ React.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-red-500/40 line-through" }),
145
+ "Decayed"))),
146
+ React.createElement("div", { className: "relative w-full overflow-auto bg-black/60 rounded border border-gray-850 p-2 h-72 custom-scrollbar" },
147
+ React.createElement("svg", { width: maxX, height: maxY, className: "absolute top-0 left-0 overflow-visible" },
148
+ React.createElement("g", null, layoutEdges.map((edge) => {
149
+ const isRejected = edge.status === 'target_rejected';
150
+ const isValidated = edge.status === 'target_validated';
151
+ // SVG Bezier path curve calculation
152
+ const controlOffset = 50;
153
+ const pathData = `M ${edge.x1} ${edge.y1} C ${edge.x1 + controlOffset} ${edge.y1}, ${edge.x2 - controlOffset} ${edge.y2}, ${edge.x2} ${edge.y2}`;
154
+ return (React.createElement("path", { key: `${edge.parentId}-${edge.childId}`, d: pathData, fill: "none", stroke: isRejected
155
+ ? 'rgba(239, 68, 68, 0.1)'
156
+ : isValidated
157
+ ? 'var(--cr-accent-cyan)'
158
+ : 'rgba(255, 255, 255, 0.15)', strokeWidth: isValidated ? 2 : 1, strokeDasharray: isRejected ? '3, 3' : undefined, className: "transition-all duration-300" }));
159
+ })),
160
+ React.createElement("g", null, particles.map((p) => (React.createElement(motion.circle, { key: p.id, cx: p.x, cy: p.y, r: p.size, fill: p.color, initial: { opacity: 1, x: 0, y: 0 }, animate: { opacity: 0, x: p.dx, y: p.dy }, transition: { duration: 0.45, ease: 'easeOut' } }))))),
161
+ React.createElement("div", { className: "absolute top-0 left-0", style: { width: maxX, height: maxY } }, layoutNodes.map((node) => {
162
+ const isValidated = node.validationStatus === 'target_validated';
163
+ const isRejected = node.validationStatus === 'target_rejected';
164
+ // Map probability value to distinct colors
165
+ const probColor = node.logitProbability >= 0.8
166
+ ? 'text-green-400'
167
+ : node.logitProbability >= 0.5
168
+ ? 'text-yellow-400'
169
+ : 'text-red-400';
170
+ return (React.createElement(motion.div, { key: node.tokenId, style: {
171
+ position: 'absolute',
172
+ left: node.x,
173
+ top: node.y,
174
+ transform: 'translate(-50%, -50%)',
175
+ zIndex: 10,
176
+ }, initial: false, animate: {
177
+ scale: isRejected ? 0.85 : 1,
178
+ opacity: isRejected ? 0.35 : 1,
179
+ }, transition: { duration: 0.3 } },
180
+ React.createElement("button", { onClick: () => handleInteraction(node), onMouseEnter: () => setHoveredToken(node), onMouseLeave: () => setHoveredToken(null), style: { borderRadius: 'var(--cr-border-radius)' }, className: `px-3 py-2 text-xs font-mono transition-all duration-300 border flex flex-col items-center select-none ${isValidated
181
+ ? 'border-[var(--cr-accent-cyan)] shadow-[0_0_12px_rgba(0,255,204,0.4)] bg-black/90 text-white'
182
+ : isRejected
183
+ ? 'border-red-500/20 bg-red-950/5 text-gray-500 line-through'
184
+ : 'border-dashed border-gray-700 bg-gray-950/80 text-gray-300 hover:border-gray-500'}` },
185
+ React.createElement("span", { className: "font-semibold tracking-wider text-[11px]" }, node.tokenValue),
186
+ React.createElement("span", { className: `text-[8px] font-bold mt-0.5 ${probColor}` },
187
+ (node.logitProbability * 100).toFixed(0),
188
+ "%"))));
189
+ }))),
190
+ React.createElement(AnimatePresence, null, hoveredToken && (React.createElement(motion.div, { initial: { opacity: 0, y: 5 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: 5 }, className: "bg-gray-950/95 border border-gray-850 p-2.5 rounded text-[10px] text-gray-400 flex flex-col space-y-1" },
191
+ React.createElement("div", { className: "flex justify-between text-white font-semibold" },
192
+ React.createElement("span", null,
193
+ "Token ID: ",
194
+ hoveredToken.tokenId),
195
+ React.createElement("span", { className: "uppercase text-[9px] tracking-widest px-1.5 py-0.5 bg-gray-900 border border-gray-800 rounded" }, hoveredToken.validationStatus.replace('target_', '').replace('speculative_', ''))),
196
+ React.createElement("div", { className: "flex justify-between" },
197
+ React.createElement("span", null, "Value representation:"),
198
+ React.createElement("span", { className: "text-white font-mono bg-black px-1.5 rounded" }, JSON.stringify(hoveredToken.tokenValue))),
199
+ React.createElement("div", { className: "flex justify-between" },
200
+ React.createElement("span", null, "Logit Probability:"),
201
+ React.createElement("span", { className: "text-white font-mono" }, hoveredToken.logitProbability.toFixed(5)))))))));
202
+ };
@@ -9,8 +9,11 @@ export interface TemporalScrubberProps {
9
9
  minRange: number;
10
10
  maxRange: number;
11
11
  forks?: TemporalFork[];
12
+ activeForkId?: string;
12
13
  onScrub: (newTime: number) => void;
13
14
  onForkSelect?: (forkId: string) => void;
15
+ onForkInitiate?: (branchPoint: number) => void;
16
+ onForkClose?: (forkId: string) => void;
14
17
  className?: string;
15
18
  }
16
19
  export declare const TemporalScrubber: React.FC<TemporalScrubberProps>;
@@ -10,11 +10,13 @@
10
10
  import React from 'react';
11
11
  import { motion } from 'framer-motion';
12
12
  import { cn } from './GlassBox';
13
- export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], onScrub, onForkSelect, className }) => {
13
+ export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], activeForkId, onScrub, onForkSelect, onForkInitiate, onForkClose, className }) => {
14
14
  const getPercentage = (val) => ((val - minRange) / (maxRange - minRange)) * 100;
15
15
  return (React.createElement("div", { className: cn('flex flex-col items-stretch gap-4 p-4 bg-[var(--cr-glass-box-black)] rounded-xl border border-gray-800', className) },
16
16
  React.createElement("div", { className: "flex justify-between items-center mb-2" },
17
- React.createElement("span", { className: "text-white uppercase tracking-widest text-xs font-bold" }, "Temporal Navigation"),
17
+ React.createElement("div", { className: "flex items-center gap-3" },
18
+ React.createElement("span", { className: "text-white uppercase tracking-widest text-xs font-bold" }, "Temporal Navigation"),
19
+ onForkInitiate && (React.createElement("button", { onClick: () => onForkInitiate(timestamp), className: "px-2 py-0.5 bg-purple-950/60 border border-purple-500/50 hover:bg-purple-900/60 text-purple-300 text-[10px] font-mono rounded transition-all uppercase tracking-wider font-bold" }, "Fork Timeline"))),
18
20
  React.createElement("span", { className: "text-[var(--cr-accent-cyan)] font-mono text-xs" },
19
21
  "T - ",
20
22
  Math.floor((Date.now() - timestamp) / 1000),
@@ -25,11 +27,21 @@ export const TemporalScrubber = ({ timestamp, minRange, maxRange, forks = [], on
25
27
  forks.map((fork, idx) => {
26
28
  const startPct = getPercentage(fork.branchPoint);
27
29
  const topOffset = idx % 2 === 0 ? 0 : 16;
28
- return (React.createElement(motion.div, { key: fork.id, initial: { opacity: 0 }, animate: { opacity: 1 }, className: "absolute h-1 bg-[var(--cr-accent-orange)] cursor-pointer group", style: { left: `${startPct}%`, top: topOffset, width: `calc(100% - ${startPct}%)` }, onClick: () => onForkSelect === null || onForkSelect === void 0 ? void 0 : onForkSelect(fork.id) },
29
- React.createElement("div", { className: "absolute -left-1 -top-1 w-3 h-3 rounded-full bg-[var(--cr-accent-orange)]" }),
30
- React.createElement("div", { className: "absolute -top-6 left-0 opacity-0 group-hover:opacity-100 transition-opacity bg-black text-[var(--cr-accent-orange)] text-[10px] font-mono px-2 py-1 rounded" },
31
- "\u2443 ",
32
- fork.name)));
30
+ const isActive = activeForkId === fork.id;
31
+ return (React.createElement(motion.div, { key: fork.id, initial: { opacity: 0 }, animate: { opacity: 1 }, className: cn("absolute h-1 cursor-pointer group transition-all duration-300", isActive
32
+ ? "bg-purple-500 shadow-[0_0_8px_rgba(168,85,247,0.8)] z-20"
33
+ : "bg-[var(--cr-accent-orange)] z-10"), style: { left: `${startPct}%`, top: topOffset, width: `calc(100% - ${startPct}%)` }, onClick: () => onForkSelect === null || onForkSelect === void 0 ? void 0 : onForkSelect(fork.id) },
34
+ React.createElement("div", { className: cn("absolute -left-1 -top-1 w-3 h-3 rounded-full transition-all duration-300", isActive ? "bg-purple-400 scale-125" : "bg-[var(--cr-accent-orange)]") }),
35
+ React.createElement("div", { className: cn("absolute -top-6 left-0 transition-opacity bg-black text-[10px] font-mono px-2 py-1 rounded flex items-center gap-1.5 whitespace-nowrap", isActive
36
+ ? "opacity-100 text-purple-300 border border-purple-500/30"
37
+ : "opacity-0 group-hover:opacity-100 text-[var(--cr-accent-orange)]") },
38
+ React.createElement("span", null,
39
+ "\u2443 ",
40
+ fork.name),
41
+ onForkClose && (React.createElement("button", { onClick: (e) => {
42
+ e.stopPropagation();
43
+ onForkClose(fork.id);
44
+ }, className: "hover:text-white text-xs ml-1 focus:outline-none font-bold", title: "Dismiss Fork" }, "\u00D7")))));
33
45
  }),
34
46
  React.createElement("input", { type: "range", min: minRange, max: maxRange, value: timestamp, onChange: (e) => onScrub(Number(e.target.value)), className: "absolute top-[26px] w-full cursor-ew-resize opacity-0 z-10" }),
35
47
  React.createElement(motion.div, { className: "absolute top-6 w-5 h-5 rounded-full bg-white border-2 border-[var(--cr-accent-cyan)] shadow-[0_0_10px_var(--cr-accent-cyan)] pointer-events-none", style: { left: `calc(${getPercentage(timestamp)}% - 10px)` }, layout: true }))));
@@ -17,11 +17,7 @@ export interface TopologicalCanvasProps {
17
17
  x: number;
18
18
  y: number;
19
19
  }) => void;
20
+ onExecuteIntervention?: (nodeId: string) => void;
20
21
  }
21
- /**
22
- * TopologicalCanvas
23
- *
24
- * Concept: Visualizes the Macro-Swarm Architecture
25
- * Uses ReactFlow to map mathematical DAGs to the UI
26
- */
22
+ export declare const computeBlastRadius: (nodes: Node[], edges: Edge[], startNodeId: string) => Set<string>;
27
23
  export declare const TopologicalCanvas: React.FC<TopologicalCanvasProps>;
@@ -17,14 +17,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  });
18
18
  };
19
19
  import React from 'react';
20
- import { ReactFlow, Background, Controls, getBezierPath, EdgeLabelRenderer, Panel } from '@xyflow/react';
20
+ import { ReactFlow, Background, Controls, getBezierPath, EdgeLabelRenderer, Panel, ReactFlowProvider, useViewport } from '@xyflow/react';
21
21
  import '@xyflow/react/dist/style.css';
22
22
  import { GlassBox } from './GlassBox';
23
23
  import { StatusPulse } from './StatusPulse';
24
- import { Lock, Unlock, ShieldAlert, ShieldX } from 'lucide-react';
24
+ import { Lock, Unlock, ShieldAlert, ShieldX, AlertTriangle } from 'lucide-react';
25
25
  import { ConformanceGuillotine } from './ConformanceGuillotine';
26
26
  // Custom Node: SwarmNode
27
- const SwarmNode = ({ data }) => {
27
+ const SwarmNode = ({ id, data }) => {
28
28
  var _a;
29
29
  const isBreached = data.status === 'suspended_security_violation' || data.isSecurityViolation;
30
30
  const isCompact = data.density === 'compact';
@@ -32,6 +32,9 @@ const SwarmNode = ({ data }) => {
32
32
  if (data.isPanicked) {
33
33
  borderColorClass = 'border-red-600/80 shadow-[0_0_15px_rgba(220,38,38,0.3)]';
34
34
  }
35
+ else if (data.isInBlastRadius) {
36
+ borderColorClass = 'border-red-500/90 shadow-[0_0_18px_rgba(239,68,68,0.6)] bg-red-950/20 animate-pulse';
37
+ }
35
38
  else if (isBreached) {
36
39
  borderColorClass = 'border-orange-500/80 shadow-[0_0_15px_rgba(249,115,22,0.3)]';
37
40
  }
@@ -48,7 +51,16 @@ const SwarmNode = ({ data }) => {
48
51
  React.createElement("div", { className: "flex flex-col" },
49
52
  React.createElement("div", { className: "flex justify-between items-center mb-2" },
50
53
  React.createElement("span", { className: "text-[10px] uppercase tracking-widest text-gray-500" }, data.typeLabel || 'AGENT'),
51
- !isCompact && React.createElement(StatusPulse, { status: data.status || 'idle' })),
54
+ React.createElement("div", { className: "flex items-center gap-1.5" },
55
+ React.createElement("button", { onMouseEnter: () => { var _a; return (_a = data.onHoverRetract) === null || _a === void 0 ? void 0 : _a.call(data, id); }, onMouseLeave: () => { var _a; return (_a = data.onLeaveRetract) === null || _a === void 0 ? void 0 : _a.call(data); }, onClick: (e) => {
56
+ var _a;
57
+ e.stopPropagation();
58
+ (_a = data.onExecuteIntervention) === null || _a === void 0 ? void 0 : _a.call(data, id);
59
+ }, className: "text-gray-500 hover:text-red-500 transition-colors p-0.5 rounded cursor-pointer flex items-center justify-center bg-black/40 border border-white/5 hover:border-red-500/30", title: "Retract Node (Do-Operator)" },
60
+ React.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
61
+ React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
62
+ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" }))),
63
+ !isCompact && React.createElement(StatusPulse, { status: data.status || 'idle' }))),
52
64
  !isCompact && (React.createElement("span", { className: "text-sm font-mono text-white truncate max-w-[120px]", title: data.urn }, ((_a = data.urn) === null || _a === void 0 ? void 0 : _a.split(':').slice(-2).join(':')) || 'urn:unknown')),
53
65
  data.causalRole && (React.createElement("div", { className: `mt-2 text-[8px] font-bold uppercase tracking-wider px-1 py-0.5 rounded text-center ${data.causalRole === 'confounder'
54
66
  ? 'bg-yellow-500/20 text-yellow-400 border border-yellow-500/30'
@@ -76,13 +88,24 @@ const SandboxNode = ({ id, data }) => {
76
88
  const isCompact = data.density === 'compact';
77
89
  return (React.createElement("div", { className: `bg-[rgba(20,20,20,0.8)] border relative rounded-lg p-4 min-w-[300px] ${isCompact ? 'min-h-[50px]' : 'min-h-[200px]'} shadow-[0_0_15px_rgba(255,100,0,0.2)] ${data.isPanicked
78
90
  ? 'border-red-600/80 shadow-[0_0_20px_rgba(220,38,38,0.4)]'
79
- : 'border-[var(--cr-accent-orange)]'}` },
91
+ : data.isInBlastRadius
92
+ ? 'border-red-500/90 shadow-[0_0_20px_rgba(239,68,68,0.6)] bg-red-950/20 animate-pulse'
93
+ : 'border-[var(--cr-accent-orange)]'}` },
80
94
  React.createElement("div", { className: `absolute top-0 left-0 right-0 text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded-t-sm flex justify-between items-center ${data.isPanicked ? 'bg-red-600 text-white' : 'bg-[var(--cr-accent-orange)] text-black'}` },
81
95
  React.createElement("span", null,
82
96
  "\u26CA ",
83
97
  data.sandboxType || 'WASM ENCLAVE',
84
98
  " ISOLATION BOUNDARY"),
85
- React.createElement("span", { className: "font-mono" }, data.id || id)),
99
+ React.createElement("div", { className: "flex items-center gap-2" },
100
+ React.createElement("button", { onMouseEnter: () => { var _a; return (_a = data.onHoverRetract) === null || _a === void 0 ? void 0 : _a.call(data, id); }, onMouseLeave: () => { var _a; return (_a = data.onLeaveRetract) === null || _a === void 0 ? void 0 : _a.call(data); }, onClick: (e) => {
101
+ var _a;
102
+ e.stopPropagation();
103
+ (_a = data.onExecuteIntervention) === null || _a === void 0 ? void 0 : _a.call(data, id);
104
+ }, className: `p-0.5 rounded transition-colors cursor-pointer flex items-center justify-center bg-black/40 border border-white/5 ${data.isPanicked ? 'text-white/70 hover:text-white hover:border-white/30' : 'text-black/70 hover:text-red-600 hover:border-red-600/30'}`, title: "Retract WASM Sandbox" },
105
+ React.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
106
+ React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
107
+ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" }))),
108
+ React.createElement("span", { className: "font-mono" }, data.id || id))),
86
109
  !isCompact && (React.createElement("div", { className: "mt-6 mb-2 flex flex-col gap-2" },
87
110
  React.createElement("div", { className: "flex items-center justify-between text-[10px] font-mono text-gray-400" },
88
111
  React.createElement("span", null, "CPU FUEL"),
@@ -124,6 +147,8 @@ const TelemetryEdge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition,
124
147
  });
125
148
  const [showDetails, setShowDetails] = React.useState(false);
126
149
  const getEdgeColor = () => {
150
+ if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
151
+ return '#ef4444'; // Flashing red hazard line
127
152
  if (data === null || data === void 0 ? void 0 : data.isSecurityViolation)
128
153
  return '#f97316'; // Flashing firewall orange
129
154
  if (data === null || data === void 0 ? void 0 : data.isSecureMtls)
@@ -133,11 +158,15 @@ const TelemetryEdge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition,
133
158
  return (data === null || data === void 0 ? void 0 : data.isStreaming) ? 'var(--cr-accent-orange)' : '#4B5563';
134
159
  };
135
160
  const getStrokeDashArray = () => {
161
+ if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
162
+ return '5,5';
136
163
  if ((data === null || data === void 0 ? void 0 : data.isSecureMtls) || (data === null || data === void 0 ? void 0 : data.isStreaming) || (data === null || data === void 0 ? void 0 : data.isSecurityViolation))
137
164
  return '5,5';
138
165
  return 'none';
139
166
  };
140
167
  const getAnimation = () => {
168
+ if (data === null || data === void 0 ? void 0 : data.isInBlastRadius)
169
+ return 'dashdraw 0.3s linear infinite'; // Accelerated dash warning
141
170
  if (data === null || data === void 0 ? void 0 : data.isSecurityViolation)
142
171
  return 'dashdraw 0.5s linear infinite';
143
172
  if ((data === null || data === void 0 ? void 0 : data.isStreaming) || (data === null || data === void 0 ? void 0 : data.isSecureMtls))
@@ -212,15 +241,101 @@ const nodeTypes = {
212
241
  const edgeTypes = {
213
242
  telemetryEdge: TelemetryEdge,
214
243
  };
215
- /**
216
- * TopologicalCanvas
217
- *
218
- * Concept: Visualizes the Macro-Swarm Architecture
219
- * Uses ReactFlow to map mathematical DAGs to the UI
220
- */
221
- export const TopologicalCanvas = ({ nodes, edges, availableCapabilities = [], onNodeClick, onNodesChange, onEdgesChange, onConnect, onDropCapability }) => {
244
+ export const computeBlastRadius = (nodes, edges, startNodeId) => {
245
+ const visited = new Set();
246
+ const queue = [startNodeId];
247
+ while (queue.length > 0) {
248
+ const current = queue.shift();
249
+ if (!visited.has(current)) {
250
+ visited.add(current);
251
+ const downstream = edges
252
+ .filter(e => e.source === current)
253
+ .map(e => e.target);
254
+ queue.push(...downstream);
255
+ }
256
+ }
257
+ return visited;
258
+ };
259
+ const CausalInterventionOverlay = ({ nodes, hoveredNodeId }) => {
260
+ var _a, _b, _c, _d;
261
+ const { x, y, zoom } = useViewport();
262
+ const [pulseRadius, setPulseRadius] = React.useState(0);
263
+ React.useEffect(() => {
264
+ let frame;
265
+ const start = performance.now();
266
+ const animate = (time) => {
267
+ const elapsed = time - start;
268
+ const progress = (elapsed % 1500) / 1500;
269
+ setPulseRadius(progress * 120);
270
+ frame = requestAnimationFrame(animate);
271
+ };
272
+ frame = requestAnimationFrame(animate);
273
+ return () => cancelAnimationFrame(frame);
274
+ }, []);
275
+ const targetNode = nodes.find(n => n.id === hoveredNodeId);
276
+ if (!targetNode)
277
+ return null;
278
+ const isSandbox = targetNode.type === 'sandboxNode';
279
+ const width = (_b = (_a = targetNode.measured) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : (isSandbox ? 300 : 150);
280
+ const height = (_d = (_c = targetNode.measured) === null || _c === void 0 ? void 0 : _c.height) !== null && _d !== void 0 ? _d : (isSandbox ? 200 : 100);
281
+ const cx = targetNode.position.x + width / 2;
282
+ const cy = targetNode.position.y + height / 2;
283
+ const screenCx = cx * zoom + x;
284
+ const screenCy = cy * zoom + y;
285
+ return (React.createElement("svg", { style: {
286
+ position: 'absolute',
287
+ left: 0,
288
+ top: 0,
289
+ width: '100%',
290
+ height: '100%',
291
+ pointerEvents: 'none',
292
+ zIndex: 9999,
293
+ } },
294
+ React.createElement("circle", { cx: screenCx, cy: screenCy, r: pulseRadius * zoom, fill: "rgba(239, 68, 68, 0.08)", stroke: "rgba(239, 68, 68, 0.5)", strokeWidth: "2", style: {
295
+ transformOrigin: `${screenCx}px ${screenCy}px`,
296
+ } }),
297
+ React.createElement("circle", { cx: screenCx, cy: screenCy, r: 8 * zoom, fill: "#ef4444", className: "animate-ping" }),
298
+ React.createElement("circle", { cx: screenCx, cy: screenCy, r: 5 * zoom, fill: "#ef4444" })));
299
+ };
300
+ const TopologicalCanvasInner = ({ nodes, edges, availableCapabilities = [], onNodeClick, onNodesChange, onEdgesChange, onConnect, onDropCapability, onExecuteIntervention }) => {
301
+ var _a, _b;
222
302
  const [isLayouting, setIsLayouting] = React.useState(false);
223
303
  const [activePanicNode, setActivePanicNode] = React.useState(null);
304
+ const [hoveredRetractNodeId, setHoveredRetractNodeId] = React.useState(null);
305
+ const blastRadiusIds = React.useMemo(() => {
306
+ if (!hoveredRetractNodeId)
307
+ return new Set();
308
+ return computeBlastRadius(nodes, edges, hoveredRetractNodeId);
309
+ }, [nodes, edges, hoveredRetractNodeId]);
310
+ const processedNodes = React.useMemo(() => {
311
+ return nodes.map(node => {
312
+ const isInBlast = blastRadiusIds.has(node.id);
313
+ const isTarget = node.id === hoveredRetractNodeId;
314
+ return Object.assign(Object.assign({}, node), { data: Object.assign(Object.assign({}, node.data), { isInBlastRadius: isInBlast, isInterventionTarget: isTarget, onHoverRetract: (id) => setHoveredRetractNodeId(id), onLeaveRetract: () => setHoveredRetractNodeId(null), onExecuteIntervention: (id) => {
315
+ setHoveredRetractNodeId(null);
316
+ if (onExecuteIntervention) {
317
+ onExecuteIntervention(id);
318
+ }
319
+ } }) });
320
+ });
321
+ }, [nodes, blastRadiusIds, hoveredRetractNodeId, onExecuteIntervention]);
322
+ const processedEdges = React.useMemo(() => {
323
+ return edges.map(edge => {
324
+ const isInBlast = blastRadiusIds.has(edge.source);
325
+ return Object.assign(Object.assign({}, edge), { data: Object.assign(Object.assign({}, edge.data), { isInBlastRadius: isInBlast }) });
326
+ });
327
+ }, [edges, blastRadiusIds]);
328
+ const affectedSandboxCount = React.useMemo(() => {
329
+ return Array.from(blastRadiusIds).filter(id => {
330
+ var _a;
331
+ const node = nodes.find(n => n.id === id);
332
+ if (!node)
333
+ return false;
334
+ const urn = ((_a = node.data) === null || _a === void 0 ? void 0 : _a.urn) || '';
335
+ return node.type === 'sandboxNode' || urn.includes('urn:coreason:node:sandbox');
336
+ }).length;
337
+ }, [blastRadiusIds, nodes]);
338
+ const deficitForecast = blastRadiusIds.size * 150.0;
224
339
  const onDragStart = (event, capability) => {
225
340
  event.dataTransfer.setData('application/reactflow', JSON.stringify(capability));
226
341
  event.dataTransfer.effectAllowed = 'move';
@@ -291,8 +406,8 @@ export const TopologicalCanvas = ({ nodes, edges, availableCapabilities = [], on
291
406
  onNodesChange(changes);
292
407
  }
293
408
  }
294
- catch (error) {
295
- console.error('ELK Layout error:', error);
409
+ catch (err) {
410
+ console.error('ELK Layout fault:', err);
296
411
  }
297
412
  finally {
298
413
  setIsLayouting(false);
@@ -314,15 +429,41 @@ export const TopologicalCanvas = ({ nodes, edges, availableCapabilities = [], on
314
429
  background-color: #000;
315
430
  }
316
431
  `),
317
- React.createElement(ReactFlow, { nodes: nodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodeClick: handleInternalNodeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, fitView: true, proOptions: { hideAttribution: true } },
432
+ React.createElement(ReactFlow, { nodes: processedNodes, edges: processedEdges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodeClick: handleInternalNodeClick, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, onConnect: onConnect, fitView: true, proOptions: { hideAttribution: true } },
318
433
  React.createElement(Background, { color: "#1f2937", gap: 20 }),
319
434
  React.createElement(Controls, { className: "bg-[var(--cr-glass-box-black)] border border-gray-800 fill-white" }),
320
435
  React.createElement(Panel, { position: "top-right", className: "m-4" },
321
- React.createElement("button", { onClick: handleAutoLayout, disabled: isLayouting, className: `bg-[var(--cr-accent-orange)] text-black font-bold uppercase tracking-wider text-[10px] px-4 py-2 rounded shadow-lg transition-opacity ${isLayouting ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}` }, isLayouting ? 'Computing Topology...' : 'Orthogonal Layout')))),
436
+ React.createElement("button", { onClick: handleAutoLayout, disabled: isLayouting, className: `bg-[var(--cr-accent-orange)] text-black font-bold uppercase tracking-wider text-[10px] px-4 py-2 rounded shadow-lg transition-opacity ${isLayouting ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}` }, isLayouting ? 'Computing Topology...' : 'Orthogonal Layout')),
437
+ hoveredRetractNodeId && (React.createElement(Panel, { position: "bottom-center", className: "mb-4" },
438
+ React.createElement(GlassBox, { density: "dense", className: "border border-red-500/30 bg-black/85 backdrop-blur-md p-4 rounded-lg w-[450px] shadow-[0_0_20px_rgba(239,68,68,0.2)]" },
439
+ React.createElement("div", { className: "flex items-start gap-3" },
440
+ React.createElement(AlertTriangle, { className: "w-5 h-5 text-red-500 animate-pulse shrink-0 mt-0.5" }),
441
+ React.createElement("div", { className: "flex-1 space-y-1.5" },
442
+ React.createElement("div", { className: "text-[11px] font-bold text-red-400 uppercase tracking-widest" }, "Causal Intervention Forecast"),
443
+ React.createElement("div", { className: "text-[10px] font-mono text-gray-400 break-all leading-normal" },
444
+ "Target URN: ",
445
+ React.createElement("span", { className: "text-white font-bold" }, String(((_b = (_a = nodes.find(n => n.id === hoveredRetractNodeId)) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.urn) || hoveredRetractNodeId))),
446
+ React.createElement("div", { className: "grid grid-cols-3 gap-2 py-1.5 border-t border-b border-white/5 my-1" },
447
+ React.createElement("div", null,
448
+ React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "AFFECTED NODES"),
449
+ React.createElement("div", { className: "text-xs font-bold text-white font-mono" }, blastRadiusIds.size)),
450
+ React.createElement("div", null,
451
+ React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "SANDBOXES"),
452
+ React.createElement("div", { className: "text-xs font-bold text-white font-mono" }, affectedSandboxCount)),
453
+ React.createElement("div", null,
454
+ React.createElement("div", { className: "text-[9px] text-gray-500 font-mono" }, "DEFICIT FORECAST"),
455
+ React.createElement("div", { className: "text-xs font-bold text-white font-mono" },
456
+ deficitForecast.toFixed(1),
457
+ " u"))),
458
+ React.createElement("div", { className: "text-[9px] text-red-400/80 font-sans italic leading-relaxed" }, "CAUTION: Retracting this node executes a Do-operator mutation. All downstream dependent nodes will be invalidated."))))))),
459
+ hoveredRetractNodeId && (React.createElement(CausalInterventionOverlay, { nodes: nodes, hoveredNodeId: hoveredRetractNodeId }))),
322
460
  activePanicNode && (React.createElement("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm z-[9999] flex justify-center items-center p-6" },
323
461
  React.createElement(ConformanceGuillotine, { nodeId: activePanicNode.nodeId, panicMessage: activePanicNode.panicMessage, backtrace: activePanicNode.backtrace, onClose: () => setActivePanicNode(null), onRecover: () => {
324
462
  console.log(`Triggering hot enclave recovery for ${activePanicNode.nodeId}`);
325
- // In production this emits a hot-attestation reload request to the Temporal ledger
326
463
  setActivePanicNode(null);
327
464
  } })))));
328
465
  };
466
+ export const TopologicalCanvas = (props) => {
467
+ return (React.createElement(ReactFlowProvider, null,
468
+ React.createElement(TopologicalCanvasInner, Object.assign({}, props))));
469
+ };
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ export interface AttestationReceipt {
3
+ transactionId: string;
4
+ proofStatus: 'VALIDATED' | 'FORGED' | 'INVALID' | 'UNCHECKED';
5
+ originatingAgentUrn: string;
6
+ verificationTimestamp: string;
7
+ zkProofHash: string;
8
+ sdJwtCompliance: boolean;
9
+ }
10
+ export interface SandboxHardwareTelemetry {
11
+ sandboxUrn: string;
12
+ cpuFuelRemaining: number;
13
+ cpuFuelBurnRate: number;
14
+ ramBytesAllocated: number;
15
+ }
16
+ export interface WasmSandboxCagingHudProps {
17
+ telemetry: SandboxHardwareTelemetry;
18
+ attestation?: AttestationReceipt;
19
+ className?: string;
20
+ }
21
+ export declare const WasmSandboxCagingHud: React.FC<WasmSandboxCagingHudProps>;