an unrecognized act says so and lists nothing (V-556)

Reciting the allowlist answered a question he did not ask. She says the command
is not one she knows, once, and parks nothing.
This commit is contained in:
2026-08-05 23:43:22 +04:00
parent d988154063
commit 5bd1406c7a
3 changed files with 52 additions and 121 deletions
+12 -30
View File
@@ -1,8 +1,6 @@
package main
import (
"strings"
"github.com/kami/maven/internal/dialogue"
"github.com/kami/maven/internal/router"
)
@@ -42,6 +40,9 @@ var clarifyQuestionVariants = map[dialogue.Slot][]string{
"Что именно отметить?",
"Назови, что записать — например, «выпил воды».",
},
// Not spoken since Vikunja #556: askClarify answers actNotRecognized for a
// missing capability rather than asking. Kept because clarifyQuestion still
// reports the gap, and a re-ask deck with a hole in it is harder to read.
dialogue.SlotFn: {
"Что сделать?",
"Какое действие выполнить?",
@@ -49,35 +50,16 @@ var clarifyQuestionVariants = map[dialogue.Slot][]string{
},
}
// namedActsCap bounds how many capability names one question may recite. Six is
// what a spoken sentence carries; past that the list stops being an answer and
// becomes a wall he has to hold in his head.
const namedActsCap = 6
// fnClarify decides what to say about an act whose capability is missing, and
// whether the request is worth parking (Vikunja #556).
// actNotRecognized is what an act she cannot run gets (Vikunja #556).
//
// The old deck asked "Что сделать?" whatever was on the other end. With an empty
// allowlist that question has no answer: nothing he says can match, so she asks,
// fails, asks again and gives up — three turns spent on a request she could have
// declined in the first one. So an empty allowlist names the gap and parks
// nothing, and a non-empty one asks a question he can actually answer by naming
// what she has.
func fnClarify(allow []string, attempt int) (reply string, ask bool) {
if len(allow) == 0 {
return "Я пока ничего не умею делать — мне не разрешён ни один инструмент.", false
}
q, ok := clarifyQuestionFor(dialogue.SlotFn, attempt)
if !ok {
return "", false
}
named := allow
tail := ""
if len(named) > namedActsCap {
named, tail = named[:namedActsCap], "…"
}
return q + " Я умею: " + strings.Join(named, ", ") + tail + ".", true
}
// The deck used to ask "Что сделать?" instead. That question has no answer he
// can give: he already said what he wanted, and nothing he repeats will match a
// capability that is not there. So she asked, failed, asked again and gave up —
// three turns spent on one refusal. She says it once now, and parks nothing.
//
// It does not recite the allowlist. A list of names he did not ask about is not
// an answer to the thing he did ask about.
const actNotRecognized = "Такую команду я не знаю."
// clarifyQuestionFor picks the wording for this attempt. attempt is 1-based, as
// PendingQuestion.Attempts counts it; anything past the list uses the last and