Instructions for AI agents working on the terni crate.
terni — ternary error handling for Rust. The type is Imperfect<T, E, L: Loss>.
Three states: Success(T), Partial(T, L), Failure(E, L).
Package name on crates.io: terni.
Repo directory: imperfect/ (historical).
cd /Users/alexwolf/dev/projects/prism/imperfect
nix develop -c cargo test
nix develop -c cargo test --doc
nix develop -c cargo clippy --all-targets
nix develop -c cargo fmt --all -- --check
nix develop -c cargo llvm-cov --workspace --fail-under-lines 99Bare cargo is not in PATH. Always use nix develop -c cargo ....
Non-negotiable. Every test must be proven real.
- Write the test with the correct assertion. The test is the specification.
- Break the implementation deliberately. Make the code path return the wrong thing.
- Run tests. The test must fail. This proves it catches the bug.
- Commit
🔴— broken code + correct test = failing. - Restore the implementation. Undo the deliberate break.
- Run tests. The test must pass.
- Commit
🟢— correct code + correct test = passing.
- The TEST is always correct. Never write a wrong assertion.
- The CODE breaks deliberately. You introduce a temporary bug.
- A test that was never red is a test that potentially lies.
- If a test passes despite broken code, the test is worthless. Delete it.
- The git log proves both states existed.
Every commit message must start with a phase marker:
| Marker | Phase | Tests must... |
|---|---|---|
🔴 |
Red | Fail (deliberately broken code) |
🟢 |
Green | Pass |
♻️ |
Refactor | Pass (no new behavior) |
🔧 |
Tooling | Pass (infrastructure/config) |
🔀 |
Merge | Pass |
The pre-commit hook enforces this.
Each agent commits as themselves:
| Agent | Role | |
|---|---|---|
| Reed | reed@systemic.engineer | Supervisor, architecture |
| Mara | mara@systemic.engineer | Builder, tests, coverage |
| Glint | glint@systemic.engineer | Polish, docs, release |
| Taut | taut@systemic.engineer | Benchmarks, performance |
| Seam | seam@systemic.engineer | Adversarial review, security |
git commit --author="Name <name@systemic.engineer>" -m "🟢 message"GPG signing is configured. Commits are signed automatically.
Line coverage gate: 99%. Enforced by CI and pre-push hook.
nix develop -c cargo llvm-cov --workspace --fail-under-lines 99- Monomorphization phantoms: Generic code produces separate LLVM
monomorphizations per type parameter combination. Some match arms in
generic functions show as "uncovered" because no test instantiates
that specific
(T, E, L)combination through that arm. These are phantom regions, not real uncovered code. - Stale profdata: After significant refactors, run
cargo clean && cargo llvm-cov clean --workspacebefore re-running coverage.
.eh() // the shrug
.imp() // the name
.tri() // the mathSame operation. Three names. The terni-functor bind.
Imperfect::success(value) // Success(value)
Imperfect::partial(value, loss) // Partial(value, loss)
Imperfect::failure(error) // Failure(error, L::zero())
Imperfect::failure_with_loss(error, l) // Failure(error, l)let mut eh = Eh::new();
let a = eh.eh(some_operation())?; // accumulates loss, ? on Result
eh.finish(a) // wraps with accumulated loss#[must_use] — dropping Eh without .finish() discards loss.
pub trait Loss: Clone + Default {
fn zero() -> Self;
fn total() -> Self;
fn is_zero(&self) -> bool;
fn combine(self, other: Self) -> Self;
}Shipped loss types: ConvergenceLoss, ApertureLoss, RoutingLoss.
Stdlib impls: Vec<T>, HashSet<T>, BTreeSet<T>, String, usize, u64, f64, (A, B).
- Do NOT add
ShannonLossback. It was removed deliberately. - Do NOT add a default type parameter to
Imperfect. It was removed deliberately. - Do NOT skip the red phase. Ever.
- Do NOT lower the coverage threshold.
- Do NOT add dependencies without discussion.
- Do NOT rename the type
Imperfect. The crate isterni. The type isImperfect. - Do NOT write in Alex's voice. Agent writes as agent.
src/lib.rs — everything. Single-file crate.
benches/ — criterion benchmarks
docs/ — detailed documentation
benchmarks.md
context.md
flight-recorder.md
loss-types.md
migration.md
pipeline.md
terni-functor.md
The cost of honesty is 0.65 nanoseconds per step, only when there's something to be honest about. Otherwise: zero.