5ac0618a33
The 7 code_path_audit*.py files (2604 lines total) are pure static analysis tools. They do AST traversal of src/, no intrusive profiling, no runtime markers. They were inlaid with src/ but only import: - src.result_types (the Result[T] convention type) - each other (the 6 siblings) After the move: - src/ is now pure application code; line-count audit metrics are clean - scripts/code_path_audit/ is a new namespace-isolated subdir per AGENTS.md 'scripts are namespace-isolated by directory' rule TIER-3 READ AGENTS.md + conductor/workflow.md + conductor/edit_workflow.md + conductor/code_styleguides/code_path_audit.md + the 7 files before this commit. Changes: - 7 files moved: src/code_path_audit*.py -> scripts/code_path_audit/ - 7 files updated: internal imports rom src.code_path_audit_X -> rom code_path_audit_X (siblings in same subdir) - 7 files updated: add sys.path.insert(0, str(Path(__file__).resolve().parents[2] / 'src')) to find src.result_types when run standalone - 5 test files updated: rom src.code_path_audit -> rom code_path_audit + sys.path setup to find the new subdir - 6 throwaway scripts in scripts/tier2/artifacts/ updated: import path + sys.path setup (parents[3] / 'src' + parents[3] / 'scripts' / 'code_path_audit') - 2 styleguide/spec references updated: conductor/code_styleguides/code_path_audit.md + conductor/tracks/code_path_audit_20260607/spec_v2.md - 1 meta-audit docstring updated: scripts/audit_code_path_audit_coverage.py - 1 type registry entry deleted: docs/type_registry/src_code_path_audit.md (the type is no longer in src/) - 1 type registry index updated: docs/type_registry/index.md (22 files, was 23) Verification: - 7/7 audit gates pass --strict (weak_types 102<=112, type_registry 22 files, main_thread_imports OK, no_models_config_io OK, code_path_audit_coverage 0 violations, exception_handling 0 violations, optional_in_3_files 0 violations) - 6/6 test files pass: test_code_path_audit, test_code_path_audit_integration, test_code_path_audit_phase78, test_code_path_audit_phase89, test_code_path_audit_ssdl_behavioral, test_metadata_nil_sentinel - src/ line count: 29997 lines (down from 32621 = -2624 lines) - scripts/code_path_audit/ line count: 2620 lines
64 lines
2.9 KiB
Python
64 lines
2.9 KiB
Python
"""Behavioral tests for the Metadata nil sentinel.
|
|
|
|
Child 1 of metadata_ssdl_defusing_20260624. Asserts:
|
|
- NIL_METADATA constant is defined in src/aggregate.py (the Metadata parent module).
|
|
- NIL_METADATA is a valid Metadata (dict[str, Any]).
|
|
- Sentinel pattern is usable: `entry or NIL_METADATA` returns a safe Metadata.
|
|
- detect_nil_check_pattern returns False for at least one migrated function in
|
|
src/aggregate.py + src/ai_client.py (the files named in the parent campaign spec).
|
|
"""
|
|
from __future__ import annotations
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit"))
|
|
|
|
from code_path_audit_ssdl import detect_nil_check_pattern
|
|
|
|
|
|
def test_nil_metadata_is_defined() -> None:
|
|
from src.aggregate import NIL_METADATA
|
|
assert NIL_METADATA is not None, "NIL_METADATA must be a valid Metadata sentinel"
|
|
assert isinstance(NIL_METADATA, dict), f"NIL_METADATA must be a dict (Metadata TypeAlias); got {type(NIL_METADATA)}"
|
|
|
|
|
|
def test_nil_metadata_safe_defaults() -> None:
|
|
from src.aggregate import NIL_METADATA
|
|
assert NIL_METADATA.get("any_missing_key") is None, "NIL_METADATA must return None for missing keys"
|
|
assert NIL_METADATA.get("any_missing_key", "default") == "default", "NIL_METADATA must honor .get(default)"
|
|
assert len(NIL_METADATA) >= 0, "NIL_METADATA must be a valid dict with len() support"
|
|
|
|
|
|
def test_sentinel_pattern_works() -> None:
|
|
from src.aggregate import NIL_METADATA
|
|
entry: dict = {}
|
|
result = entry or NIL_METADATA
|
|
assert result is NIL_METADATA, "empty dict should fall through to NIL_METADATA"
|
|
entry_filled: dict = {"key": "value"}
|
|
result2 = entry_filled or NIL_METADATA
|
|
assert result2 is entry_filled, "filled dict should NOT be replaced by NIL_METADATA"
|
|
|
|
|
|
def test_migration_reduces_nil_check_count() -> None:
|
|
from code_path_audit import build_pcg
|
|
from code_path_audit_ssdl import detect_nil_check_pattern
|
|
pcg = build_pcg("src").data
|
|
metadata_consumers = pcg.consumers.get("Metadata", [])
|
|
target_files = {"aggregate.py", "ai_client.py"}
|
|
remaining = [f for f in metadata_consumers if f.file in target_files and detect_nil_check_pattern(f, "src")]
|
|
migrated_funcs = ["_build_files_section_from_items"]
|
|
migrated = [f for f in metadata_consumers if f.file in target_files and f.fqname.rsplit(".", 1)[-1] in migrated_funcs]
|
|
for m in migrated:
|
|
assert not detect_nil_check_pattern(m, "src"), f"{m.fqname} should no longer have nil-check pattern"
|
|
|
|
|
|
def test_detect_nil_check_pattern_works_for_migrated_function() -> None:
|
|
from code_path_audit import FunctionRef
|
|
from src.aggregate import _build_files_section_from_items
|
|
fref = FunctionRef(fqname="src.aggregate._build_files_section_from_items", file="aggregate.py", line=300, role="consumer")
|
|
has_nil = detect_nil_check_pattern(fref, "src")
|
|
assert has_nil is False, (
|
|
"_build_files_section_from_items should no longer have a nil-check pattern after sentinel migration"
|
|
)
|