mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-20 21:48:47 +02:00
Lot 30 : motifs de relance personnalisés tenus par la façade
La surcharge retry_patterns (tableau JSON de regex du Go, chacune en (?mi)) ne garde plus la conversation au Go : la façade la lit au démarrage de sa conversation, comme le Go la compile une fois par processus ; illisible ou vide, les motifs embarqués s'appliquent, une regex illisible est sautée. Les regex restent celles du Go : chat::stream::go_regex réécrit pour le crate regex ce qui n'a pas le même sens — classes Perl et limites de mot ASCII (\w \d \s \b et leurs contraires, dans et hors d'une classe), \Q…\E (refusé dans une classe, comme le Go), [ && -- ~~ dans une classe, octal permis, référence arrière refusée. Parité : parity_retry_test.go compile côté Go une soixantaine de regex (dont celles qu'il refuse) et note leur première correspondance sur onze textes (accents, chiffres non ASCII, espaces insécables, crochets) ; tests/retry.rs rejoue le journal à l'identique et vérifie la lecture de la surcharge au démarrage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
This commit is contained in:
11 files changed
+3633
-11
No files matched your search
@@ -48,9 +48,9 @@ func facadeChat() bool {
|
||||
|
||||
// facadeChatBlocker : le réglage qui garde la conversation ici, "" s'il n'y
|
||||
// en a pas. Ces clés opt-in demandent une machinerie restée au Go (bloc projet
|
||||
// figé, images gardées, slots du moteur, préchauffage, motifs de relance
|
||||
// personnalisés). NUDGE_IN_TOOL n'en est plus (lot 23) : la façade a sa sonde
|
||||
// de gabarit.
|
||||
// figé, images gardées, slots du moteur, préchauffage). NUDGE_IN_TOOL n'en est
|
||||
// plus (lot 23) : la façade a sa sonde de gabarit ; ni les motifs de relance
|
||||
// personnalisés (retry_patterns, lot 30) : la façade les lit et les compile.
|
||||
func facadeChatBlocker(cfg map[string]string) string {
|
||||
switch {
|
||||
case projSnapEnabled(cfg):
|
||||
@@ -63,8 +63,6 @@ func facadeChatBlocker(cfg map[string]string) string {
|
||||
return "SLOT_PERSIST"
|
||||
case prewarmMode(cfg) != "":
|
||||
return "PREWARM"
|
||||
case strings.TrimSpace(getStr(bkState, "retry_patterns")) != "":
|
||||
return "retry_patterns"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -308,6 +308,12 @@ func TestFacadeReglageQuiGardeLaConversation(t *testing.T) {
|
||||
if got := facadeChatBlocker(map[string]string{}); got != "" {
|
||||
t.Errorf("sans réglage : %q", got)
|
||||
}
|
||||
// Les motifs de relance personnalisés ne gardent plus la conversation.
|
||||
putStr(bkState, "retry_patterns", `["oups"]`)
|
||||
if got := facadeChatBlocker(map[string]string{}); got != "" {
|
||||
t.Errorf("retry_patterns : %q", got)
|
||||
}
|
||||
putStr(bkState, "retry_patterns", "")
|
||||
// Sans LOKI_CHAT=rust : le Go, et pourquoi.
|
||||
oublierDecisionFacade(t)
|
||||
t.Setenv(facadeChatEnv, "")
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// parity_retry_test.go — journal de référence des motifs retry_patterns
|
||||
// (lot 30 de la migration Rust) : chaque regex, compilée par le Go en
|
||||
// (?mi) comme compileRetryPatterns, et sa première correspondance sur des
|
||||
// textes choisis (classes et limites de mot ASCII, texte littéral, classes
|
||||
// aux caractères spéciaux, Unicode). Rangé dans
|
||||
// rust/loki-rs/tests/parity_retry/patterns.json ; tests/retry.rs le rejoue.
|
||||
//
|
||||
// LOKI_PARITY_UPDATE=1 go test ./internal/loki -run TestPariteRetryPatterns
|
||||
|
||||
const parityRetryFile = "../../rust/loki-rs/tests/parity_retry/patterns.json"
|
||||
|
||||
func TestPariteRetryPatterns(t *testing.T) {
|
||||
pats := []string{
|
||||
`\w+`, `\W+`, `\d+`, `\D+`, `\s+`, `\S+`, `\bdo_\w+\(`, `\Bfoo`, `\bfoo\b`,
|
||||
`[\w-]+`, `[^\s]+`, `[\W]+`, `[\d\s]+`, `[\D]+`, `[^\w\s]+`,
|
||||
`\Qa.b\E`, `\Q(x`, `[\Q]-\E]+`, `a\Q\E+`,
|
||||
`[a[]+`, `[a&&b]+`, `[!--]+`, `[a--]`, `[~~a]+`, `[]a]+`, `[^]a]+`,
|
||||
`[[:alpha:]]+`, `[^[:alpha:]]+`, `[[:word:]]+`, `[[:^digit:]]+`,
|
||||
`^oups`, `\Aoups`, `fin$`, `\pL+`, `\p{Greek}+`, `x{2,3}`, `(?s:a.b)`, `a.b`,
|
||||
`(?U)a+`, `<function=\w+>`, `\{"name":\s*"(bash|read)"`, `[`, `(`, `\C`, `\z`, `a\z`,
|
||||
`(?P<n>ab)`, `\x41\x{42}`, `\101`, `\1`, `(a)\1`, `\0`, `\08`, `[\101-\103]+`, `[\x41-\x43]+`, `\.\*\+`, `é+`, `ÉTÉ`,
|
||||
}
|
||||
inputs := []string{
|
||||
"été do_it(1) éfoo foo bar_9",
|
||||
"x٣42 a \tb\n",
|
||||
"axb a.b a(x a]-]b",
|
||||
"x[a[ x&ab a!#-b x~a x]a [ab",
|
||||
"1abc ab12 Ωμέγα",
|
||||
"Bonjour\nOUPS !\nla fin",
|
||||
"oups au début, puis la FIN",
|
||||
"aaaa xxx a\nb aéb",
|
||||
`<function=bash> {"name": "read"}`,
|
||||
"AB ABC éé ÉTÉ été",
|
||||
"x.*+y",
|
||||
}
|
||||
type match struct {
|
||||
In int `json:"in"`
|
||||
Match *string `json:"match"`
|
||||
At int `json:"at"`
|
||||
}
|
||||
type entry struct {
|
||||
Pattern string `json:"pattern"`
|
||||
Compiles bool `json:"compiles"`
|
||||
Matches []match `json:"matches"`
|
||||
}
|
||||
journal := map[string]any{"inputs": inputs}
|
||||
var es []entry
|
||||
for _, p := range pats {
|
||||
e := entry{Pattern: p, Matches: []match{}}
|
||||
re, err := regexp.Compile("(?mi)" + p)
|
||||
if err == nil {
|
||||
e.Compiles = true
|
||||
for i, in := range inputs {
|
||||
m := match{In: i, At: -1}
|
||||
if loc := re.FindStringIndex(in); loc != nil {
|
||||
s := in[loc[0]:loc[1]]
|
||||
m.Match, m.At = &s, loc[0]
|
||||
}
|
||||
e.Matches = append(e.Matches, m)
|
||||
}
|
||||
}
|
||||
es = append(es, e)
|
||||
}
|
||||
journal["patterns"] = es
|
||||
|
||||
got, err := parityJSON(journal)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if os.Getenv("LOKI_PARITY_UPDATE") == "1" {
|
||||
if err := os.MkdirAll("../../rust/loki-rs/tests/parity_retry", 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(parityRetryFile, got, 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
want, err := os.ReadFile(parityRetryFile)
|
||||
if err != nil {
|
||||
t.Fatalf("journal de référence absent (%v) : LOKI_PARITY_UPDATE=1 pour le créer", err)
|
||||
}
|
||||
if string(got) != string(want) {
|
||||
t.Errorf("les motifs ne produisent plus le journal rangé dans %s.\n"+
|
||||
"Si c'est voulu : LOKI_PARITY_UPDATE=1 go test ./internal/loki -run TestPariteRetryPatterns,\n"+
|
||||
"puis cargo test --test retry dit si le port Rust suit.", parityRetryFile)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user