from __future__ import annotations from dataclasses import dataclass from core.runner import run_skill_script @dataclass(frozen=True) class SelectResult: selected_ids: tuple[str, ...] # ordered — the determinism artifact carried verbatim to Phase E indicator_defs: dict[str, dict] # get_indicators "indicators" map, keyed by id count_by_sector: dict[str, int] def select_step(sectors: list[str], *, subpillars: list[str] | None = None) -> SelectResult: """Deterministic Step-2 selection. No LLM. Calls two vendored scripts via run_skill_script. select_indicators.py gives the ordered candidate id list (the determinism contract); get_indicators.py gives the sliced field defs the bind loop (Phase E) consumes. """ if subpillars is None: subpillars = [] args = ["--sectors", *sectors] if subpillars: args += ["--subpillars", *subpillars] selection = run_skill_script("select_indicators.py", args) selected_ids = tuple(item["id"] for item in selection["selected"]) count_by_sector = selection.get("count_by_sector", {}) if selected_ids: fetched = run_skill_script("get_indicators.py", ["--ids", *selected_ids]) indicator_defs = fetched["indicators"] else: indicator_defs = {} return SelectResult( selected_ids=selected_ids, indicator_defs=indicator_defs, count_by_sector=count_by_sector, )