Skip to content

canonical: 3 duplicated code-analysis analyzers (performance/anti_pattern/security) + diverged PerformanceIssue type — NOT a whole-tree fork #12362

Description

@mrveiss

Summary

The code-analysis domain exists as two parallel package trees with independent, live implementations of the same analyzers. code_intelligence/ is the modern tree (produced by the #381 god-class refactor); code_analysis/src/ is the older fat implementation. The refactor built the clean tree but never migrated the old consumers off, so both are in production simultaneously — an unfinished rename that has since diverged.

This is the "one concept, two implementations" canonical violation, and it is systematic across at least three analyzers, not a one-off.

The duplication

At the top level of code_intelligence/ sit thin facades that re-export from code_intelligence's own modern subtrees — not from code_analysis:

concept code_analysis/src/ (old, fat) code_intelligence/ facade re-exports from
performance_analyzer 740 lines code_intelligence.performance_analysis
anti_pattern_detector 2,320 lines code_intelligence.anti_pattern_detection
security_analyzer 861 lines code_intelligence.security

So each concept has two full implementations — the old one in code_analysis/src/ (~3,921 lines across the three) and a separate modern one under code_intelligence/*/. The facades make the modern side look consolidated while the old side keeps running underneath.

Both sides have live consumers — including API code

code_analysis/src/performance_analyzer  <- code_analysis/scripts/analyze_performance.py
                                           code_analysis/src/code_quality_dashboard.py
code_analysis/src/anti_pattern_detector <- api/codebase_analytics/cross_file_analysis.py   ← API path uses the OLD tree
                                           code_analysis/src/remediation_loop.py
code_analysis/src/security_analyzer     <- code_analysis/src/code_quality_dashboard.py

code_intelligence/performance_analysis  <- api/code_intelligence.py                         ← API path uses the NEW tree

So two different API modules analyse the same codebase through two different analyzer implementations. Which analyzer runs depends purely on which import path the endpoint happened to be written against.

The two implementations have already diverged

The shared output type, PerformanceIssue, is structurally incompatible between the trees:

# code_analysis/src/performance_analyzer.py:27      # code_intelligence/performance_analysis/types.py:87
class PerformanceIssue:                              class PerformanceIssue:
    file_path: str                                      issue_type: PerformanceIssueType   # enum, not str
    line_number: int                                    severity: PerformanceSeverity      # enum, not str
    function_name: str | None                           file_path: str
    issue_type: str    # "memory_leak", ...             line_start: int                    # vs line_number
    severity: str      # "critical", ...                line_end: int
    code_snippet: str                                   recommendation: str                # new field, absent in old

One is stringly-typed with line_number; the other uses enums with line_start/line_end and adds recommendation. Any code that consumes "a PerformanceIssue" gets a different shape depending on which analyzer produced it — the exact failure the single-source rule exists to prevent. The anti-pattern and security analyzers, being independent 2,320- and 861-line bodies, carry the same divergence risk in their detection rules: the two trees can flag different issues on identical code, and neither is authoritative.

Why this matters beyond tidiness

  • Inconsistent results. The two analytics surfaces can disagree about the same repository, and there is no defined winner — directly relevant to the "some analytics data looks off / work-in-progress" observations elsewhere.
  • Double maintenance. A rule fix or false-positive suppression must be made twice or it silently regresses on one surface.
  • ~3,900 lines of parallel logic to keep in sync by hand, with no test asserting the two produce equivalent output (they can't — the types differ).

Recommendation (architecture decision — needs owner sign-off)

Per the canonical rule for "two implementations already exist": pick the canonical tree, migrate every consumer to it, and reduce the other to a re-export shim or delete it — do not add a third.

  1. Declare code_intelligence/ canonical (it is the post-refactor tree, is enum-typed, and already backs the primary API). Confirm with whoever owns code-analysis.
  2. Migrate the remaining code_analysis/src/ consumers — api/codebase_analytics/cross_file_analysis.py, code_quality_dashboard.py, remediation_loop.py, scripts/analyze_performance.py — onto the code_intelligence implementations and its PerformanceIssue type.
  3. Reduce code_analysis/src/{performance_analyzer,anti_pattern_detector,security_analyzer}.py to re-export shims, then delete once no importer remains.
  4. Record the consolidation as an ADR; this is a module-boundary decision, not a mechanical cleanup.

This is a discovery issue — filing per the marketing-session rule (expose, do not fix). The migration itself is an implementation task for a later session and should not proceed without the canonical-tree decision in step 1.

Secondary observation (lower confidence)

RateLimiter is independently reimplemented in four places with different algorithms — services/gateway/message_queue.py (token bucket, per-platform), agents/web_researcher.py (sliding window), security/threat_intelligence.py (requests-per-minute), api/secrets.py ("simple in-memory"). These may be a legitimate case where "duplication is cheaper than the wrong abstraction" — the algorithms genuinely differ — so this is flagged for a judgement call, not asserted as a fork. Worth a look when someone touches rate limiting; not necessarily worth unifying.

Environment

install.sh deploy at /opt/autobot; deployed tree matches origin/Dev_new_gui. Line counts and imports from the deployed backend source.

Activity

  1. changed the title [-]canonical: code-analysis forked across two trees — code_analysis/src (old) and code_intelligence (post-#381) both live with API consumers each; PerformanceIssue type has diverged (str vs enum, line_number vs line_start/end)[/-] [+]canonical: 3 duplicated code-analysis analyzers (performance/anti_pattern/security) + diverged PerformanceIssue type — NOT a whole-tree fork[/+] on Jul 26, 2026
  2. mrveiss commented on Jul 26, 2026

    @mrveiss
    OwnerAuthor

    Reframed after evidence audit (the original 'two forked trees' premise is wrong). code_analysis/src/ and code_intelligence/ are NOT duplicates — they serve different scopes: code_analysis/src/ is project/cross-file (ownership, architectural-pattern, quality-dashboard, remediation-loop, coverage) while code_intelligence/ is per-artifact intelligence (bug_predictor, evolution_miner, review_engine, doc_generator, ts/vue/shell analyzers). Merging the trees would be wrong.

    Actual overlap = only 3 analyzers by name: performance / anti_pattern / security. code_intelligence/performance_analyzer.py is already a back-compat facade re-exporting code_intelligence.performance_analysis; code_analysis/src/performance_analyzer.py is the old impl with a diverged PerformanceIssue type (line_number:int/issue_type:str vs the modern enum PerformanceIssueType + line_start/line_end). Both have live API consumers.

    Narrowed decision: pick the canonical impl for those 3 analyzers (recommend the modern code_intelligence/* subpackages) and migrate the old consumers (api/anti_pattern.py, api/codebase_analytics/cross_file_analysis.py, endpoints/ownership.py); do NOT merge the trees.

  3. mrveiss commented on Jul 26, 2026

    @mrveiss
    OwnerAuthor

    Resolved by #12588 (merged): performance + security analyzers migrated to the canonical code_intelligence impls via thin, exhaustively-tested adapters (legacy dataclass shapes preserved, no code deleted). anti_pattern was NOT migrated — investigation found code_analysis/src.anti_pattern_detector is already the established canonical there (cross-file rules the per-file code_intelligence pkg can't do), so migrating would have lost capability. Also fixed 3 pre-existing bugs (conftest not real-loading performance_analyzer → 25 MagicMock tests; unreachable SYNC_IN_ASYNC finding; unemitted enum members). 415+193 tests pass. Follow-ups: #12586 (systemic conftest-stub, 10 files), #12587 (4 legacy security categories with no canonical detector).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions