# Code Placement Decision Tree
Quick reference for determining where new code belongs in the two-layer architecture.
## Simple Decision Tree
```mermaid
flowchart TD
START([New code to write?]) --> Q1{Is it about building
validating/managing documents?}
Q1 -->|YES| L1[LAYER 1: INFRASTRUCTURE
Add to infrastructure/]
Q1 -->|NO| Q2{Does it implement research
algorithms/analysis?}
Q2 -->|YES| L2["LAYER 2: PROJECT
Add to projects/{name}/src/"]
Q2 -->|NO| RECONSIDER[Reconsider scope
or ask team]
classDef layer1 fill:#e1f5fe,stroke:#01579b,stroke-width:2px
classDef layer2 fill:#f1f8e9,stroke:#33691e,stroke-width:2px
classDef decision fill:#fff3e0,stroke:#e65100,stroke-width:2px
classDef warning fill:#ffebee,stroke:#c62828,stroke-width:2px
class L1 layer1
class L2 layer2
class Q1,Q2,START decision
class RECONSIDER warning
```
---
## Detailed Examples
### Questions to Ask
**1. Will this code be used in EVERY research project using this template?**
- YES → Infrastructure
- NO → Scientific
**2. Does this code validate or build outputs?**
- YES → Infrastructure
- NO → Scientific
**3. Is this code specific to our research domain?**
- YES → Scientific
- NO → Infrastructure
**4. Does this code depend on knowing what our research is about?**
- YES → Scientific
- NO → Infrastructure
**5. Would another research group reuse this code unchanged?**
- YES → Infrastructure
- NO → Scientific
---
## Layer 1: Infrastructure Examples
### ✅ Belongs in infrastructure/
**Build and Document Management:**
- PDF generation and LaTeX compilation
- Markdown file processing and validation
- Figure numbering and cross-referencing
- Image file management and insertion
- Document quality checking
- Cross-reference validation
**Example: Figure Manager**
```python
# infrastructure/documentation/figure_manager.py
class FigureManager:
"""Manage figure numbering and references.
This is infrastructure - works for ANY research project.
"""
def register_figure(
self,
filename: str,
caption: str,
label: Optional[str] = None,
section: Optional[str] = None,
**kwargs
) -> FigureMetadata:
"""Register a figure with automatic numbering."""
pass
def generate_latex_figure_block(self, label: str) -> str:
"""Generate LaTeX figure block."""
pass
```
**Publishing and Metadata:**
- DOI validation
- Citation generation (BibTeX, APA, etc.)
- Publication metadata extraction
- Academic profile integration
**Build Verification:**
- Build artifact checking
- Reproducibility verification
- Environment state capture
- File integrity validation
**Example: Integrity Verification**
```python
# infrastructure/validation/integrity/checks.py
def verify_output_integrity(
output_dir: str,
expected_files: List[str]
) -> bool:
"""Verify expected build artifacts exist.
This is infrastructure - validates ANY project's outputs.
"""
pass
```
### ❌ NOT Infrastructure
- Domain-specific algorithms
- Research-specific visualization
- Custom statistical analysis
- Project-specific data processing
- Experimental simulations
---
## Layer 2: Scientific Examples
### ✅ Belongs in projects/{name}/src/
**Algorithms and Computation:**
- Simulation implementations
- Statistical analysis
- Data processing specific to problem
- Optimization algorithms
- Model training/inference
**Example: Simulation**
```python
# projects/{name}/src/simulation.py
class MySimulation(SimulationBase):
"""Specific simulation for our research.
This is scientific - implements OUR algorithm.
"""
def step(self) -> None:
"""Execute one simulation step."""
# Our specific algorithm here
pass
```
**Data Generation and Processing:**
- Synthetic data generators for experiments
- Domain-specific preprocessing
- Feature extraction for analysis
- Dataset normalization
**Analysis and Reporting:**
- Statistical hypothesis testing
- Convergence analysis
- Performance metrics specific to problem
- Custom report generation
**Example: Analysis**
```python
# projects/{name}/src/analysis.py
def analyze_convergence(
results: np.ndarray,
tolerance: float
) -> Dict[str, Any]:
"""Analyze convergence of OUR algorithm.
This is scientific - domain-specific analysis.
"""
pass
```
**Visualization:**
- Domain-specific plots
- Research-specific visualizations
- Custom chart types for analysis
- Interactive visualizations
**Example: Plotting**
```python
# projects/{name}/src/plots.py
def plot_experimental_results(
data: Dict[str, np.ndarray]
) -> plt.Figure:
"""Plot results specific to our experiments.
This is scientific - domain-specific visualization.
"""
pass
```
### ❌ NOT Scientific
- Generic figure numbering (→ Infrastructure)
- PDF generation (→ Infrastructure)
- Document validation (→ Infrastructure)
- Generic plotting utilities (could be infrastructure)
- Cross-project utilities (→ Infrastructure)
---
## Gray Areas
### When Code Could Go Either Way
**Data Processing:**
- Generic preprocessing → Infrastructure (e.g., `normalize_data`)
- Domain-specific preprocessing → Scientific (e.g., `preprocess_brain_scans`)
**Visualization:**
- Generic plotting → Infrastructure (e.g., `plot_scatter`)
- Domain-specific plots → Scientific (e.g., `plot_convergence_with_our_metric`)
**Metrics:**
- Generic metrics → Infrastructure (e.g., `calculate_accuracy`)
- Domain-specific metrics → Scientific (e.g., `calculate_domain_score`)
**Strategies:**
1. If unsure, ask: "Could we use this in another project?"
2. If yes → Infrastructure
3. If the generic version goes to Infrastructure, specific version stays in Scientific
4. Example:
```python
# Infrastructure: Generic normalization
from infrastructure.data_processing import normalize_data # noqa: docs-lint
# Scientific: Use generic + add domain logic
def preprocess_our_data(raw_data):
normalized = normalize_data(raw_data)
# Add our specific processing here
return our_transform(normalized)
```
---
## Practical Workflow
### Starting a Feature
**Feature:** Add convergence analysis with custom stopping criterion
```mermaid
flowchart TB
S1[1 - Analyze the feature]
S1 --> S1A[Generic part:
benchmarking · performance measurement
→ infrastructure/scientific/benchmarking.py]
S1 --> S1B[Specific part:
our stopping criterion
→ projects/<name>/src/analysis.py]
S1 --> S1C[Decision: split into two files]
S1 --> S2[2 - Create infrastructure first]
S2 --> S2A[infrastructure/scientific/benchmarking.py
Generic timing/measurement ·
Reusable benchmark/report helpers ·
100% tested]
S2 --> S3[3 - Use infrastructure in project code]
S3 --> S3A[projects/<name>/src/analysis.py
Import from infrastructure ·
Add domain-specific logic ·
100% tested]
S3 --> S4[4 - Use project code in scripts]
S4 --> S4A[projects/<name>/scripts/analyze_results.py
Import from project.src ·
Orchestrate execution ·
Generate outputs]
S4 --> S5[5 - Document everywhere]
S5 --> S5A[infrastructure/scientific/AGENTS.md ·
projects/<name>/src/AGENTS.md ·
projects/<name>/scripts/AGENTS.md]
classDef step fill:#1e3a8a,stroke:#0f172a,color:#fff
classDef detail fill:#0f766e,stroke:#0f172a,color:#fff
class S1,S2,S3,S4,S5 step
class S1A,S1B,S1C,S2A,S3A,S4A,S5A detail
```
### Adding a New Data Processing Step
```mermaid
flowchart TB
Q[Question: Where does this belong?]
Q --> A1{For our specific
problem?}
A1 -- yes --> P1[Project layer
projects/<name>/src/data_processing.py
def process_our_specific_data(raw_data):
pass]
A1 -- no --> A2{Any research
could use this?}
A2 -- yes --> I1[Infrastructure layer
infrastructure/scientific/data_processing.py
def normalize_data(raw_data):
pass]
A2 -- both --> SPLIT{Generic + specific}
SPLIT --> I2[Infrastructure: Generic version
def normalize_data(raw_data, method="zscore")]
SPLIT --> P2[Project: Specific usage
def process_our_data(raw_data):
return normalize_data(..., method="our_method")]
classDef q fill:#1e3a8a,stroke:#0f172a,color:#fff
classDef p fill:#7c2d12,stroke:#0f172a,color:#fff
classDef i fill:#0f766e,stroke:#0f172a,color:#fff
class Q,A1,A2,SPLIT q
class P1,P2 p
class I1,I2 i
```
---
## Anti-Patterns
### ❌ Wrong: Infrastructure Imports Scientific
```python
# BAD: infrastructure/validation/integrity/checks.py
from project.src.simulation import MySimulation # ❌ Don't do this!
def verify_scientific_output(sim: MySimulation):
pass
```
**Problem:** Breaks abstraction, makes infrastructure project-specific
**Fix:** Move to scientific layer or refactor to use generic interfaces
### ❌ Wrong: Business Logic in Scripts
```python
# BAD: scripts/analysis.py
def custom_algorithm(data):
# Complex algorithm here ❌ Don't do this!
pass
# Scripts should orchestrate, not compute
```
**Problem:** Violates thin orchestrator pattern
**Fix:** Move to projects/{name}/src/, import in script
### ❌ Wrong: Duplicate Code Across Layers
```python
# BAD: infrastructure/plots.py
def plot_convergence(data):
pass
# BAD: projects/{name}/src/plots.py
def plot_convergence(data): # ❌ Duplicate!
pass
```
**Problem:** Maintenance nightmare, inconsistency
**Fix:** Keep in one layer, import from other if needed
### ❌ Wrong: Too Much in One Module
```python
# BAD: projects/{name}/src/everything.py - 2000+ lines
# Simulation, statistics, plotting, data processing...all mixed
# Better: Separate modules
# projects/{name}/src/simulation.py
# projects/{name}/src/statistics.py
# projects/{name}/src/plots.py
# projects/{name}/src/data_processing.py
```
**Problem:** Hard to test, understand, and maintain
**Fix:** One responsibility per module
---
## Common Questions
### "Where does utility function X go?"
1. Is it used by build/document generation? → Infrastructure
2. Is it used by scientific code? → Scientific
3. Is it used by both? → Both use each other appropriately
- Generic version in Infrastructure
- Specific version in Scientific
- Scientific imports Infrastructure
### "Where should orchestration scripts go?"
- Build/document orchestration → scripts/
- Business logic → src/
Scripts should be thin orchestrators that import from src/.
### "Should scientific code be in src/ or scripts/?"
- **projects/{name}/src/** - Business logic, algorithms, computations (tested)
- **projects/{name}/scripts/** - Orchestration and I/O (thin orchestrators, calls projects/{name}/src/)
Rule: If it can be tested independently, it goes in src/.
### "How do I use infrastructure code in scientific code?"
```python
# projects/{name}/src/my_analysis.py
from infrastructure.documentation import FigureManager, MarkdownIntegration
def analyze_and_report(data):
# Scientific computation
results = run_analysis(data)
# Use infrastructure for document management
fm = FigureManager()
fm.register_figure(
filename="results.png",
caption="Analysis results",
label="fig:results"
)
return results
```
✅ This is fine - scientific uses infrastructure
### "How do I use scientific code in infrastructure code?"
❌ **Don't.**
Infrastructure should be generic and not depend on specific research.
If you need to, reconsider:
- Is the code really infrastructure?
- Should it be in scientific layer instead?
- Can you extract the generic parts?
---
## Testing Location
Choose based on WHAT you're testing, not WHERE:
```python
# Infrastructure code → tests/infra_tests/
# tests/infra_tests/documentation/test_figure_manager.py
def test_figure_numbering():
fm = FigureManager()
fm.register_figure(filename="a.png", caption="Figure A", label="fig:a")
assert len(fm.figures) == 1
# Project code → projects/{name}/tests/
# projects/{name}/tests/test_simulation.py
def test_simulation_step():
sim = MySimulation()
sim.step()
assert sim.time == 1.0
# Integration tests → tests/integration/
# tests/integration/test_full_pipeline.py
def test_script_execution():
# Test that scientific scripts use infrastructure correctly
pass
```
---
## Summary Matrix
| Aspect | Infrastructure | Scientific |
|--------|---|---|
| **Location** | `infrastructure/` | `projects/{name}/src/` |
| **Purpose** | Build & validation tools | Algorithms & analysis |
| **Reusable** | Across all projects | Project-specific |
| **Examples** | PDF generation, figure mgmt | Simulation, statistics |
| **Dependencies** | Other infrastructure | Infrastructure + other scientific |
| **Testing** | `tests/infra_tests/` | `projects/{name}/tests/` |
| **Scripts** | `scripts/*.py` | `scripts/*.py` |
---
## Quick Reference
**For Infrastructure:**
```mermaid
flowchart TB
INFRA[Add to infrastructure/]
INFRA --> I1[If it helps build documents]
INFRA --> I2[If it validates outputs]
INFRA --> I3[If any project would use it]
INFRA --> I4[If it does not know about our research]
classDef root fill:#1e3a8a,stroke:#0f172a,color:#fff
classDef cond fill:#0f766e,stroke:#0f172a,color:#fff
class INFRA root
class I1,I2,I3,I4 cond
```
**For Project:**
```mermaid
flowchart TB
PROJ[Add to projects/<name>/src/]
PROJ --> P1[If it implements our algorithms]
PROJ --> P2[If it analyzes our data]
PROJ --> P3[If it visualizes our results]
PROJ --> P4[If it is specific to our research]
classDef root fill:#7c2d12,stroke:#0f172a,color:#fff
classDef cond fill:#0f766e,stroke:#0f172a,color:#fff
class PROJ root
class P1,P2,P3,P4 cond
```
---
When in doubt: **Ask yourself** — "Would another research group use this unchanged?" If yes → Infrastructure. If no → Scientific.
## See Also
- **[Two-Layer Architecture](../architecture/two-layer-architecture.md)** — Full system design overview