@@ -2699,3 +2699,318 @@ export function NotionOpenFigure() {
26992699 </ svg >
27002700 ) ;
27012701}
2702+
2703+ /** Vendor silo problem — four tools, each seeing only its own data, engineer bridges them. */
2704+ export function VendorSiloFigure ( ) {
2705+ const tools = [
2706+ { label : "Sentry" , color : C . rose , y : 70 } ,
2707+ { label : "GitHub" , color : C . sage , y : 70 } ,
2708+ { label : "Datadog" , color : C . butter , y : 70 } ,
2709+ { label : "Linear" , color : C . lavender , y : 70 } ,
2710+ ] ;
2711+ const colW = 58 ;
2712+ const gap = 12 ;
2713+ const totalW = tools . length * colW + ( tools . length - 1 ) * gap ;
2714+ const startX = ( 320 - totalW ) / 2 ;
2715+
2716+ return (
2717+ < svg viewBox = "0 0 320 320" className = "w-full" role = "img" aria-labelledby = "vendorsilo-title" >
2718+ < title id = "vendorsilo-title" > Vendor chatbots as isolated silos: each sees only its own data</ title >
2719+
2720+ < text x = "160" y = "24" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . faint } letterSpacing = "0.06em" >
2721+ the incident spans all four
2722+ </ text >
2723+
2724+ { /* Incident line spanning all silos */ }
2725+ < line x1 = { startX - 8 } y1 = "42" x2 = { startX + totalW + 8 } y2 = "42" stroke = { C . terracotta } strokeWidth = "1.4" strokeDasharray = "6 4" />
2726+ < circle cx = { startX - 8 } cy = "42" r = "3" fill = { C . terracotta } />
2727+ < circle cx = { startX + totalW + 8 } cy = "42" r = "3" fill = { C . terracotta } />
2728+
2729+ { /* Silo columns */ }
2730+ { tools . map ( ( tool , i ) => {
2731+ const x = startX + i * ( colW + gap ) ;
2732+ return (
2733+ < g key = { tool . label } >
2734+ < rect x = { x } y = { 54 } width = { colW } height = { 130 } rx = "6" fill = { tool . color } opacity = "0.35" stroke = { C . ink } strokeWidth = "1" />
2735+ < text x = { x + colW / 2 } y = { 72 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8.5" fill = { C . ink } fontWeight = "600" >
2736+ { tool . label }
2737+ </ text >
2738+ < line x1 = { x + 8 } y1 = { 84 } x2 = { x + colW - 8 } y2 = { 84 } stroke = { C . faint } strokeWidth = "0.8" />
2739+ < line x1 = { x + 8 } y1 = { 96 } x2 = { x + colW - 12 } y2 = { 96 } stroke = { C . faint } strokeWidth = "0.8" />
2740+ < line x1 = { x + 8 } y1 = { 108 } x2 = { x + colW - 8 } y2 = { 108 } stroke = { C . faint } strokeWidth = "0.8" />
2741+ { /* Chatbot icon */ }
2742+ < circle cx = { x + colW / 2 } cy = { 148 } r = "12" fill = { C . paper } stroke = { C . ink } strokeWidth = "1" />
2743+ < circle cx = { x + colW / 2 - 4 } cy = { 146 } r = "1.5" fill = { C . ink } />
2744+ < circle cx = { x + colW / 2 + 4 } cy = { 146 } r = "1.5" fill = { C . ink } />
2745+ < path d = { `M${ x + colW / 2 - 4 } ${ 152 } Q${ x + colW / 2 } ${ 155 } ${ x + colW / 2 + 4 } ${ 152 } ` } stroke = { C . ink } strokeWidth = "0.8" fill = "none" />
2746+ { /* Vertical wall lines */ }
2747+ < line x1 = { x } y1 = { 54 } x2 = { x } y2 = { 184 } stroke = { C . ink } strokeWidth = "1" />
2748+ < line x1 = { x + colW } y1 = { 54 } x2 = { x + colW } y2 = { 184 } stroke = { C . ink } strokeWidth = "1" />
2749+ </ g >
2750+ ) ;
2751+ } ) }
2752+
2753+ { /* Engineer at bottom bridging silos */ }
2754+ < circle cx = "160" cy = "230" r = "14" fill = { C . paper } stroke = { C . ink } strokeWidth = "1.4" />
2755+ < circle cx = "156" cy = "228" r = "1.5" fill = { C . ink } />
2756+ < circle cx = "164" cy = "228" r = "1.5" fill = { C . ink } />
2757+ < line x1 = "155" y1 = "234" x2 = "165" y2 = "234" stroke = { C . ink } strokeWidth = "1" />
2758+
2759+ { /* Arrows from engineer to each silo */ }
2760+ { tools . map ( ( _ , i ) => {
2761+ const x = startX + i * ( colW + gap ) + colW / 2 ;
2762+ return (
2763+ < g key = { i } stroke = { C . faint } strokeWidth = "1" fill = "none" strokeLinecap = "round" >
2764+ < line x1 = "160" y1 = "216" x2 = { x } y2 = "188" />
2765+ < circle cx = { x } cy = "186" r = "2" fill = { C . faint } />
2766+ </ g >
2767+ ) ;
2768+ } ) }
2769+
2770+ < text x = "160" y = "264" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . faint } >
2771+ engineer = integration layer
2772+ </ text >
2773+
2774+ < text x = "160" y = "280" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . terracotta } >
2775+ each bot sees 1/4 of the picture
2776+ </ text >
2777+ </ svg >
2778+ ) ;
2779+ }
2780+
2781+ /** Junior plugin architecture — hub-and-spoke with egress proxy ring. */
2782+ export function JuniorPluginFigure ( ) {
2783+ const plugins = [
2784+ { label : "GitHub" , angle : - 90 , type : "app" , color : C . sage } ,
2785+ { label : "Sentry" , angle : - 30 , type : "oauth" , color : C . rose } ,
2786+ { label : "Datadog" , angle : 30 , type : "api-key" , color : C . butter } ,
2787+ { label : "Linear" , angle : 90 , type : "MCP" , color : C . lavender } ,
2788+ { label : "Notion" , angle : 150 , type : "MCP" , color : C . sky } ,
2789+ { label : "Hex" , angle : 210 , type : "MCP" , color : C . peach } ,
2790+ ] ;
2791+ const cx = 160 ;
2792+ const cy = 150 ;
2793+ const innerR = 28 ;
2794+ const proxyR = 60 ;
2795+ const outerR = 110 ;
2796+
2797+ return (
2798+ < svg viewBox = "0 0 320 320" className = "w-full" role = "img" aria-labelledby = "juniorplugin-title" >
2799+ < title id = "juniorplugin-title" > Junior architecture: one agent hub with plugins connected through an egress proxy</ title >
2800+
2801+ < text x = "160" y = "20" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . faint } letterSpacing = "0.06em" >
2802+ one runtime, many plugins
2803+ </ text >
2804+
2805+ { /* Egress proxy ring */ }
2806+ < circle cx = { cx } cy = { cy } r = { proxyR } fill = "none" stroke = { C . terracotta } strokeWidth = "1.2" strokeDasharray = "5 3" opacity = "0.6" />
2807+ < text x = { cx + proxyR - 12 } y = { cy - proxyR + 14 } fontFamily = "var(--font-mono)" fontSize = "7" fill = { C . terracotta } opacity = "0.8" >
2808+ egress proxy
2809+ </ text >
2810+
2811+ { /* Center agent */ }
2812+ < circle cx = { cx } cy = { cy } r = { innerR } fill = { C . sage } opacity = "0.5" stroke = { C . ink } strokeWidth = "1.4" />
2813+ < text x = { cx } y = { cy - 4 } textAnchor = "middle" fontFamily = "var(--font-display)" fontSize = "14" fill = { C . ink } fontWeight = "600" > jr</ text >
2814+ < text x = { cx } y = { cy + 10 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "7" fill = { C . inkSoft } > slack bot</ text >
2815+
2816+ { /* Plugin nodes */ }
2817+ { plugins . map ( ( p ) => {
2818+ const rad = ( p . angle * Math . PI ) / 180 ;
2819+ const px = cx + Math . cos ( rad ) * outerR ;
2820+ const py = cy + Math . sin ( rad ) * outerR ;
2821+ const proxyX = cx + Math . cos ( rad ) * proxyR ;
2822+ const proxyY = cy + Math . sin ( rad ) * proxyR ;
2823+ return (
2824+ < g key = { p . label } >
2825+ { /* Connection line */ }
2826+ < line x1 = { proxyX } y1 = { proxyY } x2 = { px } y2 = { py } stroke = { C . faint } strokeWidth = "1" />
2827+ { /* Proxy crossing dot */ }
2828+ < circle cx = { proxyX } cy = { proxyY } r = "2.5" fill = { C . terracotta } opacity = "0.7" />
2829+ { /* Plugin node */ }
2830+ < circle cx = { px } cy = { py } r = "20" fill = { p . color } opacity = "0.4" stroke = { C . ink } strokeWidth = "0.8" />
2831+ < text x = { px } y = { py - 4 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . ink } fontWeight = "600" >
2832+ { p . label }
2833+ </ text >
2834+ < text x = { px } y = { py + 7 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "6.5" fill = { C . faint } >
2835+ { p . type }
2836+ </ text >
2837+ </ g >
2838+ ) ;
2839+ } ) }
2840+
2841+ { /* Sandbox label */ }
2842+ < rect x = "50" y = "278" width = "220" height = "22" rx = "4" fill = { C . paper } stroke = { C . faint } strokeWidth = "0.8" />
2843+ < text x = "160" y = "293" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . faint } >
2844+ sandbox: bash, readFile, editFile, grep, browser
2845+ </ text >
2846+ </ svg >
2847+ ) ;
2848+ }
2849+
2850+ /** Agent scope spectrum — narrow to generalized, four vendors positioned. */
2851+ export function AgentScopeFigure ( ) {
2852+ const axisY = 160 ;
2853+ const axisX1 = 30 ;
2854+ const axisX2 = 290 ;
2855+
2856+ const vendors = [
2857+ { label : "PostHog" , x : 62 , desc : "in-app only" , color : C . rose } ,
2858+ { label : "CodeRabbit" , x : 138 , desc : "expanding" , color : C . butter } ,
2859+ { label : "Notion" , x : 210 , desc : "hub model" , color : C . lavender } ,
2860+ { label : "Junior" , x : 264 , desc : "open runtime" , color : C . sage } ,
2861+ ] ;
2862+
2863+ return (
2864+ < svg viewBox = "0 0 320 320" className = "w-full" role = "img" aria-labelledby = "agentscope-title" >
2865+ < title id = "agentscope-title" > Spectrum from narrow vendor chatbot to generalized agent runtime</ title >
2866+
2867+ < text x = "160" y = "28" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . faint } letterSpacing = "0.06em" >
2868+ scope vs. depth
2869+ </ text >
2870+
2871+ { /* Gradient background bar */ }
2872+ < defs >
2873+ < linearGradient id = "scope-grad" x1 = "0" x2 = "1" y1 = "0" y2 = "0" >
2874+ < stop offset = "0%" stopColor = { C . rose } stopOpacity = "0.25" />
2875+ < stop offset = "50%" stopColor = { C . butter } stopOpacity = "0.2" />
2876+ < stop offset = "100%" stopColor = { C . sage } stopOpacity = "0.3" />
2877+ </ linearGradient >
2878+ </ defs >
2879+ < rect x = { axisX1 } y = { axisY - 40 } width = { axisX2 - axisX1 } height = "80" rx = "8" fill = "url(#scope-grad)" />
2880+
2881+ { /* Axis line */ }
2882+ < line x1 = { axisX1 } y1 = { axisY } x2 = { axisX2 } y2 = { axisY } stroke = { C . ink } strokeWidth = "1.2" />
2883+ { /* Arrow */ }
2884+ < path d = { `M${ axisX2 - 6 } ${ axisY - 4 } L${ axisX2 } ${ axisY } L${ axisX2 - 6 } ${ axisY + 4 } ` } stroke = { C . ink } strokeWidth = "1.2" fill = "none" />
2885+
2886+ { /* Axis labels */ }
2887+ < text x = { axisX1 + 4 } y = { axisY + 56 } fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . faint } > narrow</ text >
2888+ < text x = { axisX2 - 4 } y = { axisY + 56 } textAnchor = "end" fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . faint } > generalized</ text >
2889+
2890+ { /* Vendor markers */ }
2891+ { vendors . map ( ( v ) => (
2892+ < g key = { v . label } >
2893+ { /* Vertical line */ }
2894+ < line x1 = { v . x } y1 = { axisY - 32 } x2 = { v . x } y2 = { axisY - 4 } stroke = { C . ink } strokeWidth = "1" opacity = "0.4" />
2895+ { /* Dot on axis */ }
2896+ < circle cx = { v . x } cy = { axisY } r = "6" fill = { v . color } stroke = { C . ink } strokeWidth = "1.2" />
2897+ { /* Label above */ }
2898+ < text x = { v . x } y = { axisY - 38 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . ink } fontWeight = "600" >
2899+ { v . label }
2900+ </ text >
2901+ { /* Description below */ }
2902+ < text x = { v . x } y = { axisY + 22 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "7" fill = { C . inkSoft } >
2903+ { v . desc }
2904+ </ text >
2905+ </ g >
2906+ ) ) }
2907+
2908+ { /* Key insight */ }
2909+ < text x = "160" y = "260" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8.5" fill = { C . faint } >
2910+ different bets on where the value lives
2911+ </ text >
2912+
2913+ { /* MCP convergence note */ }
2914+ < g >
2915+ < rect x = "60" y = "272" width = "200" height = "20" rx = "4" fill = { C . paper } stroke = { C . faint } strokeWidth = "0.8" />
2916+ < text x = "160" y = "286" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "7.5" fill = { C . terracotta } >
2917+ MCP narrows the gap between all four
2918+ </ text >
2919+ </ g >
2920+ </ svg >
2921+ ) ;
2922+ }
2923+
2924+ /** Phase-specific agents — PDERO pipeline with cross-phase integrations. */
2925+ export function PhaseAgentFigure ( ) {
2926+ const phases = [
2927+ { label : "Plan" , short : "P" , color : C . lavender } ,
2928+ { label : "Delegate" , short : "D" , color : C . butter } ,
2929+ { label : "Execute" , short : "E" , color : C . sage } ,
2930+ { label : "Review" , short : "R" , color : C . rose } ,
2931+ { label : "Observe" , short : "O" , color : C . sky } ,
2932+ ] ;
2933+ const boxW = 46 ;
2934+ const gap = 8 ;
2935+ const totalW = phases . length * boxW + ( phases . length - 1 ) * gap ;
2936+ const startX = ( 320 - totalW ) / 2 ;
2937+ const cy = 130 ;
2938+ const boxH = 64 ;
2939+
2940+ return (
2941+ < svg viewBox = "0 0 320 320" className = "w-full" role = "img" aria-labelledby = "phaseagent-title" >
2942+ < title id = "phaseagent-title" > Phase-specific agents: Plan, Delegate, Execute, Review, Observe with cross-phase integrations</ title >
2943+
2944+ < text x = "160" y = "22" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "9" fill = { C . faint } letterSpacing = "0.06em" >
2945+ agents per phase, not per tool
2946+ </ text >
2947+
2948+ { /* Phase boxes */ }
2949+ { phases . map ( ( phase , i ) => {
2950+ const x = startX + i * ( boxW + gap ) ;
2951+ return (
2952+ < g key = { phase . label } >
2953+ < rect
2954+ x = { x } y = { cy - boxH / 2 } width = { boxW } height = { boxH }
2955+ rx = "6" fill = { phase . color } opacity = "0.4"
2956+ stroke = { C . ink } strokeWidth = "1"
2957+ />
2958+ < text x = { x + boxW / 2 } y = { cy - 10 } textAnchor = "middle" fontFamily = "var(--font-display)" fontSize = "16" fill = { C . ink } fontWeight = "600" >
2959+ { phase . short }
2960+ </ text >
2961+ < text x = { x + boxW / 2 } y = { cy + 8 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "7" fill = { C . inkSoft } >
2962+ { phase . label }
2963+ </ text >
2964+ { /* Agent dot */ }
2965+ < circle cx = { x + boxW / 2 } cy = { cy + 22 } r = "5" fill = { C . paper } stroke = { C . ink } strokeWidth = "0.8" />
2966+ < circle cx = { x + boxW / 2 - 2 } cy = { cy + 21 } r = "0.8" fill = { C . ink } />
2967+ < circle cx = { x + boxW / 2 + 2 } cy = { cy + 21 } r = "0.8" fill = { C . ink } />
2968+ { /* Forward arrow to next phase */ }
2969+ { i < phases . length - 1 && (
2970+ < g stroke = { C . terracotta } strokeWidth = "1.2" fill = "none" strokeLinecap = "round" >
2971+ < line x1 = { x + boxW + 1 } y1 = { cy } x2 = { x + boxW + gap - 1 } y2 = { cy } />
2972+ < path d = { `M${ x + boxW + gap - 4 } ${ cy - 3 } L${ x + boxW + gap - 1 } ${ cy } L${ x + boxW + gap - 4 } ${ cy + 3 } ` } />
2973+ </ g >
2974+ ) }
2975+ </ g >
2976+ ) ;
2977+ } ) }
2978+
2979+ { /* Cross-phase integration arcs */ }
2980+ < g stroke = { C . faint } strokeWidth = "0.8" fill = "none" strokeDasharray = "3 3" >
2981+ { /* Plan → Review arc */ }
2982+ < path d = { `M${ startX + boxW / 2 } ${ cy - boxH / 2 - 2 } Q160 ${ cy - boxH / 2 - 30 } ${ startX + 3 * ( boxW + gap ) + boxW / 2 } ${ cy - boxH / 2 - 2 } ` } />
2983+ { /* Execute → Observe arc */ }
2984+ < path d = { `M${ startX + 2 * ( boxW + gap ) + boxW / 2 } ${ cy + boxH / 2 + 2 } Q${ startX + 3.5 * ( boxW + gap ) } ${ cy + boxH / 2 + 26 } ${ startX + 4 * ( boxW + gap ) + boxW / 2 } ${ cy + boxH / 2 + 2 } ` } />
2985+ </ g >
2986+
2987+ { /* Arc labels */ }
2988+ < text x = "160" y = { cy - boxH / 2 - 32 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "6.5" fill = { C . faint } >
2989+ traces back to intent
2990+ </ text >
2991+ < text x = { startX + 3.25 * ( boxW + gap ) } y = { cy + boxH / 2 + 32 } textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "6.5" fill = { C . faint } >
2992+ closes the loop
2993+ </ text >
2994+
2995+ { /* Tool integrations below */ }
2996+ < text x = "160" y = "228" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8" fill = { C . inkSoft } >
2997+ tools cross phase boundaries
2998+ </ text >
2999+ { [ "tickets" , "code" , "runtime" , "metrics" , "logs" ] . map ( ( tool , i ) => {
3000+ const x = startX + i * ( boxW + gap ) + boxW / 2 ;
3001+ return (
3002+ < g key = { tool } >
3003+ < line x1 = { x } y1 = { cy + boxH / 2 + 4 } x2 = { x } y2 = "238" stroke = { C . faint } strokeWidth = "0.6" strokeDasharray = "2 2" />
3004+ < text x = { x } y = "250" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "6.5" fill = { C . faint } >
3005+ { tool }
3006+ </ text >
3007+ </ g >
3008+ ) ;
3009+ } ) }
3010+
3011+ < text x = "160" y = "278" textAnchor = "middle" fontFamily = "var(--font-mono)" fontSize = "8.5" fill = { C . terracotta } >
3012+ narrow in purpose, broad in reach
3013+ </ text >
3014+ </ svg >
3015+ ) ;
3016+ }
0 commit comments