Skip to content

Latest commit

 

History

History
172 lines (127 loc) · 4.88 KB

File metadata and controls

172 lines (127 loc) · 4.88 KB

Agents

Instructions for AI agents working on the terni crate.

The 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).

Build

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 99

Bare cargo is not in PATH. Always use nix develop -c cargo ....

TDD Discipline

Non-negotiable. Every test must be proven real.

The arc

  1. Write the test with the correct assertion. The test is the specification.
  2. Break the implementation deliberately. Make the code path return the wrong thing.
  3. Run tests. The test must fail. This proves it catches the bug.
  4. Commit 🔴 — broken code + correct test = failing.
  5. Restore the implementation. Undo the deliberate break.
  6. Run tests. The test must pass.
  7. Commit 🟢 — correct code + correct test = passing.

What this means

  • 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.

Phase markers

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.

Commit Identity

Each agent commits as themselves:

Agent Email 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.

Coverage

Line coverage gate: 99%. Enforced by CI and pre-push hook.

nix develop -c cargo llvm-cov --workspace --fail-under-lines 99

Known LLVM coverage quirks

  • 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 --workspace before re-running coverage.

API Surface

Three aliases for the bind

.eh()  // the shrug
.imp() // the name
.tri() // the math

Same operation. Three names. The terni-functor bind.

Constructors

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)

The Eh context

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.

Loss trait

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).

What NOT to do

  • Do NOT add ShannonLoss back. 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 is terni. The type is Imperfect.
  • Do NOT write in Alex's voice. Agent writes as agent.

File Layout

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 Headline

The cost of honesty is 0.65 nanoseconds per step, only when there's something to be honest about. Otherwise: zero.