repo-architecture-analysis

Scan a Python repo's package structure, count classes/functions, classify module maturity (PRODUCTION/DEVELOPMENT/SKELETON/GAP), and generate architecture reports with Mermaid diagrams. Use when asked to analyze codebase structure, find untested packages, or assess module maturity.

5 stars

Best use case

repo-architecture-analysis is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Scan a Python repo's package structure, count classes/functions, classify module maturity (PRODUCTION/DEVELOPMENT/SKELETON/GAP), and generate architecture reports with Mermaid diagrams. Use when asked to analyze codebase structure, find untested packages, or assess module maturity.

Teams using repo-architecture-analysis should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/repo-architecture-analysis/SKILL.md --create-dirs "https://raw.githubusercontent.com/vamseeachanta/workspace-hub/main/.agents/skills/github/repo-architecture-analysis/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/repo-architecture-analysis/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How repo-architecture-analysis Compares

Feature / Agentrepo-architecture-analysisStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Scan a Python repo's package structure, count classes/functions, classify module maturity (PRODUCTION/DEVELOPMENT/SKELETON/GAP), and generate architecture reports with Mermaid diagrams. Use when asked to analyze codebase structure, find untested packages, or assess module maturity.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Repo Architecture Analysis & Module Maturity Classification

Scan Python repositories to discover packages, count classes/functions, classify maturity levels, and generate markdown/JSON reports.

## When to Use

- User asks "what packages does this repo have?"
- User wants to know which modules lack tests
- User asks for a module maturity or readiness matrix
- User wants an architecture overview with diagrams
- Before prioritizing test coverage work

## Three Scripts (workspace-hub)

1. `scripts/analysis/repo_architecture_scanner.py` — Basic package discovery, counting, Mermaid structure diagrams
2. `scripts/analysis/architecture-scanner.py` — **Enhanced** scanner with LOC, public API surface, import dependency graph, YAML output (#1604)
3. `scripts/analysis/module_status_matrix.py` — Maturity classification (PRODUCTION/DEVELOPMENT/SKELETON/GAP) (#1567)

## Running

```bash
# Enhanced architecture scan with API surface + dependency graph (preferred)
uv run python scripts/analysis/architecture-scanner.py [REPO_PATH] [-o OUTPUT_DIR]
# Outputs: docs/architecture/api-surface-map.md + .yaml

# With collision detection (added #1627)
uv run python scripts/analysis/architecture-scanner.py --detect-collisions
# Appends collision report to api-surface-map.md, prints top-20 to stdout

# Basic architecture scan
uv run scripts/analysis/repo_architecture_scanner.py [REPO_PATH] [-o OUTPUT_DIR]

# Module status matrix (with LOC-weighted scoring + trend tracking, #1629)
uv run scripts/analysis/module_status_matrix.py [REPO_PATH] [-o OUTPUT_DIR]
# Defaults to docs/reports/ — use `-o docs/architecture` for canonical location
# Outputs: module-status-matrix.md + .json (JSON includes quality_score for trend tracking)

# All default to digitalmodel/ if no path given
```

## Enhanced Scanner Features (architecture-scanner.py)

The enhanced scanner adds capabilities beyond the basic one:
- **LOC counts** per package (non-blank lines)
- **Public API surface** detection: classes/functions not prefixed with `_`
- **Import dependency graph**: scans for inter-package imports (absolute via namespace + relative)
- **YAML report** output alongside markdown
- **Mermaid dependency graph** (edges between packages, not just tree structure)
- **Cross-package API name collision detection** (`--detect-collisions` flag, #1627): builds reverse index of symbol→packages, flags symbols exported by 2+ packages (179 collisions found across 31 packages)
- Functions: `discover_packages()`, `build_dependency_graph()`, `build_reverse_index()`, `detect_collisions()`, `generate_collision_report()`, `generate_yaml_report()`, `generate_markdown()`, `scan_repo()`

## Module Status Matrix Scoring (module_status_matrix.py)

Added in #1629 — LOC-weighted quality scoring and trend tracking:
- **Quality score**: `test_count × file_count / LOC × 100` — higher = better tested per LOC
- **Test-to-source ratio**: `test_count / file_count`
- **Trend tracking**: compares current quality_score to previous JSON snapshot (↑↓→/NEW/—)
- Previous snapshot auto-loaded from existing `module-status-matrix.json` before overwrite
- Functions: `compute_quality_score()`, `compute_test_source_ratio()`, `compute_trend()`
- JSON output now includes `loc`, `quality_score`, `test_source_ratio` per package for future trend comparisons

## Maturity Classification Rules

| Status | Criteria |
|--------|----------|
| PRODUCTION | >5 test files AND >3 source files AND >50% files have docstrings |
| DEVELOPMENT | has source files AND ≥1 test files AND not all files tiny (<20 lines) |
| SKELETON | source files but 0 test files, OR all files <20 non-blank lines (even with tests) |
| GAP | directory exists but only `__init__.py` |

**Priority order:** GAP (only __init__.py) → PRODUCTION (>5 tests, >3 files, >50% docstrings) → DEVELOPMENT (≥1 test, not all files tiny) → SKELETON (everything else — 0 tests, or all files tiny).

## Key Pitfalls (Discovered Through Iteration)

### 1. `.egg-info` directories break namespace detection
The src-layout scanner looks for a single child directory under `src/` to detect namespace packages. `.egg-info` dirs count as children and break this heuristic.

**Fix:** Always filter out `.egg-info` and `.dist-info`:
```python
subdirs = [d for d in src_dir.iterdir()
           if d.is_dir()
           and not d.name.startswith((".", "_"))
           and not d.name.endswith((".egg-info", ".dist-info"))]
```

### 2. `.venv` pollutes entry point discovery
`rglob("__main__.py")` will find hundreds of `__main__.py` files inside `.venv/lib/python3.x/site-packages/`. Same for `scripts/` rglob hitting deep legacy trees.

**Fix:** Skip known directories:
```python
skip_dirs = {".venv", "venv", "node_modules", ".git", "__pycache__", ".tox", ".nox"}
def _skip_venv(path):
    return any(part in skip_dirs for part in path.parts)
```

### 3. src-layout namespace detection
For repos using `src/mypackage/` layout with a single namespace package, the scanner must detect this pattern and drill one level deeper to find the real sub-packages.

**Pattern:** If `src/` has exactly 1 non-hidden, non-egg-info child with `__init__.py`, treat it as the namespace root and scan its children.

### 4. Entry point scripts/ scanning depth
Use `glob("*.py")` (top-level only) instead of `rglob("*.py")` for scripts/ to avoid listing hundreds of legacy/deep scripts.

### 5. Use relative paths in reports
Call `path.relative_to(repo_path)` for cleaner output instead of absolute paths.

## TDD Structure

Tests for all scripts live in `tests/analysis/`:
- `test_architecture_scanner.py` — 19 tests (discovery, metrics, public API, dependency graph, YAML, markdown, e2e)
- `test_collision_detection.py` — 14 tests (reverse index, collision detection, dedup, report formatting, top-N, case sensitivity)
- `test_repo_architecture_scanner.py` — 17 tests (package discovery, counting, markdown, entry points)
- `test_module_status_matrix.py` — 18 tests (scanning, classification, docstring%, key classes, markdown, JSON)
- `test_weighted_scoring.py` — 13 tests (quality score, test/source ratio, trend comparison, edge cases)

All use `tmp_path` fixtures with mock repo structures to test each classification branch.

### Hyphenated filenames need importlib (not sys.path.insert)

`architecture-scanner.py` has a hyphen, making it non-importable via normal Python import. Tests must use:

```python
import importlib.util
_script_path = Path(__file__).resolve().parents[2] / "scripts" / "analysis" / "architecture-scanner.py"
_spec = importlib.util.spec_from_file_location("architecture_scanner", _script_path)
architecture_scanner = importlib.util.module_from_spec(_spec)
sys.modules["architecture_scanner"] = architecture_scanner
_spec.loader.exec_module(architecture_scanner)
```

Then test functions can `from architecture_scanner import discover_packages` normally.

### 6. Concurrent agent file conflicts
When running alongside other agents (Codex, Gemini), your files may get overwritten mid-session. **Commit immediately** after tests pass — don't leave uncommitted work sitting. If you hit `index.lock`, run `rm -f .git/index.lock` and retry.

### 7. scan_packages takes two arguments: src_dir and tests_dir
The actual working signature is `scan_packages(src_dir: Path, tests_dir: Path)` — this is more flexible than a single repo_path since it decouples source and test locations. The CLI flags `--src-dir` and `--tests-dir` map to these. The prior single-arg approach was less testable.

### 8. Test fixture for SKELETON vs GAP distinction
GAP = only `__init__.py` (no real source files). SKELETON = has source files but 0 tests. You do NOT need files >20 lines for DEVELOPMENT — the "all tiny" check only applies when combined with 0 tests. Keep fixture files small; the classification handles it correctly.

### 9. Packages without `__init__.py` are invisible — fix by adding __init__.py
If a directory lacks `__init__.py`, the scanner skips it. Fixed in #1626: `data_models/` got `__init__.py` → scanner now reports 31 packages. When a package is missing, create an `__init__.py` with a module docstring. Commit goes to the **digitalmodel repo** (not workspace-hub — see pitfall #12).

### 10. Module status matrix summary format
The enhanced output includes a bold summary line at the top: `**X/N PRODUCTION, Y/N DEVELOPMENT, Z/N SKELETON, W/N GAP**`. This format was added to meet issue #1567 acceptance criteria.

### 12. digitalmodel/ is a separate git repo inside workspace-hub
`digitalmodel/` is in workspace-hub's `.gitignore` — it's a separate repo (`github.com/vamseeachanta/digitalmodel.git`) cloned inside. Files under `digitalmodel/src/` must be committed in the digitalmodel repo (`cd digitalmodel && git add ... && git commit`), while `scripts/analysis/`, `tests/analysis/`, `docs/architecture/` are committed in workspace-hub. Before pushing either, stash unstaged changes from other terminals: `git stash && git pull origin main --rebase && git stash pop && git push`.

### 13. Module status matrix output path discrepancy
The script defaults to `docs/reports/` but the canonical location used by other tools is `docs/architecture/`. Run with `-o docs/architecture` to update the canonical copy. Both locations exist and should be kept in sync.

### 11. Dependency graph only includes inter-package edges
The `build_dependency_graph()` function detects the namespace package name (e.g. `digitalmodel`) and only tracks imports between known sibling packages. Stdlib and third-party imports are excluded. It matches both absolute (`from digitalmodel.pkg`) and relative (`from .pkg`) import patterns.

## Test Fixture Pattern for src-layout

```python
@pytest.fixture
def sample_repo(tmp_path):
    src = tmp_path / "src" / "mypackage"
    src.mkdir(parents=True)
    (src / "__init__.py").write_text("")  # CRITICAL: must exist for namespace detection
    
    alpha = src / "alpha"
    alpha.mkdir()
    (alpha / "__init__.py").write_text('__all__ = ["Thing"]')
    (alpha / "engine.py").write_text('class Thing:\n    pass\n')
    
    tests_dir = tmp_path / "tests" / "alpha"
    tests_dir.mkdir(parents=True)
    (tests_dir / "test_engine.py").write_text("def test_thing(): pass\n")
    
    return tmp_path
```

**Critical:** The namespace package directory (`src/mypackage/`) MUST have `__init__.py` or it won't be detected as a namespace package.

Related Skills

interactive-report-generator

5
from vamseeachanta/workspace-hub

Generate interactive HTML reports with Plotly visualizations from data analysis results. Supports dashboards, charts, and professional styling.

data-validation-reporter

5
from vamseeachanta/workspace-hub

Generate interactive validation reports with quality scoring, missing data analysis, and type checking. Combines Pandas validation, Plotly visualization, and YAML configuration for comprehensive data quality reporting.

repo-ecosystem-hygiene

5
from vamseeachanta/workspace-hub

Interpret the daily read-only repo ecosystem hygiene audit and route remediation through approved workflows.

mnt-analysis-cleanup

5
from vamseeachanta/workspace-hub

Survey, classify, and clean up `/mnt/local-analysis/` (or any sibling-to-workspace-hub directory holding orphan worktrees, codex-burn artifacts, agent log accumulations, and outer-clone duplicates) without losing useful code/work. Surfaces a tiered approval menu rather than baking decisions; defers all destructive ops until user confirms.

orcaflex-reporting-fixture-proof-pattern

5
from vamseeachanta/workspace-hub

Build and extend fixture-backed OrcaFlex reporting proof paths in digitalmodel using stable metadata baselines, normalized HTML snapshots, and reusable reporting test helpers.

improve-codebase-architecture

5
from vamseeachanta/workspace-hub

Find deepening opportunities in a codebase, informed by the domain language in CONTEXT.md and the decisions in docs/adr/. Use when the user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more testable and AI-navigable.

repo-sync

5
from vamseeachanta/workspace-hub

Smart repository synchronization across workspace-hub ecosystem — diagnoses and fixes pull failures (detached HEAD, diverged branches, uncommitted changes)

repo-structure

5
from vamseeachanta/workspace-hub

Canonical source layout, test mirroring, root cleanliness, gitignore, docs classification, and committed artifact rules for all workspace-hub tier-1 repos. Consult before creating directories or files in any submodule.

repo-portfolio-steering

5
from vamseeachanta/workspace-hub

Generate a one-page portfolio steering report for workspace-hub. Use when the user invokes /repo-portfolio-steering, asks about harness vs engineering balance, wants a portfolio health check, or asks which repos to fund next. Reports on portfolio steering, GTM readiness, and provider activity balance.

repo-mission-portfolio-audit

5
from vamseeachanta/workspace-hub

Audit the workspace-hub repo portfolio to extract each repo's mission, identify documentation gaps, and prioritize a plan/approval sequence with explicit LLM-wiki weighting for future issue triage.

mixed-ops-vs-repo-fix-plan-boundary

5
from vamseeachanta/workspace-hub

Plan mixed operational-vs-repo remediation issues by proving live-state classification first, then only proposing code changes for confirmed repo-owned failure paths.

repo-separation-for-sensitive-data

5
from vamseeachanta/workspace-hub

Architecture pattern for splitting confidential data and reusable algorithms across repos