package main import ( "github.com/kami/maven/internal/memory" "github.com/kami/maven/internal/router" ) // bestRecall is the read side of the long-term memory store: the top hit when // it clears the confidence gate. The index holds BOTH notes and facts, and // either can win — the caller looks at the returned hit's meta["type"] to see // which. Facts aren't in the notes table, so this is the only path that can // answer "when did I last …?" from a captured fact. // // The whole hit is returned, not just its text, because "which memory answered" // decides how the answer is said: a note gets phrased in Maven's voice, a fact // is read back as stored. // // ok=false when the hit fails the confidence gate (see memory.Confident: an // absolute floor plus a margin over the runner-up) or carries no text. func bestRecall(results []memory.Result, minScore, minMargin float64) (memory.Result, bool) { if !memory.Confident(results, minScore, minMargin) { return memory.Result{}, false } if results[0].Meta["text"] == "" { return memory.Result{}, false } return results[0], true } // recallWiring — the recall subsystem's dependencies, held as one group on // reactiveHandler (Vikunja #433). It is the worked example for the wiring // decision in docs/handler-wiring.md: cohesive groups of fields, not thirty // loose ones, so a handler names what it needs and the package can be split // later without exporting the whole struct. // // The zero value is usable and means "no recall": no embedder, no vector // store, and a gate that is never consulted because nothing is ever searched. type recallWiring struct { // embedder — reused for note write/query (same model as the classifier). embedder router.Embedder // memStore — the vector index over notes and facts. memStore memory.Store // topics — the embedded seed sets behind the weather, house and LAN // recognisers (topics.go). Same lifecycle as boundary below: zero value is // usable, loads on first query, and with no embedder it never loads and // each source falls back to its own keyword test. topics topicIndex // boundary — the embedded seed sets behind the personal boundary // (personalboundary.go). Zero value is usable and loads on first query; // with no embedder it never loads and the boundary uses personalMarkers. boundary personalBoundary // minScore — the note-recall confidence gate. Top cosine below this ⇒ // "I don't know" instead of a guess. Tuned for the ONNX embedder; a knob, // not load-bearing math (same posture as the presence thresholds). Set by // wireVoice from VoiceConfig; default 0.55. minScore float64 // minMargin — the second half of that gate: how far the top hit must beat // the runner-up. 0 ⇒ margin off. minMargin float64 }