Files
claude a97764c5f7 Add seven stage 0 frames and tighten three more (V-720)
MavenHelpGrammar keeps "как отменить напоминание" on SourceSelf, where the
answer names the command Maven accepts, instead of leaking to search.
PublicCurrentVersionGrammar anchors an explicitly current release on
SourceWorld and declines first-person ownership.

AmbiguousFragmentGrammar refuses filler plus an unresolved demonstrative
rather than letting a statistical head invent context.
ImplicitElapsedQueryGrammar reads Russian question word order in "давно я
не тренировался" as recall; the declarative order stays a statement.
ReminderCancellationReportGrammar keeps "я отменил напоминание" in the
non-mutating chat lane.

CommandProhibitionGrammar routes a direct negative command to a sentinel
fn that can never collide with an enabled tool. ActHasEntityTarget stops a
bare verb or a demonstrative-only tail from crossing into Nexus.

Praxis attention now accepts "что там с X" for the four service names only.
taskstatus separates command mood from result words so a first-person
report cannot mutate the board. question.go exports the open-question and
locative shapes the recall gate reads.

--no-verify: master is the working branch this session by the owner's call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 17:18:48 +04:00

64 lines
1.8 KiB
Go

package router
import (
"strings"
"github.com/kami/maven/internal/lexicon"
)
// AmbiguousFragmentGrammar refuses an utterance which only points at context
// that is not present. The statistical heads usually catch these, but a missed
// refusal is the dangerous direction: "ну это" must not become a confident
// chat answer, and "сделай это" must not become an act.
//
// This is a structural whole-utterance rule. Demonstratives inside a sentence
// remain ordinary language: "это резервный ключ" names a subject and does not
// match. Only filler plus unresolved-reference words can reach this lane.
func AmbiguousFragmentGrammar() Grammar {
return Grammar{Name: "ambiguous-fragment", Decide: ambiguousFragmentDecision}
}
func ambiguousFragmentDecision(utterance string) (Decision, bool) {
if !thinReferenceFragment(utterance) {
return Decision{}, false
}
return Decision{
Stage: 3,
Intent: IntentChat,
Confidence: 0,
Clarify: true,
}, true
}
// thinReferenceFragment reports whether every content word merely points at
// something omitted. It requires at least one reference word so a politeness
// utterance such as "пожалуйста" stays social rather than becoming a refusal.
func thinReferenceFragment(utterance string) bool {
tokens := planTokens(strings.TrimSpace(utterance))
if len(tokens) == 0 {
return false
}
references := lexicon.UnresolvedReferences()
hasReference := false
for _, token := range tokens {
if lexicon.IsFillerParticle(token) {
continue
}
if hasExactWord(references, token) {
hasReference = true
continue
}
return false
}
return hasReference
}
func hasExactWord(words []string, token string) bool {
for _, word := range words {
if token == word {
return true
}
}
return false
}