Agent IA planificateur EVCS en MODE OMBRE (Advisor Shadow V1)
- Workflow n8n tdfInZns7cqo8fU2 actif (15 min): snapshot HA compact -> prompt FR -> LLM local Spark (modèle dynamique via /v1/models) avec fallback OpenRouter claude-haiku-4.5 (credential chiffré, clé hors git) -> validation stricte (enums, bornes, rejet total si invalide) -> helpers advisor_* + divergence + compteurs accord/divergence + logbook. - GARANTIE OMBRE structurelle: écritures limitées à advisor_*/logbook, vérifiée par tests/advisor/run.mjs (16 tests, bloquants au push). - Kill-switch input_boolean.evcs_advisor_enabled. - Extension R2 multi-workflows (lib-node-map WORKFLOWS[], build/extract/push par fichier, n8n-create.mjs, gen-advisor-workflow.mjs). - Helpers HA via package NFS + carte dashboard EVCS Master (backup fait). - 1re reco réelle: auto_solar_plus, cible 35%, accord avec le réel. - Fix sécurité n8n-push: plus de fallback d'id implicite vers le workflow EVCS.
This commit is contained in:
@@ -15,14 +15,14 @@ if (!INPUT) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// R2 : src/nodes/ = SOURCE DE VÉRITÉ pour le workflow EVCS.
|
||||
// Le build injecte src/nodes/*.js dans le JSON AVANT toute vérification :
|
||||
// toute édition faite directement dans le JSON (ou l'UI n8n non ré-extraite)
|
||||
// est écrasée par src/. Workflow EVCS uniquement.
|
||||
if (path.basename(INPUT) === 'evcs-surplus-controller-v2.6.json' && fs.existsSync('src/nodes')) {
|
||||
console.log('Build src/nodes/ → JSON (source de vérité : src/)...');
|
||||
// R2 : src/ = SOURCE DE VÉRITÉ pour les workflows enregistrés dans le node-map.
|
||||
// Le build injecte src/**/*.js dans le JSON AVANT toute vérification.
|
||||
const { findWorkflowByFile } = await import('./lib-node-map.mjs');
|
||||
const registered = findWorkflowByFile(INPUT);
|
||||
if (registered) {
|
||||
console.log(`Build ${registered.srcDir}/ → JSON (source de vérité : src/)...`);
|
||||
const { spawnSync } = await import('child_process');
|
||||
const b = spawnSync('node', ['tools/n8n-build.mjs'], { stdio: 'inherit' });
|
||||
const b = spawnSync('node', ['tools/n8n-build.mjs', INPUT], { stdio: 'inherit' });
|
||||
if (b.status !== 0) {
|
||||
console.error('ABANDON: échec du build src → JSON.');
|
||||
process.exit(1);
|
||||
@@ -30,7 +30,11 @@ if (path.basename(INPUT) === 'evcs-surplus-controller-v2.6.json' && fs.existsSyn
|
||||
}
|
||||
|
||||
const local = JSON.parse(fs.readFileSync(INPUT, 'utf8'));
|
||||
const WORKFLOW_ID = process.argv[3] || local.id || 'ATswvGfG4KJUls0K';
|
||||
const WORKFLOW_ID = process.argv[3] || local.id;
|
||||
if (!WORKFLOW_ID) {
|
||||
console.error('ABANDON: aucun id de workflow (ni argument, ni champ id dans le JSON).');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function loadApiConfig() {
|
||||
if (process.env.N8N_API_KEY) {
|
||||
@@ -101,20 +105,25 @@ if (syntaxErrors) {
|
||||
}
|
||||
console.log('Syntaxe OK sur tous les nodes jsCode.');
|
||||
|
||||
// 3bis. Suite golden (R3) : obligatoire pour le workflow EVCS, sauf --skip-golden
|
||||
// 3bis. Suites de tests (R3) : bloquantes par workflow, sauf --skip-golden
|
||||
const isEvcsWorkflow = path.basename(INPUT) === 'evcs-surplus-controller-v2.6.json';
|
||||
const isAdvisorWorkflow = path.basename(INPUT) === 'evcs-advisor-shadow-v1.json';
|
||||
const skipGolden = process.argv.includes('--skip-golden');
|
||||
if (isEvcsWorkflow && fs.existsSync('tests/golden/run.mjs')) {
|
||||
const testSuite =
|
||||
isEvcsWorkflow && fs.existsSync('tests/golden/run.mjs') ? 'tests/golden/run.mjs' :
|
||||
isAdvisorWorkflow && fs.existsSync('tests/advisor/run.mjs') ? 'tests/advisor/run.mjs' :
|
||||
null;
|
||||
if (testSuite) {
|
||||
if (skipGolden) {
|
||||
console.log('⚠️ Suite golden SAUTÉE (--skip-golden) — à n\'utiliser qu\'en connaissance de cause.');
|
||||
console.log('⚠️ Suite de tests SAUTÉE (--skip-golden) — à n\'utiliser qu\'en connaissance de cause.');
|
||||
} else {
|
||||
console.log('Exécution de la suite golden (tests/golden/run.mjs)...');
|
||||
console.log(`Exécution de la suite de tests (${testSuite})...`);
|
||||
const { spawnSync } = await import('child_process');
|
||||
const g = spawnSync('node', ['tests/golden/run.mjs'], { stdio: 'inherit' });
|
||||
const g = spawnSync('node', [testSuite], { stdio: 'inherit' });
|
||||
if (g.status !== 0) {
|
||||
console.error('ABANDON: la suite golden échoue. Rien n\'a été poussé.');
|
||||
console.error('ABANDON: la suite de tests échoue. Rien n\'a été poussé.');
|
||||
console.error('(Évolution volontaire du comportement ? Mettre à jour les attendus');
|
||||
console.error(' dans tests/golden/scenarios.mjs dans le même commit, puis re-pousser.)');
|
||||
console.error(' de la suite dans le même commit, puis re-pousser.)');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user