|
| 1 | +# AGENTS.md — CubeDynamics Repository Operating Guide |
| 2 | + |
| 3 | +This file is for autonomous/human coding agents working in this repo. It explains **how the project is organized**, **what is considered stable vs internal**, and **how to safely modify/debug/test changes**. |
| 4 | + |
| 5 | +## 1) Project identity and architectural intent |
| 6 | + |
| 7 | +- Package name: `cubedynamics` (formerly `climate_cube_math`). |
| 8 | +- Core idea: a **grammar of operations** for spatiotemporal cubes using `pipe(cube) | verb() | verb()`. |
| 9 | +- Design goals: |
| 10 | + - **Streaming-first** and laziness-preserving behavior. |
| 11 | + - **Composable verbs** (small transformations with minimal side effects). |
| 12 | + - Consistent cube semantics with explicit space/time dimensions. |
| 13 | + |
| 14 | +Primary references: |
| 15 | +- `README.md` |
| 16 | +- `src/cubedynamics/piping.py` |
| 17 | +- `docs/project/public_api.md` |
| 18 | + |
| 19 | +## 2) Source-of-truth directories (important) |
| 20 | + |
| 21 | +### Runtime package code (primary) |
| 22 | +- `src/cubedynamics/**` is the actual package installed via `pyproject.toml` (`package-dir = "src"`). |
| 23 | + |
| 24 | +### Legacy/doc mirror code (secondary) |
| 25 | +- `code/cubedynamics/**` is a legacy/doc-oriented mirror used by documentation tooling and some guardrail tests. |
| 26 | +- **Do not assume `code/` is authoritative** for runtime behavior. |
| 27 | +- If a change touches patterns checked in `code/` tests (e.g., eager compute bans), verify relevant tests continue to pass. |
| 28 | + |
| 29 | +### Tests |
| 30 | +- Main regression suite: `tests/**`. |
| 31 | +- Additional package-internal tests: `src/cubedynamics/tests/**`. |
| 32 | + |
| 33 | +### Docs |
| 34 | +- MkDocs site content under `docs/**` and nav in `mkdocs.yml`. |
| 35 | + |
| 36 | +## 3) Public API vs internal modules |
| 37 | + |
| 38 | +Use this boundary when making changes: |
| 39 | + |
| 40 | +### Public/canonical API (prefer to extend here) |
| 41 | +- `cubedynamics` top-level namespace (`src/cubedynamics/__init__.py`) |
| 42 | +- Pipe system: |
| 43 | + - `cubedynamics.piping.pipe` |
| 44 | + - `cubedynamics.piping.Pipe` |
| 45 | +- Verb namespace: `cubedynamics.verbs` (`from cubedynamics import verbs as v`) |
| 46 | +- Public loaders exposed from `cubedynamics` and `cubedynamics.data.*` |
| 47 | + |
| 48 | +### Internal/unstable (safe to refactor carefully) |
| 49 | +- `cubedynamics.ops*`, `cubedynamics.streaming*`, `cubedynamics.ops_fire*`, |
| 50 | + `cubedynamics.ops_io*`, `cubedynamics.plotting*`, `cubedynamics.viewers*`, |
| 51 | + `cubedynamics.utils*`, `cubedynamics.config`. |
| 52 | + |
| 53 | +### Legacy compatibility |
| 54 | +- Renamed/legacy aliases are intentionally retained with deprecation strategy. |
| 55 | +- Preserve backwards compatibility unless the task explicitly removes deprecated paths. |
| 56 | + |
| 57 | +## 4) Core programming model you must preserve |
| 58 | + |
| 59 | +## Pipe and verbs |
| 60 | +- `pipe(value)` wraps values in `Pipe`. |
| 61 | +- `Pipe.__or__` applies callable stages in sequence. |
| 62 | +- Verbs are commonly factories returning inner callables (`verb(args...) -> _op(cube)`). |
| 63 | +- Some verbs are **pass-through side-effect verbs** (e.g., plotting/viewers): preserve chainability and viewer attachment behavior. |
| 64 | + |
| 65 | +## Cube shape and metadata conventions |
| 66 | +- Standard dims/constants in `src/cubedynamics/config.py`: |
| 67 | + - time: `time` |
| 68 | + - spatial: `y`, `x` |
| 69 | + - optional: `band` |
| 70 | +- Spatial verbs should follow `docs/design/spatial_dataset_contract.md`: |
| 71 | + - reliable spatial-dim inference |
| 72 | + - CRS inference precedence |
| 73 | + - boundary-inclusive geometry semantics |
| 74 | + - strict failure on ambiguous dimensions/CRS |
| 75 | + |
| 76 | +## Streaming/lazy expectations |
| 77 | +- Avoid eager `.compute()` in library paths unless truly required. |
| 78 | +- Avoid eager disk IO side effects in core transformations. |
| 79 | +- Keep VirtualCube workflows lazy until explicit materialization (`VirtualCube.materialize()`). |
| 80 | + |
| 81 | +## 5) Data/loaders overview (what talks to network) |
| 82 | + |
| 83 | +Data sources/loaders are in: |
| 84 | +- `src/cubedynamics/data/gridmet.py` |
| 85 | +- `src/cubedynamics/data/prism.py` |
| 86 | +- `src/cubedynamics/data/sentinel2.py` |
| 87 | +- Streaming wrappers in `src/cubedynamics/streaming/` and `src/cubedynamics/prism_streaming.py` |
| 88 | + |
| 89 | +Many integration/online tests require external services/network; keep unit paths offline-friendly. |
| 90 | + |
| 91 | +## 6) Testing strategy and required commands |
| 92 | + |
| 93 | +Pytest markers are defined in `pytest.ini`: |
| 94 | +- `integration` → external services / heavier paths |
| 95 | +- `online` → explicit network/cubo dependence |
| 96 | +- `streaming` → laziness/streaming behavior |
| 97 | + |
| 98 | +Recommended validation flow after code changes: |
| 99 | +1. Fast local/offline suite: |
| 100 | + - `pytest -m "not integration" -q` |
| 101 | +2. Targeted tests for touched area: |
| 102 | + - e.g., `pytest tests/test_plot_verb.py -q` |
| 103 | +3. Optional/full if needed: |
| 104 | + - `pytest -q` |
| 105 | +4. If docs or API docs changed: |
| 106 | + - `mkdocs build --strict` |
| 107 | + |
| 108 | +## 7) Safe edit playbook for common tasks |
| 109 | + |
| 110 | +## Add/modify a verb |
| 111 | +1. Implement in appropriate module (`verbs/` and/or underlying `ops/` internals). |
| 112 | +2. Preserve factory style and pipe compatibility. |
| 113 | +3. Re-export in `src/cubedynamics/verbs/__init__.py`. |
| 114 | +4. If publicly intended, ensure top-level exposure/docs alignment as needed. |
| 115 | +5. Add/adjust tests for direct call + pipe use. |
| 116 | + |
| 117 | +## Modify plotting/viewer behavior |
| 118 | +1. Check invariants docs first: |
| 119 | + - `docs/dev/viewer_backend.md` |
| 120 | + - `docs/dev/cube_viewer_invariants.md` |
| 121 | +2. Keep cube-attached elements under cube transform node. |
| 122 | +3. Do not break time-axis orientation assumptions (front/newest convention). |
| 123 | +4. Run viewer-related tests (`tests/test_cube_viewer*.py`, plotting tests). |
| 124 | + |
| 125 | +## Modify spatial/fire workflows |
| 126 | +1. Follow Spatial & CRS contract exactly. |
| 127 | +2. Ensure reprojection rules and boundary semantics remain correct. |
| 128 | +3. Run fire/hull + spatial tests. |
| 129 | + |
| 130 | +## 8) Debugging checklist |
| 131 | + |
| 132 | +When debugging a failure, quickly classify it: |
| 133 | + |
| 134 | +- **API/export issue** |
| 135 | + - Check `src/cubedynamics/__init__.py` and `src/cubedynamics/verbs/__init__.py` exports. |
| 136 | +- **Pipe semantics issue** |
| 137 | + - Reproduce with tiny synthetic cube and direct `pipe(...) | ...` chain. |
| 138 | + - Inspect pass-through flags/attachments in `piping.py`. |
| 139 | +- **Viewer regression** |
| 140 | + - Use `tools/debug_viewer_pipeline.py`. |
| 141 | + - Confirm axis rig invariants and coordinate orientation. |
| 142 | +- **Spatial/CRS mismatch** |
| 143 | + - Verify inferred dims/EPSG precedence and date normalization rules. |
| 144 | +- **Unexpected eager compute/IO** |
| 145 | + - Search touched files for `.compute(`, `.to_netcdf(`, `.to_zarr(` and rerun relevant tests. |
| 146 | + |
| 147 | +## 9) Documentation and consistency rules |
| 148 | + |
| 149 | +- Keep docs aligned with actual API names and stability policy. |
| 150 | +- If a user-facing behavior changes, update the most relevant docs page(s) and changelog/development docs when appropriate. |
| 151 | +- Maintain terminology consistency: “CubeDynamics”, “pipe”, “verbs”, “spatiotemporal cube”, “streaming-first”. |
| 152 | + |
| 153 | +## 10) Practical command reference |
| 154 | + |
| 155 | +Environment setup: |
| 156 | +- `pip install -e .` |
| 157 | +- `pip install -r requirements.txt` (if full deps are needed) |
| 158 | + |
| 159 | +Useful targeted runs: |
| 160 | +- `pytest tests/test_public_api_smoke.py -q` |
| 161 | +- `pytest tests/test_piping_verbs.py tests/test_plot_verb.py -q` |
| 162 | +- `pytest -m "not integration" -q` |
| 163 | + |
| 164 | +Docs checks: |
| 165 | +- `mkdocs serve` |
| 166 | +- `mkdocs build --strict` |
| 167 | + |
| 168 | +## 11) Known pitfalls |
| 169 | + |
| 170 | +- Confusing `src/` (runtime truth) with `code/` (legacy/doc mirror). |
| 171 | +- Breaking pipe pass-through behavior for plotting verbs. |
| 172 | +- Violating CRS/dimension contract by silently guessing ambiguous spatial metadata. |
| 173 | +- Accidentally introducing eager compute/IO in core code paths. |
| 174 | +- Updating docs nav/content inconsistently. |
| 175 | + |
| 176 | +## 12) When in doubt |
| 177 | + |
| 178 | +- Prefer minimal, composable changes. |
| 179 | +- Preserve backward compatibility unless explicitly instructed otherwise. |
| 180 | +- Add a focused regression test for every bug fix. |
| 181 | +- Use synthetic small cubes for deterministic unit tests. |
0 commit comments