@startuml Orchestrator_Class

' ── Skin ─────────────────────────────────────────────────────────────────────

skinparam linetype ortho
skinparam nodesep 35
skinparam ranksep 45

skinparam ClassBackgroundColor        #F8F7FF
skinparam ClassBorderColor            #AFA9EC
skinparam ClassBorderThickness        1.5
skinparam ClassFontName               Helvetica
skinparam ClassFontSize               11
skinparam ClassFontColor              #26215C
skinparam ClassHeaderBackgroundColor  #EDE9F7
skinparam ClassArrowColor             #7F77DD
skinparam ClassArrowThickness         1.5

skinparam InterfaceBackgroundColor    #EDE9F7
skinparam InterfaceBorderColor        #7F77DD
skinparam InterfaceFontColor          #26215C
skinparam InterfaceFontName           Helvetica
skinparam InterfaceFontSize           11

skinparam PackageBackgroundColor      #F9F8FC
skinparam PackageBorderColor          #C5C1EB
skinparam PackageFontColor            #534AB7
skinparam PackageFontSize             11
skinparam PackageFontStyle            bold

skinparam NoteBackgroundColor         #FAEEDA
skinparam NoteBorderColor             #EF9F27
skinparam ShadowingEnabled            false
skinparam RoundCorner                 8

skinparam ClassBackgroundColor<<adapter>>  #EDE9F7
skinparam ClassBorderColor<<adapter>>      #7F77DD
skinparam ClassBackgroundColor<<usecase>>  #EBF3FC
skinparam ClassBorderColor<<usecase>>      #9EB8E6
skinparam ClassBackgroundColor<<fn>>       #F0F7EE
skinparam ClassBorderColor<<fn>>           #8CC87A

' ── Component ────────────────────────────────────────────────────────────────

package "Orchestrator" {

  class Orchestrator <<adapter>> {
    - use_case : Box<OrchestratorRunPort>
  }

  interface OrchestratorRunPort <<inbound port>> {
    + run(SessionRequest) : Result<Vec<SessionOutcome>>
  }

  class RunSessionUseCase <<usecase>> {
    + llm_engine : Box<LlmEnginePort>
    + fuzzer_engine : Box<FuzzerEnginePort>
    + executor : Box<ExecutorPort>
    + reader : Box<ReaderPort>
    + reporter : Box<ReporterPort>
    + security : Option<Box<SecurityAnalysisPort>>
  }

  together {
    class check_termination <<fn>> {
      (FuzzReport, SessionState)
      → TerminationDecision
    }
    class initialise_session <<fn>> {
      (SessionRequest)
      → SessionState
    }
    class run_round <<fn>> {
      (RoundSignal, SessionState)
      → FuzzReport
    }
  }
}

' ── Shared ───────────────────────────────────────────────────────────────────

package "Shared" #F1EFE8 {

  interface OrchestratorPort {
    + run(SessionRequest) : Result<Vec<SessionOutcome>>
  }

  together {
    interface LlmEnginePort {
      + run(RoundSignal) : Result<LlmSignal>
    }
    interface FuzzerEnginePort {
      + run(Vec<RoundSignal>) : Result<Vec<FuzzReport>>
    }
    interface ExecutorPort {
      + execute(ExecutorInput) : Result<()>
    }
  }

  together {
    interface ReaderPort {
      + get_contract_context(...) : Result<ContractContext>
      + get_fuzz_output(...) : Result<Option<String>>
    }
    interface ReporterPort {
      + emit(SessionOutcome) : Result<()>
      + emit_round_usage(RoundUsage) : Result<()>
    }
    interface SecurityAnalysisPort {
      + analyze(SecurityAnalysisRequest) : Result<String>
    }
  }

  together {
    class SessionRequest <<model>> {
      + target_paths : Vec<String>
      + max_rounds : u32
      + config : SessionConfig
    }
    class SessionState <<model>> {
      + rounds_remaining : u32
      + current_round : u32
      + found_bugs : HashMap<String, Vec<BugInfo>>
    }
  }

  together {
    class SessionOutcome <<model>> {
      + reason : TerminationReason
      + contract_name : String
      + bugs : Vec<BugInfo>
    }
    class TerminationDecision <<model>> {
      + terminate : bool
      + reason : Option<TerminationReason>
    }
  }
}

' ── Wiring ───────────────────────────────────────────────────────────────────

' ① Inbound: adapter → shared port ← use case
Orchestrator       ..|>  OrchestratorPort       : implements
Orchestrator       *-->  OrchestratorRunPort
RunSessionUseCase  ..|>  OrchestratorRunPort     : implements

' ② Outbound: use case → injected shared ports (no internal adapters)
RunSessionUseCase  *-->  LlmEnginePort
RunSessionUseCase  *-->  FuzzerEnginePort
RunSessionUseCase  *-->  ExecutorPort
RunSessionUseCase  *-->  ReaderPort
RunSessionUseCase  *-->  ReporterPort
RunSessionUseCase  *-->  SecurityAnalysisPort

' ③ Helper functions called by the use case
RunSessionUseCase  ..>   check_termination       : calls
RunSessionUseCase  ..>   initialise_session      : calls
RunSessionUseCase  ..>   run_round               : calls

' ④ Data flow
RunSessionUseCase  ..>   SessionRequest          : receives
RunSessionUseCase  ..>   SessionOutcome          : produces
RunSessionUseCase  ..>   SessionState            : manages
check_termination  ..>   TerminationDecision     : returns
initialise_session ..>   SessionState            : creates

legend bottom left
  **Legend**
  ----
  <color:#7F77DD>- - ▷</color>  **..|>**  implements / realizes interface
  <color:#7F77DD>◆ ──▶</color>  ***-->**  composition — struct owns a port or field
  <color:#7F77DD>- - ▶</color>  **..>**   calls · receives · produces
endlegend

@enduml
