| from __future__ import annotations |
| from dataclasses import dataclass |
| from core.runner import run_skill_script |
|
|
|
|
| @dataclass(frozen=True) |
| class SelectResult: |
| selected_ids: tuple[str, ...] |
| indicator_defs: dict[str, dict] |
| 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, |
| ) |
|
|