1818 ExcludedVisualization ,
1919 ExcludedTechnique ,
2020)
21+ from app .techniques .registry import get_registry
2122
2223
2324LAYER_START = 0
4445 ("laurent" , "Laurent" , "#228B22" ),
4546]
4647
47- DEFAULT_TECHNIQUES = [
48- ("tech_1" , "Code Structure Analysis" , "structure" ),
49- ("tech_2" , "Quality Assessment" , "quality" ),
50- ("tech_3" , "Security Scan" , "security" ),
51- ("tech_4" , "Innovation Check" , "innovation" ),
52- ("tech_5" , "Implementation Review" , "implementation" ),
48+ TASTING_NOTE_CATEGORIES = [
49+ ("aroma" , "Aroma" , "#9B59B6" , 11 ),
50+ ("palate" , "Palate" , "#E74C3C" , 13 ),
51+ ("body" , "Body" , "#F39C12" , 8 ),
52+ ("finish" , "Finish" , "#1ABC9C" , 12 ),
53+ ("balance" , "Balance" , "#3498DB" , 8 ),
54+ ("vintage" , "Vintage" , "#27AE60" , 10 ),
55+ ("terroir" , "Terroir" , "#E67E22" , 5 ),
56+ ("cellar" , "Cellar" , "#34495E" , 8 ),
5357]
5458
59+ ENRICHMENT_STEPS = [
60+ ("code_analysis" , "Code Analysis" , "#9370DB" ),
61+ ("rag" , "RAG Context" , "#6C3483" ),
62+ ("web_search" , "Web Search" , "#8E44AD" ),
63+ ]
64+
65+ DEFAULT_TECHNIQUES : list [tuple [str , str , str ]] = []
66+
67+
68+ def _get_category_counts () -> dict [str , int ]:
69+ """Get technique counts per category from registry, with fallback to static values."""
70+ try :
71+ registry = get_registry ()
72+ return registry .count_by_category ()
73+ except Exception :
74+ return {cat_id : total for cat_id , _ , _ , total in TASTING_NOTE_CATEGORIES }
75+
5576
5677def _build_start_node (step_number : int = 0 ) -> Graph3DNode :
5778 """Build the start node at layer 0."""
@@ -66,7 +87,7 @@ def _build_start_node(step_number: int = 0) -> Graph3DNode:
6687
6788
6889def _build_rag_node (step_number : int = 1 ) -> Graph3DNode :
69- """Build the RAG enrichment node at layer 100."""
90+ """Build the RAG enrichment node at layer 100 (legacy single node) ."""
7091 return Graph3DNode (
7192 node_id = "rag_enrich" ,
7293 node_type = "rag" ,
@@ -77,6 +98,28 @@ def _build_rag_node(step_number: int = 1) -> Graph3DNode:
7798 )
7899
79100
101+ def _build_enrichment_nodes (start_step : int = 1 ) -> list [Graph3DNode ]:
102+ """Build 3 enrichment nodes (code_analysis, rag, web_search) at layer 100."""
103+ nodes = []
104+ num_steps = len (ENRICHMENT_STEPS )
105+ spacing = 100
106+ start_x = CENTER_X - (num_steps - 1 ) * spacing / 2
107+
108+ for i , (step_id , label , color ) in enumerate (ENRICHMENT_STEPS ):
109+ x_pos = start_x + i * spacing
110+ nodes .append (
111+ Graph3DNode (
112+ node_id = step_id ,
113+ node_type = "enrichment" ,
114+ label = label ,
115+ position = Position3D (x = x_pos , y = 0 , z = LAYER_RAG ),
116+ color = color ,
117+ step_number = start_step + i ,
118+ )
119+ )
120+ return nodes
121+
122+
80123def _build_agent_nodes (
81124 start_step : int = 2 , use_techniques : bool = True
82125) -> list [Graph3DNode ]:
@@ -124,6 +167,33 @@ def _build_agent_nodes(
124167 return nodes
125168
126169
170+ def _build_category_nodes (start_step : int = 4 ) -> list [Graph3DNode ]:
171+ """Build 8 tasting note category nodes at layer 200 for full_techniques mode."""
172+ nodes = []
173+ num_categories = len (TASTING_NOTE_CATEGORIES )
174+ total_width = (num_categories - 1 ) * AGENT_SPACING
175+ start_x = CENTER_X - total_width / 2
176+
177+ dynamic_counts = _get_category_counts ()
178+
179+ for i , (cat_id , label , color , static_total ) in enumerate (TASTING_NOTE_CATEGORIES ):
180+ x_pos = start_x + i * AGENT_SPACING
181+ technique_count = dynamic_counts .get (cat_id , static_total )
182+ nodes .append (
183+ Graph3DNode (
184+ node_id = cat_id ,
185+ node_type = "category" ,
186+ label = label ,
187+ position = Position3D (x = x_pos , y = 0 , z = LAYER_AGENTS ),
188+ color = color ,
189+ step_number = start_step + i ,
190+ category = cat_id ,
191+ metadata = {"total_techniques" : technique_count },
192+ )
193+ )
194+ return nodes
195+
196+
127197def _build_synthesis_node (step_number : int = 7 ) -> Graph3DNode :
128198 """Build the synthesis node at layer 300."""
129199 return Graph3DNode (
@@ -356,6 +426,70 @@ def build_3d_graph(
356426 )
357427
358428
429+ def build_3d_graph_full_techniques (
430+ evaluation_id : str ,
431+ methodology_trace : list | None = None ,
432+ ) -> Graph3DPayload :
433+ """Build 3D graph for full_techniques mode with 8 categories and 3 enrichment steps.
434+
435+ Layered layout (z-axis):
436+ - Layer 0 (z=0): Start node
437+ - Layer 1 (z=100): 3 enrichment nodes (code_analysis, rag, web_search)
438+ - Layer 2 (z=200): 8 tasting note categories
439+ - Layer 3 (z=300): Synthesis node
440+ - Layer 4 (z=400): End node
441+ """
442+ nodes : list [Graph3DNode ] = []
443+ edges : list [Graph3DEdge ] = []
444+
445+ nodes .append (_build_start_node (step_number = 0 ))
446+
447+ enrichment_nodes = _build_enrichment_nodes (start_step = 1 )
448+ nodes .extend (enrichment_nodes )
449+
450+ category_nodes = _build_category_nodes (start_step = 4 )
451+ nodes .extend (category_nodes )
452+
453+ nodes .append (_build_synthesis_node (step_number = 12 ))
454+ nodes .append (_build_end_node (step_number = 13 ))
455+
456+ edge_id = 0
457+ for enrich in enrichment_nodes :
458+ edges .append (
459+ _create_styled_edge (f"edge_{ edge_id } " , "start" , enrich .node_id , "flow" , 0 )
460+ )
461+ edge_id += 1
462+
463+ last_enrich = enrichment_nodes [- 1 ]
464+ for cat in category_nodes :
465+ edges .append (
466+ _create_styled_edge (
467+ f"edge_{ edge_id } " , last_enrich .node_id , cat .node_id , "parallel" , 3
468+ )
469+ )
470+ edge_id += 1
471+
472+ for cat in category_nodes :
473+ edges .append (
474+ _create_styled_edge (
475+ f"edge_{ edge_id } " , cat .node_id , "synthesis" , "flow" , cat .step_number
476+ )
477+ )
478+ edge_id += 1
479+
480+ edges .append (_create_styled_edge (f"edge_{ edge_id } " , "synthesis" , "end" , "flow" , 12 ))
481+
482+ if methodology_trace :
483+ assign_step_numbers (nodes , edges , methodology_trace )
484+
485+ return Graph3DPayload .create (
486+ evaluation_id = evaluation_id ,
487+ mode = "full_techniques" ,
488+ nodes = nodes ,
489+ edges = edges ,
490+ )
491+
492+
359493# =============================================================================
360494# Phase G4: FDEB Edge Bundling and Graph3DBuilder
361495# =============================================================================
0 commit comments