This document defines the coding standards, API design rules, build system requirements, testing strategy, and documentation standards for this project. It is the reference for contributors and reviewers.
See also: ARCHITECTURE.md — source structure and dependency rules | SPEC.md — product scope and support philosophy
The codebase follows layered architecture with a strict dependency direction:
CLI / OFX Plugin
depends on
Public API (include/corridorkey/)
depends on
Core Logic (src/ — inference, post-process, frame I/O)
depends on
External Libraries (ONNX Runtime, OpenEXR, FFmpeg, MLX)
Rules:
- A lower layer never includes headers from a higher layer.
- External library types never appear in public headers in
include/corridorkey/; they are wrapped insrc/. - No circular dependencies.
| Principle | Application |
|---|---|
| S — Single Responsibility | Each class and file has one reason to change. ExrReader reads EXR. Despill does despill. |
| O — Open/Closed | New execution providers or image formats should be addable without modifying existing core code. |
| L — Liskov Substitution | Any ImageReader implementation is interchangeable through the base interface. |
| I — Interface Segregation | Clients depend only on the interfaces they use. The CLI does not see internal inference details. |
| D — Dependency Inversion | InferenceEngine depends on abstract session interfaces, not directly on ONNX Runtime types. |
This project explicitly prioritizes operational predictability, portable packaging, and stable integration over raw throughput or broad hardware coverage. Engineering decisions should reflect this: a robust, diagnostic-heavy runtime that behaves consistently on validated hardware matters more than claiming the widest possible compatibility.
- Const correctness. Everything that can be
constisconst. - RAII everywhere. No raw
new/delete. Usestd::unique_ptr,std::shared_ptr, or stack allocation. FFmpeg and OpenEXR C resources are wrapped in RAII handles. - No raw owning pointers. Non-owning observation via raw pointer or
std::spanis acceptable. - No global mutable state. Configuration is passed explicitly through parameters or dependency injection.
- No
std::exitorabortin library code. The library never terminates the process; it returnsResult<T>.
| Element | Convention |
|---|---|
| Functions, variables, files, namespaces | snake_case |
| Types (classes, structs, enums) | PascalCase |
| Constants and macros | UPPER_SNAKE_CASE |
| Private members | m_ prefix |
| File extensions | .hpp for headers, .cpp for implementation |
No abbreviations except established domain terms: fps, rgb, exr, io.
The library serves multiple frontends. These rules keep the API stable and frontend-agnostic.
- PIMPL pattern for the main
Engineclass. Implementation details are hidden from public headers for ABI stability. - Minimal public headers.
include/corridorkey/exposes only what external consumers need. - Symbol visibility is hidden by default. Only symbols marked with the
CORRIDORKEY_APImacro are exported.
- All operations that can fail use
std::expected<T, Error>return types. - Error types carry descriptive codes and messages usable in any UI context.
- The library does not throw exceptions across module boundaries where avoidable.
- Long-running operations accept a
ProgressCallbackfor progress reporting and cancellation. - The
Engineclass should be safe for concurrent read operations. - The library does not print to stdout or stderr. Output is via callback or result type.
OpenFX is a pure C API. A C++ exception escaping any exported OFX function will crash the host process immediately.
- All
extern "C"entry points andplugin_main_entrymust be wrapped in a top-leveltry/catch(...)block. - Internal exceptions must be caught, logged, and translated into a safe
OFX status code (e.g.,
kOfxStatFailed).
DaVinci Resolve schedules aggressive parallel render threads. Memory fragmentation in per-frame code causes OFX instability.
- Do not allocate
std::vector<T>or other heap containers inside per-pixel or per-frame functions. - Use persistent
ScratchStatestructs with pre-reserved capacity that are owned by the OFX instance lifecycle, not discarded at frame end.
ImageBufferowns pixel data.Image(std::span) is used for processing. Do not usestd::vector<float>for pixel data.- No heap allocation in hot loops.
- All pixel buffers are 64-byte aligned (AVX-512 / NEON compatible).
- Process rows in Y-major order for sequential memory access.
- Avoid branches inside pixel loops. Use
std::clamp,std::min,std::max. - Keep loops simple enough for the compiler auto-vectorizer.
- Use lookup tables instead of
std::poworstd::expin hot paths.
- All processing functions take
Imageviews (non-owningstd::span). - Use move semantics for
ImageBufferandFrameResultto transfer ownership without copying.
- Target-based only. No global commands (
include_directories,link_directories,add_definitions). Usetarget_include_directories,target_compile_definitions, andtarget_compile_options. CMakePresets.jsonis the source of truth for build configurations. It definesdebug,release,release-lto, and the macOS portable variants.- On Windows, use
scripts/windows.ps1as the canonical build and release entrypoint. The canonical release command isscripts/windows.ps1 -Task release -Version X.Y.Z. Lower-level Windows scripts are internal delegates for debugging the wrapper, not alternate release flows. If you invoke CMake directly, activate the MSVC developer environment first. - Windows packaging may proceed with a partial model set, but the generated artifacts must include explicit inventory and validation reports. Missing models are reportable packaging state; invalid packaged models that are present remain release blockers.
- Manifest mode via
vcpkg.jsonwith baseline pinned invcpkg-configuration.json. - Every dependency must have a
$commentinvcpkg.jsonexplaining why it exists. - No new dependencies without that comment.
- Strict warnings:
-Wall -Wextra -Wpedantic -Werror(GCC/Clang) or/W4 /WX(MSVC). - AddressSanitizer enabled in the
debugpreset.
| Tool | Purpose | Config |
|---|---|---|
| clang-format 18+ | Code formatting | .clang-format |
| clang-tidy 18+ | Static analysis and naming enforcement | .clang-tidy |
| pre-commit | Local file hygiene and documentation consistency | .pre-commit-config.yaml |
The authoritative configuration for each tool is its config file at the project root. Do not override tool settings in individual files.
Developer commits
|
pre-commit hook Fast (< 30s)
(staged files only) - clang-format
- file hygiene
|
Developer pushes
|
pre-push hook Thorough (< 5min)
(full codebase) - full release build
- all unit tests
- all integration tests
|
Repository CI (when configured)
- cross-platform build and test
Managed via pre-commit with configuration in
.pre-commit-config.yaml. Checks: formatting, trailing whitespace, YAML
syntax, large file detection, and documentation consistency.
Shell script at .githooks/pre-push. Runs a full release build, unit tests,
and integration tests. All must pass before the push proceeds.
E2E (few) Full binary, real models, real hardware
Integration Multiple modules, real files, no GPU
Unit (many) Single function or class in isolation
Single function or class, no external dependencies (no disk, no GPU, no model files). Each test must complete in under one second. Framework: Catch2 v3.
Test: color math (sRGB/linear conversions, edge cases), despill/despeckle with known input/output pairs, device detection logic, value type validation.
Do not unit test: thin wrappers around external libraries, trivial constructors, private implementation details.
Prevent specific bugs from reoccurring. Process: write a failing test that reproduces the bug, fix the bug, keep the test permanently.
Naming: test_regression_<issue_number>_<description>.
Regression tests are never deleted.
Multiple modules working together. May use real files from tests/fixtures/
(total fixture size should remain under 1 MB in the repository). No GPU.
Tests: file format round-trips (EXR, PNG, video), post-process chains, model loading and session creation with a small test model.
Full binary execution with real models, real files, real hardware. Slow and hardware-dependent. Run locally on demand, nightly in CI if configured, and mandatory before release.
| Tag | Scope | Schedule |
|---|---|---|
[unit] |
No I/O, no GPU | Every commit |
[integration] |
May use disk, no GPU | Every push and CI |
[e2e] |
Real model and hardware | Nightly and before release |
[regression] |
Bug reproductions | Same as parent level |
[benchmark] |
Performance tracking | Nightly |
Domain tags ([color], [frameio], [inference], [device]) are combined
with level tags.
main is the integration branch. It should remain releasable. Merge only
after local quality gates pass and review is complete. Do not commit directly
to main.
Branch prefixes: feat/, fix/, chore/, test/, refactor/.
Conventional Commits format. Prefixes:
feat, fix, test, refactor, chore, docs, perf.
Subject line: short imperative sentence. Body (optional): explains why, not what.
Development setup instructions are in CONTRIBUTING.md.
Documentation contains definitions and decisions. It describes what the project is, what it does, how it works, and why specific choices were made.
- Business context. Every document and every major section starts with why it exists and what problem it solves, before technical details.
- Definitions. Concrete terms, types, interfaces, behaviors, constraints.
- Current state. What is built, how it works, how to use it.
- Decisions. Choices that were made and the reasons behind them.
- Support claims tied to product tracks. Compatibility statements must
match packaged and validated product tracks in
help/SUPPORT_MATRIX.md. Backend enums, probes, or core-only provider hooks are not support claims by themselves.
- Speculation or unfounded plans. Use GitHub Issues for proposals.
- Historical notes. Git history and PRs serve that purpose.
- Dates, version stamps, or status markers in prose.
- Source code, except CLI usage examples in README that document the user interface.
- Emoji.
- Filler text ("this section will be expanded later"). If a section is not ready, it does not exist.
- Duplicated content. Each topic lives in one place.
| Document | Scope | Audience |
|---|---|---|
README.md |
What this is, how to install, how to use | Users |
CONTRIBUTING.md |
Dev environment setup, PR process | Contributors |
docs/SPEC.md |
Product scope and support philosophy | Architects, developers |
ARCHITECTURE.md |
Source structure and dependency rules | Developers |
docs/GUIDELINES.md |
Code standards, testing, build rules (this document) | Developers |
help/SUPPORT_MATRIX.md |
Support status by platform and hardware | Users, operators |
help/TROUBLESHOOTING.md |
Practical operational troubleshooting | Users, operators |
help/OFX_PANEL_GUIDE.md |
Practical OFX control guide for Resolve | Users, operators |
help/OFX_RESOLVE_TUTORIALS.md |
Step-by-step Resolve workflows | Users, operators |
docs/RELEASE_GUIDELINES.md |
Release build and packaging procedure | Release maintainers |
AGENTS.md |
Machine-readable rule summary for AI tools | AI tools |
CLAUDE.md |
Machine-readable rule summary for AI tools | AI tools |
Public API (include/corridorkey/): Doxygen-style comments on every public
function and class. States purpose, parameters, return value, preconditions,
and error conditions.
Internal code: comments explain why a decision was made — business reason, performance trade-off, workaround — not what the code does.
Do not write:
- Comments that restate what the code does.
- Commented-out code. Delete it; use version control.
- TODO or FIXME. Open a GitHub Issue.
- Plain English, professional tone.
- Active voice, direct statements.
- Concrete and specific.
- Technical terms defined on first use.
- Consistent terminology throughout.
- No network access in the core library. Model download is a separate CLI command, not implicit.
- Input validation at all system boundaries: file headers, resolution limits, parameter ranges.
- No shell command execution from the library.
- FFmpeg input is treated as untrusted. Use FFmpeg's built-in limits.
- Dependency audit via vcpkg vulnerability scanning in CI.