94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|||
|
|
"""Runtime surface manifest helpers for PlantAI-rag cleanup audits."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import json
|
||
|
|
from functools import lru_cache
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
|
||
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||
|
|
DEFAULT_MANIFEST_PATH = PROJECT_ROOT / "config" / "runtime_surface_manifest.json"
|
||
|
|
|
||
|
|
|
||
|
|
def _as_string_set(value: Any) -> frozenset[str]:
|
||
|
|
if not isinstance(value, list):
|
||
|
|
return frozenset()
|
||
|
|
return frozenset(str(item) for item in value)
|
||
|
|
|
||
|
|
|
||
|
|
def _section(manifest: dict[str, Any], name: str) -> dict[str, Any]:
|
||
|
|
value = manifest.get(name)
|
||
|
|
return value if isinstance(value, dict) else {}
|
||
|
|
|
||
|
|
|
||
|
|
@lru_cache(maxsize=4)
|
||
|
|
def load_runtime_surface(manifest_path: str | Path = DEFAULT_MANIFEST_PATH) -> dict[str, Any]:
|
||
|
|
path = Path(manifest_path)
|
||
|
|
with path.open("r", encoding="utf-8") as handle:
|
||
|
|
manifest = json.load(handle)
|
||
|
|
if not isinstance(manifest, dict):
|
||
|
|
raise ValueError(f"Runtime surface manifest must be a JSON object: {path}")
|
||
|
|
if int(manifest.get("schema_version") or 0) != 1:
|
||
|
|
raise ValueError(f"Unsupported runtime surface manifest schema: {path}")
|
||
|
|
return manifest
|
||
|
|
|
||
|
|
|
||
|
|
def current_runtime_files(manifest: dict[str, Any] | None = None) -> frozenset[str]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return _as_string_set(_section(manifest, "current_runtime").get("files"))
|
||
|
|
|
||
|
|
|
||
|
|
def current_runtime_prefixes(manifest: dict[str, Any] | None = None) -> tuple[str, ...]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return tuple(_as_string_set(_section(manifest, "current_runtime").get("prefixes")))
|
||
|
|
|
||
|
|
|
||
|
|
def required_tracked_files(manifest: dict[str, Any] | None = None) -> frozenset[str]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return _as_string_set(manifest.get("required_tracked_files"))
|
||
|
|
|
||
|
|
|
||
|
|
def legacy_prefixes(manifest: dict[str, Any] | None = None) -> tuple[str, ...]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return tuple(_as_string_set(_section(manifest, "legacy").get("prefixes")))
|
||
|
|
|
||
|
|
|
||
|
|
def legacy_files(manifest: dict[str, Any] | None = None) -> frozenset[str]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return _as_string_set(_section(manifest, "legacy").get("files"))
|
||
|
|
|
||
|
|
|
||
|
|
def docs_history_files(manifest: dict[str, Any] | None = None) -> frozenset[str]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return _as_string_set(_section(manifest, "docs_history").get("files"))
|
||
|
|
|
||
|
|
|
||
|
|
def docs_history_prefixes(manifest: dict[str, Any] | None = None) -> tuple[str, ...]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return tuple(_as_string_set(_section(manifest, "docs_history").get("prefixes")))
|
||
|
|
|
||
|
|
|
||
|
|
def test_fixture_prefixes(manifest: dict[str, Any] | None = None) -> tuple[str, ...]:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
return tuple(_as_string_set(_section(manifest, "test_fixture").get("prefixes")))
|
||
|
|
|
||
|
|
|
||
|
|
def classify_path(path: str, manifest: dict[str, Any] | None = None) -> str:
|
||
|
|
manifest = manifest or load_runtime_surface()
|
||
|
|
if path in current_runtime_files(manifest) or path.startswith(current_runtime_prefixes(manifest)):
|
||
|
|
return "current_runtime"
|
||
|
|
if path.startswith(test_fixture_prefixes(manifest)):
|
||
|
|
return "test_fixture"
|
||
|
|
if (
|
||
|
|
path in docs_history_files(manifest)
|
||
|
|
or path.startswith(docs_history_prefixes(manifest))
|
||
|
|
or path.endswith(".md")
|
||
|
|
):
|
||
|
|
return "docs_history"
|
||
|
|
if path in legacy_files(manifest) or path.startswith(legacy_prefixes(manifest)):
|
||
|
|
return "legacy_script"
|
||
|
|
return "other_tracked"
|