docs(spec): spec_ecs 0.5.3 — ECS-413, désactivation en état sûr
Exigence seule, aucune implémentation. Constat de banc du 2026-08-09 : un SetLoadConfig posant enabled: false sur une charge alors au palier 3500 W a détruit l'adaptateur en laissant les TROIS RELAIS FERMÉS. Plus personne ne les commandait ; ils y seraient restés indéfiniment, juste avant une intervention de câblage. ECS-413 exige que désactiver une charge — ou la retirer de la configuration — laisse son matériel dans l'état sûr DÉFINI PAR SON ADAPTATEUR, appliqué AVANT la destruction de l'adaptateur, l'échelle d'ECS-410 s'appliquant si l'écriture échoue. L'état sûr est propre à chaque adaptateur, et une formulation « tout couper » serait fausse : relais ouverts pour RelayRouter, consigne 0 W pour EtmVariableLoadAdapter, mais ÉTAT 2 pour SgReadyAdapter — jamais le blocage, conformément à SAFETY.md. Couper une PAC en la bloquant serait une régression de sécurité, pas une mise en sécurité. Mécanisme : le chemin d'action normal avec force = true, celui du mode dégradé L2. Rien de nouveau à inventer. Périmètre explicitement borné : NE S'APPLIQUE PAS à l'arrêt du plugin ni à un redémarrage de nymead, où l'état doit être CONSERVÉ — c'est ce qu'ECS-411 relit au démarrage, et couper l'eau chaude à chaque redémarrage de service serait une régression. La distinction est intentionnelle : la désactivation est un acte délibéré de l'opérateur, un redémarrage n'en est pas un. Test testEcsDisableLeavesSafeState, avec son cas négatif obligatoire : un rebuild SANS désactivation ne doit pas déclencher la mise en sécurité, sinon ECS-412 est annulé et chaque changement de rang coupe la charge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
81621b2bcc
commit
cf6843d50c
@ -1,6 +1,6 @@
|
||||
# SPEC — ECS multi-palier
|
||||
|
||||
Version : 0.5.2
|
||||
Version : 0.5.3
|
||||
Dépôt : `etm-powersync-energy-plugin-etm` (experience-plugin ems)
|
||||
Branche : `feature/beta-rulebased`
|
||||
Contrats faisant autorité : `docs/OPTIMIZER_PROTOCOL.md`, `docs/SAFETY.md`, `AGENTS.md`
|
||||
@ -428,6 +428,46 @@ il est simplement ignoré.
|
||||
(`relayrouter.h:106`) et aucun état de relais n'est relu. Le palier courant DOIT
|
||||
être déduit de l'état réel des Things.
|
||||
|
||||
**ECS-413 — Désactivation en état sûr.** Désactiver une charge (`enabled: false`)
|
||||
ou la retirer de la configuration DOIT laisser son matériel dans l'**état sûr
|
||||
défini par son adaptateur**, et non dans son dernier état commandé. L'état sûr est
|
||||
appliqué **avant** la destruction de l'adaptateur ; si l'écriture échoue,
|
||||
l'échelle d'ECS-410 s'applique.
|
||||
|
||||
Constaté au banc le 2026-08-09 : un `SetLoadConfig` posant `enabled: false` sur une
|
||||
charge alors au palier 3500 W a détruit l'adaptateur en laissant **les trois relais
|
||||
fermés**. Plus personne ne les commandait ; ils y seraient restés indéfiniment,
|
||||
juste avant une intervention de câblage.
|
||||
|
||||
**L'état sûr est propre à chaque adaptateur** — une exigence formulée « tout
|
||||
couper » serait FAUSSE :
|
||||
|
||||
| Adaptateur | État sûr |
|
||||
|---|---|
|
||||
| `RelayRouter` | tous relais **ouverts** |
|
||||
| `EtmVariableLoadAdapter` | consigne **0 W** |
|
||||
| `SgReadyAdapter` | **état 2** (normal, mains off) — **jamais** l'état 1 (blocage), cf. `docs/SAFETY.md` |
|
||||
|
||||
Couper une PAC en la bloquant serait une régression de sécurité, pas une mise en
|
||||
sécurité.
|
||||
|
||||
**Mécanisme.** L'application passe par le **chemin d'action normal avec
|
||||
`force = true`**, comme le mode dégradé L2 (`energyarbitrator.cpp:339-347`) :
|
||||
c'est le mécanisme qui existe déjà pour contourner les verrous dans une situation
|
||||
où l'arrêt prime. Rien de nouveau à inventer.
|
||||
|
||||
> **Cette exigence NE S'APPLIQUE PAS à l'arrêt du plugin ni à un redémarrage de
|
||||
> `nymead`.** Là, l'état DOIT être conservé : c'est précisément ce qu'ECS-411 relit
|
||||
> au démarrage, et couper l'eau chaude à chaque redémarrage de service serait une
|
||||
> régression. La distinction est **intentionnelle** — la désactivation est un acte
|
||||
> délibéré de l'opérateur, un redémarrage n'en est pas un.
|
||||
|
||||
**Test : `testEcsDisableLeavesSafeState`.** Charge à un palier non nul,
|
||||
`SetLoadConfig` avec `enabled: false` ; vérifier que les relais sont **ouverts** et
|
||||
que l'adaptateur n'est détruit qu'**ensuite**. Second cas obligatoire : un simple
|
||||
`rebuild` **sans** désactivation NE DOIT PAS déclencher la mise en sécurité — sans
|
||||
quoi ECS-412 serait annulé, chaque changement de rang coupant la charge.
|
||||
|
||||
---
|
||||
|
||||
## §6 — Configuration
|
||||
@ -550,6 +590,7 @@ mécanique reste **L0**. Perte de sonde → mode sans sonde, pas arrêt d'urgenc
|
||||
| ECS-304 | unitaire | `testEcsLevelsPure` |
|
||||
| ECS-410 | simulation | `testEcsPartialFailure` |
|
||||
| ECS-411 | simulation | `testEcsRestartRecovery` |
|
||||
| ECS-413 | simulation | `testEcsDisableLeavesSafeState` — + cas négatif : un rebuild sans désactivation ne coupe pas |
|
||||
| ECS-110, ECS-111 | unitaire | `testEcsConfigValidation` — DOIT s'exécuter aussi en build release (`QT_NO_DEBUG`), sinon il ne prouve rien du binaire livré |
|
||||
| ECS-501, ECS-502 | simulation | `testEcsStageFault` |
|
||||
| ECS-601, ECS-602 | simulation | `testEcsTemperatureTarget` |
|
||||
@ -620,6 +661,7 @@ protocole dans le même lot.**
|
||||
| 2026-08-08 | **Étape 1 OUVERTE** — trois exigences : ECS-306, ECS-411, ECS-412 |
|
||||
| 2026-08-08 | ECS-412 : au démarrage à froid, le verrou est **ARMÉ** (défaut sûr), jamais purgé |
|
||||
| 2026-08-09 | ECS-412 précisé : cet armement est **TRANSITOIRE** et posé paresseusement au premier `now`. Défaut de blocage circulaire constaté **au banc**, corrigé, couvert par `testEcsColdStartLockExpires` |
|
||||
| 2026-08-09 | **ECS-413 créé** — `enabled: false` laissait les relais fermés (constat de banc, juste avant une intervention de câblage). État sûr propre à chaque adaptateur ; ne s'applique PAS à un redémarrage de `nymead`, qu'ECS-411 couvre |
|
||||
| 2026-08-08 | ~~Câblage 500/1000/2000~~ — **donnée fausse**, corrigée le jour même (cf. ligne suivante) |
|
||||
| 2026-08-08 | ~~Câblage 500/1000/1500 (source simulateur)~~ — **donnée fausse** : le simulateur ne reflète pas l'installation |
|
||||
| 2026-08-08 | ~~ECS-302 exercé~~ — découlait de la donnée fausse |
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user