an act with nothing on the other end says so (V-556)

askClarify parked "Что сделать?" whatever was on the other end. With an empty
allowlist that question has no answer: she asks, fails, asks again and gives up,
three turns spent on a request she could have declined in the first one.

Empty allowlist now names the gap and parks nothing. A non-empty one still asks,
and names what she can run, capped at six, so the question is answerable.
This commit is contained in:
2026-08-05 23:34:25 +04:00
parent e87088afb8
commit 1b76fa8205
3 changed files with 117 additions and 3 deletions
+32
View File
@@ -1,6 +1,8 @@
package main
import (
"strings"
"github.com/kami/maven/internal/dialogue"
"github.com/kami/maven/internal/router"
)
@@ -47,6 +49,36 @@ 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).
//
// 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
}
// clarifyQuestionFor picks the wording for this attempt. attempt is 1-based, as
// PendingQuestion.Attempts counts it; anything past the list uses the last and
// most explicit phrasing rather than wrapping round to the short one, because