Skip to content

Principles

These principles are mandatory. They define what may live in a step package, what belongs in the framework, and how framework modules may depend on each other.

Violations break CI (test_step_domain_boundaries, test_layer_import_boundaries) and make steps non-portable across backends and runtimes.

Plane Question Doc
Step ↔ framework Who owns I/O, metrics, UI, orchestration? Step and framework
Inside framework Which package may import which? Framework layers
  1. Step = transform. Receive data → process → return data. No storage, Prometheus, Airflow, Ray, or file I/O in domain code.
  2. DRTML = contract. Params, datasets, feed, metrics, UI, and orchestration are declarative. Steps do not parse YAML.
  3. Framework owns the run. Feed, write, flush, checkpoint, metrics emit, Streamlit forms, Airflow/Ray transport — framework only.
  4. One dataset — one backend. No dual-write. Dispatch via registries, not if backend ==.
  5. Layers have a one-way edge.
    drtml → contracts / storage.plan → db | storage → processing → telemetry | integration
    Reverse edges are forbidden.
  6. domain.* is step-only. Framework may pass params through; it must not interpret domain fields.
  7. Algorithms = math. Policy (K, probe, early-stop) stays in the step; formulas live in framework/algorithms.
  8. Shared DTOs live in contracts/. Never copy saturation / worker-delta types into storage or telemetry.
framework package # platform runtime
drtml / storage / db / processing / algorithms / telemetry / integration …
step packages # DRTML + pure domain processors
(edge / ops / third-party)
platform stack # Docker, CLI, Grafana sync, Postgres bootstrap

Steps and platform must not become dependencies of framework Python (except contract tests that load step manifests).

Use the checklists on the detailed pages. Short version:

  1. Is this I/O / wire-format / metrics emit? → framework, not the step.
  2. New shared type across layers? → contracts/.
  3. New backend / mode / metric method? → register, do not grow an if-forest.
  4. Does the import reverse the layer edge? → redesign.
  5. Does framework Python mention a step id or domain.* field? → move out.