Patrick Schurig 1f6c7ec27a refactor(plan): le plan rule-based porte strategy « rules », comme activeStrategy (brief 4 T6)
Décision de Patrick du 2026-10-17 : un seul vocabulaire. Plan::strategy du rule-based,
GetPlan.strategy et la doc passent de « rule-based » à « rules » (INTERFACE.md, protocole §6).
Les libellés de journal (« repli rule-based ») ne sont pas des valeurs et restent.

Référence decisions régénérée. Preuve AVANT régénération, moteur de e592618 + ce seul
renommage, contre l'ancienne référence : comparateur --strategie (nouvelle option, qui ne tolère
que plan.strategy rule-based → rules) IDENTIQUE HORS STRATÉGIE — 23 792 lignes, 23 728
identiques à l'octet, 64 qui ne diffèrent que par .plan.strategy (décompte indépendant des
chemins JSON : 64 × .plan.strategy "rule-based" → "rules", rien d'autre). 0 rejeu. Le même
build, relu contre la nouvelle référence : IDENTIQUE ; 6 suites vertes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 11:46:36 +02:00

68 lines
3.2 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync
#pragma once
#include <QDateTime>
#include <QHash>
#include <QString>
#include <QVariantMap>
#include "optimizerplan.h"
/*!
* \file publishedplan.h
* \brief Le plan EN VIGUEUR tel que l'app le lit (\c NymeaEnergy.GetPlan, brief 4 T4, exigence
* app 2).
*
* Fonctions PURES. L'arbitre appelle \c serialiser() en fin de cycle et garde le résultat : le
* \c Get rend ce qui a été publié, il ne recalcule rien (même règle que \c GetLoadTelemetry).
*
* \par Ce qui franchit la frontière — invariant 12
* Des codes, des nombres, des instants. Le \c reason libre d'un optimiseur n'y est jamais ;
* \c expected et \c diagnostics sont réduits à leurs clés documentées (§6), le reste est retiré ;
* ni \c planId, ni \c strategy, ni \c solver de l'optimiseur — des chaînes qu'il écrit librement.
*/
namespace PublishedPlan {
//! Valeur de \c strategy d'un plan du rule-based publié (celle de \c Plan::strategy, et la même
//! que \c activeStrategy : \c OptimizerStatus::StrategieRegles).
constexpr const char *StrategieRegles = "rules";
/*!
* \brief Le plan du cycle, pour l'app.
*
* - **Sous un optimiseur** (\p plan.strategy == \c "optimizer", \p recu non nul) : le créneau
* courant, actions À LA PUISSANCE APPLIQUÉE (celles que l'adaptateur a rendues, après bornes,
* verrous, paliers et délestage L4), puis les créneaux suivants du plan reçu, actions à la
* puissance DEMANDÉE. \c computedAt et \c validUntil sont ceux de l'optimiseur, absents s'il ne
* les a pas donnés.
* - **Sous le rule-based** : un seul créneau, le courant, actions à la puissance appliquée ;
* \c computedAt = \p now, \c validUntil = fin du créneau. \c fallbackCode porte \p codeRepli
* s'il n'est pas vide (un optimiseur est configuré mais n'a pas commandé ce cycle).
*
* \param plan Plan du cycle (après \c finaliser()). \param slot Créneau dispatché, délestage L4
* fusionné. \param appliquees Retours d'\c applyAction() du cycle.
* \param recu Plan d'optimiseur appliqué ce cycle ; ignoré sous le rule-based.
* \param codeRepli Motif du repli rule-based d'une stratégie optimiseur ; vide sans optimiseur.
* \param now Instant du cycle.
* \return La charge utile de \c GetPlan, \c inForce à vrai.
*/
QVariantMap serialiser(const Plan &plan, const Slot &slot, const QHash<QString, LoadAction> &appliquees,
const OptimizerPlan::PlanRecu *recu, const QString &codeRepli, const QDateTime &now);
/*!
* \brief \c expected d'un créneau réduit aux clés documentées (§6).
* \param expected Tel que reçu. \return \c gridImportW, \c gridExportW s'ils sont des nombres finis.
*/
QVariantMap attenduPublie(const QVariantMap &expected);
/*!
* \brief \c diagnostics réduits à ce que l'app lit (§6, exigence app 4).
* \param diagnostics Tels que reçus.
* \return \c status s'il est l'une des quatre valeurs du §6, et \c inputsUsed.pv s'il vaut
* \c physics, \c hybrid (« plan calculé sur une prévision corrigée ») ou \c none ; rien
* d'autre — une valeur hors de cette liste fermée est un texte libre, elle est retirée.
*/
QVariantMap diagnosticsPublies(const QVariantMap &diagnostics);
}