"""Top-K — the simplest SkyDiscover search strategy: always expand the single best program.

Ported from SkyDiscover's ``TopKDatabase`` (UC Berkeley Sky Computing Lab). One module per component:

  population.py        -> TopKPopulation      (uncapped keep-all leaderboard)
  selection_policy.py  -> TopKPolicy          (parent = rank 1, inspirations = ranks 2..K+1)
  prompt_builder.py    -> TopKPromptBuilder   (the default multi-section template)
  proposer.py          -> TopKProposer        (SEARCH/REPLACE diff)
  evaluator.py         -> TopKEvaluator       (task-supplied)
  memory.py            -> TopKMemory          (none)
  scaffold.py          -> TopKScaffold        (the orchestrator that composes the six)

Pure greedy elitism: no topology, no migration, no adaptive selection — a reliable, deterministic
baseline for sanity-checking a new task or evaluator before running adaptive search.
"""
from __future__ import annotations

from ...config import GalapagosConfig
from ...models import GalapagosModel
from ..base_scaffold import GalapagosScaffold
from ..registry import register_scaffold
# one module per component (the Top-K scaffold method)
from .memory import TopKMemory
from .population import TopKPopulation
from .prompt_builder import TopKPromptBuilder
from .proposer import TopKProposer
from .selection_policy import TopKPolicy


@register_scaffold("topk")
class TopKScaffold(GalapagosScaffold):
    name = "topk"

    @classmethod
    def build_components(cls, config: GalapagosConfig, model: GalapagosModel | None) -> dict:
        seed = int(config.seed)
        sel = config.selection_policy
        return {
            "population": TopKPopulation(capacity=config.population.capacity),
            "selection_policy": TopKPolicy(seed=seed, num_inspirations=int(sel.num_inspirations)),
            "prompt_builder": TopKPromptBuilder(),
            "proposer": TopKProposer(),
            "memory": TopKMemory(),
        }
