docs: la sauvegarde se PROUVE, et counts sera toujours publié

AGENTS.md — « Sauvegarder l'historique quand la forge est injoignable », avec les
trois commandes et la seule qui compte : cloner À BLANC depuis la machine de
destination. Un bundle copié ailleurs n'est pas une sauvegarde ; un bundle cloné
à blanc depuis ailleurs en est une, et l'étape 3 est celle qu'on saute — dix
secondes, et c'est la seule qui distingue « restaurable depuis une autre
machine » de « présent sur une autre machine ». Avec ce qu'elle ne remplace pas :
un bundle est une photo, pas un remote.

R3 envoyée à l'app, avec la réponse à la question de forme : counts sera publié
TOUJOURS, même à une seule destination. L'omettre obligerait l'app à connaître la
destination par défaut, donc à la déduire, et lui donnerait deux chemins de
lecture dont un exercé sur presque toutes les charges. Surtout, l'identité
deviendrait conditionnelle — une identité à branche est une identité qu'on peut
se tromper à écrire, en silence.

C'est la règle qui a payé toute la semaine, et elle est citée comme telle : une
absence ne doit jamais vouloir dire « le défaut s'applique ». measurement.source
"none" est publié plutôt que la clé retirée ; rankOrigin absent n'affirme rien ;
levels[] absent dit « box antérieure », pas « un niveau implicite ». Le silence
ne porte que l'ignorance.

ET UNE QUESTION QUE counts FAIT APPARAÎTRE : R2 a déplacé le problème d'un cran
sans l'éliminer pour EV_GRID_START, dont le niveau est financé en partie au
surplus et en partie au réseau. funding: "grid" y est déjà une approximation — au
niveau, comme il l'était à la charge. Les deux champs ne dérivent pas l'un de
l'autre (origine contre registre), garder les deux est justifié À CONDITION QUE
CE SOIT DIT, sinon quelqu'un supprimera un jour celui qui a l'air redondant.
L'arbitrage sur le cas mixte est renvoyé à l'app, avec notre penchant motivé.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p
This commit is contained in:
Patrick Schurig 2026-08-30 08:18:27 +02:00
parent b6a6c7eebc
commit a305a0c4ee
2 changed files with 67 additions and 2 deletions

View File

@ -406,6 +406,38 @@ Ensuite : **passe contrats** (OPTIMIZER_PROTOCOL + README).
`[plancher × 0,5 ; plancher[`), `BATTERY_RESERVE` avec un surplus réel sous le seuil, et
LM-1204-b avec **deux bornes réelles** — la Terra AC ne répond toujours pas à l'ARP.
### Sauvegarder l'historique quand la forge est injoignable
**Un bundle COPIÉ ailleurs n'est pas une sauvegarde. Un bundle CLONÉ à blanc depuis ailleurs en
est une.** La différence ne se voit que le jour où elle compte, et ce jour-là il est trop tard
pour la découvrir.
```bash
# 1. produire — --all, pas une branche : les tags et les autres branches comptent aussi
git bundle create ~/etm-plugin-$(date +%Y%m%d-%H%M).bundle --all
# 2. déposer sur une AUTRE machine (le banc fait l'affaire)
ssh etm@192.168.1.75 'mkdir -p ~/git-secours'
scp ~/etm-plugin-*.bundle etm@192.168.1.75:~/git-secours/
# 3. PROUVER qu'il est restaurable — depuis la machine de destination, pas depuis celle-ci
ssh etm@192.168.1.75 'cd ~/git-secours && B=$(ls -t *.bundle | head -1) &&
git bundle verify "$B" && git clone -q --bare "$B" /tmp/v &&
git --git-dir=/tmp/v log --oneline -1 &&
git --git-dir=/tmp/v rev-list --count HEAD && rm -rf /tmp/v'
```
L'étape 3 est celle qu'on saute. Elle coûte dix secondes et c'est la seule qui distingue
« restaurable depuis une autre machine » de « présent sur une autre machine ».
> **Quand.** Dès que la forge est injoignable et que des commits s'accumulent en local. Le
> 2026-08-30, 64 commits ne vivaient que sur `etm-powersync-dev`, fibre coupée — et le bundle
> aussi, tant qu'il y restait.
>
> **Ce que ça ne remplace pas** : un `git push`. Un bundle est une photo, pas un remote — il ne
> se met pas à jour, et personne d'autre ne travaille dessus. À rafraîchir à chaque session tant
> que la forge ne répond pas.
### Lire le journal de la box — et ce qu'une absence prouve
**`journalctl -u nymead`, SANS `sudo`.** L'utilisateur `etm` est dans le groupe `adm`, qui

View File

@ -668,8 +668,41 @@ publierait donc sa ventilation :
```
`Σ counts == targetW`, toujours. L'identité devient calculable **sans exception**, et elle vaudra
telle quelle quand `draw.committedW` arrivera. Dites-nous si cette forme vous va, ou si vous
préférez lire la ventilation autrement — c'est votre réconciliation qui en dépend.
telle quelle quand `draw.committedW` arrivera.
**`counts` sera publié TOUJOURS, même à une seule destination.** Sur une charge ordinaire,
`counts: {"budget.allocatedW": 3500}` est redondant avec `targetW` — et c'est le prix à payer.
L'omettre vous obligerait à connaître la **destination par défaut**, donc à la déduire ; vous
auriez alors deux chemins de lecture, dont un qui n'est exercé que sur les charges ordinaires,
c'est-à-dire presque toutes. Et l'identité deviendrait conditionnelle (« si `counts`, sommer ;
sinon attribuer `targetW` au compteur par défaut ») — une identité à branche est une identité
qu'on peut se tromper à écrire, en silence.
> C'est la règle qui a payé toute la semaine : **une absence ne doit jamais vouloir dire « le
> défaut s'applique »**. `measurement.source: "none"` est publié plutôt que la clé retirée ;
> `rankOrigin` absent n'affirme rien, surtout pas `"user"` ; `levels[]` absent dit « box
> antérieure », pas « un seul niveau implicite ». Le silence ne porte que l'ignorance.
### Et une question que `counts` fait apparaître, sur `funding` lui-même
En posant la ventilation, on voit que **R2 a déplacé le problème d'un cran sans l'éliminer pour
`EV_GRID_START`** : ce niveau-là est financé **en partie au surplus, en partie au réseau**.
`funding: "grid"` y est donc déjà une approximation — au niveau, comme il l'était à la charge.
Nous ne touchons pas à `funding` sans vous : c'est votre champ de réconciliation. Mais il faut
choisir en connaissance de cause, et les deux ne dérivent pas l'un de l'autre —
- **`funding` dit l'ORIGINE** (« ces watts sont achetés »), une intention, voisine du motif ;
- **`counts` dit le REGISTRE** (« ils sont comptés ici »), une comptabilité.
`counts = {allocatedW: 900, evReservedW: 480}` ne dit pas si l'achat était délibéré ;
`funding: "grid"` ne dit pas où les 900 W sont comptés. **Garder les deux est justifié — à
condition que ce soit dit**, sinon quelqu'un « simplifiera » un jour en supprimant celui qui a
l'air redondant.
Reste votre arbitrage sur le cas mixte : `funding` y garde-t-il un code unique (approximatif mais
lisible), ou faut-il l'y omettre et laisser `counts` parler seul ? **Nous penchons pour le code
unique** — il porte l'intention, que `counts` ne porte pas — mais c'est votre écran.
> Et deux fils antérieurs de votre brief sont **clos**, au cas où ils ne vous seraient pas
> parvenus : l'**entrelacement des domaines** est tranché — grouper à l'affichage, **jamais à