Chaque transition dit desormais QUI l a provoquee

Le 12/09, le contacteur reseau a bascule six fois en dix minutes. Trouver
le coupable a demande sept requetes enchainees — executions n8n des deux
workflows, liste des ecrivains, puis automations.yaml — parce que la
table des evenements disait QUE ca avait bascule, jamais PAR QUI.

Home Assistant le savait pourtant. Son logbook resout le contexte d un
changement d etat et nomme l auteur. Sur la coupure de 06:29:44 :
  auteur      : automation.victron_grid_off_si_soc_35
  declencheur : triggered by numeric state of sensor.victron_battery_soc

Un appel par transition REELLE — quelques-uns par jour, pas par cycle.
Echec de lecture => pas d auteur, la ligne est ecrite quand meme : on ne
devine jamais.

⚠️ L auteur est colle au RESUME, pas seulement au detail jsonb. C est le
resume que Grafana affiche en annotation sur TOUS les tableaux et dans
les panneaux « journal des evenements », et que le rapport de nuit
reprend. Le mettre la le rend visible partout sans toucher a un seul
tableau.

 remonte l auteur et son declencheur : l enquete de ce
matin tient desormais en UNE commande, et l observateur pourra nommer le
coupable au lieu de dire « un des trois ».

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
This commit is contained in:
Tallagrand Thierry
2026-09-12 09:12:35 +02:00
parent e675ec434c
commit 9448676cbd
2 changed files with 54 additions and 3 deletions

View File

@@ -71,11 +71,13 @@ if (!commande || commande === 'outils') {
});
} else if (commande === 'bascules') {
const [motif, h = '6'] = args;
const r = sql(`select to_char(ts at time zone 'Europe/Paris','YYYY-MM-DD HH24:MI:SS'), genre, resume
const r = sql(`select to_char(ts at time zone 'Europe/Paris','YYYY-MM-DD HH24:MI:SS'), genre, resume,
coalesce(detail->>'auteur',''), coalesce(detail->>'declencheur','')
from evenement where ts > now() - interval '${Number(h)} hours'
${motif ? `and resume ilike '%${motif.replace(/'/g, '')}%'` : ''}
order by ts desc limit 80`);
const lignes = r.map(([quand, genre, resume]) => ({ quand, genre, resume }));
const lignes = r.map(([quand, genre, resume, auteur, declencheur]) =>
({ quand, genre, resume, ...(auteur ? { auteur } : {}), ...(declencheur ? { declencheur } : {}) }));
// Un ecart court entre deux transitions du meme objet est la signature d une
// oscillation : on le calcule ici pour que l appelant n ait pas a le refaire.
for (let i = 0; i < lignes.length - 1; i++) {