refactor: delete stale files and consolidate .mindmodel structure
Deleted stale root-level Python files: - main.py (unused 'Hello world' script) - verify.py (unused table info script) - scraper.py (unused MotionScraper class) - scheduler.py (unused DataUpdateScheduler class) Deleted duplicate .mindmodel root YAML files (subdirectory versions are more comprehensive): - anti-patterns.yaml, architecture.yaml, conventions.yaml - dependencies.yaml, domain.yaml, domain-glossary.yaml - stack.yaml, tech-stack.yaml, workflows.yaml Added comprehensive .mindmodel subdirectories: - constraints/ (naming, db-schema, error-handling, types, etc.) - patterns/ (api, architecture, database, python, streamlit, etc.) - examples/ (code examples for each pattern) - anti-patterns/, architecture/, conventions/, dependencies/, domain/, stack/ Updated ARCHITECTURE.md to reflect current codebase: - Removed references to non-existent files - Added missing files (explorer.py, explorer_helpers.py, pipeline/) - Added directory structure documentation - Updated tech stack to include scipy, sklearn, umap Updated .gitignore: - Added patterns for generated analysis files - Added .worktrees/ pattern (was already in gitignore but dir was deleted) Removed empty .worktrees/ directory
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
# Naming Conventions
|
||||
|
||||
## Files
|
||||
- **snake_case** for all Python files: `database.py`, `explorer_helpers.py`, `motion_cache.py`
|
||||
- **PascalCase** NOT used for files
|
||||
|
||||
## Functions
|
||||
- **snake_case**: `get_svd_vectors()`, `compute_party_coords()`, `build_scatter_trace()`
|
||||
- Private helpers prefixed with `_`: `_get_window_data()`
|
||||
|
||||
## Classes
|
||||
- **PascalCase**: `MotionDatabase`, `Config`
|
||||
- **Dataclass pattern** for Config: `@dataclass` decorator with typed fields
|
||||
|
||||
## Variables
|
||||
- **snake_case**: `party_map`, `mp_name`, `svd_vectors`, `party_centroids`
|
||||
- **CONSTANT_SNAKE_CASE** for module-level constants: `PARTY_COLOURS`, `DEFAULT_WINDOW`
|
||||
|
||||
## Module-Level Exports
|
||||
- **Singleton instance**: `db = MotionDatabase()` at module bottom (not class-level)
|
||||
- **Config instance**: `config = Config(...)` at module bottom
|
||||
- **Dicts**: `PARTY_COLOURS` exported from `config.py`
|
||||
|
||||
---
|
||||
|
||||
# Error Handling
|
||||
|
||||
## Known Patterns
|
||||
1. **Bare except with pass** (ANTI-PATTERN - see anti-patterns.yaml)
|
||||
```python
|
||||
except:
|
||||
pass # database.py:47
|
||||
```
|
||||
|
||||
2. **Graceful degradation**: catch specific exceptions, fall back to default
|
||||
```python
|
||||
try:
|
||||
result = compute_svd()
|
||||
except ImportError:
|
||||
result = DEFAULT_SVD
|
||||
```
|
||||
|
||||
3. **Optional dependency fallbacks**:
|
||||
```python
|
||||
try:
|
||||
import umap
|
||||
use_umap = True
|
||||
except ImportError:
|
||||
use_umap = False
|
||||
```
|
||||
|
||||
4. **Nested exception handling** (ANTI-PATTERN - see anti-patterns.yaml):
|
||||
```python
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
try:
|
||||
...
|
||||
except Exception:
|
||||
pass
|
||||
```
|
||||
|
||||
## Rules
|
||||
- Never use bare `except:` — always specify exception type
|
||||
- Never swallow exceptions silently — log or return a sensible default
|
||||
- For optional deps, use `ImportError` or `ModuleNotFoundError` explicitly
|
||||
- Avoid nested try/except blocks
|
||||
|
||||
---
|
||||
|
||||
# Code Organization
|
||||
|
||||
## Singleton Pattern
|
||||
Each module owns one shared instance:
|
||||
```python
|
||||
# database.py
|
||||
db = MotionDatabase()
|
||||
|
||||
# config.py
|
||||
config = Config(...)
|
||||
PARTY_COLOURS = {...}
|
||||
```
|
||||
|
||||
## Pure Functions in Helpers
|
||||
`explorer_helpers.py` contains only pure functions (no IO, no Streamlit calls):
|
||||
```python
|
||||
def compute_party_coords(svd_vectors, party_map):
|
||||
"""Pure: no side effects, no imports from this module"""
|
||||
...
|
||||
|
||||
def build_scatter_trace(df, color_col):
|
||||
"""Pure: returns Plotly trace dict"""
|
||||
...
|
||||
```
|
||||
|
||||
## Cached Data Loaders
|
||||
Use `@st.cache_data` for expensive data loading:
|
||||
```python
|
||||
@st.cache_data
|
||||
def load_svd_vectors(window: str) -> pd.DataFrame:
|
||||
return db.get_svd_vectors(window)
|
||||
```
|
||||
|
||||
## Dataclass Config
|
||||
```python
|
||||
@dataclass
|
||||
class Config:
|
||||
db_path: str = "data/stemwijzer.duckdb"
|
||||
default_window: str = "2023"
|
||||
party_colours: dict = field(default_factory=lambda: PARTY_COLOURS)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Imports
|
||||
|
||||
## Ordering (convention)
|
||||
1. Standard library
|
||||
2. Third-party (streamlit, ibis, plotly, sklearn, umap)
|
||||
3. Local/relative imports
|
||||
|
||||
## Avoid
|
||||
- Wildcard imports (`from module import *`)
|
||||
- Circular imports (ensure dependency direction: helpers → database → config)
|
||||
Reference in New Issue
Block a user