Skip to main content

Code Quality Analyzer

Prove the health of a codebase without a single byte leaving the machine.

Code Quality Analyzer is a privacy-first static analysis tool for Python packages, with bounded Go, TypeScript/JavaScript, Java, Kotlin, and C#/.NET pilots, built for environments where source code cannot leave the trusted development boundary: regulated industries, air-gapped networks, client codebases under NDA, and anyone who refuses to ship their source to a SaaS dashboard to learn whether it is healthy.

The privacy contract

Most quality platforms want your code on their servers. This tool inverts that: analysis is local-only by design, and the guarantees are enforced, not promised.

  • No network, provably. Analysis has no network-backed integration, and --offline enforces it at runtime by denying socket and name-resolution operations while analysis runs — an accidental future network call fails the command instead of silently connecting.
  • Anonymized reports for untrusted destinations. --anonymize replaces project, file, and function identities with opaque report-local tokens and strips source-derived evidence, so a report can leave the machine while the code's identity does not.
  • Baselines are hashes, not source. CI baseline files contain only schema metadata and SHA-256 fingerprints — no paths, messages, identifiers, or snippets.
  • No shell, no Git, no execution. The analyzer never invokes Git or a shell, and package intelligence never imports, builds, or executes project code. Changed-line manifests are supplied externally.
  • Honest results, enforced. Every report carries analysis_health and an authority verdict; incomplete analysis cannot silently pass as a green build (--strict makes it fail).

See docs/PRIVACY.md for the exact data boundary.

What it detects

  • Actionable correctness, maintainability, duplication, and package findings with stable rule IDs, severities, remediation, and normalized locations — including cross-file duplicate function implementations (PY-DUP-001) detected by exact AST structure, so renamed copies still report and docstring changes cannot hide one
  • Data Structures & Algorithms (DSA) patterns in Python, Go, TypeScript/JavaScript, Java, Kotlin, and C#
  • System Design principles implemented in Python, Go, TypeScript/JavaScript, Java, Kotlin, and C#
  • A compatibility architecture signal score from 1-10

Reports render as text, versioned JSON, or SARIF 2.1.0, and gate CI through baselines, changed-line selection, and severity thresholds — all under the same privacy contract.

Architecture Signal Score Scale

Score Architecture-signal breadth
1-2 Very few recognized DSA or design signals
3-4 A small set of recognized signals
5-6 Moderate signal breadth
7-8 Broad signal coverage across multiple files
9-10 Very broad recognized DSA and design signals

Architecture signal scores from 2.x are not comparable to 1.x ratings. Detection got stricter and project size no longer adds score, so most projects will score lower than they did before. Scores under scoring policy 2.0.0 (analyzer 2.32.0+) are likewise not comparable to policy 1.0.0: the catalog grew from 38 to 56 patterns to cover production-systems engineering, and the rating curves were rescaled. Every JSON report carries scoring_policy_version. See Scoring and docs/adr/002-scoring-policy-2-production-systems-catalog.md.

Project Structure

code-quality-analyzer/
├── cqa_analyzer/
│   ├── __init__.py
│   ├── __main__.py      # CLI entry point
│   ├── baseline.py      # Hashed finding baselines and comparison
│   ├── cache.py         # Bounded local parse-artifact cache
│   ├── changed_lines.py # Bounded changed-line finding selection
│   ├── config.py        # Bounded configuration, path, and rule policy
│   ├── discovery.py     # Safe file discovery (limits, symlink guard)
│   ├── duplication.py   # Cross-file duplicate function detection
│   ├── findings.py      # Language-neutral actionable finding model
│   ├── signals.py       # Per-file signal extraction + pattern matching
│   ├── python_rules.py  # Source-located Python correctness rules
│   ├── patterns.py      # DSA & System Design pattern definitions
│   ├── go_patterns.py   # Go-idiom signal definitions for the shared catalog
│   ├── ts_patterns.py   # TypeScript/JavaScript signal definitions
│   ├── java_patterns.py # Java signal definitions
│   ├── kotlin_patterns.py # Kotlin signal definitions (extends Java)
│   ├── production_patterns.py # Shared production-systems and GoF specs
│   ├── csharp_patterns.py # C#/.NET signal definitions
│   ├── manifests.py     # Shared nested-manifest discovery and hardened XML
│   ├── package_intelligence.py # Metadata, modules, imports, cycles
│   ├── protocols.py     # Source, parse, rule, provider, and reporter contracts
│   ├── registry.py      # Versioned plugin and capability negotiation registry
│   ├── plugins.py       # Built-in plugin assembly
│   ├── reporters.py     # Registered text, JSON, and SARIF renderers
│   ├── rule_metadata.py # Stable built-in rule catalog for standard reports
│   ├── languages/       # Built-in language adapters and rule packs
│   ├── scanner.py       # Language-neutral orchestration through plugins
│   ├── complexity.py    # Time/space complexity analyzer
│   └── rater.py         # Rating calculator (1-10)
├── tests/               # Regression tests
├── docs/                # Rule, workflow, and privacy guidance
├── .pre-commit-hooks.yaml # Published local-analysis hook contract
├── LICENSE
├── SECURITY.md
├── CHANGELOG.md
├── MANIFEST.in
├── pyproject.toml
├── README.md
└── .gitignore

Installation

Install from PyPI. Two names matter, and mixing them up is the most common first-run mistake:

What Name
PyPI distribution (pip install …) cqa-analyzer
Installed command code-quality-analyzer
Python module (python -m …) cqa_analyzer

code-quality-analyzer on PyPI is an unrelated project — installing it will not give you this tool.

Requirements: Python 3.11 or newer (python3 --version).

Recommended: pipx (isolated, always on PATH)

pipx install cqa-analyzer
code-quality-analyzer --version

pipx keeps the tool in its own environment and puts the command on your PATH regardless of which Python your shell or a version manager (mise, pyenv, asdf) resolves in a given directory. Install pipx with brew install pipx && pipx ensurepath (macOS) or your platform's package manager, then restart the shell.

Alternative: pip into a specific interpreter

Always install through the interpreter you will run, so the install and the invocation cannot target different Pythons:

python3 -m pip install cqa-analyzer
python3 -m cqa_analyzer --version

Inside a virtual environment, the command lives in that environment's bin/ directory: .venv/bin/code-quality-analyzer /path/to/project.

Verify

code-quality-analyzer --version   # code-quality-analyzer, version X.Y.Z
code-quality-analyzer /path/to/project

Troubleshooting

zsh: command not found: code-quality-analyzer — the shell cannot find the console script. Confirm the package is installed at all with python3 -m cqa_analyzer --version; if that works, only PATH is missing. pip drops scripts next to the interpreter that installed them (for example ~/.local/share/mise/installs/python/3.12.x/bin/ or ~/Library/Python/3.x/bin/ on macOS), and that directory may not be on PATH. Either add it to your shell profile, run pipx ensurepath if you used pipx, or use python3 -m cqa_analyzer instead of the command.

No module named cqa_analyzer — the package is installed in a different Python than the one you are running. This is common with version managers such as mise or pyenv, where python3 changes per directory. Reinstall through the exact interpreter: python3 -m pip install cqa-analyzer. To stop this recurring, use pipx.

No matching distribution found for cqa-analyzer — your Python is older than 3.11. Check python3 --version and install a newer Python (for example brew install python@3.12). Python 3.10 users can pin cqa-analyzer==2.29.0, the last release supporting 3.10.

error: externally-managed-environment — a system or Homebrew Python is refusing a bare pip install (PEP 668). Use pipx or a virtual environment; do not override the protection with --break-system-packages.

Installed but analyzing the wrong thingPROJECT_PATH must be a directory; pointing at a single file is rejected. Generated output such as node_modules, .next, dist, and .venv is excluded automatically.

Releases are published through PyPI Trusted Publishing with digital attestations, so every artifact is provably built from this repository's tagged source by CI — no maintainer-held upload token exists.

To work on the analyzer itself, install from a source checkout:

cd code-quality-analyzer
python3 -m venv .venv
.venv/bin/pip install -e .

Pre-commit

Pin a released tag in .pre-commit-config.yaml:

repos:
  - repo: https://github.com/AmitSinghOM/code-quality-analyzer
    rev: v2.29.0
    hooks:
      - id: code-quality-analyzer

The built-in hook runs one serial full-repository analysis as code-quality-analyzer . --offline; it does not pass staged filenames because the CLI accepts a directory. Findings are advisory by default. Add args: [--fail-on, error], or baseline/new-only arguments, when the project is ready to gate commits.

The analyzer invocation remains local-only. Pre-commit itself may need network access once to clone the pinned release and create its environment. See docs/PRE_COMMIT.md for trigger paths, strict and baseline profiles, and the installation privacy boundary.

Usage

# Analyze a project
code-quality-analyzer /path/to/project

# Show which signals triggered each match
code-quality-analyzer /path/to/project -v

# Output as JSON
code-quality-analyzer /path/to/project -f json

# Output normalized findings as SARIF 2.1.0
code-quality-analyzer /path/to/project -f sarif > results.sarif

# Select findings that overlap an externally generated line manifest
code-quality-analyzer /path/to/project \
  --changed-lines-manifest changed-lines.json

# Include time/space complexity analysis
code-quality-analyzer /path/to/project -c

PROJECT_PATH must be a directory. Pointing at a single file is rejected rather than silently returning an architecture signal score of 1.

Project configuration

Place .code-quality.toml in the analyzed project root to define deterministic source and rule policy:

[analysis]
include = ["src/**/*.py", "cmd/**/*.go"]
exclude = ["src/generated/**"]
respect_gitignore = true

[rules."PY-COR-001"]
enabled = true
severity = "error"

Filters are project-relative, exclusion wins, and filtered files do not consume candidate or file-limit accounting. The root .gitignore is respected by default. Python findings can be suppressed on their reported line only with an explicit rule ID and nonempty quoted reason, for example # cqa: ignore=PY-COR-001 reason="legacy API". Suppression reasons never enter reports or baselines. JSON reports identify the validated effective policy with a privacy-safe configuration_fingerprint.

See docs/CONFIGURATION.md for glob semantics, validation limits, rule policy, suppressions, and compatibility boundaries.

Incremental parse cache

Caching is explicit so analysis never writes source-derived state unless a location is selected:

code-quality-analyzer . \
  --cache-dir ~/.cache/code-quality-analyzer/my-project \
  --offline

The bounded JSON cache stores only Python/Go parse artifacts. Rules, package providers, policy, scoring, baselines, changed-line selection, reports, and gates rerun on every analysis. Content, project-relative path, adapter, codec, plugin API, and runtime identities participate in cache keys, so changed or renamed files miss safely. Corrupt, stale, oversized, or incompatible entries also become misses; cache state never reduces analysis authority.

Cache artifacts contain source-derived data and must be protected like source. Reports expose only whether caching was enabled, never its path, keys, digests, hit counts, or errors. See docs/CACHING.md for invalidation, security bounds, warm/cold determinism, and lifecycle guidance.

Privacy and offline options

Use --anonymize when a report may leave the trusted development environment:

code-quality-analyzer /path/to/project --anonymize -f json
code-quality-analyzer /path/to/project --anonymize -f sarif > results.sarif
code-quality-analyzer /path/to/project --anonymize --offline -v -c

Anonymized reports replace project, file, and function identities with opaque report-local tokens; remove package/module/dependency/script names; replace finding messages and remediation; reduce package intelligence to aggregate counts; and remove source-derived pattern signals and complexity reasoning. Rule IDs, locations, counts, scores, pattern names, complexity classes, and line numbers remain so the report is still useful.

--offline adds runtime enforcement by denying socket connection and name-resolution operations while analysis runs. Normal analysis is already local and has no network-backed integration; this option makes an accidental future network call fail the command instead of silently connecting.

See docs/PRIVACY.md for the exact data boundary and remaining disclosure considerations.

Options

Option Default Purpose
--version Print the analyzer version and exit
-v, --verbose off Include matched files and evidence; JSON omits evidence unless enabled
-f, --output-format text text, versioned json, or SARIF 2.1.0
-c, --complexity off Add experimental time/space complexity estimates
--max-file-size 2 MB Skip files larger than this positive byte count
--max-files 20000 Stop after this positive number of registered source files
--redact-paths off Report file names only, no directory structure
--anonymize off Remove project paths, metadata, and source identifiers
--offline off Deny socket operations while analysis runs
--cache-dir none Reuse bounded local parse artifacts from this directory
--fail-under none Exit non-zero when the compatibility architecture signal score is below 1–10; exits 5 when the score is not applicable
--fail-on none Exit 4 for reported findings at warning or error severity
--baseline none Compare findings with an existing hashed baseline
--write-baseline none Atomically write current finding fingerprints
--new-findings-only off Report and gate only findings absent from --baseline
--changed-lines-manifest none Report and gate findings overlapping a bounded line manifest
--strict off Exit non-zero when any requested analysis is incomplete

--anonymize is stronger than --redact-paths and takes precedence for report presentation. Baseline fingerprints continue to use hidden project-relative identities, so changing either presentation option does not change CI identity.

-f was --format in 1.x. It is now --output-format so it no longer shadows the format builtin. JSON reports include schema, analyzer, and ruleset versions plus explicit privacy state, scoring-policy version, effective-configuration fingerprint, and analysis authority so consumers can identify the contract, protections, and completeness that produced a result. SARIF emits the same baseline- and changed-line-filtered findings for standard code-scanning consumers. Changed-line manifests are supplied externally; the analyzer never invokes Git or a shell to derive them. JSON schema 1.11.0 records aggregate selection metadata and whether the local parse cache was enabled; see docs/CHANGED_LINES.md, docs/CACHING.md, and docs/SARIF.md. architecture_signal_score is the primary score field; rating is a transitional equal-valued 2.x compatibility alias.

Exit Codes

Code Meaning
0 Analysis completed and any threshold was met
1 Architecture signal score below --fail-under
2 No registered-language source candidates were discovered
3 Source candidates produced no successful analysis, or --strict found incomplete analysis
4 A reported finding met the --fail-on severity threshold
5 --fail-under was set but the architecture signal score is not applicable (no signal-capable source analyzed)

Analysis Authority

Every JSON report includes analysis_health with source-candidate, readable, and successfully analyzed counts; a completeness ratio; stable reason codes; and complete/authoritative booleans. Text reports show the same qualification before the architecture signal score.

No source candidates exit with code 2. If candidates exist but none can be successfully parsed, analysis exits with code 3 even without --strict. Partial non-strict analysis may exit successfully for inspection, but it is always marked non-authoritative. See the versioned schema in docs/report-schema-1.11.0.json and the decision record in docs/adr/001-analysis-authority-and-score-migration.md.

Use in CI

Create a baseline once after reviewing existing findings:

code-quality-analyzer . --write-baseline .code-quality-baseline.json

Then gate only newly introduced warning-or-higher findings:

code-quality-analyzer . \
  --baseline .code-quality-baseline.json \
  --new-findings-only \
  --changed-lines-manifest changed-lines.json \
  --fail-on warning \
  --strict \
  -f sarif > code-quality-results.sarif

The changed-lines manifest is generated by an external CI step. The analyzer never invokes Git, and it continues to scan the full project for authority and strict-mode decisions. Baseline filtering runs before changed-line selection; see docs/CHANGED_LINES.md.

The SARIF artifact is emitted before the gate exit code and contains the same selected findings used by --fail-on. See docs/SARIF.md for the deterministic ordering, URI, metadata, and privacy contract.

Baseline files contain only schema metadata and SHA-256 fingerprints. They do not contain source paths, messages, identifiers, snippets, or report evidence. Baseline writes are atomic, malformed or oversized baselines are rejected, and fingerprints remain stable when --redact-paths changes report presentation. See docs/BASELINES.md for workflow and review guidance.

--fail-under remains available as an architecture-signal compatibility ratchet, but actionable finding gates are more explicit. Treat the score as usable only when analysis_health.authoritative is true. --strict fails when files cannot be read or parsed, discovery is truncated, package metadata is invalid, or requested complexity analysis has a coverage gap. Incomplete analysis therefore cannot silently pass as a green build.

See .github/workflows/ci.yml for a working example that also runs the test suite, lint, and a dependency vulnerability scan.

Paths

Absolute paths are never written into reports. The project is identified by its directory name, and file paths—including skipped-file examples—are reported relative to the project root. --redact-paths reduces file paths to bare names for reports shared outside your machine.

Relative paths work fine as arguments (., ../my-project)—they are resolved internally before discovery, but the resolved absolute path is not reported.

--redact-paths is path minimization, not full anonymization: findings, package metadata, identifiers, and architecture signals can remain sensitive. Review docs/PRIVACY.md before sharing reports. Security issues should follow SECURITY.md; do not attach proprietary source to vulnerability reports.


How Detection Works

Every pattern is defined by signals, all matched case-insensitively:

Signal type Matched against
identifiers An exact identifier from the AST: name, attribute, def, class, argument, import alias
identifier_contains A substring of an identifier, for naming conventions like OrderRepository
text A substring of the source with comments and string literals blanked out, for syntax like dp[ or @app.route
imports A substring of an imported module path

Two rules keep the noise down:

Literals and comments are not evidence. A docstring saying "we should use Dijkstra here" no longer reports a shortest-path algorithm. Comments and string literals are blanked out before any text matching, with layout preserved so positional patterns still match.

Bare words match identifiers, not raw text. pop matches items.pop() but not population.

Each pattern declares min_signals — how many distinct signals a file must provide before the pattern is reported. Specific patterns like heappush need one. Generic ones need corroboration: a lone visited is not a graph traversal, and OrderedDict on its own is not an LRU cache.

Run with -v to see exactly which signals fired, so a false positive is reviewable rather than mysterious.

Signals are per file

Imports are collected per file. In 1.x the import set accumulated across the whole project, so a single import heapq anywhere made every file scanned afterwards look like it used heaps — and because results depended on directory walk order, renaming a file could change the rating.

Scoring

rating = dsa_score × 0.4 + design_score × 0.5 + maturity_score × 0.1

Breadth discount. A pattern found in one file counts for 60% of its weight; two files 80%; four or more, full weight. One incidental use is weaker evidence than a habit.

Size is not quality. The 1.x "complexity bonus" grew with file count and line count, so padding a codebase raised its rating. Size now only gates how much of the maturity_score component is reachable, saturating at 2000 lines. Past that, more code adds nothing.

Coverage gaps lower the score. If more than 10% of discovered files could not be read or parsed, the rating is scaled down and reported as a lower bound with an explicit warning.

Scoring policy 2.0.0. The DSA and design curves map total matched pattern weight to a 1–10 score. When the catalog grew to 56 patterns, the curve ceilings were scaled ×1.2 (DSA) and ×1.5 (design) and the maturity breadth target rose from 20 to 28 distinct patterns — partial rather than proportional scaling, because the added production-systems patterns are rarer than the originals. Re-derive any --fail-under threshold once after upgrading.

Scan Safety

File reads go through cqa_analyzer/discovery.py, which refuses to:

  • read a path that resolves outside the project root, so a symlink pointing at ~/.aws/credentials is skipped rather than parsed
  • read a non-regular file such as a FIFO, which would otherwise block forever
  • read a file above --max-file-size
  • walk more than --max-files paths

Skips are counted by reason and reported. Nothing is silently dropped, so a clean project is distinguishable from a project that failed to parse.

Excluded directories: .git, __pycache__, .venv, venv, env, node_modules, dist, build, site-packages, and the usual tool caches.

Actionable Findings

Actionable Python findings are separate from descriptive DSA and architecture signals. Every finding includes a stable rule ID, category, severity, confidence, message, remediation, and a one-based project-relative source location. JSON reports include both findings and an aggregate finding_summary; terminal reports show an Actionable Findings table.

The built-in Python rules detect mutable function defaults, broad exception handlers, silently swallowed exceptions, directly unreachable statements, functions above measured cyclomatic or cognitive complexity limits, oversized functions, excessive parameter lists, boolean mode proliferation, known blocking calls in async functions, locally unmanaged file/temporary resources, and cross-file duplicate function implementations. Duplication (PY-DUP-001) compares docstring-stripped bodies, parameter lists, and return annotations by exact AST structure: renamed or re-decorated copies still report, trivial functions never do, and only the outermost of nested duplicates reports. Rule enablement and severity can be configured, and valid same-line suppressions require an explicit rule ID and quoted reason. See docs/RULES.md for rule behavior and remediation examples and docs/CONFIGURATION.md for policy details.

Files are parsed once for signal extraction, actionable Python rules, package intelligence, and optional complexity analysis. Malformed files emit no semantic findings and remain visible through analysis health.

Package Intelligence

Package intelligence is passive: it does not import, build, or execute project code. Every normal scan now reports:

  • Parsed pyproject.toml name, Python requirement, build backend, dependencies, optional dependency groups, and console scripts
  • Detected src or flat package layout and source roots
  • Statically configured setuptools PEP 420 namespace modules from safe, explicit discovery roots and prefixes
  • First-party modules and their local import graph
  • Circular import groups
  • Console scripts that target missing local modules
  • Literal __all__ exports with missing bindings or duplicate names
  • Missing literal static setuptools package-data source targets

Invalid TOML produces PY-PKG-003 and makes --strict fail. Circular imports produce PY-PKG-001; invalid console-script module targets produce PY-PKG-002; missing and duplicate literal public exports produce PY-PKG-004 and PY-PKG-005. Dynamic or ambiguous __all__ declarations are conservatively skipped. Configured PEP 420 discovery accepts only setuptools metadata with namespace discovery enabled, safe project-relative where roots, and nonempty exact or prefix.* includes. Custom backends, remapping, excludes, complex globs, and ambiguous roots retain conventional discovery without executing build hooks. Literal package-data validation is limited to exact package keys and safe, non-glob paths when setuptools is the only declared build requirement and no custom setup file, backend path, command class, or package remapping is present. It checks source-tree regular-file existence with metadata operations only; wildcard declarations, generated files, and built-artifact contents remain out of scope. Test-only directories without a package initializer are excluded from unconfigured flat-layout package modules. See docs/RULES.md.

TOML parsing uses the standard-library tomllib parser; the analyzer requires Python 3.11 or newer.

Complexity Analysis

Complexity output is an experimental static estimate, not an authoritative Big-O guarantee. Use its assumptions, reasoning, and confidence to prioritize manual review; do not use inferred Big-O alone as a CI quality gate.

Use the -c flag to include time/space complexity analysis:

code-quality-analyzer /path/to/project -c
code-quality-analyzer /path/to/project -v -c  # verbose adds reasoning

Handled correctly as of 2.0:

  • async for counts as a loop. Async-heavy code used to report O(1).
  • Early exit is scoped to its own loop. A break in an inner loop no longer marks the outer loop as having an early exit. A return still does, from any depth.
  • Nested definitions are separate units. An inner function's loops no longer inflate the enclosing function's depth, and its self-calls no longer count as the parent's recursion. Each nested function is analyzed on its own.
  • Recursion inside a loop is classified as fan_out rather than linear. The branching factor is data-dependent, so it reports O(n) over visited nodes with reduced confidence instead of claiming certainty.

Confidence Score

The confidence score indicates how reliable the complexity estimate is.

Starting point: 80%

Condition Deduction Reason
Recursion without memoization -20% Hard to tell O(n) from O(2^n) without runtime analysis
Recursive call inside a loop -20% Branching factor depends on the data
Deep nesting (>2 loops) -10% Complex control flow makes static analysis less reliable
No type hints on parameters -10% Can't infer if input is a collection or its size relationship

Minimum: 30%

Interpreting confidence:

  • 80%+ → High confidence, estimate is likely accurate
  • 60-80% → Medium confidence, estimate is reasonable but verify manually
  • 30-60% → Low confidence, treat as rough estimate only

What It Detects

DSA Patterns (29 patterns)

Data Structures:

  • Hash maps (Counter, defaultdict)
  • Sets and set algebra
  • Trees (binary, general)
  • Linked lists
  • Queues and stacks (deque)
  • Heaps and priority queues
  • Trie/prefix tree
  • Segment tree
  • Fenwick/Binary Indexed Tree
  • Bloom filter

Algorithms:

  • Sorting
  • Binary search
  • Graph traversal (BFS/DFS)
  • Dynamic programming/memoization
  • Union-Find/Disjoint Set
  • Topological sort
  • Shortest path (Dijkstra/Bellman-Ford/A*)
  • Minimum spanning tree (Kruskal/Prim)
  • Backtracking

Techniques:

  • Sliding window
  • Two pointers
  • Monotonic stack
  • Interval operations
  • Manual LRU cache
  • LFU cache
  • Bit manipulation and bitmasks
  • Prefix sums
  • String matching (KMP, Rabin-Karp, Z, Aho-Corasick)
  • Consistent hashing

System Design Patterns (27 patterns)

  • API design (FastAPI, Flask, Django, Starlette)
  • Database access (ORMs and raw drivers)
  • Caching layers
  • Message queues
  • Factory, Singleton, Repository, Strategy, Observer, Adapter, Decorator, Builder patterns
  • Dependency injection
  • Error handling
  • Logging
  • Authentication/Authorization
  • Testing
  • Microservices/service clients
  • Configuration management
  • Resilience: retries with backoff, circuit breakers, bulkheads
  • Rate limiting and throttling
  • Idempotency and duplicate suppression
  • Event sourcing and CQRS
  • Dead-letter queues, redrive, and transactional outbox
  • Observability: tracing, metrics, health checks
  • Concurrency and parallelism primitives
  • Pagination

Production-systems patterns are recognized primarily through naming conventions (CircuitBreaker, RetryPolicy, DeadLetterQueue, EventStore, HealthCheck, …) and well-known library imports (tenacity, resilience4j, Polly, OpenTelemetry, Micrometer, …) in every supported language. Tokens that are common words in other contexts (projection, cursor, subscribe) require corroboration before a pattern is reported.

Python receives actionable rules, package intelligence, architecture signals, and experimental complexity analysis. The Go pilot discovers .go files, preserves import aliases, emits GO-COR-001 for discarded errors from a narrow set of imported standard-library calls, extracts Go-idiom DSA and design signals from blanked source (container/heap, sort.Search, corroborated BFS/DFS, net/http/gRPC API design, database/sql/GORM, message queues, sync.Once singletons, and more), and passively aggregates multi-file packages plus local module import edges from go.mod. It never invokes Go tooling. Go patterns reuse the shared scoring catalog IDs, so mixed projects aggregate signals across both languages under one score. Python and Go findings share the same report, baseline, privacy, offline, and CI-gate contracts. JSON project_analyses entries expose provider results normally and health-only projections under --anonymize. See docs/RULES.md.

The TypeScript/JavaScript pilot covers .ts, .tsx, .js, .jsx, .mjs, and .cjs with the same bounded, no-toolchain discipline: it blanks comments, strings, and template literals (interpolations included, so literals are never evidence), extracts bounded identifiers and import specifiers by regex, emits TS-COR-001 for empty catch blocks, and passively reads the root package.json to flag imported-but-undeclared dependencies (TS-PKG-001) and invalid manifests (TS-PKG-002). Workspace (monorepo) manifests skip drift analysis, node builtins and path aliases are never flagged, and generated output directories (.next, dist, build, coverage, and friends) are excluded from discovery. It never invokes node, tsc, or a package manager. TS/JS architecture signals match ecosystem idioms (new Map/new Set, memoization, express/fastify/NestJS/tRPC API design, Prisma/TypeORM data access, redis/react-query caching, kafkajs/bullmq queues, jsonwebtoken/next-auth authentication, vitest/jest/playwright testing) through the same shared scoring catalog, so full-stack projects aggregate one score across all three languages.

The Java pilot (.java) blanks comments, strings, char literals, and """ text blocks; extracts imports and bounded identifiers (declarations, annotations, generic type uses, new targets, calls); emits JAVA-COR-001 for empty catch blocks; and passively discovers pom.xml and build.gradle(.kts) modules with the same nested-manifest machinery, reporting invalid manifests (JAVA-PKG-002) and — for a curated set of almost-always-direct libraries only, because Maven and Gradle make transitive classes importable — undeclared dependencies (JAVA-PKG-001). Spring/JAX-RS, JPA/Hibernate/JDBC, Kafka/JMS, @Autowired/Guice, SLF4J/Log4j, JUnit/Mockito, and the java.util collections feed the shared catalog.

The C#/.NET pilot (.cs) blanks comments and every string form — regular, verbatim @"", interpolated $"" with nested holes, raw """, and char literals; extracts using directives (static, alias, global), declared namespaces, and bounded identifiers; emits CS-COR-001 for empty catch blocks (including when-filtered); and reads .csproj PackageReferences (CS-PKG-002 on invalid files), flagging using namespaces with no package matching by prefix in either direction (CS-PKG-001) while skipping System.*, shared-framework Microsoft.*, and the project's own namespaces. ASP.NET Core, EF Core/Dapper, MassTransit/Kafka, IServiceCollection DI, Serilog/ILogger, xUnit/NUnit/Moq, and the BCL collections feed the shared catalog.

The Kotlin pilot (.kt, .kts) shares the JVM ecosystem with Java, so it reuses the Maven/Gradle module intelligence (KT-PKG-001/KT-PKG-002) and extends the Java signal catalog with Kotlin idioms — kotlinx.coroutines, Ktor/http4k, Exposed/Room/Ktorm, Koin/Hilt, kotest/MockK, and the mapOf/mutableListOf collection builders. Its lexer handles nested block comments, $name/${expr} string templates (lexed as code holes, blanked), raw """ strings whose terminator is the last quote of a run, and semicolon-free imports with as aliases. KT-COR-001 reports empty catch blocks.

None of the JVM or .NET pilots execute javac, kotlinc, Maven, Gradle, dotnet, or MSBuild, and all parse build XML fail-closed: documents declaring a DOCTYPE or entities are rejected before parsing. Build output (target, obj, .gradle, TestResults) is excluded from discovery.

The architecture signal score covers Python, Go, TypeScript/JavaScript, Java, Kotlin, and C# signals. A project where no signal-capable source was successfully analyzed reports the score as not applicablenull in JSON with an explicit architecture_signal_scope field — rather than a misleading floor value, and --fail-under exits with code 5 instead of silently passing or failing. docs/ROADMAP.md tracks what comes next: a TypeScript/JavaScript pilot and decision-gated Go duplication depth.

Development

.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest        # tests
.venv/bin/python -m ruff check .  # lint
.venv/bin/python -m pip_audit     # dependency vulnerabilities

The test suite carries a regression test for each detection and safety bug fixed in 2.0, including symlink escape, FIFO reads, cross-file import leakage, and the complexity analyzer's scope handling.

License

MIT

Release files for cqa-analyzer 2.33.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cqa-analyzer 2.33.0
File Size Uploaded
cqa_analyzer-2.33.0.tar.gz 233.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cqa-analyzer 2.33.0
File Interpreter ABI Platform
cqa_analyzer-2.33.0-py3-none-any.whl Python 3 none any Details

Total release size: 385.6 kB

Release files / cqa_analyzer-2.33.0.tar.gz

Download URL cqa_analyzer-2.33.0.tar.gz
Size 233.5 kB
Tags Source
SHA-256 checksum
How to use checksums
8ef7dc7be1524e975cbd03220b8610bb74815deac80669e6f71f281645e4e76b
BLAKE2b-256 checksum
How to use checksums
7c98395c8a2c523a906ea4109e985a1b22bbde857b6d541575a7f60bad9a81b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release files / cqa_analyzer-2.33.0-py3-none-any.whl

Download URL cqa_analyzer-2.33.0-py3-none-any.whl
Size 152.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e681467e22c0c91b70379d550ba259c8a400ca7f235acfb4b8f71aa7e5bb2c4b
BLAKE2b-256 checksum
How to use checksums
90e170c7bfc3f1e5e95e64fddadf0a479fad503410f8109fd82070cd749ec3b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 9, 2026.

Transparency log

Release history Release notifications | RSS feed

3.4.1

2 release files

3.4.0

2 release files

3.3.0

2 release files

3.2.1

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.45.0

2 release files

2.44.0

2 release files

2.43.0

2 release files

2.42.0

2 release files

2.41.0

2 release files

2.40.0

2 release files

2.39.0

2 release files

2.38.1

2 release files

2.38.0

2 release files

2.37.0

2 release files

2.36.0

2 release files

This release

2.33.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page