# Agent Instructions: radiens-core-python

This is the next-generation implementation of the core Radiens Python client. It prioritizes stability, feature completeness, and proto-driven type safety using a strictly layered architecture with immutable domain models.

## Critical Setup Rules

- **NEVER use `pip`** directly. Always use `uv`.
- **NEVER modify `requirements.txt`** manually. Dependencies are managed through `pyproject.toml`.
- Python 3.12+ required
- Run `uv sync` to set up the environment

## Type Checking Workflow (Foundation Gate)

Type checking is the primary quality gate and change-detection mechanism.

1. Make changes
2. Run `uv run mypy --strict src/ tests/`
3. Fix ALL errors before considering code complete
4. Type errors cascade from `_converters/` outward — fixing converters automatically cascades fixes upward

**Pre-commit checklist** (run before every commit):

```bash
./scripts/check-fix.sh
```

This runs `ruff check --fix`, `ruff format`, `mypy --strict`, and `pytest` in sequence.

## Architecture & Layered Design

```text
src/radiens_core/
  models/                  # Pydantic v2, ZERO proto dependency
  _converters/             # Proto <-> domain (ONLY place importing _generated/)
  _services/               # RPC wrappers (domain in, domain out)
  _sub_clients/            # Domain-grouped API surfaces
  _transport/              # gRPC channels, auth, error mapping
  _generated/              # Proto stubs (DO NOT EDIT)
  specs.py                 # User-facing TimeRangeSpec, SignalSpec
  exceptions.py            # Exception hierarchy
  allego_client.py         # Real-time client
  videre_client.py         # Offline file client
  curate_client.py         # Curation client
```

### Critical Import Rules

| Layer | Can import from |
| --- | --- |
| `models/` | stdlib, pydantic, numpy only |
| `_converters/` | `models/`, `_generated/` |
| `_services/` | `_converters/`, `_generated/`, `_transport/`, `models/` |
| `_sub_clients/` | `_services/`, `models/`, `specs` |
| Client classes | `_sub_clients/`, `_transport/`, `models/` |

**Only** `_converters/` and `_services/` may import from `_generated/`. Nothing user-facing touches proto types. Breaking this rule defeats the architecture.

## Proto-Driven Type Safety

The type system is the change-detection mechanism. When proto stubs are regenerated in `_generated/`:

1. Copy updated `.pyi` and `_pb2.py` files from radix repo
2. Run `uv run mypy --strict src/` immediately
3. mypy will flag broken field references in `_converters/` with exact line numbers
4. Fix converters first — errors cascade upward to models → services → clients
5. Commit the updated `_generated/` alongside your fixes

## Key Conventions

- **`from __future__ import annotations`** everywhere (enables `TYPE_CHECKING` imports, makes annotations strings at runtime)
- **Pydantic models**: Use `# type: ignore[explicit-any]` on `class X(BaseModel):` line (required for disallow_any_explicit in strict mode)
- **Frozen models**: All domain models use `model_config = ConfigDict(frozen=True)` (immutable after creation)
- **`_generated/`**: Excluded from linting but mypy reads `.pyi` stubs for type info
