(res: SelectorResult, repo: Path)
| 285 | |
| 286 | |
| 287 | def validate_selected_paths(res: SelectorResult, repo: Path) -> SelectorResult: |
| 288 | missing: list[str] = [] |
| 289 | |
| 290 | # validate pytest paths (files/dirs) |
| 291 | for p in res.pytest_paths: |
| 292 | if not _is_safe_relpath(p) or not (repo / p).exists(): |
| 293 | missing.append(f"pytest:{p}") |
| 294 | |
| 295 | # validate functional scripts (files) |
| 296 | for s in res.functional_scripts: |
| 297 | if not _is_safe_relpath(s) or not (repo / s).exists(): |
| 298 | missing.append(f"script:{s}") |
| 299 | |
| 300 | if missing: |
| 301 | # Fail-safe escalation: disable fast lane selection, enable full lane. |
| 302 | # Preserve docs lane if it was independently selected. |
| 303 | res.lanes.fast = False |
| 304 | res.lanes.full = True |
| 305 | res.pytest_paths = [] |
| 306 | res.functional_scripts = [] |
| 307 | res.provenance = SelectionProvenance() |
| 308 | res.reasons = res.reasons + ["missing_selected_paths"] + missing |
| 309 | |
| 310 | lane_reasons = dict(res.lane_reasons) |
| 311 | lane_reasons.pop("fast", None) |
| 312 | full_reasons = list(lane_reasons.get("full", [])) |
| 313 | full_reasons.extend(["missing_selected_paths", *missing]) |
| 314 | lane_reasons["full"] = full_reasons |
| 315 | res.lane_reasons = lane_reasons |
| 316 | |
| 317 | return res |
| 318 | |
| 319 | |
| 320 | # ----------------------------- |
no test coverage detected