bbarthe (et tout compte Authentik sans email) échouait au login SSO :
Grafana, email vide, tentait l'endpoint /emails inexistant chez Authentik
→ 404 InternalError. email_attribute_path avec repli preferred_username +
login_attribute_path évitent le fallback. Plus besoin d'email par user.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Monitoring GPU consolidé (util/VRAM/temp/clocks) façon nvidia-smi, aligné
sur la ROCm 7.2.4 installée (repo rocm, /opt/rocm/bin/rocm-smi déjà dans
le PATH). Appliqué sur gpu-01 : llama-server intact (GPU non perturbé).
Doc admin/ia/rocm.md + README du rôle mis à jour.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- admin/k8s/auth-portal-admin.md : exploitation au quotidien — cycle de
vie utilisateur (créer/groupe guacamole/assigner/révoquer), gestion des
machines et des apps du hub, durcissement (MFA), table de débogage
- docs/portail-guide-utilisateur.md : guide grand public à envoyer aux
utilisateurs (connexion, console, presse-papiers, règles, dépannage)
- renvois croisés depuis auth-portal.md et CLAUDE.md
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
EXTENSION_PRIORITY "openid, *" : plus de formulaire local, l'arrivée sur
portail.lab.local redirige directement vers Authentik. L'admin passe par
un compte SSO avec « Administer system » (guacadmin devient inaccessible ;
retour arrière = remettre "*, openid").
Doc : pièges slug d'application (≠ guacamole → JWKS 404) et anti-bruteforce
(IP Traefik bloquée pour tous après 5 échecs) découverts pendant la mise
en route.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Ces deux valeurs ne vivaient que dans le secret k8s auth/authentik-secret
(etcd single control-plane, sans backup) — copie de sûreté dans le vault.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Le premier démarrage exécute les migrations de schéma (plusieurs minutes) ;
la livenessProbe (60 s) tuait le pod en boucle avant qu'il ne soit prêt.
La startupProbe accorde jusqu'à 10 min avant d'armer liveness/readiness.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Le restart de session planifié (minuit) échoue si le nom de session
contient un espace : l'URL ServerTravel est bloquée et le serveur reste
sans session chargée (process vivant, injoignable). Fix : re-sauvegarder
sous un nom sans espace.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(ansible): serveur dédié Satisfactory sur gpu-01
- Nouveau rôle satisfactory_server : install steamcmd (login anonyme,
app 1690800), service systemd avec update auto en ExecStartPre,
MemoryMax=16G + Nice=5 (protège le llama-server), firewalld 7777 tcp+udp
- Retries steamcmd (« Missing configuration » rc=8 au premier run)
- Fcontext SELinux bin_t sur steamcmd/ et server/ (203/EXEC sinon)
- gateway : DNAT 192.168.1.200:7777 → gpu-01:7777 (TCP+UDP) + forward
- Doc admin/ops/satisfactory.md (accès, exploitation, pièges rencontrés)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(satisfactory): ouvrir le port 8888/tcp Reliable Messaging
Depuis la 1.1, le client ouvre un socket TCP :8888 en plus du jeu UDP
:7777. Bloqué par firewalld, le join réussissait puis le client était
déconnecté (~60 s) avec « connection to the host has been lost »
(log client : LogReliableMessaging: Failed to connect to server socket).
- firewalld gpu-01 : + 8888/tcp (variable satisfactory_reliable_port)
- gateway s01 : DNAT + forward étendus à 8888/tcp
- doc : tableau des 3 sockets + piège n°3
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(satisfactory): accès internet via IPv4 full-stack Free
Le remap de port Freebox (17777→7777) ne fonctionne pas : le serveur
annonce ses ports dans le protocole (externe = interne obligatoire).
Option IPv4 full-stack activée → redirections 1:1 7777 tcp+udp + 8888 tcp
vers funk-s01, DNAT existant inchangé.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Rebasé sur main (post-#72). Refonte de l'interface inspirée de Revolut :
- En-tête : valeur totale + variation sur la période (1J/1S/1M/6M/1A/Tous) +
courbe de valeur du portefeuille (area chart)
- Tableau de positions style Revolut par compte (avatar, nom+ticker, quantité,
prix moyen, cours, valeur, P&L €, taux %, variation jour, répartition, ▲▼)
- Onglets de comptes (Tous/Revolut/BNP) en barre du haut
- Clic sur une ligne → fiche action : chandeliers (MM50+volume), tabs période,
chips techniques, boutons Analyse/Plan/Fondamentaux
- Sidebar (actions rapides, alertes, secteurs) + couches IA ; import image/CSV conservé
Backend : /api/portfolio-history (courbe valeur, alignée date US/EU, « Tous » 2 ans),
/api/portfolio enrichi (nom société + variation jour), data.day_change/company_name.
Validé navigateur (Playwright) + endpoints (TestClient) ; JS node --check OK.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Procédure de mise à jour du portefeuille « à chaque trade » à partir des relevés
Revolut, sans IA (exact).
- finlab/revolut.py : reconstruit les positions depuis le « trading account
statement » (toutes transactions) par COÛT MOYEN (achats − ventes, PRU pondéré),
mappe les tickers Revolut→Yahoo (ASME→ASML.AS, TOTB→TTE.PA, BNP→BNP.PA, AXA→CS.PA,
FTE→ORA.PA, AIR1→AI.PA) et vérifie les cours. Idempotent, ne touche qu'un compte,
préserve les autres comptes/cash/commentaires (round-trip ruamel.yaml)
- CLI : python -m finlab.cli import-revolut <csv> [--write] [--account]
- Dashboard : le bouton « Importer un relevé » accepte les CSV → endpoints
/api/revolut/preview (aperçu) + /api/revolut/apply (écrit), avec garde anti-évasion
de chemin ; le front affiche les positions + bouton « Appliquer »
- portfolio.yaml : compte Revolut reconstruit depuis l'historique complet → ajoute
AMAT (achetée le 29/06, manquait) ; valeurs alignées au centime
- requirements : + ruamel.yaml ; persona console + admin/ia/finlab.md documentés
Validé sur l'historique réel : 11 positions reconstruites = portfolio.yaml existant
(cours vérifiés, 0 warning) + AMAT. Flux dashboard upload→preview→apply testé
(TestClient), JS OK.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Permet de configurer des alertes « préviens-moi par mail quand NVDA atteint 200$ »
depuis la Console IA. Un sidecar surveille les cours en continu.
- finlab/watcher.py : boucle toutes les 5 min, lit price_alerts.yaml (workspace),
évalue les seuils above/below, envoie un email au franchissement. Anti-spam
(1 mail/seuil, état .watcher-state.json, ré-armé en ré-éditant). Modes --once / --test
- Email via le relais postfix du lab (storage-01:25, SMTP_HOST) qui réécrit
l'expéditeur en Gmail — AUCUN secret (pods k8s dans mynetworks)
- price_alerts.yaml : config seedée dans le workspace (email_to + rules), éditée
par la Console IA sur demande
- deployment : conteneur sidecar `watcher` (boucle 5 min, ressources minimes)
- Dockerfile : seed price_alerts.yaml ; persona console + admin/ia/finlab.md documentés
Logique testée en local (SMTP mocké) : franchissement → envoi, anti-spam au 2e run,
seuil non atteint → rien.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Process dédié pour actualiser le portefeuille à partir d'une capture de relevé :
- Dashboard : bouton « 📥 Importer un relevé » (panneau Mes comptes) → upload de
l'image vers le workspace (imports/) via POST /api/import ; une modale donne la
phrase exacte à dire à la console + un lien direct
- Backend : endpoints /api/import (UploadFile, refuse les non-images) et /api/imports
(listing), dossier imports/ sous FINLAB_HOME (workspace, persistant)
- Persona console (CLAUDE.md) : workflow « Import d'un relevé » — lire l'image,
extraire compte/positions, mapper vers tickers Yahoo en VÉRIFIANT les cours,
confirmer, puis mettre à jour portfolio.yaml
Le scan vision se fait dans la Console IA (abonnement, pas de clé API). Le dashboard
n'est que le pont d'upload. Testé : POST image→200 + listing OK, non-image→400 ;
JS node --check OK.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Console Claude Code throttlée ~11% en pic à 1 cœur (CPU moy ~0,2, RAM ~384 Mo —
non contrainte). On double le plafond CPU pour fluidifier les bursts ; un peu de
marge RAM. Mesuré via Prometheus. (La latence du modèle reste côté API.)
requests cpu 150m→300m, mem 512Mi→768Mi ; limits cpu 1→2, mem 1536Mi→2Gi.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Permet de suivre plusieurs comptes (courtiers/banques) côte à côte, avec vue par
compte et agrégée. Ajoute le PEA BNP Paribas à côté de Revolut.
- portfolio.yaml : nouveau format `accounts` (name/type/cash/positions par compte).
Compat ascendante : ancien format (cash/positions à la racine) lu comme compte
unique « Principal »
- data.py : load_accounts(), base_currency(), portfolio_tickers() (union dédupliquée)
- tracker.py : build_account / build_all (par compte + agrégat global) ; build()
reste la vue globale (digest/report) ; report() multi-comptes
- scanner/technical/alerts : helpers « portfolio » → union de tous les comptes
- dashboard /api/portfolio : renvoie accounts[] (positions+agg par compte) + global
- dashboard front : onglets de comptes (Tous / Revolut / BNP Paribas), KPI + positions
+ secteurs qui suivent le périmètre sélectionné, badge de type par ligne en vue Tous
- BNP Paribas (PEA) saisi depuis la capture : AI/PAEEM/DCAM/PCEU/PSP5/BNP/ENGI/TTE .PA
(tickers Yahoo vérifiés, cours conformes à la capture)
Vérifié : totaux conformes à la capture BNP (6 395,49 € ; P&L -39 €), global 22 444 € ;
bascule d'onglet OK au navigateur (Playwright) ; compile + JS + CLI report OK.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- Dashboard : la console Claude Code (/console/) est désormais embarquée en iframe
sous le graphique (boutons reconnecter / plein écran), en plus du lien topbar
- Nouvelle vue pleine largeur « Chaîne de valeur IA — par couche » : regroupe les
watchlists par couche de l'électron au logiciel (⚡ énergie → 🔧 puces →
🏢 datacenter → 🔌 câbles/optique → ☁️ software), tickers cliquables colorés
par biais (haussier/baissier), tooltip cours/RSI/MACD
- Backend : endpoint /api/layers (scan groupé par thème, ordre des couches)
Vérifié au navigateur (Playwright, instance locale) : layout complet OK —
portefeuille + graphique chandeliers MM50/200 + console embarquée + alertes +
5 cartes de couches colorées. Endpoints et JS validés.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute une interface graphique à finlab, en plus de la console Claude Code (les
deux cohabitent sur finance.lab.local) :
- dashboard/ : backend FastAPI (sans LLM/clé) exposant les données finlab en JSON
(/api/portfolio, /api/scan, /api/ohlc, /api/plan, /api/alerts) + front statique
(lightweight-charts) : graphiques chandeliers MM50/200 + volume, portefeuille
(P&L/poids/secteurs), watchlists thématiques scannées, alertes, plan de trade R:R
- Découplage code/data : finlab lit ses configs depuis FINLAB_HOME si défini
(workspace persistant) ; repli sur le dossier du package en dév local
- Image double usage (un build, deux conteneurs) : code → /opt/app, seed minimal
(configs + persona + MCP) → workspace
- Fix seed NFS (cause racine du workspace vide) : WORKDIR n'est plus sur le volume
(le runtime le créait en root sur NFS) ; seed déplacé dans un initContainer
robuste (recrée le dossier s'il est non-inscriptible)
- Deployment : initContainer seed + 2 conteneurs (console ttyd -b /console, dashboard
uvicorn) ; Service 2 ports ; IngressRoute 2 routes (/console + dashboard), basicAuth
Validé en local (podman) : seed OK, dashboard /api/portfolio → 16k€/10 positions
via FINLAB_HOME, endpoints ohlc/scan/plan/alerts OK, ttyd/claude/finlab présents.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(finlab): console Claude Code finance in-cluster + toolkit d'analyse
Intègre finlab (ex-projet Projets/Finance) au lab comme une console Claude Code
web spécialisée finance — l'esprit OpenAlice, mais c'est le vrai Claude Code sur
l'abonnement (login persisté, pas d'API facturée), agentique, avec la boîte à
outils finlab (Yahoo Finance) branchée en MCP.
- tools/finlab/ : source finlab rapatriée + Dockerfile (Python 3.12 + Node +
claude-code + ttyd) + persona workspace/CLAUDE.md + branchement MCP + entrypoint
(seed du workspace no-clobber sur le PVC)
- .github/workflows/build-finlab.yml : build GHCR funk-finlab + bump manifest (main)
- k8s/apps/finlab/ : Deployment/Service/PVC/IngressRoute (finance.lab.local) +
Middleware basicAuth (shell web protégé) ; PVC = HOME (login) + workspace
- k8s/apps-of-apps/apps/finlab.yaml : Application ArgoCD
- .mcp.json (racine) : outils finlab dans les sessions Claude Code du lab
- admin/ia/finlab.md + READMEs + CLAUDE.md : doc + enregistrement
Analyse/aide à la décision uniquement — aucun ordre réel (paper trading Alpaca
fictif seul exécutable).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(finlab): ttyd absent des dépôts bookworm → binaire statique GitHub
Le build amont échouait (`E: Package 'ttyd' has no installation candidate`) :
ttyd n'est pas packagé dans Debian bookworm. On récupère le binaire statique
(musl, pin TTYD_VERSION=1.7.7) depuis les releases GitHub. Build complet validé
en local (podman) : ttyd 1.7.7, claude-code 2.1.195, import finlab + seed OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Projet mis en pause : Kraken via « CCXT Custom » non supporté (fetchBalance
avorte) + pas d'automatisation actions. Pod éteint, mais Deployment + PVC
openalice-data (config, clés scellées, données) conservés. Relance = replicas 1.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Le Dockerfile amont v0.60.0-beta.1 copie src/workspaces/templates dans l'image
runtime mais oublie src/workspaces/cli, alors que cliBinPath()
(/app/src/workspaces/cli/bin) est requis au runtime pour poser les shims
alice/alice-uta/traderhub sur le PATH des agents. Sans eux, l'agent ne peut pas
joindre le moteur de trading ("alice-uta introuvable sur mon PATH").
- build-openalice.yml : patch du Dockerfile cloné (COPY src/workspaces/cli) + guard
- tag image suffixé via IMAGE_PATCH=p1 → nouveau tag immuable, ArgoCD redéploie
- deployment.yaml → :v0.60.0-beta.1-p1
- doc admin/ia/openalice.md (correctifs locaux)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Déploie TraderAlice/OpenAlice (AGPL-3.0) dans le namespace ai comme back-end de
connaissances financières pour Asa, consommé via le connecteur MCP Ask.
- CI build-openalice.yml : rebuild depuis le Dockerfile amont (ref épinglée v0.60.0-beta.1)
→ ghcr.io/alkatrazz24/funk-openalice, bump manifest sur main
- k8s/apps/openalice : Deployment (restricted + fsGroup, Recreate), PVC 5Gi NFS /data,
Service web:47331 + mcpask:3003, IngressRoute openalice.lab.local
- ArgoCD app + doc admin/ia/openalice.md (RAG) + MAJ CLAUDE.md
- Cerveau hybride : LiteLLM/Qwen3-8B local (gratuit) + Claude basculable ; données
TraderHub (sans clé) + FMP gratuit. Lecture/recherche seule — aucun broker, zéro trading.
Onboarding premier boot (Web UI) imposé : credentials scellés dans /data par design.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
La page détail d'un service (panneau « Services » du HUD) passe en PLEINE
PAGE : le drawer prend tout l'écran, le titre devient le nom du service, et
le contenu s'organise en 2 colonnes sur grand écran (données à gauche, état
+ actions à droite).
Nouvelle section « Métriques » par service, config-driven (comme `components`) :
- `[[services.metrics]]` → {label, prom, unit, hide_if_empty} évalué par le
StatusPoller (dédup + parallèle avec les composants).
- Défauts via `config._pod_metrics(ns, pod_re)` pour les 7 services : redémarrages
+ uptime (kube-state-metrics, toujours dispo) ; mémoire + CPU (cAdvisor,
`hide_if_empty` → carte masquée si non scrappé).
- Formatage HUD par unité : duration (8 j 9 h), bytes (497 Mo), cpu (30 mcœur),
count.
Client 0.19.0. PromQL vérifié live (les 4 métriques renvoient des valeurs réelles
sur les 7 services). Rendu pleine page + formats validés via Playwright.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Les pages détail du portail HUD affichent désormais un aperçu live des données
du service, pas seulement santé + lien :
- Ghostfolio → portefeuille complet : valeur, performance globale, positions
(allocation % + P/L par ligne, coloré). Nouvel endpoint serveur
POST /v1/portfolio/details (jeton client, source unique réutilisée).
- Alertmanager → TOUTES les alertes actives du homelab (total + critiques +
liste avec sévérité), rendu côté HUD depuis `all_alerts` poussé par le
StatusPoller (auto-rafraîchi, aucun appel supplémentaire).
Mécanisme extensible (`DETAIL_PROVIDERS` : `server` = requête backend |
`alerts` = liste locale). Cartes de stats + lignes de données génériques.
Client 0.18.0. Vérifié via Playwright (rendu, tons, normalisation des %).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Deux demandes côté client :
- VOLUME : slider « Volume de la voix » (0–200 %) dans le drawer Réglages du HUD,
appliqué À CHAUD (canal settings → engine.cfg.tts_volume) et persisté
(localStorage). Gain appliqué au WAV avant lecture, commun Piper/Kokoro
(engine._apply_gain, PCM16 ×gain, clip). Config [voice].tts_volume (0.0 muet …
2.0 amplifié, défaut 1.0). 0 = muet (le tour se déroule sans son).
- FENÊTRAGE : le mode existait ([ui].window_mode app|kiosk|none) ; `stt --window`
PERSISTE désormais le choix → `stt --window app` rend le HUD fenêtré (déplaçable/
redimensionnable, type Discord) durablement, y compris pour le service systemd.
Client 0.17.0. Doc : stt.example.toml + admin/ia/stt.md. Validé : gain ×0.5 exact,
HUD sans erreur JS (slider + collectSettings + label live).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Relevé live 2026-06-23 → mise à jour des écarts depuis le 21/06 :
- admin/ops/etat-cluster.md : SearXNG ajouté (ns ai deploy/svc/IngressRoute,
Application ArgoCD), date + note « STT devenu agentique ».
- CLAUDE.md : date d'état → 23/06 ; bullet STT réécrit (Asa agentique : contexte
asa par défaut, function calling, état live enrichi GPU, web_search, admin_action,
TTS Piper|Kokoro) ; nouveau bullet SearXNG ; apps-of-apps + apps + namespaces
incluent searxng.
- admin/ia/stt.md : corrige les mentions « agir via Hermes = à venir » (désormais
FAIT via admin_action/hermes-exec) ; bandeau daté complété (21→23/06).
(Re-ingestion RAG à faire après merge.)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Faciliter le changement de voix (le simple --update ne bascule rien : la config
perso prime sur le défaut).
- `stt --voices` : liste les voix Piper FR (homme/femme), URLs vérifiées sur
HuggingFace rhasspy/piper-voices.
- `stt --install-voice fr_FR-tom-medium` : télécharge .onnx + .onnx.json et
SÉLECTIONNE la voix (écrit tts_engine=piper + piper_voice dans stt.toml, en
préservant les autres réglages). Puis `stt --restart`.
- doc : admin/ia/stt.md (note « pourquoi --update ne change pas la voix »).
Client 0.16.0.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute un moteur TTS plus naturel (Kokoro, ONNX/CPU) au choix, Piper restant
le défaut et le repli.
- engine.py : synthèse enfichable (_synthesize → _synth_piper | _synth_kokoro).
Kokoro chargé une fois (préchargé au boot si sélectionné), WAV via wave stdlib
(numpy → PCM16), lecture/interruption inchangées. Repli SILENCIEUX si le modèle
ou le paquet kokoro-onnx manque (jamais de crash).
- config : [voice].tts_engine ("piper"|"kokoro") + kokoro_voice (ff_siwis, FR),
kokoro_speed, kokoro_lang.
- cli : `stt --install-kokoro` télécharge kokoro-v1.0.onnx + voices-v1.0.bin dans
~/.local/share/kokoro et imprime les étapes (pipx inject kokoro-onnx, espeak-ng).
- pyproject : extra optionnel [kokoro] ; client 0.15.0.
- doc : stt.example.toml + admin/ia/stt.md + journal.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute docs/asa-commandes.md : liste complète, classée par capacité, des
demandes que l'on peut faire à Asa (avec exemples de phrases FR), bâtie sur
l'implémentation réelle (intents client + outils serveur + services du portail) :
réveil/veille, santé homelab (host_health/cluster_status), métriques (PromQL),
doc Funk (RAG), recherche web, actions admin (confirmation), ouvrir un service,
portefeuille, mémoire, contextes. Liée depuis README.md et docs/stt-presentation.md.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- docs/stt-presentation.md : présentation de l'assistant vocal Asa (STT
client-serveur) — diagramme d'architecture (poste ↔ cluster ↔ LLM/outils/
données) et diagramme de séquence d'une question vocale via la boucle
d'outils, le tout en mermaid (rendu validé). + 2 captures du HUD réel
(conversation agentique, veille/réveil) dans docs/img/.
- README.md : Asa promue en section dédiée (capacités sait/cherche/agit +
capture), mention en vue d'ensemble, arbo stt/ (client/server) + docs/.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
- host_health : ajoute CPU%, disque /%, température CPU, uptime ; pour gpu-01
un bloc GPU complet (température, utilisation, VRAM%, puissance via
rocm_scraper) en plus de llama-server. Requêtes concurrentes (asyncio.gather).
- cluster_status : ajoute le nb de nœuds k8s Ready et une ligne CrashLoopBackOff
(pods en boucle de crash) — complète le filtrage des pods terminés.
- metrics_block (contexte grafana) : ajoute le résumé GPU (util/temp/VRAM).
- Toutes les PromQL validées contre le Prometheus in-cluster.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Asa peut désormais AGIR sur le homelab quand on le demande explicitement, via
un outil de la boucle agentique — mais jamais sans confirmation.
- Outil admin_action(description) (contexte asa) : le LLM PROPOSE une action,
n'exécute rien. brain.ask_with_tools gagne `confirm_tools` : un tel outil
arrête la boucle et surface sa réponse (la question de confirmation).
- _handle_agentic : stocke la proposition en pending par session ; au tour
suivant « confirme » → agent.run_action → hermes-exec (hermes -z --yolo),
« annule » → oubli. Réutilise le handshake + jeton du contexte agent.
- admin_action n'est exposé que si _actions_available() (STT_ACTIONS_ENABLED
+ jeton) ; sinon retiré des schémas envoyés au modèle.
- Factorisation du ctx_debug du visualiseur. 1 test unitaire (confirm_tools
arrête la boucle). Serveur 0.9.0 ; doc stt.md + journal.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Le pod SearXNG crashait en boucle : granian recevait --port tcp://<ip>:8080
au lieu d'un entier. Cause classique k8s : le Service « searxng » fait injecter
l'env service-link SEARXNG_PORT=tcp://<clusterIP>:8080, que l'entrypoint SearXNG
lit comme port de bind.
- enableServiceLinks:false (coupe l'injection des env service-link, inutiles ici)
- SEARXNG_PORT=8080 + SEARXNG_BIND_ADDRESS=0.0.0.0 explicites (défense en profondeur)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>