Concierge au branchement + moniteur LLM/RAM + docs

Concierge: declenche au BRANCHEMENT (transition on de evenement) au lieu de la session ;
helper porte 'branchement' (ts::text verbatim) ; fraicheur [on-10, min(now, on+30)].
Moniteur LLM/RAM (llm-monitor.js) : endpoint spark + RAM, alerte WhatsApp sur changement
d'etat, publie l'etat dans HA (last_seen a chaque passage) + interrupteur de pilotage.
Docs: SPEC a jour, MONITORING-LLM.md, brouillons de config HA.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RZsbhyGmRwZogdoBwT6C6y
This commit is contained in:
2026-09-15 04:59:15 +02:00
parent 534ae0d663
commit b834e3bf75
9 changed files with 345 additions and 94 deletions

View File

@@ -23,15 +23,16 @@ function haToken() {
process.env.HA_TOKEN_FILE || path.join(__dirname, '.ha-token'), 'utf8').trim();
}
// Publie le tuple {sessions[], label, confirmed_at, source} pour un branchement.
// sessions = clefs `debut` VERBATIM (ms comprises). Le service EVCS joint sur ±1 s.
async function publishLabel(sessions, label, source = 'whatsapp') {
if (!Array.isArray(sessions) || sessions.length === 0) {
throw new Error('sessions doit être une liste non vide');
// Publie le tuple {branchement, label, confirmed_at, source}.
// branchement = ts::text VERBATIM de la transition 'on' (evenement), espace et +02
// compris. Le service EVCS joint dessus (±1 s). C'est ce que PostgreSQL a rendu.
async function publishLabel(branchement, label, source = 'whatsapp') {
if (!branchement || typeof branchement !== 'string') {
throw new Error('branchement (ts::text verbatim) requis');
}
if (!label || typeof label !== 'string') throw new Error('label invalide');
const payload = JSON.stringify({
sessions, label, confirmed_at: new Date().toISOString(), source,
branchement, label, confirmed_at: new Date().toISOString(), source,
});
if (payload.length > MAX_LEN) {
throw new Error(`payload ${payload.length} > ${MAX_LEN} : scinder le groupe ` +