mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
Sélecteur Chat|Code par discussion dans le pied du composeur ; en mode chat, une détection serveur suggère la bascule (puce ignorable, jamais automatique). Conception reprise d'OpenFox (MIT), réécrite en Go — voir NOTICE.md. - Outils fichiers : read (lignes numérotées, borné), grep, glob, et le tracker « lu avant d'écrire » qui refuse write/edit sur un fichier non lu ou modifié depuis la lecture ; edit préserve les fins de ligne CRLF. - Politique d'exécution : commandes catastrophiques refusées (rm -rf /, mkfs, reboot…), chemins bornés au dossier de la discussion en mode code, mutex par fichier. - Critères d'acceptation : contrat posé via l'outil criteria (éditable dans l'UI), passe de vérification indépendante sur contexte isolé — seule habilitée à marquer « passed » — puis corrections plafonnées. - Rôles embarqués (agents/*.md) : builder, planner, verifier, explorer, code-reviewer ; badge de rôle dans le fil. - LSP : gopls / typescript-language-server / pyright (inclus dans l'image), diagnostics injectés dans le retour de write/edit. - Git natif : git_status, git_diff, git_clone (borné à la discussion). - Jobs d'arrière-plan bash_bg/bash_tail (serveur de dev, build long). - Auto-retry : un appel d'outil écrit en texte (default_api:…, <tool_call>…) relance le tour une fois avec consigne corrective. - Outil ask : question à choix rendue en carte à boutons. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
74 lines
2.4 KiB
Go
74 lines
2.4 KiB
Go
package loki
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Cycle de vie des critères : add → set → clear, avec la garde allowPass.
|
|
func TestCriteresCycleDeVie(t *testing.T) {
|
|
withWorkspace(t)
|
|
id := convEnsureActive()
|
|
|
|
out := toolCriteria(map[string]any{"action": "add", "texts": []any{"le test passe", "le build compile"}}, false)
|
|
if !strings.Contains(out, "2 critère(s)") {
|
|
t.Fatalf("ajout raté : %s", out)
|
|
}
|
|
list := critList(id)
|
|
if len(list) != 2 || list[0].ID != 1 || list[1].ID != 2 {
|
|
t.Fatalf("liste inattendue : %+v", list)
|
|
}
|
|
// Le builder (allowPass=false) ne peut PAS s'auto-valider.
|
|
out = toolCriteria(map[string]any{"action": "set", "id": float64(1), "status": "passed"}, false)
|
|
if !strings.Contains(out, "[refusé]") {
|
|
t.Fatalf("auto-validation acceptée : %s", out)
|
|
}
|
|
// Le vérificateur (allowPass=true), si.
|
|
out = toolCriteria(map[string]any{"action": "set", "id": float64(1), "status": "passed"}, true)
|
|
if !strings.Contains(out, "passed") || strings.Contains(out, "[refusé]") {
|
|
t.Fatalf("validation vérificateur refusée : %s", out)
|
|
}
|
|
// failed reste ouvert à tous (le builder peut constater un échec).
|
|
out = toolCriteria(map[string]any{"action": "set", "id": float64(2), "status": "failed", "note": "le build casse"}, false)
|
|
if !strings.Contains(out, "failed") {
|
|
t.Fatalf("échec non enregistré : %s", out)
|
|
}
|
|
list = critList(id)
|
|
if critAllPassed(list) {
|
|
t.Fatal("allPassed avec un failed")
|
|
}
|
|
if critPending(list) != 1 {
|
|
t.Fatalf("pending = %d, attendu 1", critPending(list))
|
|
}
|
|
// Rendu : les statuts sont visibles.
|
|
r := critRender(list)
|
|
if !strings.Contains(r, "[✓] #1") || !strings.Contains(r, "[✗] #2") || !strings.Contains(r, "le build casse") {
|
|
t.Fatalf("rendu incomplet :\n%s", r)
|
|
}
|
|
toolCriteria(map[string]any{"action": "clear"}, false)
|
|
if len(critList(id)) != 0 {
|
|
t.Fatal("clear sans effet")
|
|
}
|
|
}
|
|
|
|
// Une liste vide n'est pas un contrat rempli.
|
|
func TestContratVide(t *testing.T) {
|
|
if critAllPassed(nil) {
|
|
t.Fatal("liste vide considérée comme remplie")
|
|
}
|
|
}
|
|
|
|
// Le plafond de critères tient.
|
|
func TestCriteresPlafond(t *testing.T) {
|
|
withWorkspace(t)
|
|
id := convEnsureActive()
|
|
var texts []any
|
|
for i := 0; i < critMaxCount+10; i++ {
|
|
texts = append(texts, "critère")
|
|
}
|
|
toolCriteria(map[string]any{"action": "add", "texts": texts}, false)
|
|
if n := len(critList(id)); n != critMaxCount {
|
|
t.Fatalf("%d critères, plafond %d", n, critMaxCount)
|
|
}
|
|
}
|