kitt_score
The decision engine at the core of Project KITT — a real-time, in-memory matcher that picks the highest-scoring action at a location, given that location's accumulated state.
The crate is transport-agnostic: no networking, no persistence, no renderer.
The host service (typically axum + tokio) owns I/O; see
examples/axum_host.rs for the intended integration
pattern.
Model
- A Location is an abstract entity (a screen, a session, a device — your choice) carrying reference data loaded at startup and dynamic state updated by events.
- Events come in three flavors:
StateUpdate,ActionIngest,Trigger. - An Action binds a string-backed
ActionId+ a scoring function + a generic payloadT+ a start/end validity window at a location. Engine<T>receives events and, on aTrigger, selects the highest-scoring valid action and returns its payload.
Two scoring backends ship today:
- Predicate DSL — a bytecode VM over typed slot reads
(e.g.
$audience.age > 18 AND $audience.country == "CH"). - Linear SIMD vector similarity — dot or cosine against a per-location
embedding, with runtime AVX2/AVX-512/NEON dispatch via
pulp.
An HNSW ANN backend was scoped and deferred; the Scorer trait keeps the
door open for re-introduction when per-location action fan-out grows past
the linear-scan sweet spot.
Quick start
use ;
use ;
use LocationDef;
use ;
use smallvec;
// 1. Declare the schema once; it's immutable after build.
let mut b = new;
let audience = b.kind;
let schema = b.build;
let aid_male = schema.attr.unwrap;
let aid_young = schema.attr.unwrap;
// 2. Build the engine. Payload type is whatever you want returned on a win.
let engine: = builder.schema.build.unwrap;
// 3. Upsert a location.
let loc = LocId;
engine.upsert_location.unwrap;
// 4. Register an action — a scorer + payload, valid in [start, end).
engine.ingest_action;
// 5. Push state updates as they arrive from the outside world.
engine.ingest_update;
// 6. Fire a trigger and get the winning payload.
match engine.ingest_trigger
Performance
Design target: < 1 ms p99 per ingest_trigger on 10⁶ locations with
10–100 actions per location. Benchmarks in benches/ (run with
cargo bench) exercise the predicate VM, the linear dot/cosine kernels,
and end-to-end trigger throughput. See the design spec §9 for the full
performance model.
Observability
Engine::metrics() returns a MetricsSnapshot with trigger/register/update
counters and an HDR histogram of decide-latency percentiles. Enable the
serde feature to serialise it directly as JSON.
Concurrency
The engine is Send + Sync. Per-location updates are serialised through a
short-critical-section parking_lot::Mutex; reads across locations are
shard-parallel. Bulk reference-data reloads will use ArcSwap for tear-free
publishing (plumbing arriving post-v0.1.0). Core invariants are
model-checked under loom — run:
RUSTFLAGS="--cfg loom"
Documentation
- Design spec:
docs/superpowers/specs/2026-04-20-kitt-score-design.md - Implementation plan:
docs/superpowers/plans/2026-04-20-kitt-score-implementation.md - Host integration example:
examples/axum_host.rs
MSRV
Rust 1.75.
License
Dual-licensed under MIT or Apache-2.0.