@@ -9,7 +9,11 @@ import { useStaticAnimationPhase } from '../../hooks/useStaticAnimationPhase';
99import { useActs } from '../../hooks/useActs' ;
1010import { useStrokeDraw } from '../../hooks/useStrokeDraw' ;
1111import { useMounted } from '../../hooks/useMounted' ;
12- import { CONNECTOR_STYLE , ARROWHEAD_POINTS , arrowOpacity } from './diagramConstants' ;
12+ import {
13+ CONNECTOR_STYLE ,
14+ ARROWHEAD_POINTS ,
15+ arrowOpacity ,
16+ } from './diagramConstants' ;
1317
1418// Layout — ViewBox 520×352
1519//
@@ -32,12 +36,12 @@ import { CONNECTOR_STYLE, ARROWHEAD_POINTS, arrowOpacity } from './diagramConsta
3236// Font rule: --font-mono-ai for loop step labels (what the agent does),
3337// --font-mono-spec for decision/exit labels (what the system decides).
3438const ACTS = [
35- { id : 'perceive' , threshold : 0.00 } ,
36- { id : 'reason' , threshold : 0.18 } ,
37- { id : 'act' , threshold : 0.35 } ,
38- { id : 'observe' , threshold : 0.52 } ,
39- { id : 'verify' , threshold : 0.70 } ,
40- { id : 'loop' , threshold : 0.85 } ,
39+ { id : 'perceive' , threshold : 0.0 } ,
40+ { id : 'reason' , threshold : 0.18 } ,
41+ { id : 'act' , threshold : 0.35 } ,
42+ { id : 'observe' , threshold : 0.52 } ,
43+ { id : 'verify' , threshold : 0.7 } ,
44+ { id : 'loop' , threshold : 0.85 } ,
4145] as const ;
4246
4347export default function AgentLoopDiagram ( ) {
@@ -46,25 +50,25 @@ export default function AgentLoopDiagram() {
4650 const mounted = useMounted ( ) ;
4751
4852 // Node visibility
49- const reasonReached = mounted && wasReached ( 'reason' ) ;
50- const actReached = mounted && wasReached ( 'act' ) ;
53+ const reasonReached = mounted && wasReached ( 'reason' ) ;
54+ const actReached = mounted && wasReached ( 'act' ) ;
5155 const observeReached = mounted && wasReached ( 'observe' ) ;
52- const verifyReached = mounted && wasReached ( 'verify' ) ;
53- const loopReached = mounted && wasReached ( 'loop' ) ;
54-
55- const arc1Ref = useRef < SVGGeometryElement > ( null ) ;
56- const arc2Ref = useRef < SVGGeometryElement > ( null ) ;
57- const arc3Ref = useRef < SVGGeometryElement > ( null ) ;
58- const arc4Ref = useRef < SVGGeometryElement > ( null ) ;
59- const arc5Ref = useRef < SVGGeometryElement > ( null ) ;
56+ const verifyReached = mounted && wasReached ( 'verify' ) ;
57+ const loopReached = mounted && wasReached ( 'loop' ) ;
58+
59+ const arc1Ref = useRef < SVGGeometryElement > ( null ) ;
60+ const arc2Ref = useRef < SVGGeometryElement > ( null ) ;
61+ const arc3Ref = useRef < SVGGeometryElement > ( null ) ;
62+ const arc4Ref = useRef < SVGGeometryElement > ( null ) ;
63+ const arc5Ref = useRef < SVGGeometryElement > ( null ) ;
6064 const arcExitRef = useRef < SVGGeometryElement > ( null ) ;
6165
62- const t1 = useStrokeDraw ( arc1Ref , phase , 0.18 , 0.33 ) ;
63- const t2 = useStrokeDraw ( arc2Ref , phase , 0.35 , 0.50 ) ;
64- const t3 = useStrokeDraw ( arc3Ref , phase , 0.52 , 0.67 ) ;
65- const t4 = useStrokeDraw ( arc4Ref , phase , 0.70 , 0.82 ) ;
66+ const t1 = useStrokeDraw ( arc1Ref , phase , 0.18 , 0.33 ) ;
67+ const t2 = useStrokeDraw ( arc2Ref , phase , 0.35 , 0.5 ) ;
68+ const t3 = useStrokeDraw ( arc3Ref , phase , 0.52 , 0.67 ) ;
69+ const t4 = useStrokeDraw ( arc4Ref , phase , 0.7 , 0.82 ) ;
6670 // arc5 (iterate) and arcExit (done) emanate from verify simultaneously — same phase window
67- const t5 = useStrokeDraw ( arc5Ref , phase , 0.85 , 0.95 ) ;
71+ const t5 = useStrokeDraw ( arc5Ref , phase , 0.85 , 0.95 ) ;
6872 const tExit = useStrokeDraw ( arcExitRef , phase , 0.85 , 0.95 ) ;
6973
7074 return (
@@ -77,130 +81,272 @@ export default function AgentLoopDiagram() {
7781 style = { { display : 'block' , maxWidth : '520px' , margin : '0 auto' } }
7882 >
7983 { /* ── Perceive node — act 0 (threshold 0.00), visible on mount; no ghost needed ── */ }
80- < DiagramNode x = { 250 } y = { 55 } emoji = { EMOJI . microscope } label = "perceive" tone = "context" reached labelX = { 270 } labelY = { 33 } />
84+ < DiagramNode
85+ x = { 250 }
86+ y = { 55 }
87+ emoji = { EMOJI . microscope }
88+ label = "perceive"
89+ tone = "context"
90+ reached
91+ labelX = { 270 }
92+ labelY = { 33 }
93+ />
8194
8295 { /* ── Arc 1: perceive → reason ──────────────────────────────────────── */ }
8396 < path
8497 ref = { arc1Ref }
8598 d = "M 294 75 Q 350.71 75.75 372.86 122.48"
8699 { ...CONNECTOR_STYLE }
87- className = { clsx ( shared . connector , reasonReached && shared . connectorDrawing ) }
100+ className = { clsx (
101+ shared . connector ,
102+ reasonReached && shared . connectorDrawing
103+ ) }
88104 />
89- < g transform = "translate(375,127) rotate(65)" style = { { opacity : arrowOpacity ( t1 ) } } >
105+ < g
106+ transform = "translate(375,127) rotate(65)"
107+ style = { { opacity : arrowOpacity ( t1 ) } }
108+ >
90109 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
91110 </ g >
92111
93112 { /* ── Reason ghost placeholder ──────────────────────────────────────── */ }
94- < Ghost x = { 351 } y = { 127 } width = { 48 } height = { 48 } rx = { 0 }
95- fill = "var(--visual-bg-violet)" stroke = "var(--visual-violet)"
96- mounted = { mounted } reached = { reasonReached }
113+ < Ghost
114+ x = { 351 }
115+ y = { 127 }
116+ width = { 48 }
117+ height = { 48 }
118+ rx = { 0 }
119+ fill = "var(--visual-bg-violet)"
120+ stroke = "var(--visual-violet)"
121+ mounted = { mounted }
122+ reached = { reasonReached }
97123 />
98124
99125 { /* ── Reason node ───────────────────────────────────────────────────── */ }
100- < DiagramNode x = { 355 } y = { 131 } emoji = { EMOJI . brain } label = "reason" tone = "model" reached = { reasonReached } labelX = { 414.56 } labelY = { 138.03 } />
126+ < DiagramNode
127+ x = { 355 }
128+ y = { 131 }
129+ emoji = { EMOJI . brain }
130+ label = "reason"
131+ tone = "model"
132+ reached = { reasonReached }
133+ labelX = { 414.56 }
134+ labelY = { 138.03 }
135+ />
101136
102137 { /* ── Arc 2: reason → act ───────────────────────────────────────────── */ }
103138 < path
104139 ref = { arc2Ref }
105140 d = "M 375 175 Q 381.47 226.62 339.47 247.75"
106141 { ...CONNECTOR_STYLE }
107- className = { clsx ( shared . connector , actReached && shared . connectorDrawing ) }
142+ className = { clsx (
143+ shared . connector ,
144+ actReached && shared . connectorDrawing
145+ ) }
108146 />
109- < g transform = "translate(335,250) rotate(153)" style = { { opacity : arrowOpacity ( t2 ) } } >
147+ < g
148+ transform = "translate(335,250) rotate(153)"
149+ style = { { opacity : arrowOpacity ( t2 ) } }
150+ >
110151 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
111152 </ g >
112153
113154 { /* ── Act ghost placeholder ─────────────────────────────────────────── */ }
114- < Ghost x = { 311 } y = { 250 } width = { 48 } height = { 48 } rx = { 0 }
115- fill = "var(--visual-bg-cyan)" stroke = "var(--visual-cyan)"
116- mounted = { mounted } reached = { actReached }
155+ < Ghost
156+ x = { 311 }
157+ y = { 250 }
158+ width = { 48 }
159+ height = { 48 }
160+ rx = { 0 }
161+ fill = "var(--visual-bg-cyan)"
162+ stroke = "var(--visual-cyan)"
163+ mounted = { mounted }
164+ reached = { actReached }
117165 />
118166
119167 { /* ── Act node ──────────────────────────────────────────────────────── */ }
120- < DiagramNode x = { 315 } y = { 254 } emoji = { EMOJI . act } label = "act" tone = "system" reached = { actReached } labelX = { 359.34 } labelY = { 307.97 } />
168+ < DiagramNode
169+ x = { 315 }
170+ y = { 254 }
171+ emoji = { EMOJI . act }
172+ label = "act"
173+ tone = "system"
174+ reached = { actReached }
175+ labelX = { 359.34 }
176+ labelY = { 307.97 }
177+ />
121178
122179 { /* ── Arc 3: act → observe ─────────────────────────────────────────── */ }
123180 < path
124181 ref = { arc3Ref }
125182 d = "M 311 274 Q 270 304 233.04 276.95"
126183 { ...CONNECTOR_STYLE }
127- className = { clsx ( shared . connector , observeReached && shared . connectorDrawing ) }
184+ className = { clsx (
185+ shared . connector ,
186+ observeReached && shared . connectorDrawing
187+ ) }
128188 />
129- < g transform = "translate(229,274) rotate(-144)" style = { { opacity : arrowOpacity ( t3 ) } } >
189+ < g
190+ transform = "translate(229,274) rotate(-144)"
191+ style = { { opacity : arrowOpacity ( t3 ) } }
192+ >
130193 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
131194 </ g >
132195
133196 { /* ── Observe ghost placeholder ─────────────────────────────────────── */ }
134- < Ghost x = { 181 } y = { 250 } width = { 48 } height = { 48 } rx = { 0 }
135- fill = "var(--visual-bg-magenta)" stroke = "var(--visual-magenta)"
136- mounted = { mounted } reached = { observeReached }
197+ < Ghost
198+ x = { 181 }
199+ y = { 250 }
200+ width = { 48 }
201+ height = { 48 }
202+ rx = { 0 }
203+ fill = "var(--visual-bg-magenta)"
204+ stroke = "var(--visual-magenta)"
205+ mounted = { mounted }
206+ reached = { observeReached }
137207 />
138208
139209 { /* ── Observe node ─────────────────────────────────────────────────── */ }
140- < DiagramNode x = { 185 } y = { 254 } emoji = { EMOJI . observe } label = "observe" tone = "magenta" reached = { observeReached } labelX = { 180.66 } labelY = { 307.97 } />
210+ < DiagramNode
211+ x = { 185 }
212+ y = { 254 }
213+ emoji = { EMOJI . observe }
214+ label = "observe"
215+ tone = "magenta"
216+ reached = { observeReached }
217+ labelX = { 180.66 }
218+ labelY = { 307.97 }
219+ />
141220
142221 { /* ── Arc 4: observe → verify ───────────────────────────────────────── */ }
143222 < path
144223 ref = { arc4Ref }
145224 d = "M 205 250 Q 158.53 226.62 164.38 179.96"
146225 { ...CONNECTOR_STYLE }
147- className = { clsx ( shared . connector , verifyReached && shared . connectorDrawing ) }
226+ className = { clsx (
227+ shared . connector ,
228+ verifyReached && shared . connectorDrawing
229+ ) }
148230 />
149- < g transform = "translate(165,175) rotate(-83)" style = { { opacity : arrowOpacity ( t4 ) } } >
231+ < g
232+ transform = "translate(165,175) rotate(-83)"
233+ style = { { opacity : arrowOpacity ( t4 ) } }
234+ >
150235 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
151236 </ g >
152237
153238 { /* ── Verify ghost placeholder ──────────────────────────────────────── */ }
154- < Ghost x = { 141 } y = { 127 } width = { 48 } height = { 48 } rx = { 0 }
155- fill = "var(--visual-bg-warning)" stroke = "var(--visual-warning)"
156- mounted = { mounted } reached = { verifyReached }
239+ < Ghost
240+ x = { 141 }
241+ y = { 127 }
242+ width = { 48 }
243+ height = { 48 }
244+ rx = { 0 }
245+ fill = "var(--visual-bg-warning)"
246+ stroke = "var(--visual-warning)"
247+ mounted = { mounted }
248+ reached = { verifyReached }
157249 />
158250
159251 { /* ── Verify node ───────────────────────────────────────────────────── */ }
160- < DiagramNode x = { 145 } y = { 131 } emoji = { EMOJI . ruler } label = "verify" tone = "warning" reached = { verifyReached } labelX = { 108 } labelY = { 155 } />
252+ < DiagramNode
253+ x = { 145 }
254+ y = { 131 }
255+ emoji = { EMOJI . ruler }
256+ label = "verify"
257+ tone = "warning"
258+ reached = { verifyReached }
259+ labelX = { 108 }
260+ labelY = { 155 }
261+ />
161262
162263 { /* ── Arc 5: verify → perceive (iterate / "No") ────────────────────── */ }
163264 < path
164265 ref = { arc5Ref }
165266 d = "M 165 127 Q 189.29 75.75 241 75.07"
166267 { ...CONNECTOR_STYLE }
167- className = { clsx ( shared . connector , loopReached && shared . connectorDrawing ) }
268+ className = { clsx (
269+ shared . connector ,
270+ loopReached && shared . connectorDrawing
271+ ) }
168272 />
169- < g transform = "translate(246,75) rotate(-1)" style = { { opacity : arrowOpacity ( t5 ) } } >
273+ < g
274+ transform = "translate(246,75) rotate(-1)"
275+ style = { { opacity : arrowOpacity ( t5 ) } }
276+ >
170277 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
171278 </ g >
172- < text x = { 197 } y = { 78 }
279+ < text
280+ x = { 197 }
281+ y = { 78 }
173282 fill = "var(--text-muted)"
174283 style = { { fontFamily : 'var(--font-mono-spec)' } }
175- fontSize = { 9 } textAnchor = "middle"
176- className = { clsx ( styles . decisionLabel , loopReached && styles . decisionLabelIn ) }
177- > No</ text >
284+ fontSize = { 9 }
285+ textAnchor = "middle"
286+ className = { clsx (
287+ styles . decisionLabel ,
288+ loopReached && styles . decisionLabelIn
289+ ) }
290+ >
291+ No
292+ </ text >
178293
179294 { /* ── Exit arc: verify → done ("Yes") ──────────────────────────────── */ }
180295 < path
181296 ref = { arcExitRef }
182297 d = "M 141 151 Q 91.73 181.96 95.63 235.01"
183298 { ...CONNECTOR_STYLE }
184- className = { clsx ( shared . connector , loopReached && shared . connectorDrawing ) }
299+ className = { clsx (
300+ shared . connector ,
301+ loopReached && shared . connectorDrawing
302+ ) }
185303 />
186- < g transform = "translate(96,240) rotate(86)" style = { { opacity : arrowOpacity ( tExit ) } } >
304+ < g
305+ transform = "translate(96,240) rotate(86)"
306+ style = { { opacity : arrowOpacity ( tExit ) } }
307+ >
187308 < polygon points = { ARROWHEAD_POINTS } fill = "var(--text-muted)" />
188309 </ g >
189- < text x = { 127 } y = { 196 }
310+ < text
311+ x = { 127 }
312+ y = { 196 }
190313 fill = "var(--text-muted)"
191314 style = { { fontFamily : 'var(--font-mono-spec)' } }
192- fontSize = { 9 } textAnchor = "middle"
193- className = { clsx ( styles . decisionLabel , loopReached && styles . decisionLabelIn ) }
194- > Yes</ text >
315+ fontSize = { 9 }
316+ textAnchor = "middle"
317+ className = { clsx (
318+ styles . decisionLabel ,
319+ loopReached && styles . decisionLabelIn
320+ ) }
321+ >
322+ Yes
323+ </ text >
195324
196325 { /* ── Done ghost placeholder ────────────────────────────────────────── */ }
197- < Ghost x = { 72 } y = { 240 } width = { 48 } height = { 48 } rx = { 0 }
198- fill = "var(--visual-bg-success)" stroke = "var(--visual-success)"
199- mounted = { mounted } reached = { loopReached }
326+ < Ghost
327+ x = { 72 }
328+ y = { 240 }
329+ width = { 48 }
330+ height = { 48 }
331+ rx = { 0 }
332+ fill = "var(--visual-bg-success)"
333+ stroke = "var(--visual-success)"
334+ mounted = { mounted }
335+ reached = { loopReached }
200336 />
201337
202338 { /* ── Done node ─────────────────────────────────────────────────────── */ }
203- < DiagramNode x = { 76 } y = { 244 } emoji = { EMOJI . check } label = "done" tone = "success" reached = { loopReached } labelX = { 96 } labelY = { 300 } labelVoice = "spec" />
339+ < DiagramNode
340+ x = { 76 }
341+ y = { 244 }
342+ emoji = { EMOJI . check }
343+ label = "done"
344+ tone = "success"
345+ reached = { loopReached }
346+ labelX = { 96 }
347+ labelY = { 300 }
348+ labelVoice = "spec"
349+ />
204350 </ svg >
205351 ) ;
206352}
0 commit comments