console : la face ne se juge que la ou la carte du site est montee

Sur le runner de Technolibre, la vue Lien avec le site disait la face a republier :
la cle d'amorcage d'ops-01 vient du plan du site, absent du runner, et la face
recalculee la perdait. Republier d'ici l'aurait retiree. La face se lit partout et
ne se juge plus que la ou le site est monte, comme la fiche. Un test le garde.

94 preuves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-10-11 18:22:31 -04:00
parent 9592309f36
commit 1d582045f3
3 changed files with 50 additions and 4 deletions

View file

@ -1,5 +1,27 @@
# CHANGELOG — Set-OPS
## 2026-10-11 (129) — Le runner d'un locataire conseillait de republier une face juste
**94 preuves.** `make verifier` passe et `test_portee_console.py` compte un cas de plus. Ce
test échoue quand on retire la condition.
### Mesuré au premier déploiement du lot 2, sur le runner de Technolibre
Sur le runner du locataire, la vue « Lien avec le site » marquait sa face réseau « à
republier », alors que le poste la jugeait à jour. Une seule valeur différait : la clé
d'amorçage de `ops-01`. Cette clé est celle du runner du site ; la face la porte pour que le
site puisse amorcer le runner du locataire. `_cle_amorcage` va la lire dans le plan du site,
et le runner du locataire n'a pas ce plan. Il calculait donc une face sans elle. Le conseil
affiché était nuisible : republier depuis ce runner aurait retiré la clé de la face.
La face ne se juge plus que là où la carte du site est montée, comme la fiche. Ailleurs, elle
est lue et affichée « non jugeable d'ici ».
**Limite.** La cause reste dans le moteur : la face se veut calculable par le locataire seul,
et une de ses valeurs vient du plan du site. Si la fiche du site portait cette clé, le
locataire pourrait juger et republier sa face n'importe où. P92 n'est pas touchée : elle tourne
sur le poste, où le plan du site est présent.
## 2026-10-11 (128) — Le site et ses locataires se lisaient par deux fichiers que leurs consoles ne montraient pas
**94 preuves.** `make verifier` passe. Le banc de rendu dessine les deux nouvelles vues sur

View file

@ -1002,15 +1002,21 @@ def lien_du_locataire(instance: Path) -> dict:
import contexte as _ctx
loc = _ctx.Locataire(instance)
face = loc.face_publiee()
try:
ecarts_face = _ctx.verifier_face_publiee(loc)
except Exception as exc: # une face incalculable ne doit pas masquer la publiee
ecarts_face = [f"face incalculable ici : {exc}"]
fiche = loc.fiche_du_site() or {}
try:
site = loc.site()
except _ctx.ContexteInvalide:
site = None
# LA FACE NE SE JUGE QUE LA OU LA CARTE DU SITE EST MONTEE (mesure du 2026-10-11 sur
# le runner de Technolibre). Elle porte, pour le runner du locataire, la cle du runner
# du site (`_cle_amorcage`), lue dans le plan du SITE. Sans ce plan, la face calculee
# perd cette cle : la page disait « a republier », et republier d'ici l'aurait retiree.
ecarts_face = None
if site is not None and face is not None:
try:
ecarts_face = _ctx.verifier_face_publiee(loc)
except Exception as exc: # une face incalculable ne doit pas masquer la publiee
ecarts_face = [f"face incalculable ici : {exc}"]
ecarts_fiche = None
if site is not None and fiche:
try:
@ -1022,6 +1028,7 @@ def lien_du_locataire(instance: Path) -> dict:
"hebergeur": loc.nom_hebergeur(),
"face": {"publiee": face is not None,
"trace": _trace_git(loc.depot, _ctx.NOM_FICHIER_FACE_RESEAU),
"jugeable": site is not None,
"ecarts": ecarts_face,
"resume": resume_face(face) if face else None},
"fiche": {"presente": bool(fiche),
@ -4245,6 +4252,7 @@ let selMachine = null;
// MA FACE RESEAU
let etatFace;
if (!F.publiee) etatFace = '<span class="etiq e-bloq">jamais publiée</span>';
else if (!F.jugeable) etatFace = '<span class="etiq e-recon" title="Le calcul de la face lit le plan du site (la clé de son runner), absent de cette machine. Elle se juge et se republie depuis le poste du mainteneur.">lue, non jugeable d\'ici</span>';
else if ((F.ecarts || []).length) etatFace = '<span class="etiq e-div">à republier</span>';
else etatFace = '<span class="etiq e-actif">à jour avec mon plan</span>';
const face = !F.publiee ? `<div class="corps"><div class="note-contrat">Le site ne peut rien créer ni ouvrir pour moi sans elle.

View file

@ -141,6 +141,22 @@ class TestPorteeDeLaConsole(unittest.TestCase):
self.assertIsNone(l["fiche"]["ecarts"], "la fiche d'un autre site ne se juge pas ici")
self.assertEqual(l["index_attribue"], 18)
def test_le_runner_du_locataire_ne_juge_pas_sa_face(self):
"""LE DEFAUT, NOMME (2026-10-11, runner de Technolibre). La face porte la cle du
runner du site, lue dans le plan du SITE. Le runner du locataire ne l'a pas : il
recalculait une face sans elle, la disait « a republier », et republier d'ici
l'aurait retiree."""
loc = self.dossier / "OPS-Essai"
(loc / "plan").mkdir(parents=True)
(loc / "plan" / "nomenclature.yml").write_text("index: 18\n", encoding="utf-8")
(loc / "face-reseau.yml").write_text(
"locataire: OPS-Essai\nhebergeur: SITE-Absent\nindex: 18\nmachines: {}\n",
encoding="utf-8")
lien = gui.lien_du_locataire(loc)
self.assertTrue(lien["face"]["publiee"])
self.assertFalse(lien["face"]["jugeable"])
self.assertIsNone(lien["face"]["ecarts"], "sans la carte du site, aucun verdict")
if __name__ == "__main__":
unittest.main(verbosity=2)