Applies to all runner code under src/ and tests/. Keep it short; when in doubt, match the
surrounding code.
- Python 3.11+ (the reference sibling
openlan-schema-validatoris 3.10+; we standardize up). - ruff — lint and format (no separate black). CI fails on lint errors.
- mypy --strict — everything is type-hinted; no untyped public functions.
- pytest — the only test runner (see tdd.md).
- One concern per module. Prefer many small files over a few large ones. Soft cap ~300 lines.
- Every
src/package has a contractREADME.md— purpose, which spec/plan REQs it serves, its interface, its dependencies, and a "to work here read only: …" line. The card is the low-context entry point; keep it current with the code. - No cross-package reach-around. Depend on interfaces (ABCs), not concrete siblings.
- Black-box discipline. Runner code MUST NOT assume anything about DUT internals — no file paths, no SSH by default, no implementation knowledge. It acts only through the impersonated cloud and reads only the defined observation signals. (SSH is the one opt-in exception, gated by the manifest switch.)
- Determinism & pinning. No unpinned inputs. No direct
time.time()/randomin logic — inject aClock. Timing assertions are tolerance-based (e.g.10 s ± 2 s), never exact. - Interfaces first. Fixtures and DUT drivers are ABCs; concrete impls are swappable. Wiring
is dependency-injected via
RunContext— no global singletons, no import-time side effects. - Result taxonomy is sacred.
PASS/FAILare conformance verdicts;ERRORis a rig/oracle fault and is NOT a conformance result. A timeout is adjudicated by a rig health check →ERRORonly if a fixture is unhealthy, elseFAIL. Never collapse these. - Evidence, always. An assertion records the exact timeline events that decided it. A
FAILwith no captured evidence is a bug in the test, not a result. - Naming to avoid the collision.
src/suites/= certification scenarios (the product).tests/= the runner's own unit/component tests. Never blur the two in names or docs.
- Snake_case modules/functions, PascalCase classes, SCREAMING_CASE constants.
- Public functions/classes carry docstrings stating intent and, for assertions, the REQ they map to.
- Errors: raise typed exceptions;
RigError(→ ERROR) is distinct from a conformanceFAIL. - No secrets or private keys in the tree except pre-created test PKI material under the pinned bundle path (see ../src/pki/README.md).