1- # synapdrive_ai/pipeline.py
2-
31from __future__ import annotations
42
5- from typing import Any , Dict , Optional
63import random
4+ from typing import Any , Dict , Optional
75
86from synapdrive_ai .bci .signal_simulator import BrainSignalSimulator
97from synapdrive_ai .agi .core_reasoning import AGICoreReasoner
@@ -20,53 +18,60 @@ class SynapDrivePipeline:
2018 """
2119 Canonical end-to-end simulation pipeline.
2220
23- This is the repo’s single “source of truth” wiring:
24- input → intent/decoding → optimizer (memory + vision) → safety → actuation → evaluation
21+ Wiring: input → intent → optimizer (memory + vision) → safety → actuation → evaluation
2522
26- NOTE:
27- - Simulation-first. No clinical claims.
28- - Text input path is for “decoded intent” (what a BCI decoder *could* output).
29- - Signal input path uses the built-in BrainSignalSimulator + AGICoreReasoner.
23+ Args:
24+ simulate_delay: If True, actuation sleeps to emulate real timing.
25+ Set False for tests, replay, and the Flask dashboard.
3026 """
3127
32- def __init__ (self ) -> None :
33- # Shared components
28+ def __init__ (self , simulate_delay : bool = True ) -> None :
3429 self .simulator = BrainSignalSimulator ()
3530 self .reasoner = AGICoreReasoner ()
3631
3732 self .memory = EpisodicMemory ()
3833 self .visual = VisualInferenceEngine ()
3934
4035 self .optimizer = CognitiveOptimizer ()
41- # Ensure the optimizer uses the SAME memory/vision objects (more credible than duplicates)
36+ # Share the same memory/vision instances so the optimizer sees live state
4237 self .optimizer .memory = self .memory
4338 self .optimizer .visual = self .visual
4439
4540 self .guard = SafetyGuard ()
46- self .router = DecisionRouter ()
41+ self .router = DecisionRouter (simulate_delay = simulate_delay )
4742 self .evaluator = MetaEvaluator ()
4843
44+ # ------------------------------------------------------------------
45+ # Public entrypoints
46+ # ------------------------------------------------------------------
47+
4948 def run_text_command (self , command_text : str , image_label : Optional [str ] = None ) -> Dict [str , Any ]:
50- """
51- Text pathway = “decoded” intent (BCI output or operator input).
52- """
49+ """Text path: decoded intent or operator input (e.g. 'move left', 'stop')."""
5350 intent_packet = generate_intent (command_text )
54- return self ._run_common (intent_packet , image_label = image_label )
51+ return self .run_intent_packet (intent_packet , image_label = image_label )
5552
5653 def run_signal_event (self , label : Optional [str ] = None , image_label : Optional [str ] = None ) -> Dict [str , Any ]:
57- """
58- Signal pathway = simulated EEG-like waveform event.
59- """
54+ """Signal path: simulated EEG-like waveform event."""
6055 label = label or random .choice (["left_arm" , "right_arm" , "walk" , "stop" , "calculate" , "recall" , "explore" ])
6156 signal = self ._generate_signal_for_label (label )
6257 intent_packet = self .reasoner .receive_signal (label , signal )
63- return self ._run_common (intent_packet , image_label = image_label )
58+ return self .run_intent_packet (intent_packet , image_label = image_label )
6459
65- def _generate_signal_for_label (self , label : str ) :
60+ def run_intent_packet (self , intent_packet : Dict [ str , Any ], image_label : Optional [ str ] = None ) -> Dict [ str , Any ] :
6661 """
67- Uses the same label→frequency mapping as BrainSignalSimulator.emit_event() .
68- We generate directly to keep this method single-step (no subscriber side-effects) .
62+ Primary entrypoint for integrations and replay .
63+ Accepts a pre-built intent packet and runs it through the full pipeline .
6964 """
65+ return self ._run_common (intent_packet , image_label = image_label )
66+
67+ def get_action_log (self ):
68+ return self .router .get_action_log ()
69+
70+ # ------------------------------------------------------------------
71+ # Internals
72+ # ------------------------------------------------------------------
73+
74+ def _generate_signal_for_label (self , label : str ):
7075 patterns = {
7176 "left_arm" : 10 ,
7277 "right_arm" : 12 ,
@@ -77,14 +82,10 @@ def _generate_signal_for_label(self, label: str):
7782 "explore" : 30 ,
7883 }
7984 if label not in patterns :
80- raise ValueError (f"Unknown signal label: { label } " )
85+ raise ValueError (f"Unknown signal label: { label !r } . Valid labels: { sorted ( patterns ) } " )
8186 return self .simulator .generate_waveform (patterns [label ])
8287
8388 def _run_common (self , intent_packet : Dict [str , Any ], image_label : Optional [str ]) -> Dict [str , Any ]:
84- """
85- Shared pipeline:
86- optimizer → safety → route/actuate → memory → evaluate
87- """
8889 optimized = self .optimizer .optimize (intent_packet , image_label = image_label )
8990
9091 is_safe , reason = self .guard .evaluate_safety (optimized )
@@ -108,7 +109,6 @@ def _run_common(self, intent_packet: Dict[str, Any], image_label: Optional[str])
108109
109110 result = self .router .route (optimized )
110111
111- # Record episode (keep errors non-fatal — never crash the pipeline because of logging)
112112 try :
113113 self .memory .record_episode (optimized , result )
114114 except Exception :
@@ -122,6 +122,3 @@ def _run_common(self, intent_packet: Dict[str, Any], image_label: Optional[str])
122122 "result" : result ,
123123 "evaluation" : evaluation ,
124124 }
125-
126- def get_action_log (self ):
127- return self .router .get_action_log ()
0 commit comments