experimental-silo feeds powersync-nightly and landing-silo feeds powersync-testing, not the other way round. DEPLOY.md in the deploy repository is the source of truth and says so in two places: its channel table and its infrastructure inventory, where the core forks are named etm-nymea-nightly for experimental-silo and etm-nymea-testing for landing-silo. Three places carried the labels backwards, all introduced by 30b58db this morning: the diagram, the sentence on reverting a merge that breaks the nightly, and the promotion channel list. The order of the chain itself was already right and is untouched, as is everything else in the document. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
190 lines
8.8 KiB
Markdown
190 lines
8.8 KiB
Markdown
# AGENTS.md — etm-powersync-plugins-modbus
|
|
|
|
Tous les plugins Modbus supportés par ETM : plugins propres et forks de plugins amont.
|
|
Compteurs, bornes de recharge, relais, onduleurs.
|
|
|
|
- **Licence** : GPL-3.0 pour les plugins, LGPL-3.0 pour `libnymea-modbus` / `libnymea-sunspec`
|
|
- **Miroir public** : OUI
|
|
- **Paquets** : publiés sur `repos.etm-powersync.fr`, trois canaux
|
|
|
|
L'inventaire des plugins est l'arborescence du dépôt. Ne pas se fier à une liste écrite ici : elle
|
|
serait périmée, et un agent en conclurait que le reste n'existe pas.
|
|
|
|
Ce dépôt est autoportant : tout ce qui est nécessaire pour y travailler est ici.
|
|
|
|
## Placement du travail non amont
|
|
|
|
Une fois qu'un développement — plugin, correctif, extension vendor — n'est ni upstream officiel ni
|
|
destiné à y retourner à court terme, il vit dans le dépôt produit ETM correspondant
|
|
(`etm-powersync-plugins-modbus` ou `etm-powersync-plugins`), vendoré depuis sa source si elle existe
|
|
ailleurs (`VENDORED.md` avec commit et date), développé directement sinon. Le fork correspondant
|
|
(`nymea-plugins-modbus` ou `nymea-plugins`) ne garde que ce qui reste candidat à une contribution
|
|
amont.
|
|
|
|
## Branches et canaux
|
|
|
|
```
|
|
feature/* ──► experimental-silo ──► landing-silo ──► main
|
|
(nightly) (testing) (stable)
|
|
```
|
|
|
|
Vers la droite on promeut, vers la gauche on redescend un correctif. Une correction ne saute
|
|
jamais un cran.
|
|
|
|
Les trois branches existent sur le remote depuis le 2026-08-02. Les deux silos ont été créés
|
|
vides depuis `main` ; `experimental-silo` a ensuite reçu le travail Fronius comme premier
|
|
contenu, `landing-silo` est encore au niveau de `main`. Avant cette date le modèle ci-dessus
|
|
était une intention, pas un état du dépôt.
|
|
|
|
Aucun silo n'est une branche de travail : `landing-silo` ne reçoit que ce qui a déjà survécu à
|
|
`experimental-silo`. Le travail se fait dans `feature/*`.
|
|
|
|
### Critères de promotion
|
|
|
|
| Passage | Critère |
|
|
|---|---|
|
|
| commits dans `feature/*` | `verify` en local, l'agent boucle seul |
|
|
| `feature/*` → `experimental-silo` | PR, `verify` vert sur le runner, AC de la spec couverts par des tests |
|
|
| `experimental-silo` → `landing-silo` | build complet propre, banc nocturne vert |
|
|
| `landing-silo` → `main` | validation matérielle nommée : appareil, firmware, configuration |
|
|
|
|
Le dernier critère n'est pas automatisable et ne doit pas l'être.
|
|
|
|
### Correctifs
|
|
|
|
**Avant de créer une branche : reproduire le bug et déterminer la branche la plus proche de
|
|
`main` où il apparaît.** C'est elle qui décide du point de départ, pas l'urgence ressentie.
|
|
|
|
| Le bug se reproduit… | Départ | Ensuite |
|
|
|---|---|---|
|
|
| jusque dans `main` | `hotfix/*` depuis `main` | fusion dans `main`, puis redescente dans `landing-silo`, puis dans `experimental-silo` |
|
|
| dans `landing-silo`, pas dans `main` | `fix/*` depuis `landing-silo` | redescente dans `experimental-silo` |
|
|
| seulement dans `experimental-silo` | `fix/*` depuis `experimental-silo` | rien, il remonte par la promotion normale |
|
|
|
|
Ne jamais corriger en aval un bug présent en amont : le correctif remontera un jour, mais la
|
|
branche amont reste cassée entre-temps et la promotion suivante réintroduit l'ancien code par
|
|
dessus. Symptôme : « le correctif ne tient pas ».
|
|
|
|
Si une fusion casse le nightly, **révoquer la fusion** dans `experimental-silo` pour rendre le
|
|
canal de nouveau utilisable, puis corriger tranquillement dans la branche `feature/*` d'origine.
|
|
Ne pas corriger en avant sous pression.
|
|
|
|
Trois préfixes, pas davantage : `feature/*`, `fix/*`, `hotfix/*`.
|
|
|
|
### Versionnement des paquets
|
|
|
|
Tout paquet issu d'un dépôt produit ETM porte un suffixe `+etmN` sur la version amont qu'il modifie
|
|
ou remplace (ex. `1.15.2+etm1`), à tous les canaux de promotion (`experimental-silo`/nightly,
|
|
`landing-silo`/testing, `main`/stable). Ce suffixe garantit la préséance apt/dpkg sur le paquet
|
|
upstream identique.
|
|
|
|
Ne jamais le remplacer par un tiret (`-etmN`) : `-` a un sens réservé en version Debian (champ
|
|
`debian_revision`) et entre en conflit avec une éventuelle révision Debian amont.
|
|
|
|
## Agents
|
|
|
|
Les agents travaillent dans `feature/*` et `fix/*`. Jamais de commit direct dans `experimental-silo`,
|
|
`landing-silo` ou `main` : ces branches ne reçoivent que des fusions.
|
|
|
|
Une spec, une branche, un jeu de critères d'acceptation.
|
|
|
|
Un agent qui estime qu'un refactor s'impose sur un plugin publié le signale et s'arrête. Il ne le
|
|
fait pas.
|
|
|
|
## Invariants locaux
|
|
|
|
1. **NE PAS renommer les paquets PUBLIÉS** : `powersync-plugin-eastron`,
|
|
`powersync-plugin-abbb2x`, `nymea-plugin-abbterra`. Casse l'upgrade des box beta.
|
|
Valable sur toutes les branches : un renommage dans `landing-silo` finit par atteindre `main`.
|
|
2. `abbterra` est volontairement sous nom amont (transition upstream propre) — ne pas « corriger ».
|
|
3. Matrice validée beta : SDM72 / SDM120 (eastron), Waveshare D8.
|
|
4. Aucun composant propriétaire ici. Aucun ne doit y entrer.
|
|
|
|
## Miroir public — ne doit jamais être commité
|
|
|
|
Données client : adresses de site, noms, numéros de série, relevés, adresses IP d'installations
|
|
réelles. Identifiants et jetons. Documentation constructeur sous réserve de confidentialité — elle
|
|
se cite en référence (titre, version, section) dans la table de provenance des registres, jamais
|
|
en contenu.
|
|
|
|
Les captures, journaux et dumps de registres joints à un correctif sont expurgés avant commit.
|
|
|
|
---
|
|
|
|
## Repository Guidelines
|
|
|
|
These conventions apply to every `*-plugins-modbus` repository. They are not a style preference:
|
|
plugins from all of them load into the **same nymea-core**, so they share its ABI, its Qt version,
|
|
its plugin metadata format and its interface definitions. A repository that diverges produces
|
|
plugins that do not interoperate.
|
|
|
|
**Target: nymea-core `<version>`.** Where these guidelines and the core repository's `AGENTS.md`
|
|
disagree, the core repository wins and this section is corrected.
|
|
|
|
This section is identical, byte for byte, across every `*-plugins-modbus` repository, and is the
|
|
part that can be contributed upstream. Anything specific to one repository belongs above it.
|
|
|
|
### Plugin anatomy
|
|
|
|
One directory per vendor, holding its sources, headers, plugin metadata (`*.json`), translations
|
|
and packaging fragments. Plugin IDs, translation filenames and resource prefixes follow the
|
|
directory name.
|
|
|
|
Shared code stays in the shared libraries. Never move code between an LGPL library and a GPL
|
|
plugin without addressing the licence change explicitly.
|
|
|
|
### Build
|
|
|
|
Requires `plugin.pri`, provided by `libnymea1-dev`, or passed explicitly via `PLUGIN_PRI=`.
|
|
|
|
```
|
|
qmake <project>.pro && make -j"$(nproc)" # whole repository
|
|
cd <vendor> && qmake <vendor>.pro && make # single plugin — the short loop, preferred
|
|
```
|
|
|
|
Select the Qt version before calling qmake. When building against a nymea source tree rather than
|
|
a system-wide install, `PKG_CONFIG_PATH`, `CPATH`, `LIBRARY_PATH`, `LD_LIBRARY_PATH` and a `PATH`
|
|
extended with the `nymea-plugininfocompiler` build directory are also required.
|
|
|
|
Verbose logs: `QT_LOGGING_RULES="*.debug=true"`.
|
|
|
|
### Style
|
|
|
|
Qt conventions: 4-space indent, `CamelCase` classes, `lowerCamelCase` functions and members with
|
|
the `m_` prefix, Qt containers and signals over STL, log output wrapped in
|
|
`NYMEA_LOGGING_CATEGORY`, and `foreach` rather than range-based `for` to keep C++11 compatibility.
|
|
|
|
Refresh translations whenever user-visible text changes.
|
|
|
|
### Register provenance
|
|
|
|
**Never infer a register address.** Every address comes from the manufacturer's documentation or
|
|
from a read performed against a real device. A value taken from a third-party implementation is a
|
|
hypothesis until verified on hardware, and is documented as such.
|
|
|
|
Addresses, scale factors and endianness belong in the vendor's register description, not scattered
|
|
as literals through the implementation.
|
|
|
|
### Hardware validation
|
|
|
|
Compiling is not verifying. Any claim of validation names the device, its firmware version and its
|
|
configuration. Without hardware, say so and describe the validation still required rather than
|
|
implying it was performed.
|
|
|
|
Where a Modbus server can be simulated, prefer a captured register dump replayed against the
|
|
plugin over a hand-written mock: a dump carries the quirks a mock will not.
|
|
|
|
### Device writes
|
|
|
|
A write can damage equipment or void a warranty. Write paths are reviewed more strictly than read
|
|
paths: state what is written, under which conditions, and what happens if the plugin stops
|
|
mid-operation.
|
|
|
|
### Commits and pull requests
|
|
|
|
Imperative subjects under ~72 characters.
|
|
Pull request titles: `Plugin name: Add support for xyz` or `New plugin: Plugin name`.
|
|
State whether the change was tested on hardware, and if not, name someone who can confirm it.
|
|
Update the plugin's `README.md` and the translations.
|
|
Call out packaging impacts — Qt 5 and Qt 6 packaging are maintained separately.
|