"""Source-derived FeatureScript operation coverage inventory. The registry records what the current source corpus actually contains. It is deliberately independent from conversion diagnostics: an old output directory cannot make an operation appear supported, and a planned operation cannot be reported as observed merely because its name is listed in the roadmap. """ from __future__ import annotations from collections import Counter, defaultdict from pathlib import Path from typing import Any, Iterable from .dataset import Sample from .featurescript_parser import parse_featurescript REGISTRY_SCHEMA = "cadfs_to_cdsl.operation_registry.v1" # These are roadmap work items, not parser aliases or support declarations. P3_OPERATION_WORK_ITEMS = ( "draft", "thicken", "split", "moveFace", "deleteFace", "replaceFace", "transform", "derive", "import", "bend_add", ) def build_operation_registry(samples: Iterable[Sample]) -> dict[str, Any]: """Parse every available FeatureScript source and inventory feature calls. Parse failures and missing FeatureScript modalities are recorded separately instead of being treated as a zero-count result. Sample examples remain bounded only for report size; the count is computed from every feature. """ counts: Counter[str] = Counter() sample_ids: dict[str, set[str]] = defaultdict(set) parse_failures: list[dict[str, str]] = [] source_sample_count = 0 for sample in samples: source_path = sample.files.get("featurescript") if not source_path: continue source_sample_count += 1 try: model = parse_featurescript(Path(source_path).read_text(encoding="utf-8"), sample.sample_id) except Exception as error: parse_failures.append({"sample_id": sample.sample_id, "error": f"{type(error).__name__}: {error}"}) continue for feature in model.features: counts[feature.operation] += 1 sample_ids[feature.operation].add(sample.sample_id) operations: dict[str, dict[str, Any]] = {} for operation in sorted(counts): operations[operation] = { "state": "observed", "feature_count": counts[operation], "sample_count": len(sample_ids[operation]), "sample_ids": sorted(sample_ids[operation]), } for operation in P3_OPERATION_WORK_ITEMS: if operation in operations: operations[operation]["roadmap_work_item"] = True else: operations[operation] = { "state": "not_observed_in_current_source", "feature_count": 0, "sample_count": 0, "sample_ids": [], "roadmap_work_item": True, } return { "schema": REGISTRY_SCHEMA, "source_sample_count": source_sample_count, "parse_failure_count": len(parse_failures), "parse_failures": parse_failures, "operations": operations, }