Expand description
wadachi-spec (轍) — the frecency-ranking core, shared fleet-wide.
This crate is zero-I/O on purpose: it owns exactly one thing — how a
path’s worn-ness is scored from when it was visited — and nothing else
(no SQLite, no filesystem, no clock except behind a trait). That lets every
consumer depend on it without dragging in storage: wadachi’s directory
store, skim-tab’s command history, and a zoxide import all rank through
apply so there is exactly one formula and they cannot drift.
It is authored as the pleme-io TYPED-SPEC + INTERPRETER TRIPLET:
- Typed border —
FrecencyRankingSpec+DecayKind+RankPhase(spec). - Authored Lisp spec —
specs/frecency.lispdeclares the canonical instances as data. - Interpreter —
applywalks the phases against a mockableFrecencyEnvironment(interp, [env]).
use wadachi_spec::{apply, FrecencyRankingSpec, DirEntry, MockEnvironment};
use chrono::NaiveDate;
let now = NaiveDate::from_ymd_opt(2026, 6, 9).unwrap().and_hms_opt(0, 0, 0).unwrap();
let env = MockEnvironment::at(now);
let spec = FrecencyRankingSpec::skimtab_parity();
let entries = vec![DirEntry {
path: "/code".into(),
visits: vec![now], // visited "now" → age 0 → score 1.0
discovered_only: false,
}];
let ranked = apply(&spec, entries, &env).unwrap();
assert!((ranked[0].score - 1.0).abs() < 1e-9);Re-exports§
pub use env::FrecencyEnvironment;pub use env::MockEnvironment;pub use env::RealEnvironment;pub use interp::apply;pub use interp::SpecError;pub use spec::DecayKind;pub use spec::DirEntry;pub use spec::FrecencyRankingSpec;pub use spec::RankPhase;pub use spec::RankedDir;
Modules§
- env
- The interpreter’s one side effect — the clock — behind a trait so tests are deterministic with no real time, no DB, no flake.
- interp
- The frecency interpreter — walks a
FrecencyRankingSpec’s phases over a set ofDirEntrycandidates and returns them ranked. The clock is the only side effect, supplied viaFrecencyEnvironment, so the whole thing is deterministic under test. - spec
- Typed border for the frecency-ranking algorithm.