aboutsummaryrefslogtreecommitdiffstats
path: root/.agents/skills/architecture-design/references
diff options
context:
space:
mode:
authorsillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
committersillylaird <sillyfanboy@gmail.com>2026-09-03 00:33:59 +0000
commit898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch)
tree85c6ee5ad58b860144551184d4cf86b560c62b91 /.agents/skills/architecture-design/references
downloadwww-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.tar.gz
www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.zip
import live www.sillylaird.ca webrootHEADmain
Diffstat (limited to '.agents/skills/architecture-design/references')
-rw-r--r--.agents/skills/architecture-design/references/auto_import.md117
-rw-r--r--.agents/skills/architecture-design/references/code_style.md234
-rw-r--r--.agents/skills/architecture-design/references/factory_pattern.md53
-rw-r--r--.agents/skills/architecture-design/references/registry_pattern.md102
-rw-r--r--.agents/skills/architecture-design/references/structure.md150
5 files changed, 656 insertions, 0 deletions
diff --git a/.agents/skills/architecture-design/references/auto_import.md b/.agents/skills/architecture-design/references/auto_import.md
new file mode 100644
index 0000000..59c19ef
--- /dev/null
+++ b/.agents/skills/architecture-design/references/auto_import.md
@@ -0,0 +1,117 @@
+# Auto-Import Pattern
+
+## Overview
+
+The Auto-Import pattern automatically discovers and imports all submodules in a directory, ensuring all components are registered without manual imports.
+
+## Structure
+
+```python
+# In module __init__.py (e.g., data_module/dataset/__init__.py)
+import os
+from src.utils.helpers import import_modules
+
+models_dir = os.path.dirname(__file__)
+import_modules(models_dir, "src.data_module.dataset")
+```
+
+## Helper Function
+
+```python
+# In src/utils/helpers.py
+import os
+import importlib
+import pkgutil
+from typing import List
+
+def import_modules(models_dir: str, package_name: str) -> List[str]:
+ """
+ Import all Python modules in a directory.
+
+ Args:
+ models_dir: Directory path to scan
+ package_name: Full package name for imports
+
+ Returns:
+ List of imported module names
+ """
+ imported = []
+ for module_loader, name, ispkg in pkgutil.iter_modules([models_dir]):
+ if not name.startswith('_'):
+ full_name = f"{package_name}.{name}"
+ importlib.import_module(full_name)
+ imported.append(name)
+ return imported
+```
+
+## Benefits
+
+- **Zero maintenance**: Adding new file = auto-registration
+- **No遗漏**: Cannot forget to import new component
+- **Consistent**: All components follow same discovery path
+- **Scalable**: Works for any number of submodules
+
+## Implementation Details
+
+1. Scan directory for `.py` files
+2. Skip files starting with `_` (private)
+3. Import each module using full package path
+4. Import triggers decorator registration
+
+## Directory Structure Example
+
+```
+dataset/
+├── __init__.py # Contains import_modules() call
+├── simple_dataset.py # Auto-imported, registers "simple"
+├── custom_dataset.py # Auto-imported, registers "custom"
+└── _private.py # NOT imported (starts with _)
+```
+
+## Best Practices
+
+- **Skip private files**: Files starting with `_` are not imported
+- **Full package paths**: Use dot-notation for correct imports
+- **Idempotent**: Safe to call multiple times
+- **Error handling**: Import errors propagate for debugging
+
+## Common Patterns
+
+### Conditional Import
+
+```python
+def import_modules(models_dir: str, package_name: str, skip: List[str] = None):
+ skip = skip or []
+ for module_loader, name, ispkg in pkgutil.iter_modules([models_dir]):
+ if name not in skip and not name.startswith('_'):
+ importlib.import_module(f"{package_name}.{name}")
+```
+
+### Recursive Import
+
+```python
+def import_modules_recursive(models_dir: str, package_name: str):
+ """Import modules and subpackages recursively."""
+ for importer, name, ispkg in pkgutil.walk_packages([models_dir], prefix=f"{package_name}."):
+ if not name.split('.')[-1].startswith('_'):
+ importlib.import_module(name)
+```
+
+### Dry-Run Mode
+
+```python
+def import_modules(models_dir: str, package_name: str, dry_run: bool = False):
+ if dry_run:
+ return [name for _, name, _ in pkgutil.iter_modules([models_dir])
+ if not name.startswith('_')]
+ # ... actual import logic
+```
+
+## Integration with Registry
+
+The auto-import pattern is typically used WITH registry pattern:
+
+1. **Import time**: `import_modules()` imports all files
+2. **Decorator execution**: `@register_dataset()` runs
+3. **Factory population**: `DATASET_FACTORY` dict populated
+4. **Runtime**: `DatasetFactory()` looks up registered classes
diff --git a/.agents/skills/architecture-design/references/code_style.md b/.agents/skills/architecture-design/references/code_style.md
new file mode 100644
index 0000000..c07fd0a
--- /dev/null
+++ b/.agents/skills/architecture-design/references/code_style.md
@@ -0,0 +1,234 @@
+# Code Style Guidelines
+
+## Type Annotations
+
+Always use type hints for function signatures and class attributes:
+
+```python
+from typing import Dict, List, Optional, Tuple
+import torch
+
+def __getitem__(self, i: int) -> Dict[str, torch.Tensor]:
+ """Get item by index."""
+ return self.data[i]
+
+def compute_metrics(predictions: torch.Tensor, labels: torch.Tensor) -> Dict[str, float]:
+ """Compute evaluation metrics."""
+ pass
+
+class MyModel(nn.Module):
+ hidden_dim: int # Class attribute type hints
+ output_dim: int
+
+ def __init__(self, cfg):
+ self.hidden_dim: int = cfg.model.hidden_dim
+ self.output_dim: int = cfg.model.output_dim
+```
+
+## Import Order
+
+Organize imports in three sections with blank lines between:
+
+```python
+# 1. Standard library imports
+import os
+from typing import Dict, List, Optional
+from pathlib import Path
+
+# 2. Third-party imports
+import torch
+import torch.nn as nn
+from torch.utils.data import Dataset
+import numpy as np
+
+# 3. Local imports
+from src.data_module.dataset import register_dataset
+from src.utils.helpers import import_modules
+from src.model_module.brain_decoder import register_model
+```
+
+## __init__.py Files
+
+### Module __init__.py (with factory)
+
+Contains factory/registry logic and auto-import:
+
+```python
+# src/data_module/dataset/__init__.py
+import os
+from typing import Dict, Callable, TypeVar
+from src.utils.helpers import import_modules
+
+T = TypeVar('T')
+
+DATASET_FACTORY: Dict[str, type] = {}
+
+def register_dataset(name: str) -> Callable[[T], T]:
+ """Decorator to register dataset classes."""
+ def decorator(cls: T) -> T:
+ DATASET_FACTORY[name] = cls
+ return cls
+ return decorator
+
+def DatasetFactory(data_name: str):
+ """Create dataset instance by name."""
+ dataset = DATASET_FACTORY.get(data_name, None)
+ if dataset is None:
+ dataset = DATASET_FACTORY.get('simple')
+ return dataset
+
+# Auto-import all submodules
+models_dir = os.path.dirname(__file__)
+import_modules(models_dir, "src.data_module.dataset")
+```
+
+### Subpackage __init__.py (can be empty)
+
+```python
+# src/data_module/augmentation/__init__.py
+# Empty file - just marks as package
+```
+
+Or with exports:
+
+```python
+# src/data_module/__init__.py
+from .dataset import DatasetFactory, register_dataset
+from .augmentation import AugmentationFactory
+```
+
+## Naming Conventions
+
+### Files
+
+- **Modules**: `simple_dataset.py`, `custom_model.py`
+- **Pipelines**: `training.sh`, `inference.sh`
+- **Configs**: `config.yaml`, `brain_decoder.yaml`
+- **Utilities**: `get_optimizer.py`, `helpers.py`, `compute_metrics.py`
+
+### Classes and Functions
+
+```python
+# Classes: PascalCase
+class SimpleDataset(Dataset):
+ pass
+
+class MyCustomModel(nn.Module):
+ pass
+
+# Functions and variables: snake_case
+def compute_accuracy(predictions, labels):
+ pass
+
+def get_optimizer(cfg):
+ pass
+
+learning_rate = 0.001
+batch_size = 32
+```
+
+### Constants
+
+```python
+# Constants: UPPER_SNAKE_CASE
+DEFAULT_HIDDEN_DIM = 256
+MAX_EPOCHS = 100
+LEARNING_RATE = 0.001
+```
+
+## Docstrings
+
+Use Google-style docstrings:
+
+```python
+def DatasetFactory(data_name: str) -> type:
+ """Create dataset class by name.
+
+ Args:
+ data_name: Name of the dataset to create.
+
+ Returns:
+ Dataset class if found, otherwise simple dataset.
+
+ Raises:
+ ValueError: If no dataset is found and no default exists.
+ """
+ pass
+```
+
+## Configuration-Driven Classes
+
+Model classes must be config-driven:
+
+```python
+@register_model('MyModel')
+class MyModel(nn.Module):
+ def __init__(self, cfg):
+ """Initialize model from config.
+
+ Args:
+ cfg: Hydra config object with model attributes.
+ """
+ super().__init__()
+ self.cfg = cfg
+
+ # ALL parameters from cfg
+ self.hidden_dim = cfg.model.hidden_dim
+ self.output_dim = cfg.dataset.target_size[cfg.dataset.task]
+ self.dropout = cfg.model.dropout
+
+ def forward(self, x, labels=None, **kwargs):
+ """Forward pass.
+
+ Args:
+ x: Input tensor.
+ labels: Ground truth labels (training mode).
+ **kwargs: Additional arguments.
+
+ Returns:
+ Dict with loss, labels, and logits.
+ """
+ # Implementation
+ return {"loss": loss, "labels": labels, "logits": logits}
+```
+
+## Error Handling
+
+```python
+def DatasetFactory(data_name: str) -> type:
+ """Create dataset class by name."""
+ dataset = DATASET_FACTORY.get(data_name)
+ if dataset is None:
+ available = ', '.join(DATASET_FACTORY.keys())
+ raise ValueError(
+ f"Dataset '{data_name}' not found. "
+ f"Available: {available}"
+ )
+ return dataset
+```
+
+## Logging
+
+```python
+import logging
+
+logger = logging.getLogger(__name__)
+
+@register_dataset('custom')
+class CustomDataset(Dataset):
+ def __init__(self, cfg):
+ self.cfg = cfg
+ logger.info(f"Initializing {self.__class__.__name__}")
+ logger.debug(f"Config: {cfg.dataset}")
+```
+
+## Code Review Checklist
+
+- [ ] All functions have type hints
+- [ ] Imports are correctly ordered
+- [ ] Classes use PascalCase, functions use snake_case
+- [ ] Docstrings follow Google style
+- [ ] Model classes are config-driven
+- [ ] Registration decorators are used
+- [ ] Error messages are informative
+- [ ] Logging is added for key operations
diff --git a/.agents/skills/architecture-design/references/factory_pattern.md b/.agents/skills/architecture-design/references/factory_pattern.md
new file mode 100644
index 0000000..f700dd4
--- /dev/null
+++ b/.agents/skills/architecture-design/references/factory_pattern.md
@@ -0,0 +1,53 @@
+# Factory Pattern
+
+## Overview
+
+The Factory pattern allows dynamic creation of instances without specifying the exact class. Each module uses a factory to decouple creation from usage.
+
+## Structure
+
+```python
+# In module __init__.py (e.g., data_module/dataset/__init__.py)
+DATASET_FACTORY: Dict[str, type] = {}
+
+def DatasetFactory(data_name: str):
+ """Create dataset instance by name."""
+ dataset = DATASET_FACTORY.get(data_name, None)
+ if dataset is None:
+ # Fallback to default
+ dataset = DATASET_FACTORY.get('simple')
+ return dataset
+```
+
+## Usage
+
+```python
+# Consumer code doesn't need to know concrete class
+dataset = DatasetFactory(cfg.dataset.name)
+```
+
+## Benefits
+
+- **Loose coupling**: Consumer doesn't import concrete classes
+- **Extensibility**: Add new types without changing consumer code
+- **Fallback handling**: Graceful degradation for unknown types
+- **Centralized registry**: Single source of truth for available types
+
+## Implementation Details
+
+1. Define factory dict at module level
+2. Factory function handles lookup and fallback
+3. Return class (not instance) for deferred initialization
+4. None result triggers fallback to default implementation
+
+## Common Patterns
+
+```python
+# With config integration
+def DatasetFactory(cfg):
+ data_name = cfg.dataset.name
+ dataset_cls = DATASET_FACTORY.get(data_name)
+ if dataset_cls is None:
+ raise ValueError(f"Unknown dataset: {data_name}")
+ return dataset_cls(cfg)
+```
diff --git a/.agents/skills/architecture-design/references/registry_pattern.md b/.agents/skills/architecture-design/references/registry_pattern.md
new file mode 100644
index 0000000..0b9c34e
--- /dev/null
+++ b/.agents/skills/architecture-design/references/registry_pattern.md
@@ -0,0 +1,102 @@
+# Registry Pattern
+
+## Overview
+
+The Registry pattern allows components to register themselves via decorators, enabling automatic discovery and centralized management of available types.
+
+## Structure
+
+```python
+# In module __init__.py (e.g., data_module/dataset/__init__.py)
+from typing import Dict, Callable, TypeVar
+
+T = TypeVar('T')
+
+DATASET_FACTORY: Dict[str, type] = {}
+
+def register_dataset(name: str) -> Callable[[T], T]:
+ """Decorator to register dataset classes."""
+ def decorator(cls: T) -> T:
+ DATASET_FACTORY[name] = cls
+ return cls
+ return decorator
+```
+
+## Usage
+
+```python
+# In implementation file (e.g., simple_dataset.py)
+from data_module.dataset import register_dataset
+
+@register_dataset("simple")
+class SimpleDataset(Dataset):
+ def __init__(self, cfg):
+ # Implementation
+ pass
+```
+
+## Benefits
+
+- **Automatic registration**: Components register themselves on import
+- **Declarative**: Single decorator line replaces manual registration code
+- **Import-time discovery**: Auto-import pattern finds all implementations
+- **Type-safe**: Preserves original class type
+
+## Implementation Details
+
+1. Decorator returns the class unchanged (for immediate use)
+2. Side effect: adds class to factory dict
+3. Name parameter must be unique per module
+4. Registration happens at module import time
+
+## Advanced Patterns
+
+### Registration with Config
+
+```python
+def register_model(name: str):
+ def decorator(cls):
+ MODEL_FACTORY[name] = cls
+ # Add config validation
+ cls._config_schema = getattr(cls, '_config_schema', {})
+ return cls
+ return decorator
+```
+
+### Conditional Registration
+
+```python
+def register_dataset(name: str, experimental: bool = False):
+ def decorator(cls):
+ if not experimental or cfg.enable_experimental:
+ DATASET_FACTORY[name] = cls
+ return cls
+ return decorator
+```
+
+### Multi-Registry
+
+```python
+# Multiple registries in one module
+DATASET_FACTORY = {}
+AUGMENTATION_FACTORY = {}
+
+def register_dataset(name: str):
+ def decorator(cls):
+ DATASET_FACTORY[name] = cls
+ return cls
+ return decorator
+
+def register_augmentation(name: str):
+ def decorator(fn):
+ AUGMENTATION_FACTORY[name] = fn
+ return fn
+ return decorator
+```
+
+## Best Practices
+
+- **Unique names**: Use descriptive, unique registration names
+- **Documentation**: Document required parameters in class docstring
+- **Validation**: Validate config in `__init__`, not in decorator
+- **Consistency**: Use same naming convention across modules
diff --git a/.agents/skills/architecture-design/references/structure.md b/.agents/skills/architecture-design/references/structure.md
new file mode 100644
index 0000000..fcd6b09
--- /dev/null
+++ b/.agents/skills/architecture-design/references/structure.md
@@ -0,0 +1,150 @@
+# Detailed Directory Structure
+
+This document provides a comprehensive breakdown of the ML project template directory structure.
+
+## Root Level Files
+
+| File | Purpose |
+|------|---------|
+| `README.md` | Project documentation, installation guide, usage examples |
+| `TODO.md` | Task tracking with weekly focus and daily tasks |
+| `.gitignore` | Git ignore patterns for Python, Jupyter, IDEs, logs, cache |
+| `pyproject.toml` | Project configuration for build system and dependencies |
+| `uv.lock` | Locked dependency versions for reproducibility |
+
+## run/ - Execution Layer
+
+### pipeline/
+
+Main workflow scripts organized by stage:
+
+| Directory | Purpose |
+|-----------|---------|
+| `training/` | Training execution scripts (training.sh, inference.sh) |
+| `prepare_data/` | Data preparation and preprocessing pipelines |
+| `analysis/` | Evaluation and analysis workflows |
+
+### conf/
+
+Hydra configuration files organized by module:
+
+| Directory | Purpose |
+|-----------|---------|
+| `training/` | Training hyperparameters, model configs, optimizer settings |
+| `dataset/` | Dataset configurations, data paths, preprocessing options |
+| `model/` | Model architecture configurations |
+| `prepare_data/` | Data preparation parameters |
+| `analysis/` | Analysis and evaluation configurations |
+| `dir/` | Directory path configurations |
+| `analysis/` | Analysis-specific settings |
+
+## src/ - Source Code Layer
+
+### data_module/ - Data Processing Module
+
+```
+data_module/
+├── __init__.py # Module exports
+├── utils.py # Data-specific utility functions
+├── dataset/ # Dataset implementations
+│ ├── __init__.py # Dataset factory and registry
+│ └── simple_dataset.py # Simple dataset example
+├── augmentation/ # Data augmentation methods
+│ ├── __init__.py
+│ ├── mixup.py # Mixup augmentation
+│ ├── random_shift.py # Random shifting
+│ ├── channel_mask.py # Channel masking
+│ ├── time_masking.py # Time masking
+│ └── add_noise.py # Noise injection
+├── collate_fn/ # Batch collation functions
+│ ├── __init__.py
+│ └── simple_collate_fn.py
+├── compute_metrics/ # Metrics computation
+│ ├── __init__.py
+│ └── simple_compute_metrics.py
+├── prepare_data/ # Data preparation logic
+│ ├── __init__.py
+│ ├── prepare_data.py
+│ └── generate_yaml.py
+└── data_func/ # Data utility functions
+ ├── __init__.py
+ └── simple_data_func.py
+```
+
+### model_module/ - Model Module
+
+```
+model_module/
+├── __init__.py # Module exports
+└── model/ # Model implementations
+ └── [model files]
+```
+
+### trainer_module/ - Training Module
+
+Contains training loop logic, validation, and checkpoint management.
+
+### analysis_module/ - Analysis Module
+
+Contains evaluation, visualization, and result analysis code.
+
+### llm/ - LLM Module
+
+LLM-related code and integrations.
+
+### utils/ - Shared Utilities
+
+```
+utils/
+├── __init__.py
+├── helpers.py # Helper functions (import_modules, etc.)
+├── logging.py # Logging configuration
+├── get_optimizer.py # Optimizer factory
+├── get_scheduler.py # Learning rate scheduler factory
+├── get_callback.py # Training callbacks
+├── get_activation.py # Activation functions
+└── get_checkpoint_aggregation.py # Checkpoint handling
+```
+
+## data/ - Data Layer
+
+Following the Cookiecutter Data Science standard:
+
+| Directory | Purpose |
+|-----------|---------|
+| `raw/` | Original, immutable data dump |
+| `processed/` | Cleaned, transformed data ready for use |
+| `external/` | Data from third-party sources |
+
+## outputs/ - Output Layer
+
+| Directory | Purpose |
+|-----------|---------|
+| `logs/` | Training logs, tensorboard logs |
+| `checkpoints/` | Model checkpoints for resuming training |
+| `tables/` | Result tables, CSV outputs |
+| `figures/` | Plots, visualizations, figures |
+
+## Module Interaction Flow
+
+```
+run/pipeline/ -> src/trainer_module/ -> src/model_module/
+ src/data_module/ src/utils/
+ src/utils/
+
+run/conf/ -> Hydra config loader -> All modules
+```
+
+## File Naming Conventions
+
+- **Modules**: `simple_dataset.py`, `custom_model.py`
+- **Pipelines**: `training.sh`, `inference.sh`
+- **Configs**: `config.yaml`, dataset-specific names
+- **Utilities**: Descriptive names (`get_optimizer.py`, `helpers.py`)
+
+## Python Package Structure
+
+Each module is a proper Python package:
+- Has `__init__.py` with factory/registry logic
+- Can be imported as `from src.module import Component`
+- Subpackages are automatically discovered via `import_modules()`