Merge: a confirm answer is a whole word, not a substring (#213)
V-567, severe. classifyConfirm was strings.Contains over bare stems, so "погода" contained "да" and "покажи" contained "ок". resolveConfirm runs before routing, so asking the weather while a confirm was parked executed the destructive tool or the bound Hexis capability. Measured on the box before the fix: "какая погода" ran the parked act. Second defect found while fixing: an unrecognised utterance also disarmed the confirm, because claim() cleared the pending slot before the verdict was read. An utterance that is not an answer is not a cancellation either. The yes and no words are now two closed sets in internal/lexicon, matched as whole tokens, phrases longest-first so "не надо" is read before "нет", and negatives before positives. The whole utterance must be answer words plus filler, so "давай посмотрим погоду" is unknown and leaves the confirm parked. "хорошо", "ладно" and "точно" are deliberately absent: they open a sentence about something else as often as they answer one. Conflict in lexicon_ru_v1.json resolved by hand: V-560's slot_value_frame and dialogue_cancel and V-567's confirm_yes and confirm_no all belong. 22 sets, JSON validated, lexicon, mavend, router and router/eval green with -race. --no-verify: the pre-commit hook refuses master, and the owner asked for straight-to-master merges for this unattended run.
This commit is contained in:
@@ -65,6 +65,7 @@ func mustLoad() lexiconFile {
|
||||
"day_offsets", "weekdays", "months_genitive", "hours_spoken",
|
||||
"not_place_after_v", "parts_of_day", "reminder_verbs", "half_hour",
|
||||
"filler_particles", "task_done_words", "task_drop_words",
|
||||
"confirm_yes", "confirm_no",
|
||||
} {
|
||||
s, ok := f.Sets[name]
|
||||
if !ok || (len(s.Words) == 0 && len(s.Values) == 0) {
|
||||
@@ -121,6 +122,16 @@ func ReminderVerbs() []string { return words("reminder_verbs") }
|
||||
// notes say: an imperative exactly, a stative by lemma.
|
||||
func TaskDoneWords() []string { return words("task_done_words") }
|
||||
|
||||
// ConfirmYes returns the words that answer a parked confirm with yes, and
|
||||
// ConfirmNo the ones that answer it with no. Some members are multi-word ("не
|
||||
// надо"), so a caller matches longest-first over tokens rather than looking up
|
||||
// one word at a time. See the sets' notes for why neither may be matched as a
|
||||
// substring.
|
||||
func ConfirmYes() []string { return words("confirm_yes") }
|
||||
|
||||
// ConfirmNo — see ConfirmYes.
|
||||
func ConfirmNo() []string { return words("confirm_no") }
|
||||
|
||||
// TaskDropWords — see TaskDoneWords.
|
||||
func TaskDropWords() []string { return words("task_drop_words") }
|
||||
|
||||
|
||||
@@ -217,6 +217,22 @@
|
||||
"отмена", "отмени", "отменить", "отставить", "забудь", "забей", "неважно", "проехали", "передумал", "передумала",
|
||||
"cancel", "nevermind", "forget"
|
||||
]
|
||||
},
|
||||
"confirm_yes": {
|
||||
"note": "The whole vocabulary of saying yes to a parked confirm, Russian and English. Closed because it is her question that is being answered: she asked \"да или нет\", and the answers to that question can be listed. Matched as whole tokens and never as substrings — \"погода\", \"давление\" and \"дальше\" all contain \"да\", and a substring test executed a destructive act when he asked about the weather (V-567). Words that merely sound agreeable — \"хорошо\", \"ладно\", \"точно\" — are deliberately absent: they open a sentence about something else as often as they answer, and an unclear answer must route rather than execute.",
|
||||
"words": [
|
||||
"да", "ага", "угу", "давай", "давайте", "конечно",
|
||||
"подтверждаю", "подтверди", "подтвердить", "выполняй", "валяй",
|
||||
"yes", "yeah", "yep", "yup", "ok", "okay", "sure", "confirm", "affirmative"
|
||||
]
|
||||
},
|
||||
"confirm_no": {
|
||||
"note": "The answers that decline a parked confirm. Same matching rule as confirm_yes and the same reason. The multi-word members are here rather than assembled by a caller because \"надо\" alone is not an answer and \"не надо\" is the opposite of one: the two must land on opposite sides, and only the phrase says which. \"не\" on its own is NOT a member — \"не забудь купить хлеб\" is a reminder, not a refusal.",
|
||||
"words": [
|
||||
"нет", "неа", "нельзя", "отмена", "отмени", "отменить", "отставить",
|
||||
"стоп", "стой", "не надо", "не нужно", "не стоит", "не сейчас", "не хочу",
|
||||
"no", "nope", "nah", "negative", "cancel", "stop", "don't", "dont"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user