Files
Maven/cmd/mavend/notefragment.go
T
claude b705a786ef a note stores his words, not the model's (V-576)
The note body was already the utterance. Two other holes were not.

The LLM router filled Slots.Text for a note from the model's own text
field, and that slot is what the replier reads out. So the confirmation
he heard named things he never said, twice over, differently each time.
The note payload is now the utterance and the model cannot touch it.

A correction with no referent is also not a note. 'нет, не маме, а папе'
names no intent, so parseRepair declines it and it routed as a fresh
note. actionNote now declines it and asks instead of filing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 01:39:38 +04:00

59 lines
1.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"strings"
"github.com/kami/maven/internal/lexicon"
"github.com/kami/maven/internal/morph"
)
// correctionFragment reports that an utterance replaces a referent and states
// nothing of its own: "нет, не маме, а папе" (V-576).
//
// Measured on the box 2026-08-06, that fragment routed to note and was filed.
// It is not a repair either, because it names no intent, so parseRepair
// declines it and repair.go is the wrong place to catch it. This is the note
// path saying it has nothing to store.
//
// Three offline tests, all of them narrow on purpose. The sentence opens with a
// refusal word from the lexicon, it carries the contrastive "а" that names the
// replacement, and no token in it is a verb form. The verb test is what keeps
// the rule off real notes: "нет, я не поеду, а останусь" says something, and a
// Russian verb carries its own subject and tense.
func correctionFragment(utterance string) bool {
toks := repairTokens(strings.ToLower(strings.TrimSpace(utterance)))
if len(toks) < 3 {
return false
}
if !refusalWord(toks[0]) {
return false
}
var negated, contrasted bool
for _, tok := range toks[1:] {
switch tok {
case "не", "not":
negated = true
case "а", "but":
contrasted = true
}
if morph.IsVerbForm(tok) {
return false
}
}
return negated && contrasted
}
// refusalWord reports that a token is a one-word refusal. The lexicon set holds
// phrases too ("не надо"), and those are not what opens a correction.
func refusalWord(tok string) bool {
for _, w := range lexicon.ConfirmNo() {
if strings.ContainsRune(w, ' ') {
continue
}
if w == tok {
return true
}
}
return false
}