PREWARM ne garde plus la conversation au Go. La façade tient
l'historique : elle assemble et envoie la requête du prochain tour ; le
Go garde le compteur des requêtes en vol et ce qui l'annule.
Go (facade_prewarm.go) :
- /internal/v1/prewarm/check : moteur libre d'un vrai travail, loin de
minuit, en bonne santé, slot visé ;
- /internal/v1/prewarm/begin : rechargement SLOT_PERSIST puis inscription
comme LA requête en vol ; son annulation est relayée à la façade ;
- /internal/v1/prewarm/end : place rendue, cache repris noté ;
- /internal/v1/oai/begin : prewarm_keep pour l'étape qui le prolonge ;
- fin de tâche planifiée : le déclencheur part à la façade.
Rust (chat/prewarm.rs) :
- assemblage par les mêmes fonctions que le tour, sentinelle « . », un
seul jeton, non streamé ; abstention (capacités inconnues, tour en
cours, discussion vide, compaction attendue, assemblage inattendu) ;
- déclencheurs : fin de tour, fin de tâche, changement de discussion ou
de projet (full : après 3 s) ;
- le tour garde le préchauffage qu'il prolonge (empreintes des messages
et des options de rendu) et coupe tout de suite les autres ;
- télémétrie kind=prewarm.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
KEEP_TURN_IMAGES ne garde plus la conversation au Go. L'état du tour vit
dans la façade ; les fichiers et la vision restent au Go.
Go (facade_keepimg.go) :
- /internal/v1/turn/keepimg : vision réellement active, budget des images
gardées ;
- /internal/v1/turn/keepimg/store : une image relayée rangée par
référence (refRelayImage), relue à l'octet près.
Rust :
- chat/keepimg.rs : port de keepImages (image à l'essai, mesure par le
moteur répartie au prorata des octets, budget, publication, fin de tour).
- La boucle du tour : budget demandé pour le fil principal, image rangée
par le Go, historique réécrit publié sans les relais non gardés ; les
images gardées partent avant tout résumé (filet réactif, en cours de
tour, fenêtre pleine).
- Début et fin de tour : retirées si le contexte le demande ou si elles
ne doivent plus partir (clé retirée, vision absente).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Quand la façade tient la conversation (LOKI_CHAT=rust), ses complétions
rejoignent l'anneau de télémétrie du Go (perf_log.go) au lieu de passer
inaperçues : /api/perf/summary les compte, l'optimiseur en tire ses
poids, et l'interface reçoit à nouveau la perte de cache.
- chat/perf.rs : perfRecFromStats, perfRecFromWire (lu sans échec
possible, mêmes tolérances que perfNum, timings d'un autre type
présents mais vides comme le Go) et perfPrefix (FNV-1a cumulé) ;
- la boucle du tour range chaque complétion lue, numérotée dans le tour,
avec ses empreintes si elle est complète ; une complétion coupée par un
stop est rangée incomplète ; la dernière statistique porte la nature,
la perte, ce qui s'est intercalé et l'alerte ;
- natures : main (tour), verify (vérification du mode Code), compact
(résumé de compaction, rangé dès que la réponse se lit) ;
- le Go (/internal/v1/perf/record) range le relevé comme les siens et
calcule l'alerte au seuil du preset actif, jamais pour un preset
externe.
Tests : relevés et empreintes (chat/perf.rs), télémétrie de la boucle
(complète, coupée), du vrai hôte et des résumés (tests/lot6.rs),
TestFacadePerf côté Go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port de chat_tplprobe.go : la façade sonde le gabarit du moteur après ses
complétions (/health, /props, /apply-template), avec les verdicts
preserves_history, prefix_stable et renders_reasoning, le cache par
build/modèle/gabarit/forme et la relance bornée.
- l'écho du raisonnement suit le verdict de la sonde (echo_policy_for) ;
- NUDGE_IN_TOOL ne garde plus la conversation au Go : le rappel de budget
va dans le dernier résultat d'outil quand le préfixe n'est pas stable ;
- le Go lit le verdict de la façade (/internal/facade/v1/chat/tpl) quand
elle tient la conversation.
Parité : parity_tplprobe_test.go tire du Go un journal d'échanges rejoué
octet pour octet par tests/tplprobe.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port de codeVerifyLoop (rust/loki-rs/src/chat/verify.rs) : à la fin d'un
tour de build en mode Code, relances du builder sur les critères encore
ouverts, passe de vérification sur un contexte isolé, corrections, abandon
dit dans le fil après deux corrections — mêmes deltas que le Go (role,
verify_done, mesures ctx_isolated), relances et corrections rangées dans
l'historique, vérifications non.
Le Go garde les critères (l'outil criteria s'y exécute) : la façade les lit
en base (chat/crit:<id>) et reçoit le contexte isolé du vérificateur par
POST /internal/v1/turn/verifier (prompt du rôle et faits de la machine,
outils fermés, rôle verifier, seul autorisé à marquer passed). Toute
compaction en mode Code rend l'état des critères au résumé, comme
compactMessages.
generate : vue du tour factorisée (turn_view), question à l'utilisateur
suivie (une question posée suspend la vérification).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port d'EnqueueOrStart, StartTurn, generate, drainQueued,
startQueuedIfAny, dropQueued et compactAndPublish :
- envoi : réessai reconnu (cid), tour préparé par le Go (/turn/start), mis
en file si un tour tourne, sinon moteur prêt (/health), verrou du tour
puis bail du moteur du Go, bulle journalisée et enregistrée tout de suite ;
- tour : compaction de début de tour, vue d'envoi (tête du Go, historique
sans <context_update>, préambule fusionné comme InjectSkills), boucle
dont chaque événement devient un delta du journal, historique rangé
(outils, réponse, raisonnement renvoyé, rappels en porte-à-faux retirés),
contexte estimé si le moteur ne le compte pas, compaction de fin de tour ;
- fin : turn_done, journal coalescé, verrou et bail rendus, discussion
enregistrée, file abandonnée après un stop ou message suivant lancé,
sinon Web Push ;
- stop : le tour en cours, ou le détenteur Go du moteur.
chat::history porte historyFromView, dropStrayNudges, le rappel des pages
mémoire lues, l'assemblage d'InjectSkills et la forme des tool_used du
journal, avec leurs tests Go. ConvState garde ctxUsedLen et genPeak en
mémoire seulement. EngineLease::interrupted ne garde plus de verrou à
travers une attente.
Écarts : boucle de vérification du mode Code, critères pour la
compaction, préchauffage, télémétrie, retry_patterns personnalisés.
Tests de bout en bout : tour complet (outil, réponse, bail rendu,
discussion enregistrée, doublon), message en file injecté entre deux
étapes, moteur tenu par une tâche planifiée (409, stop), moteur pas prêt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
GoTurnHost est le TurnHost de la façade : envoi par EngineHttp (clé de
l'endpoint, pannes classées comme friendlyLLMError), outils par l'API du Go
avec leurs suites (capture, aperçu, image relayée), résultats complets
confiés à l'écrivain des discussions (id « <discussion>.<aléa> »),
compaction par Compactor avec un résumeur qui interroge le moteur
(EngineSummarizer) et l'archive recall du Go (StoreRecall), images jointes
lues sur disque et ouvertes par le Go, en cache borné à 64 Mio.
RecallArchive devient asynchrone ; la boucle consulte la mémoire des
refus de compaction avant d'annoncer une compaction en cours de tour.
Écarts : pas de résumé en continuation (état du slot tenu par le Go), ni
conseil de cache, ni garde d'écriture du mode Code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port de runChatLoop : complétions enchaînées jusqu'à la réponse, sur les
modules déjà portés (charge utile, flux, compactage). Les filets du Go y
sont : reprises réseau et statuts passagers, flux externe coupé (rejoué ou
poursuivi après le texte affiché), intensité refusée par le gabarit,
raisonnement renvoyé refusé ou trop long, compaction réactive puis
réduction forcée, 500 (tool_choice none puis outils retirés), réponse vide
(rejeu si fenêtre pleine, relances « pensé sans agir »), appel écrit en
texte, budget souple, appels identiques court-circuités, arguments
illisibles jamais exécutés, pré-vol du mode Code, compaction en cours de
tour, file d'attente injectée entre deux étapes.
Aucune entrée-sortie dans la boucle : envoi, outils, compaction, résultats
complets et mémoires des refus passent par TurnHost ; l'arrêt par Cancel.
Non portés (clés opt-in ou machinerie du moteur local restée au Go) :
KEEP_TURN_IMAGES, PROJ_SNAPSHOT, NUDGE_IN_TOOL, SIDE_SLOT, SLOT_PERSIST,
préchauffage, sonde de gabarit, télémétrie.
15 tests sur un faux hôte aux réponses scriptées (temps suspendu pour les
reprises).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port des opérations de chat_sessions.go et de LoadConversation :
discussion active créée au besoin (reprise du fil unique d'avant les
discussions, clé d'origine gardée), chargement au démarrage qui réessaie et
n'écrit rien sur une base illisible, liste du projet actif, création,
bascule (la courante enregistrée sous SON identifiant), renommage,
suppression (l'écriture en vol ne la fait pas renaître ; bascule sur la plus
récente restante ou une neuve : toujours une discussion active).
Les opérations sont sérialisées ; l'index partage son verrou avec
l'écrivain (StoreSink::index_lock, convIndexMu en Go). Fichiers, travaux,
critères, mode, résultats d'outils d'une discussion supprimée et
préchauffage après bascule passent par SessionHooks. Store gagne
get_open / put_seal (getStoreBytesErr / putStoreBytes).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port de l'état de Conversation et de subscribeSink : état persisté et
discussion chargée, epoch (reset, bascule), verrou du tour et son arrêt,
ajout au journal avec rejet des deltas d'un tour périmé, coalescence de fin
de tour, instantané numéroté sous le même verrou, /api/chat/state.
Subscription rend les lots à émettre : rejeu (padding, reset si le curseur
vient d'une autre discussion, pagination, caught_up, contexte), puis le
direct, avec {reset} et l'en-tête paginé quand l'epoch change. Réveil par
compteur de version marqué lu avant la relecture de l'état : aucun réveil
perdu.
Tests Go de l'abonnement portés.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
EngineLease prend le verrou de génération du Go, le renouvelle au tiers de
sa durée en tâche de fond et signale au tour un stop passé par le Go ou la
perte du bail (Reset, bascule, expiration). Rendu par release, ou en tâche
de fond s'il est lâché. engine_stop arrête un détenteur Go (tâche, bench,
optimiseur). Store::internal_post garde le statut HTTP pour distinguer les
refus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Port de chat_persist.go et de la partie index de chat_sessions.go, au même
format en base que le Go (chat/conv:<id>, chat/index, toolres/<clé>, tous
scellés par l'API interne) :
- ConvState : JSON de Conversation à l'octet près (tranches vides en null,
bloc projet omis), relecture tolérante comme json.Unmarshal et guérison
stripImageParts ; instantané en plein tour avec le journal compacté ;
- index : ConvMeta, titre déduit (rappels de loki et <context_update>
exclus, 60 caractères), tri, projets, renommage, rafraîchissement d'une
entrée ;
- écrivain unique (Persister) : lots fusionnés, jamais un état plus ancien
qu'un état écrit, résultats d'outils servis depuis la mémoire jusqu'à
l'écriture, suppressions qui ne font rien renaître, file jamais bloquée
par un écrivain qui panique ;
- StoreSink : écriture par l'API interne du Go. Mémoire verrouillée : rien
en clair ; index illisible : jamais réécrit.
Tests Go de l'écrivain portés, plus des tests de bout en bout contre le
faux Go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
Envoi de la requête de complétion (clé de CET endpoint seulement, jamais
celle du serveur local vers une API externe), découpe du flux en lignes
comme bufio.Scanner (8 Mio au plus par ligne, arrêt net au-delà), et les
primitives de reprise de llm_retry_net.go : statuts rejouables, délai
800 ms doublé et plafonné à 5 s, classement des pannes réseau et messages
de friendlyLLMError / streamCutError à l'identique. La décision de rejouer
reste à la boucle.
HTTPS pour les presets externes : reqwest + rustls (ring), derrière une
fonctionnalité Cargo « tls » activée par défaut — le contrôle croisé Linux
sous Windows s'en passe, faute d'en-têtes libc Linux. L'étape Alpine de
l'image installe gcc pour ring.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Message, ToolCall, Tool, événements de flux, statistiques, journal :
sérialisation JSON identique aux types Go (omitempty, contenu any). Socle
commun des ports parallèles qui suivent (charge utile, flux, compactage,
journal).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>