from app.schemas.observation import ObservationSummary from app.schemas.orchestration import ( Hypothesis, OrchestratorPlan, PlannedExperiment, PlannedNode, StopDecision, ) class StubOrchestratorService: def create_initial_plan(self, observation: ObservationSummary) -> OrchestratorPlan: tags = set(observation.tags) looks_periodic = "periodic" in tags or observation.duration_ms >= 4500 looks_mixed = "mixed" in tags hypotheses = [ Hypothesis( id="periodic-alert-h1", label="Periodic alert tone", rationale=( "Observation metadata and initial capture profile suggest a " "repeatable alert-like signal rather than a diffuse ambient event." ), confidence=0.78 if looks_periodic else 0.56, related_signal_profiles=["periodic_pulse", "steady_tonal"], ), Hypothesis( id="mechanical-sequence-h2", label="Mechanical click sequence", rationale=( "A secondary possibility is a short repeating mechanical event " "pattern with less tonal stability." ), confidence=0.33 if looks_periodic else 0.48, related_signal_profiles=["multi_event_sequence", "transient_event"], ), ] if looks_mixed: hypotheses.append( Hypothesis( id="mixed-source-h3", label="Mixed source contamination", rationale=( "Capture tags indicate the possibility of overlapping sources, " "which could distort classifier confidence." ), confidence=0.42, related_signal_profiles=["mixed_source"], ) ) experiments = [ PlannedExperiment( hypothesis_id="periodic-alert-h1", goal="Validate periodic repeat structure", preferred_chain_id="periodic_validation_chain", pipeline=[ PlannedNode(module_id="segment_repeat_based", params={}), PlannedNode( module_id="autocorrelation_period_check", params={"window_ms": 1200}, ), PlannedNode( module_id="cepstrum_period_check", params={"min_interval_ms": 200, "max_interval_ms": 1000}, ), ], expected_evidence=[ "repeat_interval_ms", "repeat_stability", "periodicity_confidence", ], stop_if=["repeat_stability >= 0.85"], ), PlannedExperiment( hypothesis_id="periodic-alert-h1", goal="Check tonal stability of the leading hypothesis", preferred_chain_id="harmonic_validation_chain", pipeline=[ PlannedNode(module_id="spectrogram_extract", params={}), PlannedNode( module_id="f0_tracking", params={"frame_hop_ms": 20}, ), PlannedNode( module_id="harmonicity_check", params={"harmonic_threshold": 0.65}, ), ], expected_evidence=[ "f0_track", "harmonic_ratio", "tonal_stability", ], stop_if=["tonal_stability >= 0.70"], ), ] if looks_mixed: experiments.append( PlannedExperiment( hypothesis_id="mixed-source-h3", goal="Check whether source separation improves confidence", preferred_chain_id="mixed_source_chain", pipeline=[ PlannedNode(module_id="denoise_basic", params={}), PlannedNode( module_id="source_separation_basic", params={"max_sources": 2}, ), PlannedNode( module_id="reclassify_with_alt_window", params={"window_ms": 800}, ), ], expected_evidence=[ "mixed_source_probability", "post_separation_top_k", ], stop_if=["mixed_source_probability >= 0.60"], ) ) return OrchestratorPlan( hypotheses=hypotheses, experiments=experiments, stop_decision=StopDecision( should_stop=False, reason="Initial plan created. Probe and validation experiments should run first.", ), notes=[ "Stub orchestrator generated a plan from observation metadata and tags.", ], )