From aaf1f0236b330917940168fc0fd86adfc0d2c6f9 Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 6 Aug 2026 02:10:22 +0400 Subject: [PATCH 1/2] store/tasks: dedupe live-status literal against the named constants (V-581) lookupLiveTaskByNorm hardcoded 'candidate','open' in SQL, drifting from liveTaskStatuses which ListTasks already uses for the same query. Bind the constants instead so there is one place that names the live set. --- internal/store/tasks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/store/tasks.go b/internal/store/tasks.go index 8e37258..57c5b51 100644 --- a/internal/store/tasks.go +++ b/internal/store/tasks.go @@ -246,7 +246,7 @@ func (s *Store) lookupTaskByExternalID(ctx context.Context, ext string) (Task, e // lookupLiveTaskByNorm finds the outstanding task with this normalised text. func (s *Store) lookupLiveTaskByNorm(ctx context.Context, norm string) (Task, error) { row := s.db.QueryRowContext(ctx, taskSelect+` - WHERE norm = ? AND status IN ('candidate','open')`, norm) + WHERE norm = ? AND status IN (?,?)`, norm, liveTaskStatuses[0], liveTaskStatuses[1]) t, err := scanTask(row) if errors.Is(err, sql.ErrNoRows) { return Task{}, ErrTaskNotFound From 02ce730cb2b1b1eb35770e0c4898223d61466bf3 Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 6 Aug 2026 02:10:22 +0400 Subject: [PATCH 2/2] recalleval: fold a doubled doc comment, name the top-k literal (V-581) bestRecall carried two stacked doc comments (both starting "bestRecall mirrors...") from a prior edit that appended rather than replaced; folded into one. Also named the literal 3 passed to Search as daemonTopK, mirroring memoryRecallWidth in actions_query.go, so the Recall3 doc and the call site cannot drift from each other again. --- internal/memory/recalleval/recalleval.go | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/internal/memory/recalleval/recalleval.go b/internal/memory/recalleval/recalleval.go index e1be017..9c70013 100644 --- a/internal/memory/recalleval/recalleval.go +++ b/internal/memory/recalleval/recalleval.go @@ -38,6 +38,11 @@ var fixtureJSON []byte // other version rather than misreading a fixture and reporting a number. const SchemaVersion = 1 +// daemonTopK — how many candidates the read path asks for, mirroring +// memoryRecallWidth in cmd/mavend/actions_query.go. Kept in step so recall@3 +// measures the same top-3 the daemon actually reads, not an arbitrary width. +const daemonTopK = 3 + // StoredNote — one thing the user said once, as it lands in the semantic store. // Kind is "note" or "fact"; both share the vector index (see // cmd/mavend/recall.go), so a fact can legitimately win a recall. @@ -267,8 +272,9 @@ type TagStat struct{ Passed, Total int } // Recall1 — fraction of answerable cases whose wanted note ranked first. func (r Report) Recall1() float64 { return ratio(r.Rank1, r.Answerable) } -// Recall3 — same, in the top three. The daemon asks for 3 (voice.go), so this -// is the ceiling a better gate or a reranker could reach. +// Recall3 — same, in the top three. The daemon asks for daemonTopK candidates +// (mirroring memoryRecallWidth in voice.go's caller), so this is the ceiling a +// better gate or a reranker could reach. func (r Report) Recall3() float64 { return ratio(r.Rank3, r.Answerable) } // Answered — fraction of answerable cases the daemon would actually answer @@ -399,7 +405,7 @@ func scoreCase(ctx context.Context, emb router.Embedder, newStore NewStore, minS o.Reasons = []string{fmt.Sprintf("embed query: %v", err)} return o, nil } - hits, err := st.Search(ctx, qvec, 3) + hits, err := st.Search(ctx, qvec, daemonTopK) o.Latency = time.Since(start) if err != nil { o.Err = err @@ -455,14 +461,13 @@ func rankNote(inTop3 bool) string { } // bestRecall mirrors cmd/mavend/recall.go — the gate the daemon actually -// applies to a memory hit. Duplicated rather than imported because package main -// is not importable; recalleval_test.go asserts the two agree in behaviour. -// The daemon returns the whole hit (a note and a fact are said differently); -// the harness only scores what came back, so it keeps returning the text. -// bestRecall mirrors the daemon's gate in cmd/mavend/recall.go, including the -// topic veto added for #470: a score that clears the gate still has to be -// about what he asked. Keep the two in step — a fixture that measures a -// weaker gate than the daemon runs flatters it. +// applies to a memory hit, including the topic veto added for #470: a score +// that clears the gate still has to be about what he asked. Duplicated rather +// than imported because package main is not importable; recalleval_test.go +// asserts the two agree in behaviour, so a weaker gate here than the daemon +// runs cannot flatter the score. The daemon returns the whole hit (a note and +// a fact are said differently); the harness only scores what came back, so it +// keeps returning the text. func bestRecall(query string, results []memory.Result, minScore, minMargin float64) string { if !memory.Confident(results, minScore, minMargin) { return ""