router/semantic: slice 23 corpus fast-path reconciliation — DeriveFastPath over the real router replaces the regex mirror, factory/merge validated, corpus rebuilt (dataset_hash unchanged), drift diagnostic and rerun tooling

This commit is contained in:
2026-09-08 04:02:00 +04:00
parent bb6bd8efb9
commit be71ac406b
12 changed files with 8460 additions and 7890 deletions
+6 -81
View File
@@ -15,7 +15,6 @@ import (
"fmt"
"log"
"os"
"regexp"
"sort"
"strings"
@@ -1089,85 +1088,11 @@ func generatorQuestion(seed semantic.SemanticSeed) []semantic.GeneratedSurface {
}
// ─── Fast-path classifier ────────────────────────────────────────────────────
// Simplified pattern matcher that mirrors stage-0 grammar outcomes.
var (
reminderVerbRe = regexp.MustCompile(`(?i)^\s*(напомни|напомните|напомнить|напоминай|разбуди|разбудите|разбудить|буди|remind|wake)\b`)
timeQueryRe = regexp.MustCompile(`(?i)^\s*(сколько\s+сейчас\s+времени|который\s+час|какое\s+число|какой\s+день|what\s+time|what's\s+the\s+date)\b`)
captureVerbRe = regexp.MustCompile(`(?i)^\s*(запиши|запомни|отметь|заметь|добавь|сохрани|занеси|внеси|note|remember|log|save|add)\b`)
praxisItemRe = regexp.MustCompile(`(?i)\b(item[_-][a-z0-9_-]+)`)
quietOnRe = regexp.MustCompile(`(?i)(тихий\s+режим|режим\s+тишина|тише|потише|quiet\s+(mode|on))`)
quietOffRe = regexp.MustCompile(`(?i)(хватит\s+тихого|громкий\s+режим|выключи\s+тихий|quiet\s+(off|end))`)
taskDoneRe = regexp.MustCompile(`(?i)^\s*(закрой\s+задачу|заверши\s+задачу|close\s+the\s+task|finish\s+the\s+task)\b`)
taskDropRe = regexp.MustCompile(`(?i)^\s*(убери\s+задачу|удали\s+задачу|отмени\s+задачу|drop\s+the\s+task|remove\s+the\s+task)\b`)
)
// tool aliases → fast-path matchers (subset of what DefaultActMatcher would match)
var toolAliasRe = []*regexp.Regexp{
regexp.MustCompile(`(?i)^\s*(перезапусти|перезагрузи|рестарт)\b`),
regexp.MustCompile(`(?i)^\s*(останови|выключи)\b`),
regexp.MustCompile(`(?i)^\s*(запусти|старт)\b`),
regexp.MustCompile(`(?i)^\s*(перезапусти\s+контейнер|перезагрузи\s+контейнер)\b`),
regexp.MustCompile(`(?i)^\s*(останови\s+контейнер)\b`),
regexp.MustCompile(`(?i)^\s*(перезагрузи\s+сервер|перезагрузи\s+хост|ребут)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+статус|проверь\s+статус|статус)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+контейнеры|список\s+контейнеров|что\s+запущено)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+uptime|аптайм|как\s+работает\s+сервер)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+диск|сколько\s+места\s+на\s+диске)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+память|свободная\s+память)\b`),
regexp.MustCompile(`(?i)^\s*(покажи\s+логи|логи|лог)\b`),
}
// praxis lifecycle verbs (bare, without item reference → residual action)
var praxisLifecycleRe = regexp.MustCompile(`(?i)^\s*(закрой|закрыть|resolve|close|принято|принять|acknowledge|ack|игнорируй|игнорировать|пропусти|ignore|skip|закрепи|закрепить|pin)\b`)
var praxisAttentionRe = regexp.MustCompile(`(?i)^\s*(что\s+требует\s+внимания|что\s+нового\s+по\s+(задачам|проектам|сервисам)|needs\s+attention)\b`)
var praxisChangesRe = regexp.MustCompile(`(?i)^\s*(что\s+изменилось|какие\s+изменения|changed|changes)\b`)
var praxisEntityRe = regexp.MustCompile(`(?i)^\s*(статус|status|как\s+дела\s+у|how\s+is)\s+`)
// classifyFastPath determines whether a surface would be handled by stage-0.
func classifyFastPath(text string) bool {
t := strings.TrimSpace(text)
// Reminder verbs → always fast-path
if reminderVerbRe.MatchString(t) {
return true
}
// Time/date queries → fast-path
if timeQueryRe.MatchString(t) {
return true
}
// Task-status commands → fast-path
if taskDoneRe.MatchString(t) || taskDropRe.MatchString(t) {
return true
}
// Tool aliases → fast-path (only for verbs alone, not when combined with objects in ways the matcher wouldn't handle)
for _, re := range toolAliasRe {
if re.MatchString(t) {
return true
}
}
// Praxis lifecycle with item reference → fast-path
if praxisLifecycleRe.MatchString(t) && praxisItemRe.MatchString(t) {
return true
}
// Praxis attention/changes → fast-path
if praxisAttentionRe.MatchString(t) || praxisChangesRe.MatchString(t) {
return true
}
// Praxis entity attention → fast-path
if praxisEntityRe.MatchString(t) {
return true
}
// Quiet mode → fast-path (resolved pre-route)
if quietOnRe.MatchString(t) || quietOffRe.MatchString(t) {
return true
}
// Capture verbs → some are fast-path (note capture)
if captureVerbRe.MatchString(t) {
return true
}
return false
}
// Fast-path metadata is derived from the real router, not a regex mirror:
// DeriveFastPath runs the production TryFastPath over the stage-0 grammars
// with the experiment's act allowlist (see internal/router/semantic/fastpath.go).
// A hand-maintained pattern list drifted from the grammars and labelled 185
// residual rows as fast (docs/evals/2026-09-08-slice22-*); it is removed.
// ─── Helpers ─────────────────────────────────────────────────────────────────
@@ -1241,7 +1166,7 @@ func buildCorpus(seeds []semantic.SemanticSeed) []semantic.RouteExample {
exampleCounter++
srcID := fmt.Sprintf("%s-%03d", seed.ID, exampleCounter)
fp := classifyFastPath(surf.Text)
fp := semantic.DeriveFastPath(surf.Text).Matched
isResidual := !fp
tags := append([]string{}, seed.Tags...)