# proxy/flow | 1025 func | 12 pipelines | 11 hub-types | 2026-03-23

PIPELINES[12] (Core:2, IO:4, Unknown:6):
  Src [Unknown]: ? → ?
              → execute() → StreamingResponse | JSONResponse CC=1    pure ▶
              → _build_context() → None                 CC=2    mutation
              → detect_project(messages:list[dict], headers:dict[str, str] | None) → ProjectContext CC=8    pure
              → _from_directory(directory:str) → ProjectContext CC=2    pure
              → _detect_stack(root:Path) → list[str]    CC=4    mutation
              → sorted()                                CC=4    pure
              → cmp()                                   CC=2    pure ■
              PURITY: 5/7 pure  BOTTLENECK: detect_project(CC=8)

  Src [Core]: ? → ?
              → start() → None                          CC=2    mutation ▶
              → _worker_loop() → None                   CC=4    pure
              → _execute_job(job:ToolJob) → None        CC=5    pure
              → get_adapter(tool_name:str) → BaseAdapter | None CC=3    pure
              → get(cls) → ToolRegistry                 CC=2    pure
              → cls()                                   CC=3    pure ■
              PURITY: 5/6 pure  BOTTLENECK: _execute_job(CC=5)

  Src [IO]: Request → None
              → chat_completions(request:Request, x_task_tier:str | None) CC=13   IO ▶
              → _route_to_model(messages, model:str | None, x_task_tier:str | None) CC=4    pure
              → _analyze_request(messages, x_task_tier:str | None) CC=1    pure
              → analyze_request(messages:list[dict] | str) → AnalysisResult CC=7    pure
              → _apply_heuristics(user_text:str, all_text:str, file_count:int, context_tokens:int, tier_scores:dict[TaskTier, float], caps:set[Capability], signals:list[str]) → None CC=1    pure
              → _keyword_signals(user_text:str, all_text:str, tier_scores:dict, caps:set, signals:list) → None CC=9    mutation ■
              PURITY: 4/6 pure  BOTTLENECK: chat_completions(CC=13)

  Src [Unknown]: Request → ?
              → detect_context(request:Request)         CC=5    mutation ▶
              → detect_project(messages:list[dict], headers:dict[str, str] | None) → ProjectContext CC=8    pure
              → _from_directory(directory:str) → ProjectContext CC=2    pure
              → _detect_stack(root:Path) → list[str]    CC=4    mutation
              → sorted()                                CC=4    pure
              → cmp()                                   CC=2    pure ■
              PURITY: 4/6 pure  BOTTLENECK: detect_project(CC=8)

  Src [Unknown]: ? → ?
              → VoiceChat()                             CC=70   IO  !! ▶
              → h()                                     CC=8    pure
              → processInput()                          CC=20   cache  !!
              → label()                                 CC=2    pure
              → executeDSL()                            CC=4    pure
              → apiCall()                               CC=6    cache ■
              PURITY: 3/6 pure  BOTTLENECK: VoiceChat(CC=70)

  Src [Unknown]: ? → ?
              → onKey()                                 CC=4    pure ▶
              → startListening()                        CC=8    pure
              → processInput()                          CC=20   cache  !!
              → label()                                 CC=2    pure
              → executeDSL()                            CC=4    pure
              → apiCall()                               CC=6    cache ■
              PURITY: 4/6 pure  BOTTLENECK: processInput(CC=20)

  Src [Unknown]: str | None → ?
              → board(sprint_id:str | None) → dict[str, list[dict]] CC=3    pure ▶
              → list_tickets(sprint_id:str | None, status:TicketStatus | None, priority:TicketPriority | None, tool:str | None, tag:str | None) → list[Ticket] CC=1    pure
              → _sort_tickets(tickets:list[Ticket]) → list[Ticket] CC=1    pure
              → sorted()                                CC=4    pure
              → cmp()                                   CC=2    pure ■
              PURITY: 5/5 pure  BOTTLENECK: sorted(CC=4)

  Src [IO]: ? → ?
              → compute_delta() → DeltaPayload          CC=5    mutation ▶
              → _make_full_payload(current:dict[str, FileSnapshot], modified:int, added:int, removed:int) → DeltaPayload CC=1    pure
              → _build_full_context(snapshots:dict[str, FileSnapshot]) → str CC=4    mutation
              → sorted()                                CC=4    pure
              → cmp()                                   CC=2    pure ■
              PURITY: 3/5 pure  BOTTLENECK: compute_delta(CC=5)

  Src [Unknown]: ? → bool
              → list_vms() → list[VMStatus]             CC=3    pure ▶
              → get_status(vm_id:str) → VMStatus | None CC=6    pure
              → _refresh_state_clonebox(vm:VMConfig) → None CC=7    pure
              → _get_clonebox()                         CC=3    mutation
              → _check_clonebox() → bool                CC=3    mutation ■
              PURITY: 3/5 pure  BOTTLENECK: _refresh_state_clonebox(CC=7)

  Src [IO]: args → float
              → cmd_browser_list(args)                  CC=6    IO ▶
              → detect_all_profiles() → list[BrowserProfile] CC=1    mutation
              → detect_chromium_profiles() → list[BrowserProfile] CC=1    pure
              → _detect_chromium_family(base_dir:Path, browser:str) → list[BrowserProfile] CC=9    IO
              → _dir_size_mb(path:Path) → float         CC=4    pure ■
              PURITY: 2/5 pure  BOTTLENECK: _detect_chromium_family(CC=9)

  Src [Core]: AnalysisResult → ?
              → route(analysis:AnalysisResult, explicit_model:str | None) → RoutingDecision CC=3    mutation ▶
              → _find_candidates(analysis:AnalysisResult, available_providers:set[str]) → list[ModelSpec] CC=9    pure
              → models_for_tier(tier:TaskTier, required_caps:frozenset[Capability] | None, available_providers:set[str] | None) → list[ModelSpec] CC=8    mutation
              → sorted()                                CC=4    pure
              → cmp()                                   CC=2    pure ■
              PURITY: 3/5 pure  BOTTLENECK: _find_candidates(CC=9)

  Src [IO]: VMConfig → Path | None
              → create_vm(config:VMConfig) → VMConfig   CC=4    pure ▶
              → _create_vm_clonebox(config:VMConfig) → None CC=7    IO
              → _inject_vm_config(config:VMConfig) → dict[str, Any] CC=9    IO
              → _load_profile_cloud_init(tool:str) → dict[str, Any] CC=3    pure
              → get_builtin_profile(tool:str) → Path | None CC=2    pure ■
              PURITY: 3/5 pure  BOTTLENECK: _inject_vm_config(CC=9)


TRANSFORMS (fan-out ≥10):
  VoiceChat()                                             fan=54   !! mutation-heavy
  run_all_tests(request:Request)                          fan=28   !! side-effects
  chat_completions(request:Request, x_task_tier:str | None) fan=27   !! side-effects
  DiagnosticsPanel()                                      fan=22   !! side-effects
  useDashboardData()                                      fan=20   !! side-effects
  AddProjectForm() → AnalysisResult                       fan=20   !! side-effects
  LogPanel()                                              fan=19   fan=19
  TicketsPanel()                                          fan=18   fan=18
  detect_firefox_profiles() → list[BrowserProfile]        fan=17   fan=17
  _detect_chromium_family(base_dir:Path, browser:str) → list[BrowserProfile] fan=17   fan=17
  ollama_status()                                         fan=17   fan=17
  VMsPanel()                                              fan=17   fan=17
  ProjectCard() → AnalysisResult                          fan=17   fan=17
  analyze_request(messages:list[dict] | str) → AnalysisResult fan=16   fan=16
  _check_roo_cline_config() → dict[str, Any]              fan=16   fan=16

CONTRACTS:
  Pipeline: Src
    execute() → StreamingResponse | JSONResponse
      IN:  ()
      OUT: StreamingResponse | JSONResponse

    _build_context() → None
      IN:  ()
      OUT: None
      SIDE-EFFECT: mutates self.project_ctx

    detect_project(messages:list[dict], headers:dict[str, str] | None) → ProjectContext
      IN:  messages:list[dict], headers:dict[str, str] | None
      OUT: ProjectContext

    _from_directory(directory:str) → ProjectContext
      IN:  directory:str
      OUT: ProjectContext

    _detect_stack(root:Path) → list[str]
      IN:  root:Path
      OUT: list[str]
      SIDE-EFFECT: pure

    sorted()
      IN:  ()
      OUT: None
      INVARIANT: output is sorted

    cmp()
      IN:  ()
      OUT: None

  Pipeline: Src
    start() → None
      IN:  ()
      OUT: None
      SIDE-EFFECT: mutates self._running, self._worker_task

    _worker_loop() → None
      IN:  ()
      OUT: None

    _execute_job(job:ToolJob) → None
      IN:  job:ToolJob
      OUT: None

    get_adapter(tool_name:str) → BaseAdapter | None
      IN:  tool_name:str
      OUT: BaseAdapter | None

    get(cls) → ToolRegistry
      IN:  cls
      OUT: ToolRegistry

    cls()
      IN:  ()
      OUT: None

  Pipeline: Src
    chat_completions(request:Request, x_task_tier:str | None)
      IN:  request:Request, x_task_tier:str | None
      OUT: None
      SIDE-EFFECT: IO(execute, dumps); generator

    _route_to_model(messages, model:str | None, x_task_tier:str | None)
      IN:  messages, model:str | None, x_task_tier:str | None
      OUT: None

    _analyze_request(messages, x_task_tier:str | None)
      IN:  messages, x_task_tier:str | None
      OUT: None

    analyze_request(messages:list[dict] | str) → AnalysisResult
      IN:  messages:list[dict] | str
      OUT: AnalysisResult

    _apply_heuristics(user_text:str, all_text:str, file_count:int, context_tokens:int, tier_scores:dict[TaskTier, float], caps:set[Capability], signals:list[str]) → None
      IN:  user_text:str, all_text:str, file_count:int, context_tokens:int, tier_scores:dict[TaskTier, float], caps:set[Capability], signals:list[str]
      OUT: None

    _keyword_signals(user_text:str, all_text:str, tier_scores:dict, caps:set, signals:list) → None
      IN:  user_text:str, all_text:str, tier_scores:dict, caps:set, signals:list
      OUT: None
      SIDE-EFFECT: pure

  Pipeline: Src
    detect_context(request:Request)
      IN:  request:Request
      OUT: None
      SIDE-EFFECT: pure

    detect_project(messages:list[dict], headers:dict[str, str] | None) → ProjectContext
      IN:  messages:list[dict], headers:dict[str, str] | None
      OUT: ProjectContext

    _from_directory(directory:str) → ProjectContext
      IN:  directory:str
      OUT: ProjectContext

    _detect_stack(root:Path) → list[str]
      IN:  root:Path
      OUT: list[str]
      SIDE-EFFECT: pure

    sorted()
      IN:  ()
      OUT: None
      INVARIANT: output is sorted

    cmp()
      IN:  ()
      OUT: None

  Pipeline: Src
    VoiceChat()
      IN:  ()
      OUT: None
      SIDE-EFFECT: IO(calls:IO)
      SMELL: CC=70 → split

    h()
      IN:  ()
      OUT: None

    processInput()
      IN:  ()
      OUT: None
      SIDE-EFFECT: cache(calls:cache)
      SMELL: CC=20 → split

    label()
      IN:  ()
      OUT: None

    executeDSL()
      IN:  ()
      OUT: None

    apiCall()
      IN:  ()
      OUT: None
      SIDE-EFFECT: cache(calls:cache)

  Pipeline: Src
    onKey()
      IN:  ()
      OUT: None

    startListening()
      IN:  ()
      OUT: None

    processInput()
      IN:  ()
      OUT: None
      SIDE-EFFECT: cache(calls:cache)
      SMELL: CC=20 → split

    label()
      IN:  ()
      OUT: None

    executeDSL()
      IN:  ()
      OUT: None

    apiCall()
      IN:  ()
      OUT: None
      SIDE-EFFECT: cache(calls:cache)

  Pipeline: Src
    board(sprint_id:str | None) → dict[str, list[dict]]
      IN:  sprint_id:str | None
      OUT: dict[str, list[dict]]

    list_tickets(sprint_id:str | None, status:TicketStatus | None, priority:TicketPriority | None, tool:str | None, tag:str | None) → list[Ticket]
      IN:  sprint_id:str | None, status:TicketStatus | None, priority:TicketPriority | None, tool:str | None, tag:str | None
      OUT: list[Ticket]

    _sort_tickets(tickets:list[Ticket]) → list[Ticket]
      IN:  tickets:list[Ticket]
      OUT: list[Ticket]
      INVARIANT: output is sorted

    sorted()
      IN:  ()
      OUT: None
      INVARIANT: output is sorted

    cmp()
      IN:  ()
      OUT: None

  Pipeline: Src
    compute_delta() → DeltaPayload
      IN:  ()
      OUT: DeltaPayload
      SIDE-EFFECT: mutates self._version, self._snapshots, self._initialized

    _make_full_payload(current:dict[str, FileSnapshot], modified:int, added:int, removed:int) → DeltaPayload
      IN:  current:dict[str, FileSnapshot], modified:int, added:int, removed:int
      OUT: DeltaPayload

    _build_full_context(snapshots:dict[str, FileSnapshot]) → str
      IN:  snapshots:dict[str, FileSnapshot]
      OUT: str
      SIDE-EFFECT: pure

    sorted()
      IN:  ()
      OUT: None
      INVARIANT: output is sorted

    cmp()
      IN:  ()
      OUT: None

  Pipeline: Src
    list_vms() → list[VMStatus]
      IN:  ()
      OUT: list[VMStatus]

    get_status(vm_id:str) → VMStatus | None
      IN:  vm_id:str
      OUT: VMStatus | None

    _refresh_state_clonebox(vm:VMConfig) → None
      IN:  vm:VMConfig
      OUT: None

    _get_clonebox()
      IN:  ()
      OUT: None
      SIDE-EFFECT: mutates self._clonebox

    _check_clonebox() → bool
      IN:  ()
      OUT: bool
      SIDE-EFFECT: global(_CLONEBOX_AVAILABLE)
      INVARIANT: raises on invalid input

  Pipeline: Src
    cmd_browser_list(args)
      IN:  args
      OUT: None
      SIDE-EFFECT: IO(print, print)

    detect_all_profiles() → list[BrowserProfile]
      IN:  ()
      OUT: list[BrowserProfile]
      SIDE-EFFECT: pure

    detect_chromium_profiles() → list[BrowserProfile]
      IN:  ()
      OUT: list[BrowserProfile]

    _detect_chromium_family(base_dir:Path, browser:str) → list[BrowserProfile]
      IN:  base_dir:Path, browser:str
      OUT: list[BrowserProfile]
      SIDE-EFFECT: IO(loads, read_text)

    _dir_size_mb(path:Path) → float
      IN:  path:Path
      OUT: float

  Pipeline: Src
    route(analysis:AnalysisResult, explicit_model:str | None) → RoutingDecision
      IN:  analysis:AnalysisResult, explicit_model:str | None
      OUT: RoutingDecision
      SIDE-EFFECT: pure

    _find_candidates(analysis:AnalysisResult, available_providers:set[str]) → list[ModelSpec]
      IN:  analysis:AnalysisResult, available_providers:set[str]
      OUT: list[ModelSpec]

    models_for_tier(tier:TaskTier, required_caps:frozenset[Capability] | None, available_providers:set[str] | None) → list[ModelSpec]
      IN:  tier:TaskTier, required_caps:frozenset[Capability] | None, available_providers:set[str] | None
      OUT: list[ModelSpec]
      SIDE-EFFECT: pure

    sorted()
      IN:  ()
      OUT: None
      INVARIANT: output is sorted

    cmp()
      IN:  ()
      OUT: None

  Pipeline: Src
    create_vm(config:VMConfig) → VMConfig
      IN:  config:VMConfig
      OUT: VMConfig

    _create_vm_clonebox(config:VMConfig) → None
      IN:  config:VMConfig
      OUT: None
      SIDE-EFFECT: IO(unlink)

    _inject_vm_config(config:VMConfig) → dict[str, Any]
      IN:  config:VMConfig
      OUT: dict[str, Any]
      SIDE-EFFECT: IO(loads, dumps)

    _load_profile_cloud_init(tool:str) → dict[str, Any]
      IN:  tool:str
      OUT: dict[str, Any]

    get_builtin_profile(tool:str) → Path | None
      IN:  tool:str
      OUT: Path | None


DATA_TYPES (by cross-function usage) [579 annotated, 10 inferred / 1025 functions]:
  str                  consumed:288 produced:42   !! HUB-TYPE → split interface
  click.Context        consumed:101 produced:0    !! HUB-TYPE → split interface
  dict[str, Any]       consumed:10  produced:75   !! HUB-TYPE → split interface
  str | None           consumed:64  produced:7    !! HUB-TYPE → split interface
  int                  consumed:49  produced:4    !! HUB-TYPE → split interface
  bool                 consumed:15  produced:29   !! HUB-TYPE → split interface
  dict                 consumed:26  produced:14   !! HUB-TYPE → split interface
  list[str]            consumed:15  produced:12   !! HUB-TYPE → split interface
  float                consumed:21  produced:3    !! HUB-TYPE → split interface
  list[dict]           consumed:9   produced:8  
  VMConfig             consumed:16  produced:1    !! HUB-TYPE → split interface
  AnalysisResult       consumed:5   produced:9  
  CloneBoxResult       consumed:0   produced:11   output-heavy
  Request              consumed:10  produced:0    !! HUB-TYPE → split interface
  Path                 consumed:9   produced:1    input-heavy (read-only flow)
  Path | None          consumed:4   produced:4  
  dict[str, FileSnapshot] consumed:6   produced:1    input-heavy (read-only flow)
  Project              consumed:2   produced:4  
  list[Ticket]         consumed:2   produced:4  
  ProjectContext       consumed:2   produced:3  

  HUB TYPES (consumed ≥10):
    str → 288 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    click.Context → 101 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    dict[str, Any] → 10 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    str | None → 64 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    int → 49 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    bool → 15 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    dict → 26 consumers → split into:
      - replace with typed alternatives (dataclass/TypedDict)
    list[str] → 15 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    float → 21 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    VMConfig → 16 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)
    Request → 10 consumers → split into:
      - (analyze consumers to suggest sub-interfaces)

SIDE_EFFECTS:
  IO:        install_voice_deps, main, main, get_logs, list_tools, TicketManager._save, TicketManager._load, ProjectRegistry._enrich_local, ProjectRegistry._save, ProjectRegistry._load
  Cache:     ct, get, post, r, stored_list, apiCall, processInput, ctrl, res
  Mutation:  _make_args, get_settings, _accounts, _vms, list_providers, _accounts, cost_detailed, Ticket.__init__, TicketManager.__init__, TicketManager.add_comment
  Pure:      check_voice_deps, cli, serve, status, models, chat, logs_cmd, providers_cmd, routing_test_cmd, projects_cmd

  PIPELINE PURITY:
    Src             ██░░ 71% pure
    Src             ███░ 83% pure
    Src             ██░░ 66% pure
    Src             ██░░ 66% pure
    Src             ██░░ 50% pure
    Src             ██░░ 66% pure
    Src             ████ 100% pure
    Src             ██░░ 60% pure
    Src             ██░░ 60% pure
    Src             █░░░ 40% pure
    Src             ██░░ 60% pure
    Src             ██░░ 60% pure
