2026-07-22 21:32:42 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Le GUI sait-il editer tout ce que les plans reels contiennent ?
|
|
|
|
|
|
|
|
|
|
Principe 10 : « un operateur humain exploite Set-OPS sans IA — la doc, `make` et
|
|
|
|
|
le GUI suffisent ». Ce principe se dement en silence des qu'un registre accepte un
|
|
|
|
|
champ que l'interface ne sait pas ecrire : l'operateur doit editer le YAML a la
|
|
|
|
|
main, et personne ne s'en apercoit avant de buter dessus.
|
|
|
|
|
|
|
|
|
|
Ce script rend le trou VISIBLE et mesurable. Il croise :
|
|
|
|
|
- les champs REELLEMENT presents dans les plans (instance courante + tous les
|
|
|
|
|
modeles decouverts par scripts/modeles.py) ;
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
- `champs_ecrits_par_gui()` de scripts/inventory_gui.py, qui declare ce que les
|
2026-07-22 21:32:42 -04:00
|
|
|
fonctions de sauvegarde ecrivent.
|
|
|
|
|
|
|
|
|
|
Deux sens de verification :
|
|
|
|
|
1. champ dans un plan, absent du GUI -> TROU d'interface (signale) ;
|
|
|
|
|
2. champ declare au GUI, introuvable dans son source -> DERIVE de la
|
|
|
|
|
declaration (signale) — le tableau ment sur ce que le GUI fait.
|
|
|
|
|
|
|
|
|
|
Usage :
|
|
|
|
|
python3 scripts/couverture_gui.py lister
|
|
|
|
|
python3 scripts/couverture_gui.py verifier # rc=2 s'il reste un trou
|
|
|
|
|
python3 scripts/couverture_gui.py verifier --tolerer nomenclature
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
import yaml
|
|
|
|
|
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
from inventory_gui import REGISTRES_GENERES, champs_ecrits_par_gui
|
2026-07-22 21:32:42 -04:00
|
|
|
from modeles import decouvrir as decouvrir_modeles
|
|
|
|
|
|
resolution d'instance : une seule, partagee — au lieu de neuf copies
Cinq jours, cinq defauts, tous de la meme famille : « quelle instance, quel inventaire ? »
Neuf modules portaient chacun leur reponse.
- 18 aout : P03 comparait chaque instance a l'inventaire d'une AUTRE ;
- 19 aout : verifier_ports codait `principal/` en dur ; verifier_intrants et
_frontiere_absente lisaient le symlink au lieu de la variable ;
- 20 aout : devis_placement rendait un verdict juste sur le mauvais tenant ;
- 22 aout : P35, puis P36 — la dixieme, trouvee par la preuve elle-meme.
Aucune n'etait une faute d'inattention : chacune avait ete ecrite de bonne foi, a un
moment ou le besoin semblait local. C'est le mode de panne de la duplication — pas
l'erreur, mais la DERIVE, invisible depuis l'interieur d'un fichier.
LA RESOLUTION UNIQUE. `inventory_rules` porte instance_courante(), inventaire_de(),
dossier_inventaire() et plan_de(). Trois niveaux de repli, dont le TROISIEME manquait a la
moitie des copies : un hosts.yml existant, puis un REPERTOIRE existant (instance neuve —
c'est ce qui faisait echouer `make instancier` sur le modele public), puis le defaut.
Vingt-huit modules y sont branches.
CE QUI REND CE REFACTOR SUR : avant de toucher quoi que ce soit, chaque module a ete
interroge sur ce qu'il resolvait, pour les DEUX ecosystemes. Apres refactor, meme mesure :
17 modules x 2 instances, diff VIDE. Aucune resolution n'a change — prouve, pas suppose.
P41 echoue des qu'un module reintroduit une copie. Eprouvee en negatif : une copie
replacee dans genome.py est signalee avec son numero de ligne. Trois exemptions nommees :
instances.py et inventory_gui.py manipulent le SYMLINK lui-meme (bascule d'instance), et
devis_opnsense lit deliberement quelle instance est ACTIVE. Elles parlent du lien, pas de
la resolution.
make verifier 41 OK, 0 echec, 0 saute ; make ci idem ; lint vert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:19:55 -04:00
|
|
|
from inventory_rules import instance_courante, instance_courante # noqa: E402
|
|
|
|
|
|
2026-07-22 21:32:42 -04:00
|
|
|
RACINE = Path(__file__).resolve().parents[1]
|
resolution d'instance : une seule, partagee — au lieu de neuf copies
Cinq jours, cinq defauts, tous de la meme famille : « quelle instance, quel inventaire ? »
Neuf modules portaient chacun leur reponse.
- 18 aout : P03 comparait chaque instance a l'inventaire d'une AUTRE ;
- 19 aout : verifier_ports codait `principal/` en dur ; verifier_intrants et
_frontiere_absente lisaient le symlink au lieu de la variable ;
- 20 aout : devis_placement rendait un verdict juste sur le mauvais tenant ;
- 22 aout : P35, puis P36 — la dixieme, trouvee par la preuve elle-meme.
Aucune n'etait une faute d'inattention : chacune avait ete ecrite de bonne foi, a un
moment ou le besoin semblait local. C'est le mode de panne de la duplication — pas
l'erreur, mais la DERIVE, invisible depuis l'interieur d'un fichier.
LA RESOLUTION UNIQUE. `inventory_rules` porte instance_courante(), inventaire_de(),
dossier_inventaire() et plan_de(). Trois niveaux de repli, dont le TROISIEME manquait a la
moitie des copies : un hosts.yml existant, puis un REPERTOIRE existant (instance neuve —
c'est ce qui faisait echouer `make instancier` sur le modele public), puis le defaut.
Vingt-huit modules y sont branches.
CE QUI REND CE REFACTOR SUR : avant de toucher quoi que ce soit, chaque module a ete
interroge sur ce qu'il resolvait, pour les DEUX ecosystemes. Apres refactor, meme mesure :
17 modules x 2 instances, diff VIDE. Aucune resolution n'a change — prouve, pas suppose.
P41 echoue des qu'un module reintroduit une copie. Eprouvee en negatif : une copie
replacee dans genome.py est signalee avec son numero de ligne. Trois exemptions nommees :
instances.py et inventory_gui.py manipulent le SYMLINK lui-meme (bascule d'instance), et
devis_opnsense lit deliberement quelle instance est ACTIVE. Elles parlent du lien, pas de
la resolution.
make verifier 41 OK, 0 echec, 0 saute ; make ci idem ; lint vert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:19:55 -04:00
|
|
|
INSTANCE = instance_courante()
|
2026-07-22 21:32:42 -04:00
|
|
|
SOURCE_GUI = RACINE / "scripts" / "inventory_gui.py"
|
|
|
|
|
|
|
|
|
|
# (fichier du plan, cle racine, nom du registre) — les registres tables-de-tables.
|
|
|
|
|
REGISTRES = [
|
|
|
|
|
("serveurs.yml", "serveurs", "serveurs"),
|
|
|
|
|
("applications.yml", "applications", "applications"),
|
|
|
|
|
("bases-donnees.yml", "bases_donnees", "bases_donnees"),
|
|
|
|
|
("bases-donnees.yml", "serveurs_bd", "serveurs_bd"),
|
|
|
|
|
("domaines.yml", "domaines_publics", "domaines_publics"),
|
|
|
|
|
("nomenclature.yml", "fonctions", "nomenclature"),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _plans() -> list[Path]:
|
|
|
|
|
"""Dossiers plan/ a inspecter : l'instance courante + tous les modeles."""
|
|
|
|
|
trouves = []
|
|
|
|
|
if (INSTANCE / "plan").is_dir():
|
|
|
|
|
trouves.append(INSTANCE / "plan")
|
|
|
|
|
trouves += [m / "plan" for m in decouvrir_modeles() if (m / "plan").is_dir()]
|
|
|
|
|
return trouves
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def champs_utilises() -> dict[str, dict[str, set[str]]]:
|
|
|
|
|
"""{registre: {champ: {origines}}} — champs vus dans les plans reels."""
|
|
|
|
|
vus: dict[str, dict[str, set[str]]] = {r: {} for _, _, r in REGISTRES}
|
|
|
|
|
for plan in _plans():
|
|
|
|
|
etiquette = plan.parent.name
|
|
|
|
|
for fichier, racine_cle, registre in REGISTRES:
|
|
|
|
|
p = plan / fichier
|
|
|
|
|
if not p.is_file():
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
data = yaml.safe_load(p.read_text(encoding="utf-8")) or {}
|
|
|
|
|
except yaml.YAMLError:
|
|
|
|
|
continue
|
|
|
|
|
entrees = (data or {}).get(racine_cle) or {}
|
|
|
|
|
if not isinstance(entrees, dict):
|
|
|
|
|
continue
|
|
|
|
|
for entree in entrees.values():
|
|
|
|
|
if isinstance(entree, dict):
|
|
|
|
|
for champ in entree:
|
|
|
|
|
vus[registre].setdefault(str(champ), set()).add(etiquette)
|
|
|
|
|
return vus
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def declaration_derive() -> list[str]:
|
|
|
|
|
"""Champs declares au GUI mais introuvables dans son source (declaration qui ment)."""
|
|
|
|
|
src = SOURCE_GUI.read_text(encoding="utf-8")
|
|
|
|
|
# On coupe le tableau lui-meme : sa presence ne prouve rien.
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
debut = src.find("champs_ecrits_par_gui()")
|
2026-07-22 21:32:42 -04:00
|
|
|
fin = src.find("\n}\n", debut)
|
|
|
|
|
ailleurs = src[:debut] + src[fin:] if debut != -1 and fin != -1 else src
|
|
|
|
|
absents = []
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
for registre, champs in champs_ecrits_par_gui().items():
|
|
|
|
|
# UN REGISTRE GENERE N'A PLUS SES CHAMPS DANS LE SOURCE, et c'est le but : ils
|
|
|
|
|
# vivent dans le schema, et le formulaire en derive. Chercher `secret` dans le JS
|
|
|
|
|
# ferait crier cette garde sur precisement le progres qu'elle devrait constater.
|
|
|
|
|
# Pour ces registres-la, c'est P61 qui tient la promesse — elle verifie que le
|
|
|
|
|
# schema decrit tout ce que les plans contiennent.
|
|
|
|
|
if registre in REGISTRES_GENERES:
|
|
|
|
|
continue
|
2026-07-22 21:32:42 -04:00
|
|
|
for champ in sorted(champs):
|
|
|
|
|
if champ not in ailleurs:
|
|
|
|
|
absents.append(f"{registre}.{champ}")
|
|
|
|
|
return absents
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> int:
|
|
|
|
|
parser = argparse.ArgumentParser(description="Couverture du schema du plan par le GUI.")
|
|
|
|
|
sub = parser.add_subparsers(dest="commande", required=True)
|
|
|
|
|
sub.add_parser("lister", help="Detaille champ par champ.")
|
|
|
|
|
pv = sub.add_parser("verifier", help="Echoue s'il reste un champ non editable.")
|
|
|
|
|
pv.add_argument("--tolerer", action="append", default=[], metavar="REGISTRE",
|
|
|
|
|
help="Registre dont les trous sont connus et assumes (repetable).")
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
utilises = champs_utilises()
|
|
|
|
|
|
|
|
|
|
if args.commande == "lister":
|
|
|
|
|
for registre in sorted(utilises):
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
couverts = champs_ecrits_par_gui().get(registre, set())
|
2026-07-22 21:32:42 -04:00
|
|
|
print(f"\n== {registre} ==")
|
|
|
|
|
for champ in sorted(utilises[registre]):
|
|
|
|
|
etat = "GUI" if champ in couverts else "-- hors GUI --"
|
|
|
|
|
print(f" {champ:<18} {etat:<16} vu dans : "
|
|
|
|
|
f"{', '.join(sorted(utilises[registre][champ]))}")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
tolere = set(args.tolerer)
|
|
|
|
|
trous: list[str] = []
|
|
|
|
|
for registre, champs in utilises.items():
|
|
|
|
|
if registre in tolere:
|
|
|
|
|
continue
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
couverts = champs_ecrits_par_gui().get(registre, set())
|
2026-07-22 21:32:42 -04:00
|
|
|
for champ in sorted(set(champs) - couverts):
|
|
|
|
|
trous.append(f"{registre}.{champ} (vu dans : "
|
|
|
|
|
f"{', '.join(sorted(champs[champ]))})")
|
|
|
|
|
|
|
|
|
|
derive = declaration_derive()
|
|
|
|
|
|
|
|
|
|
if trous:
|
|
|
|
|
print(f"erreur: {len(trous)} champ(s) present(s) dans un plan reel que le GUI "
|
|
|
|
|
f"ne sait pas ecrire :", file=sys.stderr)
|
|
|
|
|
for t in trous:
|
|
|
|
|
print(f" - {t}", file=sys.stderr)
|
|
|
|
|
if derive:
|
GUI : le formulaire des bases est GENERE depuis le schema
Etape 3, sur un seul registre — `bases_donnees`, le plus simple et le seul ou
observe et editable coincidaient deja. Les cinq autres gardent leurs formulaires
ecrits a la main : on ne bascule pas six vues d un coup.
CE QUI DISPARAIT DU JAVASCRIPT
Huit `<label>` en dur, trois constructions de `<option>`, et la regle qui
choisissait la source du consommateur selon la portee. Cette derniere ne vivait
que dans le JS ; elle est desormais DECLAREE au schema (`x-source-selon`), donc
lisible et gardee.
Le formulaire rend exactement les memes huit champs qu avant — verifie en
EXECUTANT le moteur sous node avec le schema et des donnees reelles, pas
seulement en passant `node --check`.
LA BOUCLE EST FERMEE DES DEUX COTES
Le chemin de SAUVEGARDE enumerait lui aussi les sept champs en dur. Un champ
ajoute au registre serait apparu au formulaire genere et aurait disparu
SILENCIEUSEMENT a l enregistrement — le pire des deux mondes. Il derive
maintenant du schema, valeurs par defaut comprises (`default`).
LA SEPARATION FORME / COHERENCE, MONTREE
portee=groupe + consommateur APPLICATION -> REFUSE par valider_bases
portee=application + consommateur app -> ACCEPTE
secret absent -> REFUSE
Le schema a rempli la FORME (les defauts `groupe` et `principale` se sont
poses), le validateur a attrape l INCOHERENCE. Aucune de ces trois regles ne
s exprime en JSON Schema, et vouloir l y mettre creerait la seconde source de
verite que ce depot refuse.
CHAMPS_ECRITS_PAR_GUI COMMENCE A DISPARAITRE
Renomme CHAMPS_ECRITS_A_LA_MAIN, et `bases_donnees` en est SORTIE : sa
couverture se derive du schema. P19 lit desormais `champs_ecrits_par_gui()`, qui
reunit les deux. Le jour ou la table sera vide, elle gardera un mecanisme au
lieu d une liste.
UNE GARDE A CORRIGER AU PASSAGE
`declaration_derive()` verifiait que chaque champ declare apparait dans le
SOURCE du GUI. Pour un registre genere il n y apparait plus — c est le but.
Elle aurait crie sur precisement le progres qu elle devait constater. Les
registres generes en sont exemptes : c est P61 qui tient la promesse pour eux.
make prouver : CONFORME, 60 OK, 0 echec, 1 saute.
P07 (node --check), P19 (couverture), P61 (schema) : verts.
Reste : les cinq autres vues, et le trou de la nomenclature — que le passage au
generateur fermera par construction, puisque le schema decrit deja `categorie`
et `service`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:30:08 -04:00
|
|
|
print(f"erreur: {len(derive)} champ(s) declare(s) dans champs_ecrits_par_gui() mais "
|
2026-07-22 21:32:42 -04:00
|
|
|
f"introuvable(s) dans le source du GUI : {', '.join(derive)}", file=sys.stderr)
|
|
|
|
|
|
|
|
|
|
if trous or derive:
|
|
|
|
|
return 2
|
|
|
|
|
total = sum(len(c) for c in utilises.values())
|
|
|
|
|
print(f"GUI : les {total} champ(s) des plans reels sont editables "
|
|
|
|
|
f"({len(_plans())} plan(s) inspecte(s))"
|
|
|
|
|
+ (f", registres toleres : {', '.join(sorted(tolere))}." if tolere else "."))
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
raise SystemExit(main())
|