# Adding a backend or kernel

A new backend is complete only when its source, package resources, parity,
physical evidence, and consumer integration land together.

## 1. Choose the owning domain

Place the implementation under IO, detector, DPC, display, SSB, or another
existing scientific domain. If no domain owns the operation, define the
backend-neutral contract before writing accelerator code.

Do not create `cuda_*`, `mps_*`, `metal_*`, or `webgpu_*` public workflows.
Public callers select a backend through the domain API and receive the same
result/provenance model.

## 2. Freeze the reference

Record the current public call, fixture hash, parameters, output shape/dtype,
output hashes, floating metrics, and accepted tolerances. Include odd and
rectangular geometry and incomplete edge bins where applicable.

The backend under development cannot generate its own acceptance golden.

## 3. Implement without hidden policy

The backend may change memory layout, batching, fusion, scheduling, or kernel
topology. It may not silently change crop, bin, mask, precision, objective, or
scientific output.

Resource estimators belong in `quantem.gpu`; a consuming application owns the
user-visible choice and reason for an automatic resource policy.

## 4. Package the source

Update the appropriate package-data or SwiftPM resources and add a source
presence/compile test. Browser sources remain beside their scientific domain.
Native clients consume Swift products rather than copied `.metal` files.

## 5. Add parity and hardware evidence

Update `tests/parity/backend_matrix.json`, add focused numerical tests, and run
the qualified physical-device gate. Record source revision, hardware/runtime,
memory, stage timings, and run-level results using the
[benchmark methodology](../performance/methodology.md).

## 6. Integrate consumers

Test each supported client through a local package override. Publish the shared
package first, then pin clients to the exact verified revision. A copied kernel
or client-side compatibility fork is not an integration.

## 7. Migrate paths safely

Move one domain per commit. A moved module keeps no import-only compatibility
shim or alias: every caller, in this repository and in every downstream package
that imports the old path, changes in the same coordinated change. Repeat the
parity gates before the move lands.
