Le conseiller devient observateur, et une couche d enquete voit le jour

SPECIALISATION. Campagne du 12/09 : lui demander d observer ET de
planifier degradait les deux — l ecart de cible entre passages est passe
de 0 a 35 points sur certains cas des l ajout de la mission
d observation. Il ne planifie plus : la planification est faite par le
bilan, qui est calcule, mesure et teste a 48/48. Sortie reduite a
constat / gravite / ce_qui_cloche / piste. Prompt 7609 -> 6250 caracteres.

Mesure apres specialisation, horloge epinglee : oscillation reelle
detectee 5/5, contrefactuel calme 5/5. La discrimination est parfaite.
⚠️ Mais la gravite est retombee de « haute » a « moyenne » : mon echelle
a quatre niveaux n est ancree sur aucun exemple. Defaut de briefing a
corriger, pas defaut de detection.

Le compteur mesure desormais le VOLUME de signalements : on ne peut pas
verifier automatiquement s il a raison, on peut mesurer s il crie au loup.

COUCHE D ENQUETE. Trouver le coupable ce matin a demande sept requetes
enchainees ; rien n y exigeait un humain, seulement d appeler des outils
et d enchainer d apres ce qu on vient de lire. Six sous-commandes en
LECTURE SEULE, exposees en ligne de commande pour qu OpenClaw — que le
proprietaire veut utiliser — ou tout autre pilote les appelle sans
reecriture : bascules, mesures, decisions, ecrivains, bilan, cherche.

`bascules` calcule l ecart entre transitions successives du meme objet :
c est la signature d une oscillation, et l appelant n a pas a la refaire.

L enquete de ce matin se rejoue en trois commandes, jusqu a
automations.yaml ligne 22.

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 08:36:31 +02:00
parent 6a647dc685
commit 1945fdfe5c
9 changed files with 4586 additions and 185 deletions

View File

@@ -34,64 +34,30 @@ setText('input_text.evcs_advisor_last_run', stampParis());
setText('input_text.evcs_advisor_model', modelUsed);
if (status === 'ok' && advice) {
// Observation — la sortie principale desormais.
// Observation — la seule sortie desormais. Le conseiller ne planifie plus :
// la planification est faite par le bilan, qui est calcule et mesure, et la
// campagne du 12/09 a montre que lui demander les deux degradait les deux
// (ecart de cible passe de 0 a 35 points sur certains cas des l ajout de la
// mission d observation).
setText('input_text.evcs_advisor_constat', advice.constat);
setText('input_text.evcs_advisor_gravite', advice.gravite);
setText('input_text.evcs_advisor_ce_qui_cloche', advice.ceQuiCloche || 'rien de signale');
setText('input_text.evcs_advisor_reason', `[${Math.round(advice.confidence * 100)}%] ${advice.piste || advice.constat}`);
// Recommandations
setText('input_text.evcs_advisor_strategy', advice.strategy);
// Les champs d action ne sont publies que s ils sont exploitables : un
// helper numerique ne doit jamais porter une valeur hors bornes.
if (advice.actionUtilisable) {
setNumber('input_number.evcs_advisor_night_target_soc', advice.nightTargetSoc);
setNumber('input_number.evcs_advisor_current_max_a', advice.currentMaxA);
}
setText('input_text.evcs_advisor_ev_charge_tonight', advice.evChargeTonight);
setText('input_text.evcs_advisor_reason', `[${Math.round(advice.confidence * 100)}%] ${advice.reason}`);
// Divergence vs réel (stratégie + cible nuit)
const diffs = [];
if (advice.strategy !== context.userStrategy) {
diffs.push(`stratégie: agent=${advice.strategy} ≠ réel=${context.userStrategy}`);
}
if (Math.abs(advice.nightTargetSoc - context.nightTargetActual) > 10) {
diffs.push(`cible nuit: agent=${advice.nightTargetSoc}% vs réel=${context.nightTargetActual}%`);
}
const divergenceText = diffs.length ? diffs.join(' | ') : 'accord avec le réel';
setText('input_text.evcs_advisor_divergence', divergenceText);
// ⚠️ LE COMPTEUR MESURAIT LE MAUVAIS CHAMP (corrige le 12/09/2026).
// Il comparait la STRATEGIE, qui vaut `auto_solar_plus` la quasi-totalite du
// temps : 517 accords contre 23 divergences, soit 95,7 % — un score qui
// mesurait une constante, pas une decision. Pendant ce temps la cible SOC,
// seul champ reellement cable, divergeait de treize points du bilan sans
// que rien ne le compte (12/09 05:30 : conseiller 35 %, bilan 48,4 %).
//
// On compte desormais l'accord sur la CIBLE, et contre le BILAN — la
// reference, pas contre la valeur appliquee qui peut elle-meme etre fausse.
// Bilan indisponible => on ne compte rien plutot que de compter faux.
const refSoc = Number(context.balanceRequiredSoc);
const bilanUtilisable = advice.actionUtilisable && context.balanceStatus === 'ok' && Number.isFinite(refSoc);
if (bilanUtilisable) {
const ecart = Math.abs(advice.nightTargetSoc - refSoc);
if (ecart <= 5) {
setNumber('input_number.evcs_advisor_agree_count', context.agreeCount + 1);
} else {
setNumber('input_number.evcs_advisor_diverge_count', context.divergeCount + 1);
}
setText(
'input_text.evcs_advisor_divergence',
`cible: agent=${advice.nightTargetSoc}% vs bilan=${Math.round(refSoc)}% (ecart ${Math.round(ecart)} pts)`
+ (diffs.length ? ` | ${diffs.join(' | ')}` : '')
);
// Un observateur qui signale en permanence ne sert a rien : on compte le
// VOLUME de signalements pour pouvoir le constater.
if (advice.gravite === 'aucune') {
setNumber('input_number.evcs_advisor_agree_count', context.agreeCount + 1);
} else {
setNumber('input_number.evcs_advisor_diverge_count', context.divergeCount + 1);
}
// Trace logbook pour l'historique long terme
push('logbook', 'log', {
name: 'EVCS Advisor (ombre)',
message: `[${advice.gravite}] ${advice.constat}${advice.ceQuiCloche ? ` || ${advice.ceQuiCloche}` : ''} || ${advice.strategy} | cible nuit ${advice.nightTargetSoc}% | ${advice.evChargeTonight === 'oui' ? 'charge VE cette nuit' : advice.evChargeTonight === 'non' ? 'pas de charge nuit' : 'VE sans objet'} | ${divergenceText} | ${advice.reason}`,
entity_id: 'input_text.evcs_advisor_strategy',
name: 'EVCS Advisor (observateur)',
message: `[${advice.gravite}] ${advice.constat}`
+ (advice.ceQuiCloche ? ` || ${advice.ceQuiCloche}` : '')
+ (advice.piste ? ` || piste : ${advice.piste}` : ''),
entity_id: 'input_text.evcs_advisor_constat',
});
}