Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6c124b2
fix: Critical MCP defaults, packaging, and CI
cursoragent Aug 12, 2026
b1f871b
docs: Add comprehensive modularization plan for oversized modules
cursoragent Aug 12, 2026
87bc57f
docs: Clarify Core-6 entry point and remove contradictions
cursoragent Aug 12, 2026
164c60b
refactor: Modularize import_cache and health into packages
cursoragent Aug 12, 2026
a7136e6
fix: Export private functions used by tests for backward compat
cursoragent Aug 12, 2026
944923e
test: Verify update_maps works in production (57 files parsed in repo)
cursoragent Aug 12, 2026
d6bd143
refactor: Extract wikifier/api.py from cli.py
cursoragent Aug 12, 2026
8db65d6
wip: MCP modularization attempt - rolling back for pragmatic approach
cursoragent Aug 12, 2026
58e8494
fix: Import health_pkg in api.py (was importing old health name)
cursoragent Aug 12, 2026
aa0a4ee
fix: Check excludes against relative path, not absolute path
cursoragent Aug 12, 2026
1302260
fix: Export _entry_is_under_root from health_pkg
cursoragent Aug 12, 2026
93448e2
refactor: Modularize mcp/server.py into tools package
cursoragent Aug 12, 2026
71e6f1f
refactor: Modularize parsers/javascript.py into package
cursoragent Aug 12, 2026
828bceb
refactor: Modularize parsers/bree.py into package
cursoragent Aug 12, 2026
7432576
Fix all test failures: green suite (140 tests OK, 4 skipped)
cursoragent Aug 12, 2026
ccf2463
Fix Python 3.8-3.11 compatibility: remove f-string backslash in expre…
cursoragent Aug 12, 2026
39efb9d
Fix Python 3.8/3.9 compatibility: add future annotations
cursoragent Aug 12, 2026
7c37dea
Fix Python 3.8 compat: add future annotations to api.py
cursoragent Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
push:
branches:
- main
- 'cursor/**'
pull_request:
branches:
- main

jobs:
test:
name: Test Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v6

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build wheel setuptools
pip install -e .

- name: Run tests
run: python -m unittest discover tests -v

- name: Verify package build
run: python -m build --wheel --outdir dist/
21 changes: 21 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,30 @@ permissions:
contents: read

jobs:
test:
name: Run Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build wheel setuptools
pip install -e .

- name: Run test suite
run: python -m unittest discover tests -v

build:
name: Build distribution
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v6

Expand Down
227 changes: 227 additions & 0 deletions MODULARIZATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Wikifier Modularization Plan

## Overview

Several modules in wikifier have grown to 2000+ lines, making them difficult to navigate and maintain. This document outlines a plan for modularizing these "god modules" into coherent package structures.

## Current State (as of v4.6.9)

### Modules Needing Modularization

| Module | Lines | Priority | Complexity |
|--------|-------|----------|------------|
| `wikifier/parsers/javascript.py` | 2681 | High | High - barrel resolution, CDIA integration |
| `wikifier/import_cache.py` | 2588 | High | High - graph algorithms, cycles, ACS |
| `wikifier/health.py` | 2504 | High | Medium - file operations, status tracking |
| `wikifier/mcp/server.py` | 2238 | Medium | Medium - many tool definitions |
| `wikifier/cli.py` | 2034 | Medium | Medium - argparse + API mixing |
| `wikifier/parsers/bree.py` | 2012 | Low | Medium - barrel resolution |
| `wikifier/contracts.py` | 1726 | Low | Low - dataclasses |
| `wikifier/resolution.py` | 1597 | Low | Medium - path resolution |

## Proposed Package Structures

### 1. `wikifier/cache/` (from `import_cache.py`)

**Priority: HIGH** - This is the largest single-concern module with clear boundaries.

```
wikifier/cache/
β”œβ”€β”€ __init__.py # Public API, backward compatibility exports
β”œβ”€β”€ io.py # load_cache, save_cache, cache paths
β”œβ”€β”€ files.py # get/update file data, mtime, content hashing
β”œβ”€β”€ graph.py # build_dependency_graph, graph_signature
β”œβ”€β”€ cycles.py # compute_cycles, Tarjan SCC, CIABRE
β”œβ”€β”€ acs.py # compute_acs_summary, ACS v1.3 logic
β”œβ”€β”€ barrel.py # barrel resolution, invalidation
β”œβ”€β”€ diagnostics.py # get_resolution_diagnostics, reporting
└── streaming.py # generate_update_events, partial results
```

**Functions per module:**
- `io.py`: load_cache, save_cache, load_mtime_index, _get_cache_path, _do_save_cache (~150 lines)
- `files.py`: get/update_file_data, get_mtime, compute_file_content_hash (~200 lines)
- `graph.py`: build_dependency_graph, graph_signature, reverse_dependency ops (~300 lines)
- `cycles.py`: compute_cycles, _tarjan_sccs, get/set_cycles, cycle_analyses, CIABRE (~600 lines)
- `acs.py`: compute_acs_summary, classify_edge_agent_signal, get/set_acs_summary (~400 lines)
- `barrel.py`: get/set_barrel_resolutions, invalidate_stale_barrel_entries, barrel reports (~300 lines)
- `diagnostics.py`: get_resolution_diagnostics, get_unresolved_imports, get_low_confidence_edges (~200 lines)
- `streaming.py`: generate_update_events, run_update_stream (~400 lines)

**Backward Compatibility:**
```python
# wikifier/cache/__init__.py
"""Import cache + graph intelligence (agent-first)."""

from .io import load_cache, save_cache, load_mtime_index
from .files import get_file_data, update_file_data, get_mtime, compute_file_content_hash
from .graph import (
build_dependency_graph,
get_reverse_dependencies,
set_reverse_dependencies,
maintain_reverse_dependencies_for_source,
rebuild_reverse_dependencies
)
from .cycles import compute_cycles, get_cycles, set_cycles, compute_cycle_analyses
from .acs import compute_acs_summary, get_acs_summary, set_acs_summary, classify_edge_agent_signal
from .barrel import (
get_barrel_resolutions,
set_barrel_resolutions,
invalidate_stale_barrel_entries,
get_barrel_invalidation_reports
)
from .diagnostics import get_resolution_diagnostics, get_unresolved_imports, get_low_confidence_edges
from .streaming import generate_update_events, run_update_stream

# Maintain old import paths
__all__ = [
'load_cache', 'save_cache', 'load_mtime_index',
'get_file_data', 'update_file_data',
# ... (all public functions)
]
```

### 2. `wikifier/health_pkg/` (from `health.py`)

**Priority: HIGH** - Name collision issue (`wikifier.health` shadows module), large module

**Note:** Cannot use `wikifier/health/` as that would conflict with the existing `wikifier/health.py`. Use `health_pkg` temporarily, or do atomic rename.

```
wikifier/health_pkg/
β”œβ”€β”€ __init__.py # Public API, exports, health() accessor function
β”œβ”€β”€ io.py # load_health, save_health, paths
β”œβ”€β”€ core.py # upsert_entry, get_summary
β”œβ”€β”€ pending.py # pending_updates.md operations
β”œβ”€β”€ status.py # mark_green, record_meaningful_edit, status mutations
β”œβ”€β”€ analysis.py # assess_autonomous_readiness, detect_scope_risks
β”œβ”€β”€ stale.py # get_stale_wikis, _is_stale_wiki
β”œβ”€β”€ mapfirst.py # seed_health_from_map, find_ghost_entries, validate_health
β”œβ”€β”€ healing.py # heal_with_policy, heal_outdated_stubs
└── pruning.py # prune_pending_to_monitored, prune_health_outside_monitored
```

**Migration Path:**
1. Create `health_pkg/` with all modules
2. Add `wikifier.health_module` alias in `wikifier/__init__.py` pointing to health_pkg
3. Keep `health.py` as thin compatibility shim for one release
4. Update all imports to use `wikifier.health_pkg` or `wikifier.health_module`
5. Remove `health.py` in next major version

### 3. `wikifier/parsers/javascript/` (from `parsers/javascript.py`)

**Priority: HIGH** - Largest single file, complex logic

```
wikifier/parsers/javascript/
β”œβ”€β”€ __init__.py # parse_javascript_imports (main entry)
β”œβ”€β”€ extract.py # Import statement extraction patterns
β”œβ”€β”€ resolve.py # Path resolution (ES modules, CommonJS)
β”œβ”€β”€ barrel.py # Barrel/re-export handling
β”œβ”€β”€ cdia.py # CDIA integration for conditionals
└── metadata.py # Confidence scoring, edge metadata
```

### 4. `wikifier/mcp/tools/` (split `mcp/server.py`)

**Priority: MEDIUM** - Large but lower risk, clear tool boundaries

```
wikifier/mcp/
β”œβ”€β”€ __init__.py
β”œβ”€β”€ server.py # FastMCP setup, main() entry point (~200 lines)
β”œβ”€β”€ tools/
β”‚ β”œβ”€β”€ __init__.py
β”‚ β”œβ”€β”€ core.py # Core-6: session_bootstrap, check_changes, suggest_next_actions
β”‚ β”œβ”€β”€ health.py # health, get_files_needing_attention
β”‚ β”œβ”€β”€ dependencies.py # get_dependencies, get_dependents, get_file_wiki
β”‚ β”œβ”€β”€ maps.py # update_maps, get_project_status
β”‚ β”œβ”€β”€ cycles.py # get_cycles, get_cycle_analyses
β”‚ β”œβ”€β”€ barrel.py # get_barrel_reports, barrel operations
β”‚ β”œβ”€β”€ diagnostics.py # get_resolution_diagnostics, get_unresolved_imports
β”‚ β”œβ”€β”€ workflow.py # record_change, mark_green, prepare_edit
β”‚ └── advanced.py # heal_stubs, prune operations
β”œβ”€β”€ prompts.py # MCP prompts (audit_project_health, plan_refactoring, etc)
└── models.py # Pydantic models (DependencyInfo, FileDependencies, etc)
```

### 5. `wikifier/api.py` + Thin `cli.py`

**Priority: MEDIUM** - Separate concerns: argparse vs library API

**Current issue:** `cli.py` mixes argparse with substantial library functions that should be public API.

**Proposed:**
- `wikifier/api.py`: Public library API functions (run_full_update, check_changes, suggest_next_actions, etc.)
- `wikifier/cli.py`: Thin argparse wrapper calling api.py functions (~300-400 lines max)
- MCP server uses `wikifier.api` directly instead of importing from cli

## Implementation Guidelines

### 1. Backward Compatibility

**Critical:** All existing imports must continue to work. Use `__init__.py` to re-export public API:

```python
# Old code still works:
from wikifier.import_cache import load_cache, compute_cycles

# New code can use:
from wikifier.cache import load_cache
from wikifier.cache.cycles import compute_cycles
```

### 2. Testing Strategy

For each modularization:
1. Create new package structure
2. Move code to new modules
3. Add backward-compatible imports in `__init__.py`
4. Run full test suite: `python -m unittest discover tests`
5. Fix any import errors or test failures
6. Verify wheel builds correctly
7. Test MCP server still works

### 3. Module Size Targets

- Individual modules: 300-600 lines max
- Keep related functions together (cohesion)
- Clear single responsibility per module
- Minimize cross-module dependencies within package

### 4. One Package at a Time

Do not attempt multiple packages in one PR. Each modularization should be:
- Separate PR
- Fully tested
- Documented in CHANGELOG
- Reviewed for backward compatibility

## Recommended Order

1. **`wikifier/cache/`** (from import_cache.py) - Largest, clearest boundaries
2. **`wikifier/health_pkg/`** (from health.py) - Fixes name collision
3. **`wikifier/api.py` split** - Improves library/CLI separation
4. **`wikifier/mcp/tools/`** - MCP tool organization
5. **`wikifier/parsers/javascript/`** - Complex but isolatable

## Benefits

- **Navigability:** New contributors can find code faster
- **Maintainability:** Clear boundaries reduce cognitive load
- **Testing:** Easier to test individual concerns
- **Import time:** Potential for lazy imports to speed startup
- **Name collision:** Fixes `wikifier.health` vs `from wikifier import health` footgun

## Non-Goals

- Do NOT break zero-dependency core
- Do NOT change public API signatures
- Do NOT merge unrelated functions just to hit line counts
- Do NOT create packages for modules <1000 lines (diminishing returns)

## References

- User rule: `Code limit.md` - 600 LOC guideline per file
- CLAUDE.md: "god-module cliff" warning for javascript.py, import_cache.py, etc.
- skills/run.md: "Do not open megamodules for workflow decisions"
Loading