diff --git a/conductor/code_styleguides/code_path_audit.md b/conductor/code_styleguides/code_path_audit.md index 8395f567..d518bf3c 100644 --- a/conductor/code_styleguides/code_path_audit.md +++ b/conductor/code_styleguides/code_path_audit.md @@ -2,7 +2,7 @@ > **Status:** Active convention as of 2026-06-22. Established by the `code_path_audit_20260607` v2 track. -This styleguide codifies the contract for `src/code_path_audit.py` v2 and the 6 input audit scripts it consumes. Companion to `data_oriented_design.md`, `error_handling.md`, `type_aliases.md`, and `agent_memory_dimensions.md`. +This styleguide codifies the contract for `scripts/code_path_audit/code_path_audit.py` v2 and the 6 input audit scripts it consumes. Companion to `data_oriented_design.md`, `error_handling.md`, `type_aliases.md`, and `agent_memory_dimensions.md`. ## The 5 Conventions @@ -10,7 +10,7 @@ This styleguide codifies the contract for `src/code_path_audit.py` v2 and the 6 Every `AggregateProfile` (the central artifact) has 15 fields (14 required + 1 default): `name`, `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` (plus `mermaid` and `markdown` with defaults). The `is_candidate: bool` flag distinguishes the 3 placeholder aggregates (`ToolSpec`, `ChatMessage`, `ProviderHistory`) from the 10 real aggregates. -The custom postfix `.dsl` output is the canonical artifact: each section is a self-contained tagged record (flat, streamable, tag-scannable). The 14 new v2 DSL words: `kind`, `mem-dim`, `fn-ref`, `access-pattern`, `ap-evidence`, `frequency`, `freq-evidence`, `result-coverage`, `type-alias-coverage`, `cross-audit-finding`, `cross-audit-findings`, `decomp-cost`, `opt-candidate`, `is-candidate`. Arity table in `src/code_path_audit.py:DSL_WORD_ARITY_V2`. +The custom postfix `.dsl` output is the canonical artifact: each section is a self-contained tagged record (flat, streamable, tag-scannable). The 14 new v2 DSL words: `kind`, `mem-dim`, `fn-ref`, `access-pattern`, `ap-evidence`, `frequency`, `freq-evidence`, `result-coverage`, `type-alias-coverage`, `cross-audit-finding`, `cross-audit-findings`, `decomp-cost`, `opt-candidate`, `is-candidate`. Arity table in `scripts/code_path_audit/code_path_audit.py:DSL_WORD_ARITY_V2`. ### 2. The 4 decomposition directions @@ -21,7 +21,7 @@ For each aggregate, the audit computes a `DecompositionCost` (8 fields: `current - **`hold`** - current shape is correct; default for `frozen + whole_struct` (the ideal shape). - **`insufficient_data`** - access pattern is `mixed` or frequency is `unknown`; needs runtime profiling per pipeline. -The 4-direction logic is in `src/code_path_audit.py:recommended_direction()`. The savings estimates are heuristic (calibrated by `pipeline_runtime_profiling_20260607`); use as ranking input, not as actual savings. +The 4-direction logic is in `scripts/code_path_audit/code_path_audit.py:recommended_direction()`. The savings estimates are heuristic (calibrated by `pipeline_runtime_profiling_20260607`); use as ranking input, not as actual savings. ### 3. The override file format @@ -39,7 +39,7 @@ The file is optional. Missing file = empty overrides (the canonical mappings + h ### 4. The 4 mem dim classification rules -`MemoryDim` is a 7-value Literal: `curation`, `discussion`, `rag`, `knowledge`, `config`, `control`, `unknown`. The classification precedence (per `src/code_path_audit.py:classify_memory_dim()`): overrides > canonical mappings > file-of-origin heuristic > `unknown`. +`MemoryDim` is a 7-value Literal: `curation`, `discussion`, `rag`, `knowledge`, `config`, `control`, `unknown`. The classification precedence (per `scripts/code_path_audit/code_path_audit.py:classify_memory_dim()`): overrides > canonical mappings > file-of-origin heuristic > `unknown`. - **`curation`**: per-file structural (FileItem, FileItems, ContextPreset). - **`discussion`**: per-turn conversational (Metadata, CommsLog, History, ChatMessage). diff --git a/conductor/tracks/code_path_audit_20260607/spec_v2.md b/conductor/tracks/code_path_audit_20260607/spec_v2.md index 26ed8447..cebac286 100644 --- a/conductor/tracks/code_path_audit_20260607/spec_v2.md +++ b/conductor/tracks/code_path_audit_20260607/spec_v2.md @@ -7,7 +7,7 @@ **Folder:** `conductor/tracks/code_path_audit_20260607/` **Files:** `spec.md` (v1; preserved), `spec_v2.md` (this file), `plan.md` (v1; preserved), `plan_v2.md` (after this spec is approved) -> **v2 revision note (2026-06-22).** The v1 spec.md (approved 2026-06-07; revised 2026-06-08) was never executed (no `state.toml`, no `metadata.json`, no `src/code_path_audit.py` in the working tree). The 14-day gap saw 4 foundational tracks ship (`qwen_llama_grok_integration_20260606`, `data_oriented_error_handling_20260606`, `data_structure_strengthening_20260606`, `mcp_architecture_refactor_20260606`), the entire 5-sub-track `result_migration` campaign ship (2026-06-16 through 2026-06-21; 100% complete), and the `nagent_review` corpus grow from v1 to v3.1. v2 re-scopes the audit from "expensive operations per action" to "data pipelines per aggregate" — the v1 framing was correct at the time (the 4 tracks were future) but is now stale. v2 also cross-validates the `data_structure_strengthening_20260606` + `data_oriented_error_handling_20260606` deductions directly, which v1 could not (those tracks didn't exist on 2026-06-07). See §"Why v2" below. +> **v2 revision note (2026-06-22).** The v1 spec.md (approved 2026-06-07; revised 2026-06-08) was never executed (no `state.toml`, no `metadata.json`, no `scripts/code_path_audit/code_path_audit.py` in the working tree). The 14-day gap saw 4 foundational tracks ship (`qwen_llama_grok_integration_20260606`, `data_oriented_error_handling_20260606`, `data_structure_strengthening_20260606`, `mcp_architecture_refactor_20260606`), the entire 5-sub-track `result_migration` campaign ship (2026-06-16 through 2026-06-21; 100% complete), and the `nagent_review` corpus grow from v1 to v3.1. v2 re-scopes the audit from "expensive operations per action" to "data pipelines per aggregate" — the v1 framing was correct at the time (the 4 tracks were future) but is now stale. v2 also cross-validates the `data_structure_strengthening_20260606` + `data_oriented_error_handling_20260606` deductions directly, which v1 could not (those tracks didn't exist on 2026-06-07). See §"Why v2" below. --- @@ -31,7 +31,7 @@ The user's framing (2026-06-22): ## Overview -Build `src/code_path_audit.py` v2 — a data-oriented static-analysis tool that audits the data pipelines in `src/` and produces per-data-aggregate profiles. The output (custom postfix `.dsl` data + markdown + prefix tree text, organized per-aggregate) is the artifact that informs per-aggregate refactor decisions. The actual code changes are follow-up tracks (the 3 high-priority candidates from `decomposition_matrix.md`). +Build `scripts/code_path_audit/code_path_audit.py` v2 — a data-oriented static-analysis tool that audits the data pipelines in `src/` and produces per-data-aggregate profiles. The output (custom postfix `.dsl` data + markdown + prefix tree text, organized per-aggregate) is the artifact that informs per-aggregate refactor decisions. The actual code changes are follow-up tracks (the 3 high-priority candidates from `decomposition_matrix.md`). The v2 audit's primary value is **cross-validation**: it consumes the JSON outputs of the 5 existing audit scripts and synthesizes them with the per-aggregate producer/consumer call graph. The result is a per-aggregate report that says "this aggregate has 12 weak-type sites (cross-checks `data_structure_strengthening`), 5 exception-handling sites (cross-checks `data_oriented_error_handling`), and 1 high-priority optimization candidate (decomposition direction: componentize)." The user reads one report per aggregate, not one per action. @@ -51,7 +51,7 @@ The v2 audit is **read-only** on `src/` (the only new file is the tool itself + 3. **`scripts/audit_exception_handling.py`** — the exception-handling CI gate (per `error_handling.md`). v2 consumes its JSON output. v2 does not modify this script. -4. **`scripts/audit_optional_in_3_files.py`** — the `Optional[T]` ban CI gate for the 3 refactored files (`mcp_client.py`, `ai_client.py`, `rag_engine.py`). v2 extends this script by 1 line (add `src/code_path_audit.py` to the baseline list); the convention is the same. +4. **`scripts/audit_optional_in_3_files.py`** — the `Optional[T]` ban CI gate for the 3 refactored files (`mcp_client.py`, `ai_client.py`, `rag_engine.py`). v2 extends this script by 1 line (add `scripts/code_path_audit/code_path_audit.py` to the baseline list); the convention is the same. 5. **`scripts/audit_no_models_config_io.py`** — the config-I/O ownership CI gate (per `conductor/code_styleguides/config_state_owner.md`). v2 consumes its JSON output. v2 does not modify this script. @@ -108,11 +108,11 @@ The v2 audit is **read-only** on `src/` (the only new file is the tool itself + - A cross-audit integration layer that consumes the 6 input JSON streams and produces per-aggregate `cross_audit_findings` + 2 coverage metrics (`result_coverage`, `type_alias_coverage`). - The v2 postfix DSL (14 new tagged words + the v1's 7 preserved). The flat-section format (streamable, tag-scannable). - Output: per-aggregate `.dsl` + `.md` + `.tree` files + 4 top-level rollup files (summary.md, cross_audit_summary.md, decomposition_matrix.md, candidates.md). -- A CLI (`python -m src.code_path_audit --all --date `) and an MCP tool (`code_path_audit_v2(action=None) -> dict`). +- A CLI (`python scripts/code_path_audit/code_path_audit.py --all --date `) and an MCP tool (`code_path_audit_v2(action=None) -> dict`). - A meta-audit (`scripts/audit_code_path_audit_coverage.py`) that validates the v2 audit's output schema. - The actual audit run on the 13 aggregates, with the report committed to `docs/reports/code_path_audit//`. - A new styleguide (`conductor/code_styleguides/code_path_audit.md`) documenting the v2 audit's contract. -- A 1-line extension to `scripts/audit_optional_in_3_files.py` to include `src/code_path_audit.py` in the baseline. +- A 1-line extension to `scripts/audit_optional_in_3_files.py` to include `scripts/code_path_audit/code_path_audit.py` in the baseline. --- @@ -130,7 +130,7 @@ The v2 audit is **read-only** on `src/` (the only new file is the tool itself + ## Functional Requirements -The 11 public functions in `src/code_path_audit.py`. All return `Result[T]` per the `error_handling.md` hard rule (or return a deterministic `T` when no runtime failure is possible). +The 11 public functions in `scripts/code_path_audit/code_path_audit.py`. All return `Result[T]` per the `error_handling.md` hard rule (or return a deterministic `T` when no runtime failure is possible). | # | Function | Returns | Failure mode | |---|---|---|---| @@ -146,7 +146,7 @@ The 11 public functions in `src/code_path_audit.py`. All return `Result[T]` per | 10 | `to_markdown(profile)` | `str` | n/a (deterministic) | | 11 | `to_tree(profile)` | `str` | n/a (deterministic) | -Plus the CLI (`python -m src.code_path_audit ...`) and the MCP tool (`code_path_audit_v2`). +Plus the CLI (`python scripts/code_path_audit/code_path_audit.py ...`) and the MCP tool (`code_path_audit_v2`). --- @@ -158,10 +158,10 @@ Plus the CLI (`python -m src.code_path_audit ...`) and the MCP tool (`code_path_ - **Type hints required** for all public functions. - **No comments in Python source** (documentation lives in `/docs`). - **`Result[T]` return types** for all functions that can fail at runtime (per the `error_handling.md` hard rule). The new file is held to the same standard as the 3 refactored files. -- **`Optional[T]` return types are FORBIDDEN** in `src/code_path_audit.py`. Verified by the extended `scripts/audit_optional_in_3_files.py` (1-line extension). +- **`Optional[T]` return types are FORBIDDEN** in `scripts/code_path_audit/code_path_audit.py`. Verified by the extended `scripts/audit_optional_in_3_files.py` (1-line extension). - **Per-task commits** (1 task = 1 commit). Per `conductor/workflow.md` TDD protocol. - **Per-task git notes** (each commit gets a `git notes add -m "..."` summary). -- **Coverage target: >80%** for `src/code_path_audit.py`. The 4 audit scripts (`audit_exception_handling.py --strict`, `audit_weak_types.py --strict`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) are the verification gates. +- **Coverage target: >80%** for `scripts/code_path_audit/code_path_audit.py`. The 4 audit scripts (`audit_exception_handling.py --strict`, `audit_weak_types.py --strict`, `audit_main_thread_imports.py`, `audit_no_models_config_io.py`) are the verification gates. - **The audit's runtime is bounded.** The full audit run against the real `src/` (65 files) completes in <60s on a developer machine. The unit + integration tests complete in <30s. The live_gui E2E tests are opt-in. --- @@ -481,7 +481,7 @@ uv run python scripts/audit_no_models_config_io.py ### 9.4 End-of-track verification ```bash -uv run python -m src.code_path_audit --all --date 2026-06-22 +uv run python scripts/code_path_audit/code_path_audit.py --all --date 2026-06-22 uv run python scripts/audit_exception_handling.py --strict uv run python scripts/audit_weak_types.py --strict uv run python scripts/audit_main_thread_imports.py diff --git a/docs/type_registry/index.md b/docs/type_registry/index.md index a291efd7..e69d736d 100644 --- a/docs/type_registry/index.md +++ b/docs/type_registry/index.md @@ -7,7 +7,6 @@ Generated by `scripts/generate_type_registry.py`. Re-run the script (or invoke ` - [`src\api_hooks.py`](src\api_hooks.md) - [`src\beads_client.py`](src\beads_client.md) -- [`src\code_path_audit.py`](src\code_path_audit.md) - [`src\command_palette.py`](src\command_palette.md) - [`src\diff_viewer.py`](src\diff_viewer.md) - [`src\history.py`](src\history.md) @@ -31,18 +30,6 @@ Generated by `scripts/generate_type_registry.py`. Re-run the script (or invoke ` - `WebSocketMessage` (dataclass) - [`src\api_hooks.py`](src\api_hooks.md#src\api_hooks.py::WebSocketMessage) - `Bead` (dataclass) - [`src\beads_client.py`](src\beads_client.md#src\beads_client.py::Bead) -- `FunctionRef` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::FunctionRef) -- `AccessPatternEvidence` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::AccessPatternEvidence) -- `FrequencyEvidence` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::FrequencyEvidence) -- `ResultCoverage` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::ResultCoverage) -- `TypeAliasCoverage` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::TypeAliasCoverage) -- `CrossAuditFinding` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::CrossAuditFinding) -- `CrossAuditFindings` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::CrossAuditFindings) -- `DecompositionCost` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::DecompositionCost) -- `OptimizationCandidate` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::OptimizationCandidate) -- `AggregateProfile` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::AggregateProfile) -- `ProducerConsumerGraph` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::ProducerConsumerGraph) -- `AuditSummary` (dataclass) - [`src\code_path_audit.py`](src\code_path_audit.md#src\code_path_audit.py::AuditSummary) - `Command` (dataclass) - [`src\command_palette.py`](src\command_palette.md#src\command_palette.py::Command) - `ScoredCommand` (dataclass) - [`src\command_palette.py`](src\command_palette.md#src\command_palette.py::ScoredCommand) - `DiffHunk` (dataclass) - [`src\diff_viewer.py`](src\diff_viewer.md#src\diff_viewer.py::DiffHunk) diff --git a/docs/type_registry/src_code_path_audit.md b/docs/type_registry/src_code_path_audit.md deleted file mode 100644 index de744845..00000000 --- a/docs/type_registry/src_code_path_audit.md +++ /dev/null @@ -1,169 +0,0 @@ -# Module: `src\code_path_audit.py` - -Auto-generated from source. 12 struct(s) defined in this module. - -## `src\code_path_audit.py::AccessPatternEvidence` - -**Kind:** `dataclass` -**Defined at:** line 70 - -**Fields:** -- `function: FunctionRef` -- `pattern: AccessPattern` -- `field_accesses: dict[str, int]` -- `confidence: str` - - -## `src\code_path_audit.py::AggregateProfile` - -**Kind:** `dataclass` -**Defined at:** line 136 - -**Fields:** -- `name: str` -- `aggregate_kind: AggregateKind` -- `memory_dim: MemoryDim` -- `producers: tuple[FunctionRef, ...]` -- `consumers: tuple[FunctionRef, ...]` -- `access_pattern: AccessPattern` -- `access_pattern_evidence: tuple[AccessPatternEvidence, ...]` -- `frequency: Frequency` -- `frequency_evidence: tuple[FrequencyEvidence, ...]` -- `result_coverage: ResultCoverage` -- `type_alias_coverage: TypeAliasCoverage` -- `cross_audit_findings: CrossAuditFindings` -- `decomposition_cost: DecompositionCost` -- `optimization_candidates: tuple[OptimizationCandidate, ...]` -- `is_candidate: bool` -- `mermaid: str` -- `markdown: str` - - -## `src\code_path_audit.py::AuditSummary` - -**Kind:** `dataclass` -**Defined at:** line 1032 - -**Fields:** -- `aggregate_profiles: tuple[AggregateProfile, ...]` -- `output_paths: dict[str, str]` - - -## `src\code_path_audit.py::CrossAuditFinding` - -**Kind:** `dataclass` -**Defined at:** line 99 - -**Fields:** -- `audit_script: str` -- `site_count: int` -- `example_file: str` -- `example_line: int` -- `note: str` - - -## `src\code_path_audit.py::CrossAuditFindings` - -**Kind:** `dataclass` -**Defined at:** line 107 - -**Fields:** -- `weak_types: tuple[CrossAuditFinding, ...]` -- `exception_handling: tuple[CrossAuditFinding, ...]` -- `optional_in_baseline: tuple[CrossAuditFinding, ...]` -- `config_io_ownership: tuple[CrossAuditFinding, ...]` -- `import_graph: tuple[CrossAuditFinding, ...]` - - -## `src\code_path_audit.py::DecompositionCost` - -**Kind:** `dataclass` -**Defined at:** line 115 - -**Fields:** -- `current_cost_estimate: int` -- `componentize_savings: int` -- `unify_savings: int` -- `recommended_direction: RecommendedDirection` -- `recommended_rationale: str` -- `batch_size: int | None` -- `struct_field_count: int` -- `struct_frozen: bool` - - -## `src\code_path_audit.py::FrequencyEvidence` - -**Kind:** `dataclass` -**Defined at:** line 77 - -**Fields:** -- `function: FunctionRef` -- `frequency: Frequency` -- `source: str` -- `note: str` - - -## `src\code_path_audit.py::FunctionRef` - -**Kind:** `dataclass` -**Defined at:** line 63 - -**Fields:** -- `fqname: str` -- `file: str` -- `line: int` -- `role: str` - - -## `src\code_path_audit.py::OptimizationCandidate` - -**Kind:** `dataclass` -**Defined at:** line 126 - -**Fields:** -- `candidate: str` -- `direction: RecommendedDirection` -- `affected_files: tuple[str, ...]` -- `estimated_savings_us: int` -- `effort: str` -- `priority: str` -- `cross_ref: str` - - -## `src\code_path_audit.py::ProducerConsumerGraph` - -**Kind:** `dataclass` -**Defined at:** line 156 -**Summary:** Bipartite graph: aggregates <-> functions. - -**Fields:** -- `edges: dict[tuple[str, str], set[str]]` -- `producers: dict[str, set[FunctionRef]]` -- `consumers: dict[str, set[FunctionRef]]` -- `field_accesses: dict[tuple[str, str], tuple[str, int]]` - - -## `src\code_path_audit.py::ResultCoverage` - -**Kind:** `dataclass` -**Defined at:** line 84 - -**Fields:** -- `total_producers: int` -- `result_producers: int` -- `total_consumers: int` -- `result_consumers: int` -- `summary: str` - - -## `src\code_path_audit.py::TypeAliasCoverage` - -**Kind:** `dataclass` -**Defined at:** line 92 - -**Fields:** -- `total_sites: int` -- `typed_sites: int` -- `untyped_sites: int` -- `summary: str` - diff --git a/scripts/audit_code_path_audit_coverage.py b/scripts/audit_code_path_audit_coverage.py index a4a50e05..8df9f8b5 100644 --- a/scripts/audit_code_path_audit_coverage.py +++ b/scripts/audit_code_path_audit_coverage.py @@ -1,4 +1,4 @@ -"""Meta-audit for src.code_path_audit v2 output schema. +"""Meta-audit for code_path_audit v2 output schema. The audit tool now lives in scripts/code_path_audit/ (moved from src/ on 2026-06-24). Verifies that every real (non-candidate) AggregateProfile DSL has all 14 required section markers and the closing 'cross-audit-findings' diff --git a/src/code_path_audit.py b/scripts/code_path_audit/code_path_audit.py similarity index 99% rename from src/code_path_audit.py rename to scripts/code_path_audit/code_path_audit.py index 40475ced..6cbd179c 100644 --- a/src/code_path_audit.py +++ b/scripts/code_path_audit/code_path_audit.py @@ -9,11 +9,13 @@ postfix DSL + markdown + prefix tree text. See conductor/tracks/code_path_audit_20260607/spec_v2.md. """ from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) import ast import tomllib from collections import Counter from dataclasses import dataclass, field -from pathlib import Path from typing import Literal from src.result_types import Result, ErrorInfo, ErrorKind @@ -969,7 +971,7 @@ def synthesize_aggregate_profile( producers[0].file if producers else "", overrides.get("memory_dim", {}) if isinstance(overrides, dict) else {}, ) - from src.code_path_audit_analysis import ( + from code_path_audit_analysis import ( aggregate_pattern_from_consumers, compute_real_type_alias_coverage, compute_real_decomposition_cost, @@ -980,7 +982,7 @@ def synthesize_aggregate_profile( consumers[:50], aggregate, type_registry, "src" ) tac = compute_real_type_alias_coverage(aggregate, producers[:50], consumers[:50], type_registry, "src") - from src.code_path_audit_cross_audit import ( + from code_path_audit_cross_audit import ( aggregate_findings, build_cross_audit_findings_for_aggregate, ) @@ -1075,7 +1077,7 @@ def run_audit( for profile in profiles: agg_dir = output_dir_p / "aggregates" md_path = agg_dir / f"{profile.name}.md" - from src.code_path_audit_render import render_full_markdown + from code_path_audit_render import render_full_markdown md_path.write_text(render_full_markdown(profile), encoding="utf-8") output_paths[profile.name] = str(md_path) return Result(data=AuditSummary(aggregate_profiles=tuple(profiles), output_paths=output_paths)) @@ -1107,7 +1109,7 @@ def render_rollups(summary: AuditSummary, output_dir: Path) -> dict[str, str]: summary_lines.append(f"- `{p.name}.md` - {p.aggregate_kind}, {p.memory_dim}-dim, {p.access_pattern}, {len(p.producers)} producers / {len(p.consumers)} consumers") summary_path.write_text("\n".join(summary_lines), encoding="utf-8") - from src.code_path_audit_gen import generate_audit_report + from code_path_audit_gen import generate_audit_report audit_report_path = output_dir / "AUDIT_REPORT.md" audit_report_text = generate_audit_report( profiles=profiles, diff --git a/src/code_path_audit_analysis.py b/scripts/code_path_audit/code_path_audit_analysis.py similarity index 98% rename from src/code_path_audit_analysis.py rename to scripts/code_path_audit/code_path_audit_analysis.py index 3b45901e..77257bb8 100644 --- a/src/code_path_audit_analysis.py +++ b/scripts/code_path_audit/code_path_audit_analysis.py @@ -11,11 +11,13 @@ These functions AST-walk real src/ files to extract actual signal: All functions return REAL data, not hardcoded defaults. """ from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) import ast from collections import Counter -from pathlib import Path from typing import Literal -from src.code_path_audit import ( +from code_path_audit import ( FunctionRef, AccessPatternEvidence, FrequencyEvidence, @@ -289,7 +291,7 @@ def compute_real_decomposition_cost( componentize_savings: based on field_by_field + many-fields detection unify_savings: based on whole_struct + small-struct detection """ - from src.code_path_audit import ( + from code_path_audit import ( recommended_direction, generate_rationale, per_call_cost_us, diff --git a/src/code_path_audit_cross_audit.py b/scripts/code_path_audit/code_path_audit_cross_audit.py similarity index 97% rename from src/code_path_audit_cross_audit.py rename to scripts/code_path_audit/code_path_audit_cross_audit.py index ba861e0e..745dd7f7 100644 --- a/src/code_path_audit_cross_audit.py +++ b/scripts/code_path_audit/code_path_audit_cross_audit.py @@ -4,8 +4,10 @@ Maps each audit finding (file:line) to one or more aggregates via the PCG's producers + consumers dictionaries. """ from __future__ import annotations +import sys from pathlib import Path -from src.code_path_audit import ( +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) +from code_path_audit import ( CrossAuditFinding, CrossAuditFindings, FunctionRef, diff --git a/src/code_path_audit_gen.py b/scripts/code_path_audit/code_path_audit_gen.py similarity index 89% rename from src/code_path_audit_gen.py rename to scripts/code_path_audit/code_path_audit_gen.py index a0973607..f068ed9f 100644 --- a/src/code_path_audit_gen.py +++ b/scripts/code_path_audit/code_path_audit_gen.py @@ -10,8 +10,10 @@ Single coherent report that embeds: - Verification + reproduction steps """ from __future__ import annotations +import sys from pathlib import Path -from src.code_path_audit import AggregateProfile +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) +from code_path_audit import AggregateProfile def strip_h1(text: str) -> str: @@ -67,16 +69,16 @@ def generate_audit_report( ## 2. Methodology -The audit is implemented in `src/code_path_audit.py` (the main pipeline) plus 5 supporting modules: +The audit is implemented in `scripts/code_path_audit/code_path_audit.py` (the main pipeline) plus 5 supporting modules: | Module | Purpose | |---|---| -| `src/code_path_audit.py` | Pipeline orchestrator + 5 enums + 9 dataclasses + AggregateProfile + run_audit + render_rollups | -| `src/code_path_audit_analysis.py` | AST-walking analyzers: field counts, producer size, access pattern, type alias coverage, decomposition cost | -| `src/code_path_audit_cross_audit.py` | 3-tier finding-to-aggregate mapping (function lookup -> file-level fallback -> unbucketed) | -| `src/code_path_audit_render.py` | Per-profile markdown renderer (15 sections per aggregate) | -| `src/code_path_audit_rollups.py` | Cross-aggregate rollups (call graph, hot paths, field usage, dead fields) | -| `src/code_path_audit_ssdl.py` | **SSDL analysis layer** (the deductions engine: effective codepaths, nil-check detection, defusing techniques) | +| `scripts/code_path_audit/code_path_audit.py` | Pipeline orchestrator + 5 enums + 9 dataclasses + AggregateProfile + run_audit + render_rollups | +| `scripts/code_path_audit/code_path_audit_analysis.py` | AST-walking analyzers: field counts, producer size, access pattern, type alias coverage, decomposition cost | +| `scripts/code_path_audit/code_path_audit_cross_audit.py` | 3-tier finding-to-aggregate mapping (function lookup -> file-level fallback -> unbucketed) | +| `scripts/code_path_audit/code_path_audit_render.py` | Per-profile markdown renderer (15 sections per aggregate) | +| `scripts/code_path_audit/code_path_audit_rollups.py` | Cross-aggregate rollups (call graph, hot paths, field usage, dead fields) | +| `scripts/code_path_audit/code_path_audit_ssdl.py` | **SSDL analysis layer** (the deductions engine: effective codepaths, nil-check detection, defusing techniques) | **Pipeline steps:** @@ -163,7 +165,7 @@ Each aggregate has its full 15-section profile in `aggregates/.md`. This s parts.append("### Per-aggregate summary table\n\n") parts.append("| Aggregate | Memory dim | Pattern | Producers | Consumers | Sites | Typed | Branches | Effective codepaths |\n") parts.append("|---|---|---|---|---|---|---|---|---|\n") - from src.code_path_audit_ssdl import compute_effective_codepaths + from code_path_audit_ssdl import compute_effective_codepaths for p in real_profiles: ec = compute_effective_codepaths(p, "src") branches = sum(1 for _ in [p]) # placeholder @@ -190,7 +192,7 @@ Each aggregate has its full 15-section profile in `aggregates/.md`. This s parts.append("Per-aggregate analysis: effective codepaths, branch points, defusing opportunities.\n\n") parts.append("| Aggregate | Consumers | Total branches | Effective codepaths | Field efficiency |\n") parts.append("|---|---|---|---|---|\n") - from src.code_path_audit_ssdl import compute_effective_codepaths, count_branches_in_function, compute_field_access_efficiency + from code_path_audit_ssdl import compute_effective_codepaths, count_branches_in_function, compute_field_access_efficiency for p in sorted(real_profiles, key=lambda p: -compute_effective_codepaths(p, "src")): ec = compute_effective_codepaths(p, "src") tc = sum(count_branches_in_function(f, "src") for f in p.consumers) @@ -203,7 +205,7 @@ Each aggregate has its full 15-section profile in `aggregates/.md`. This s parts.append("Cross-aggregate view of codebase organization.\n\n") parts.append("| Aggregate | Verdict | Notes |\n") parts.append("|---|---|---|\n") - from src.code_path_audit_ssdl import detect_nil_check_pattern + from code_path_audit_ssdl import detect_nil_check_pattern for p in real_profiles: ec = compute_effective_codepaths(p, "src") eff = compute_field_access_efficiency(p) * 100 @@ -267,7 +269,7 @@ Each aggregate has its full 15-section profile in `aggregates/.md`. This s parts.append("uv run python scripts/audit_main_thread_imports.py --json > tests/artifacts/audit_inputs/audit_main_thread_imports.json\n") parts.append("uv run python scripts/generate_type_registry.py --json > tests/artifacts/audit_inputs/type_registry.json\n\n") parts.append("# Run the v2 audit\n") - parts.append("uv run python -c \"from src.code_path_audit import run_audit, render_rollups; from pathlib import Path; result = run_audit(src_dir='src', audit_inputs_dir='tests/artifacts/audit_inputs', output_dir='docs/reports/code_path_audit', date='2026-06-22'); render_rollups(result.data, Path('docs/reports/code_path_audit/2026-06-22'))\"\n\n") + parts.append("uv run python -c \"import sys; sys.path.insert(0, 'scripts/code_path_audit'); from code_path_audit import run_audit, render_rollups; from pathlib import Path; result = run_audit(src_dir='src', audit_inputs_dir='tests/artifacts/audit_inputs', output_dir='docs/reports/code_path_audit', date='2026-06-22'); render_rollups(result.data, Path('docs/reports/code_path_audit/2026-06-22'))\"\n\n") parts.append("# Run the meta-audit\n") parts.append("uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/2026-06-22/ --strict\n\n") parts.append("# Run the tests\n") diff --git a/src/code_path_audit_render.py b/scripts/code_path_audit/code_path_audit_render.py similarity index 98% rename from src/code_path_audit_render.py rename to scripts/code_path_audit/code_path_audit_render.py index c7e7c36c..b67a1444 100644 --- a/src/code_path_audit_render.py +++ b/scripts/code_path_audit/code_path_audit_render.py @@ -5,12 +5,15 @@ struct shape, frequency per function, and concrete optimization candidates. Designed for 2k+ line audit reports. """ from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) from collections import Counter -from src.code_path_audit import ( +from code_path_audit import ( AggregateProfile, FunctionRef, ) -from src.code_path_audit_ssdl import render_ssdl_sketch +from code_path_audit_ssdl import render_ssdl_sketch def render_full_markdown(profile: AggregateProfile) -> str: diff --git a/src/code_path_audit_rollups.py b/scripts/code_path_audit/code_path_audit_rollups.py similarity index 98% rename from src/code_path_audit_rollups.py rename to scripts/code_path_audit/code_path_audit_rollups.py index 0553e3ef..0df57555 100644 --- a/src/code_path_audit_rollups.py +++ b/scripts/code_path_audit/code_path_audit_rollups.py @@ -1,6 +1,9 @@ """Additional rollups for code_path_audit v2.""" from __future__ import annotations -from src.code_path_audit import AggregateProfile +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) +from code_path_audit import AggregateProfile def render_decomposition_matrix_rich(profiles): diff --git a/src/code_path_audit_ssdl.py b/scripts/code_path_audit/code_path_audit_ssdl.py similarity index 99% rename from src/code_path_audit_ssdl.py rename to scripts/code_path_audit/code_path_audit_ssdl.py index 37368bdc..b482543c 100644 --- a/src/code_path_audit_ssdl.py +++ b/scripts/code_path_audit/code_path_audit_ssdl.py @@ -9,9 +9,11 @@ organization: not just "this is a fat struct" but "this branch explosion can be defused by introducing a nil sentinel here". """ from __future__ import annotations -import ast +import sys from pathlib import Path -from src.code_path_audit import ( +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "src")) +import ast +from code_path_audit import ( AggregateProfile, FunctionRef, ) diff --git a/scripts/tier2/artifacts/code_path_audit_20260607/_gen_report2.py b/scripts/tier2/artifacts/code_path_audit_20260607/_gen_report2.py index b4c29eed..3eaf2a47 100644 --- a/scripts/tier2/artifacts/code_path_audit_20260607/_gen_report2.py +++ b/scripts/tier2/artifacts/code_path_audit_20260607/_gen_report2.py @@ -404,7 +404,7 @@ uv run python scripts/audit_main_thread_imports.py --json > tests/artifacts/audi uv run python scripts/generate_type_registry.py --json > tests/artifacts/audit_inputs/type_registry.json # Run the v2 audit -uv run python -c "from src.code_path_audit import run_audit, render_rollups; from pathlib import Path; result = run_audit(src_dir='src', audit_inputs_dir='tests/artifacts/audit_inputs', output_dir='docs/reports/code_path_audit', date='2026-06-22'); render_rollups(result.data, Path('docs/reports/code_path_audit/2026-06-22'))" +uv run python -c "import sys; sys.path.insert(0, 'scripts/code_path_audit'); from code_path_audit import run_audit, render_rollups; from pathlib import Path; result = run_audit(src_dir='src', audit_inputs_dir='tests/artifacts/audit_inputs', output_dir='docs/reports/code_path_audit', date='2026-06-22'); render_rollups(result.data, Path('docs/reports/code_path_audit/2026-06-22'))" # Run the meta-audit uv run python scripts/audit_code_path_audit_coverage.py --input-dir docs/reports/code_path_audit/2026-06-22/ --strict diff --git a/scripts/tier2/artifacts/code_path_audit_20260607/_generate_audit_report.py b/scripts/tier2/artifacts/code_path_audit_20260607/_generate_audit_report.py index 95732506..2b3b520c 100644 --- a/scripts/tier2/artifacts/code_path_audit_20260607/_generate_audit_report.py +++ b/scripts/tier2/artifacts/code_path_audit_20260607/_generate_audit_report.py @@ -605,7 +605,7 @@ code("uv run python scripts/generate_type_registry.py --json > tests/artifacts/a code("") code("# Run the v2 audit") code("uv run python -c \"") -code("from src.code_path_audit import run_audit, render_rollups") +code("import sys; sys.path.insert(0, 'scripts/code_path_audit'); from code_path_audit import run_audit, render_rollups") code("from pathlib import Path") code("result = run_audit(src_dir='src', audit_inputs_dir='tests/artifacts/audit_inputs', output_dir='docs/reports/code_path_audit', date='2026-06-22')") code("render_rollups(result.data, Path('docs/reports/code_path_audit/2026-06-22'))") diff --git a/scripts/tier2/artifacts/code_path_audit_phase_2_20260624/measure_codepaths.py b/scripts/tier2/artifacts/code_path_audit_phase_2_20260624/measure_codepaths.py index 02f7eca3..6139e40d 100644 --- a/scripts/tier2/artifacts/code_path_audit_phase_2_20260624/measure_codepaths.py +++ b/scripts/tier2/artifacts/code_path_audit_phase_2_20260624/measure_codepaths.py @@ -1,7 +1,9 @@ import sys -sys.path.insert(0, ".") -from src.code_path_audit import build_pcg -from src.code_path_audit_ssdl import compute_effective_codepaths, count_branches_in_function +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "scripts" / "code_path_audit")) +from code_path_audit import build_pcg +from code_path_audit_ssdl import compute_effective_codepaths, count_branches_in_function pcg_result = build_pcg("src") pcg = pcg_result.data diff --git a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/find_nil_funcs.py b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/find_nil_funcs.py index bdf2b290..9bab450d 100644 --- a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/find_nil_funcs.py +++ b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/find_nil_funcs.py @@ -1,7 +1,9 @@ import sys -sys.path.insert(0, ".") -from src.code_path_audit_ssdl import detect_nil_check_pattern -from src.code_path_audit import build_pcg +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "scripts" / "code_path_audit")) +from code_path_audit_ssdl import detect_nil_check_pattern +from code_path_audit import build_pcg r = build_pcg("src") pcg = r.data diff --git a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc2_check.py b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc2_check.py index f07ed0fb..82290971 100644 --- a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc2_check.py +++ b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc2_check.py @@ -1,7 +1,9 @@ import sys -sys.path.insert(0, ".") -from src.code_path_audit_ssdl import detect_nil_check_pattern -from src.code_path_audit import FunctionRef +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "scripts" / "code_path_audit")) +from code_path_audit_ssdl import detect_nil_check_pattern +from code_path_audit import FunctionRef fref = FunctionRef( fqname="src.aggregate._build_files_section_from_items", diff --git a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc4_budget_gate.py b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc4_budget_gate.py index d00e3935..37e34ff0 100644 --- a/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc4_budget_gate.py +++ b/scripts/tier2/artifacts/metadata_nil_sentinel_20260624/vc4_budget_gate.py @@ -1,19 +1,21 @@ import sys -sys.path.insert(0, ".") -from src.code_path_audit_ssdl import compute_effective_codepaths -from src.code_path_audit import build_pcg, FunctionRef -from src.code_path_audit_analysis import aggregate_pattern_from_consumers -from src.code_path_audit_cross_audit import ( +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "scripts" / "code_path_audit")) +from code_path_audit_ssdl import compute_effective_codepaths +from code_path_audit import build_pcg, FunctionRef +from code_path_audit_analysis import aggregate_pattern_from_consumers +from code_path_audit_cross_audit import ( aggregate_findings, build_cross_audit_findings_for_aggregate, ) -from src.code_path_audit_analysis import ( +from code_path_audit_analysis import ( compute_real_type_alias_coverage, compute_real_decomposition_cost, extract_real_optimization_candidates, ) -from src.code_path_audit import AggregateProfile, ResultCoverage, TypeAliasCoverage, CrossAuditFindings, DecompositionCost, FrequencyEvidence -from src.code_path_audit import classify_memory_dim +from code_path_audit import AggregateProfile, ResultCoverage, TypeAliasCoverage, CrossAuditFindings, DecompositionCost, FrequencyEvidence +from code_path_audit import classify_memory_dim pcg_result = build_pcg("src") pcg = pcg_result.data diff --git a/tests/test_code_path_audit.py b/tests/test_code_path_audit.py index eeca7efb..bdf56d90 100644 --- a/tests/test_code_path_audit.py +++ b/tests/test_code_path_audit.py @@ -1,12 +1,14 @@ """Tests for src.code_path_audit v2 - Phase 1 (data model).""" from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit")) import ast import textwrap import tempfile -from pathlib import Path from collections import Counter import pytest -from src.code_path_audit import ( +from code_path_audit import ( AggregateKind, MemoryDim, AccessPattern, diff --git a/tests/test_code_path_audit_integration.py b/tests/test_code_path_audit_integration.py index c40f5ccd..904777ab 100644 --- a/tests/test_code_path_audit_integration.py +++ b/tests/test_code_path_audit_integration.py @@ -1,8 +1,10 @@ """Integration tests for src.code_path_audit v2.""" from __future__ import annotations -import tempfile +import sys from pathlib import Path -from src.code_path_audit import ( +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit")) +import tempfile +from code_path_audit import ( run_audit, render_rollups, ) diff --git a/tests/test_code_path_audit_phase78.py b/tests/test_code_path_audit_phase78.py index daf93df0..bf069235 100644 --- a/tests/test_code_path_audit_phase78.py +++ b/tests/test_code_path_audit_phase78.py @@ -1,13 +1,15 @@ """Tests for src.code_path_audit v2 - cross-audit integration + DSL.""" from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit")) import ast import textwrap import tempfile import json -from pathlib import Path from collections import Counter import pytest -from src.code_path_audit import ( +from code_path_audit import ( AggregateKind, MemoryDim, AccessPattern, diff --git a/tests/test_code_path_audit_phase89.py b/tests/test_code_path_audit_phase89.py index 96d70f82..dcb9da6a 100644 --- a/tests/test_code_path_audit_phase89.py +++ b/tests/test_code_path_audit_phase89.py @@ -1,12 +1,13 @@ """Tests for src.code_path_audit v2 - DSL renderers + run_audit + CLI + MCP.""" from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit")) import ast import tempfile -from pathlib import Path import subprocess -import sys from datetime import date -from src.code_path_audit import ( +from code_path_audit import ( AggregateKind, MemoryDim, AccessPattern, diff --git a/tests/test_code_path_audit_ssdl_behavioral.py b/tests/test_code_path_audit_ssdl_behavioral.py index 1558d9ba..df91368d 100644 --- a/tests/test_code_path_audit_ssdl_behavioral.py +++ b/tests/test_code_path_audit_ssdl_behavioral.py @@ -6,8 +6,11 @@ synthetic fixture so future refactors cannot silently change the formula. CONVENTION: 1-space indentation. NO COMMENTS. """ from __future__ import annotations +import sys +from pathlib import Path +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts" / "code_path_audit")) -from src.code_path_audit import ( +from code_path_audit import ( AggregateProfile, CrossAuditFindings, DecompositionCost, @@ -17,7 +20,7 @@ from src.code_path_audit import ( ResultCoverage, TypeAliasCoverage, ) -from src.code_path_audit_ssdl import compute_effective_codepaths +from code_path_audit_ssdl import compute_effective_codepaths FIXTURE_FILE = "sample_module.py" diff --git a/tests/test_metadata_nil_sentinel.py b/tests/test_metadata_nil_sentinel.py index 0c82d815..f39c5f98 100644 --- a/tests/test_metadata_nil_sentinel.py +++ b/tests/test_metadata_nil_sentinel.py @@ -12,8 +12,9 @@ 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 src.code_path_audit_ssdl import detect_nil_check_pattern +from code_path_audit_ssdl import detect_nil_check_pattern def test_nil_metadata_is_defined() -> None: @@ -40,8 +41,8 @@ def test_sentinel_pattern_works() -> None: def test_migration_reduces_nil_check_count() -> None: - from src.code_path_audit import build_pcg - from src.code_path_audit_ssdl import detect_nil_check_pattern + 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"} @@ -53,7 +54,7 @@ def test_migration_reduces_nil_check_count() -> None: def test_detect_nil_check_pattern_works_for_migrated_function() -> None: - from src.code_path_audit import FunctionRef + 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")