# Adding An Operation
Adding an operation means adding a permanent contract to the conformance
registry. The entry must be precise enough that two backend implementors can
produce identical bytes without asking for clarification.
## File To Create
Primitive operations live in Rust source files under:
```text
src/specs/primitive/<name>.rs
```
Start from the complete template:
```text
TEMPLATE_OP.rs
```
From the `vyre-conform/` crate root:
```sh
cp TEMPLATE_OP.rs src/specs/primitive/<name>.rs
```
Then replace every TODO slot in the copied file. The template includes all
boilerplate, imports, the CPU reference shape, the WGSL fragment shape, and the
`make_spec` call.
Template link: [../../TEMPLATE_OP.rs](../../TEMPLATE_OP.rs)
## Module Wire-Up
After creating `src/specs/primitive/<name>.rs`, wire it into the primitive
registry in `src/specs/primitive/mod.rs`.
Add the module declaration in the correct operation group:
```rust
pub mod <name>;
```
Add the spec to the `specs()` function:
```rust
<name>::spec(),
```
The operation is not registered until both lines exist. If either line is
missing, `cargo test --test algebra_self_test` cannot validate the new op.
## Required Fields
Every operation must provide:
- `id`: stable hierarchical identifier.
- `signature`: exact input and output types.
- `cpu_fn`: CPU reference function for point truth.
- `laws`: algebraic laws the operation satisfies.
- `equivalence_classes`: complete semantic input partition.
- `boundary_values`: every required edge input.
- `wgsl_fn`: canonical WGSL operation fragment for conformance dispatch.
- `comparator`: output comparison rule.
- `convention`: required calling convention.
- `version`: initial semantic version.
## CPU Reference
The CPU reference must be simple, deterministic, and correct by inspection. It
must handle every input, including empty buffers, short buffers, zero,
`u32::MAX`, overflow, underflow, masked shifts, out-of-bounds behavior, and any
operation-specific edge. It must not panic, read global state, call backend
code, or depend on time or randomness.
## Laws
Declare every law that is true and useful. Do not declare aspirational laws.
The suite self-tests the CPU reference against the law set; if the reference
violates a law, the operation entry is invalid.
When a law set does not uniquely characterize the function, document that
honestly and rely on the CPU reference as the tiebreaker. Partial laws are
valuable, but false completeness is harmful.
## Coverage
Equivalence class coverage must be complete. Every semantic region needs a
representative. Boundary value coverage must be complete. Every transition,
overflow point, zero case, maximum case, one-past-end case, and mask edge that
can change behavior must be listed.
Random generation is not a substitute for missing classes or missing
boundaries.
## WGSL Fragment
`wgsl_fn` must emit the operation fragment expected by the conformance wrapper.
For primitive scalar `u32` operations, the fragment must define:
```wgsl
fn vyre_op(index: u32, input_len: u32) -> u32
```
The fragment must implement the same semantics as `cpu_fn`, including edge
cases that hardware might otherwise treat differently. If the operation
requires a lookup buffer or different calling convention, declare it in the
spec rather than assuming backend-specific behavior.
Scalar inputs are available as `input.data[0u]`, `input.data[1u]`, and so on.
Keep WGSL edge behavior explicit. For example, guard shifts or rotations when a
backend language would otherwise make the edge undefined.
## Verification Commands
Run commands from the `vyre-conform/` crate root.
First run the algebra self-test for fast feedback:
```sh
cargo test --test algebra_self_test
```
If that passes, run the full suite:
```sh
cargo test
```
## If The Self-Test Fails
Treat a self-test failure as a critical specification bug.
- If the failure names a law, the CPU reference does not satisfy the declared
law. Fix the CPU reference or remove the false law.
- If the failure is a panic, fix `cpu_fn` so malformed, empty, or short input
returns the operation's defined default output.
- If the failure exposes a missing edge case, add that input to
`boundary_values` and make `cpu_fn` and `wgsl_fn` agree on the result.
- If no available law in `docs/algebra/laws/` truly applies, use
`spec.laws = Vec::new()` and rely on the CPU reference, equivalence classes,
and boundaries. Empty laws are acceptable for operations with no true useful
law.
- Do not keep an operation registered in `specs()` while
`cargo test --test algebra_self_test` is failing.
## Acceptance
An operation is ready when its CPU reference passes every declared law, every
equivalence class and boundary is reachable by the generators, parity tests can
compare backend output, and failures produce actionable diagnostics. An entry
that lacks a real reference, lacks coverage, or contains placeholder semantics
must not be registered.