From b04d801e9b89b3819c1340c577a0190877a9de17 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 22 Jun 2026 02:09:12 -0400 Subject: [PATCH] feat(audit-meta): add scripts/audit_code_path_audit_coverage.py Schema validator for the v2 audit's output. Verifies all 14 required profile sections, all 5 cross-audit fields, all 8 decomposition_cost fields. Per feature_flags.md 'delete to turn off' pattern. --- scripts/audit_code_path_audit_coverage.py | 55 ++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/scripts/audit_code_path_audit_coverage.py b/scripts/audit_code_path_audit_coverage.py index cb12eb69..c16630cd 100644 --- a/scripts/audit_code_path_audit_coverage.py +++ b/scripts/audit_code_path_audit_coverage.py @@ -10,4 +10,57 @@ Usage: uv run python scripts/audit_code_path_audit_coverage.py uv run python scripts/audit_code_path_audit_coverage.py --strict """ -from __future__ import annotations \ No newline at end of file +from __future__ import annotations +import argparse +import sys +from pathlib import Path + +REQUIRED_PROFILE_FIELDS: tuple[str, ...] = ( + "aggregate_kind", "memory_dim", "producers", "consumers", + "access_pattern", "access_pattern_evidence", "frequency", "frequency_evidence", + "result_coverage", "type_alias_coverage", "cross_audit_findings", + "decomposition_cost", "optimization_candidates", "is_candidate", +) +REQUIRED_CROSS_AUDIT_FIELDS: tuple[str, ...] = ( + "weak_types", "exception_handling", "optional_in_baseline", + "config_io_ownership", "import_graph", +) +REQUIRED_DECOMP_COST_FIELDS: tuple[str, ...] = ( + "current_cost_estimate", "componentize_savings", "unify_savings", + "recommended_direction", "recommended_rationale", "batch_size", + "struct_field_count", "struct_frozen", +) + +def main() -> int: + parser = argparse.ArgumentParser(description="Meta-audit for code_path_audit v2 output schema.") + parser.add_argument("--input-dir", default="docs/reports/code_path_audit/latest", help="Path to the v2 audit output") + parser.add_argument("--strict", action="store_true", help="Exit 1 on any violation") + args = parser.parse_args() + input_dir = Path(args.input_dir) + if not input_dir.exists(): + print(f"ERROR: input dir does not exist: {input_dir}") + return 1 + violations: list[str] = [] + for dsl_path in sorted(input_dir.glob("aggregates/*.dsl")): + content = dsl_path.read_text(encoding="utf-8") + for field in REQUIRED_PROFILE_FIELDS: + if f"\\ === {field} ===" not in content: + violations.append(f"{dsl_path.name}: missing section '{field}'") + for field in REQUIRED_CROSS_AUDIT_FIELDS: + if field not in content: + violations.append(f"{dsl_path.name}: missing cross-audit field '{field}'") + for field in REQUIRED_DECOMP_COST_FIELDS: + if field not in content: + violations.append(f"{dsl_path.name}: missing decomposition_cost field '{field}'") + if violations: + print(f"Meta-audit: {len(violations)} violations") + for v in violations: + print(f" - {v}") + if args.strict: + return 1 + return 0 + print("Meta-audit: 0 violations") + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file