Document de séance — réunion du 31 août 2026. Toutes les sorties encadrées de cette page ont été produites le 2026-08-31 10:45:27 CEST en exécutant le code, hors ligne, sans aucun appel à un service payant.
bash verifier-demo.sh (même dossier) ré-exécute
les quatre preuves, recompare chaque nombre cité ici et sort en erreur si l'un
d'eux a bougé. Les sorties brutes sont archivées dans demo-sorties/.
Pour un architecte : vous donnez une parcelle, le rapport vous rend les règles opposables — hauteur, emprise, recul, stationnement — et à côté de chaque règle, d'où elle vient (document, article, page, date) et ce qu'on en sait. Une règle non lue n'est jamais rendue comme une règle absente.
FAIT ET VÉRIFIÉ RÉEL
mock/llm-test) et d'un règlement fabriqué
pour l'exercice — pas d'une lecture par modèle de langage d'un vrai PLU
communal. Ce qui est démontré ici, c'est la mécanique du rapport :
les cinq états, la provenance à six champs, l'arbitrage d'une contradiction.
Ce qui n'est pas démontré, c'est la qualité de lecture d'un règlement réel :
elle exige le run avec clé plafonnée à 5 $ et le corpus de référence rédigé par
un architecte (voir §6).
cd $SCRATCH/demo-aq && PYTHONPATH=. .venv-plu/bin/python demo-sorties/demo_plu.py demo-sorties/Le règlement écrit dit 12 m à l'article UB 10 (page 42). Le règlement graphique dit 9 m. Le rapport ne choisit pas en silence : il déclare l'état Contradictoire, cite les deux sources, retient la valeur la plus restrictive (9 m) et écrit que l'arbitrage est à confirmer en mairie.
| Règle | Valeur | État | Source (document · article · page · date) | Confiance |
|---|---|---|---|---|
| Article UB 10 — Hauteur | La hauteur maximale est de 12 m. | Confirmé |
PDF règlement p.42
· art. UB 10
· p.42
· 2024-06-01
Extrait lu tel quel au règlement (pdfplumber)
|
0.70 |
| Hauteur max m | 12.0 | Confirmé |
LLM extraction from article UB 10 (mock/llm-test)
· art. UB 10
· 2024-06-01
Valeur citée à l'article — « hauteur maximale 12 mètres »
|
0.90 |
| Divergence hauteur texte / graphique | texte 12 m ≠ graphique 9 m — retenu 9 m (le plus restrictif) | Contradictoire |
règlement graphique — GPU / règlement graphique (hauteur maximale de façade) vs article UB 10
· art. UB 10 (écrit) / hauteur maximale de façade (graphique)
· 2024-06-01
CONTRADICTION : règlement écrit 12 m (article UB 10) vs règlement graphique — GPU / règlement graphique (hauteur maximale de façade) 9 m — la plus restrictive (9 m) est retenue, arbitrage à confirmer en mairie
|
0.60 |
| Hauteur maximale retenue | 9 m | Contradictoire |
règlement graphique — GPU / règlement graphique (hauteur maximale de façade)
· art. UB 10
· 2024-06-01
CONTRADICTION : règlement écrit 12 m (article UB 10) vs règlement graphique — GPU / règlement graphique (hauteur maximale de façade) 9 m — la plus restrictive (9 m) est retenue, arbitrage à confirmer en mairie
|
0.60 |
Règlement fourni en PDF scanné, donc illisible. Le rapport ne dit pas
« aucune règle de hauteur » : il dit Non vérifié, avec le code de cause
pdf_scanne dans la provenance, et l'action à faire.
| Règle | Valeur | État | Source (document · article · page · date) | Confiance |
|---|---|---|---|---|
| Règles de constructibilité non déterminées | règlement fourni en PDF scanné, aucun texte extractible — aucune règle chiffrée ne peut être avancée. | Non vérifié |
Document d'urbanisme existant, règlement non lu (pdf_scanne)
cause : pdf_scanne — règlement non lu ; non lu n'est pas absent, aucune valeur n'est inventée
|
0.90 |
Même parcelle, règlement réellement parsé : rien sur le stationnement. Là, et là seulement, le rapport a le droit de dire Absent — et il écrit sur quoi il s'appuie pour le dire.
| Règle | Valeur | État | Source (document · article · page · date) | Confiance |
|---|---|---|---|---|
| Cos | Aucune règle trouvée dans le règlement lu | Absent (confirmé) |
Règlement PDF lu — 2 sections parsées
· 2024-06-01
Règle « cos » cherchée dans le règlement lu et non trouvée — absence constatée, pas un défaut de lecture
|
0.70 |
| Stationnement min | Aucune règle trouvée dans le règlement lu | Absent (confirmé) |
Règlement PDF lu — 2 sections parsées
· 2024-06-01
Règle « stationnement_min » cherchée dans le règlement lu et non trouvée — absence constatée, pas un défaut de lecture
|
0.70 |
« L'emprise au sol maximale varie selon la destination des constructions » : pas un nombre. Le rapport le dit, cite l'article, et n'émet aucun verdict.
| Règle | Statut | État donnée | Raison / Source |
|---|---|---|---|
| Emprise au sol | À vérifier — donnée non disponible |
Ambigu
art. UB 9
|
Valeur non chiffrée dans le règlement : « selon destination » (UB 9) — interprétation manuelle requise
|
Même parcelle (800 m², bâti existant 120 m² d'emprise, 110 m² de plancher, 6 m de haut), projet déclaré : extension de 42 m² d'emprise. Le rapport raisonne le projet et rend le calcul, pas seulement la règle.
| Question | Verdict | État donnée | Calcul & démarche |
|---|---|---|---|
| Puis-je agrandir sans dépasser l'emprise au sol autorisée ? | Autorisé |
Confirmé
UB 9 · p.12 · 2024-03-15
|
Démarche : aucune formalité
|
| Quelle démarche dois-je engager pour cette extension ? | Conditionnel |
Confirmé
R.421-14 du code de l'urbanisme
|
Démarche : permis de construire
|
| Dois-je faire appel à un architecte ? | Conditionnel |
Confirmé
art. 4 de la loi n° 77-2 du 3 janvier 1977, seuil fixé par R.431-2 du code de l'urbanisme
|
Démarche : recours à un architecte obligatoire
|
Et voici ce qui compte le plus pour vous : le même projet, sur un règlement où le coefficient d'emprise au sol n'a pas été lu. Le rapport ne bascule pas sur une valeur nationale par défaut et ne dit jamais « autorisé » : il dit Non vérifié et donne la démarche pour lever le doute.
| Question | Verdict | État donnée | Calcul & démarche |
|---|---|---|---|
| Puis-je agrandir sans dépasser l'emprise au sol autorisée ? | Non vérifié | Non vérifié |
Démarche : certificat d'urbanisme opérationnel (CUb)
|
| Quelle démarche dois-je engager pour cette extension ? | Conditionnel |
Confirmé
R.421-14 du code de l'urbanisme
|
Démarche : permis de construire
|
| Dois-je faire appel à un architecte ? | Conditionnel |
Confirmé
art. 4 de la loi n° 77-2 du 3 janvier 1977, seuil fixé par R.431-2 du code de l'urbanisme
|
Démarche : recours à un architecte obligatoire
|
cd $SCRATCH/demo-aq && PYTHONPATH=. .venv-plu/bin/python -m pytest tests/test_plu_plus_*.py tests/test_plu_phase2*.py tests/test_plu_parcelle_reelle.py -q438 passed, 1 skipped, 639 warnings in 22.61s
Dont 39 tests pour les cinq états
(tests/test_plu_plus_etats.py) et 27 pour le raisonnement par
projet (tests/test_plu_plus_project_reasoner.py). Deux fichiers de
tests du dépôt hors périmètre PLU+ (test_admin_core_basic.py,
test_output_and_sketch3d.py) échouent : ils ne sont pas comptés dans
ce chiffre et rien ici ne prétend que le dépôt entier est vert.
Pour un ingénieur : vous décrivez un ouvrage une fois (une cloison 72/48, une ouverture dans un container), vous donnez les dimensions, le moteur rend la liste des matériaux, les quantités, le nombre d'unités de vente, le prix et le temps de pose — et chaque nombre porte sa formule, ses entrées, sa perte et sa source.
FAIT ET VÉRIFIÉ RÉEL — module pur : aucune base de données, aucun réseau.
cd $SCRATCH/demo-zf && backend/.venv-fabrik/bin/python demo-sorties/demo_fabrik.py backend/ demo-sorties/Paramètres : longueur_m 3,2 · hauteur_m 2,5 · nb_portes 1 ·
quantite_ouvrage 8,0.
Résultat : 197,5 € de matériaux,
7,95 h de main-d'œuvre,
12 lignes,
total_partiel = true.
| Ligne | Quantité | Unités de vente | Prix unitaire | Total | Statut |
|---|---|---|---|---|---|
| Plaque de plâtre BA13 standard 13mm | 14,1903 m2 | 5 | 8,1 € | 40,5 € | PROVISOIRE |
| Rail métallique 48mm (haut/bas) | 6,72 ml | 3 | 5,5 € | 16,5 € | PROVISOIRE |
| Montant métallique 48mm | 18,2 ml | 7 | 5,9 € | 41,3 € | PROVISOIRE |
| Montant métallique 48mm | 6,0632 ml | 3 | 5,9 € | 17,7 € | PROVISOIRE |
| Laine de verre 45mm (isolation phonique cloison) | 6,9375 m2 | 2 | 24,9 € | 49,8 € | PROVISOIRE |
| Vis TRPB 25mm (plaque sur métal) | 168,0 u | 1 | 9,9 € | 9,9 € | PROVISOIRE |
| Bande à joint papier | 8,4 ml | 1 | 4,9 € | 4,9 € | PROVISOIRE |
| Enduit à joint poudre | 2,64 kg | 1 | 16,9 € | 16,9 € | PROVISOIRE |
| Implantation, pose des rails et des montants | 2,0 h | — | prix inconnu | — | PROVISOIRE |
| Pose des plaques, 2 faces | 2,8 h | — | prix inconnu | — | PROVISOIRE |
| Bandes et enduit, 2 passes + poncage | 2,4 h | — | prix inconnu | — | PROVISOIRE |
| Encadrement d'ouverture (par porte) | 0,75 h | — | prix inconnu | — | PROVISOIRE |
Ligne ba13_faces — Plaque de plâtre BA13 standard 13mm :
2 * (longueur_m * hauteur_m - nb_portes * largeur_porte_m * hauteur_porte_m)calepinage_plaques (calepinage), valeur 12,5 %.Ce calcul est écrit à la main dans la docstring du test
qui garde le moteur (backend/tests/test_assemblies_moteur.py) :
aucune valeur attendue n'y est recopiée depuis la sortie du moteur. Extrait
réel :
CAS DE RÉFÉRENCE CLOISON — mur de 3,20 m × 2,50 m = 8,00 m², 1 porte 0,83 × 2,04 m
=================================================================================
Recette `data/assemblies/exemples/cloison_72_48.json`, catalogue
`data/materiaux_second_oeuvre.json` (coef_chute et conditionnements cités ligne à ligne).
surface brute 3,20 × 2,50 = 8,0000 m²
ouverture porte 0,83 × 2,04 = 1,6932 m²
surface nette 8,0000 − 1,6932 = 6,3068 m²
BA13 (2 faces) 2 × 6,3068 = 12,6136 m²
calepinage ceil(3,20/1,20) = 3 plaques → 3 × 1,20 = 3,60 m posés
3,60/3,20 − 1 = 12,5 % (remplace le
coef_chute catalogue de 10 % : remplace_coef_materiau = true)
avec chute 12,6136 × 1,125 = 14,1903 m²
conditionnement plaque de 3 m² → 14,1903/3 = 4,7301 → ceil = 5 PLAQUES
Rail 48 2 × 3,20 (rail haut + rail bas) = 6,4000 ml
coef catalogue rail_48 coef_chute = 0,05 → 6,40 × 1,05 = 6,7200 ml
conditionnement barre de 3 m → 6,72/3 = 2,24 → ceil = 3 BARRES
Montants courants (ceil(3,20/0,60) = 6, +1 de rive) = 7 montants × 2,50
= 17,5000 ml
Montants encadr. 1 porte × (2 × 2,50 + 0,83) = 5,8300 ml
chute barre ceil(2,50/2,60) = 1 barre → 2,60/2,50 − 1 = 4 %
17,50 × 1,04 = 18,2000 ml → /2,60 = 7,00 = 7 BARRES
5,83 × 1,04 = 6,0632 ml → /2,60 = 2,3320 = 3 BARRES
total montant_48 = 10 BARRES
Laine 45 6,3068 m² (surface nette, porte déduite)
coef catalogue 0,10 → 6,3068 × 1,10 = 6,9375 m²
conditionnement paquet de 5,4 m² → 1,2847 → ceil = 2 PAQUETS
Visserie 20 × 8,00 = 160 u ; ×1,05 = 168 → boîte 1000 = 1 BOÎTE
Bande 1 × 8,00 = 8,00 ml ; ×1,05 = 8,40 → rouleau 75 = 1 ROULEAU
Enduit 0,3 × 8,00 = 2,40 kg ; ×1,10 = 2,64 → sac 25 = 1 SAC
Total matériaux 5×8,10 + 3×5,50 + 7×5,90 + 3×5,90 + 2×24,90
+ 1×9,90 + 1×4,90 + 1×16,90
= 40,50 + 16,50 + 41,30 + 17,70 + 49,80 + 9,90 + 4,90 + 16,90
= 197,50 €
Main-d'œuvre 8,00 m² × (0,25 + 0,35 + 0,30) = 7,20 h
+ 0,75 h × 1 porte (temps global) = 7,95 h
Paramètres : largeur_ouverture_m 2,0 · hauteur_ouverture_m 2,1 ·
type_container 20ft. Le moteur rend
9 lignes et
18,62 h de main-d'œuvre, mais
aucun total en euros : les quatre références matériaux de cet ouvrage
n'existent pas dans le catalogue rénovation, et le moteur refuse de composer un
total incomplet.
| Ligne | Quantité | Unités de vente | Prix unitaire | Total | Statut |
|---|---|---|---|---|---|
| tube_acier_60x40_3mm | 9,072 ml | — | prix inconnu | — | INTROUVABLE |
| disque_tronconnage_230 | 4,0 u | — | prix inconnu | — | INTROUVABLE |
| fil_fourre_mag_1_2 | 1,312 kg | — | prix inconnu | — | INTROUVABLE |
| primaire_epoxy_antirouille | 1,476 L | — | prix inconnu | — | INTROUVABLE |
| poste_grutage_camion_grue_demi_journee | 1,0 forfait | — | prix inconnu | — | INTROUVABLE |
| Tracage et decoupe de la tremie | 4,92 h | — | prix inconnu | — | PROVISOIRE |
| Debit, presentation et soudure du cadre de renfort | 8,2 h | — | prix inconnu | — | PROVISOIRE |
| Preparation et application du primaire anticorrosion | 1,5 h | — | prix inconnu | — | PROVISOIRE |
| Manutention et calage pendant grutage | 4,0 h | — | prix inconnu | — | PROVISOIRE |
Avertissements produits par le moteur lui-même :
RENFORT_NON_OPPOSABLE — Le cadre de renfort n'est PAS dimensionne : sa section vient d'une pratique d'atelier, pas d'un calcul structure. Resultat a faire valider par un bureau d'etudes avant execution — non opposable (40-FABRIK.md « ce que je supprimerais » : Fabrik reste au niveau quantitatif + regles de bon sens + avertissement « faire valider »).DIMENSIONS_ISO_A_VERIFIER — Les dimensions ISO 668 portees en references sont PROVISOIRE : elles ont ete saisies de memoire, sans acces a la norme. A revalider sur le texte achete avant tout usage engageant.MATERIAUX_HORS_CATALOGUE — Aucune des 4 references materiaux de cet ouvrage n'existe dans backend/data/materiaux_second_oeuvre.json (catalogue second-oeuvre renovation, 457 references mesurees). Les lignes sortiront INTROUVABLE / PRIX_INCONNU et le BOM sera total_partiel=true — jamais un total complet mensonger.POSTE_LOGISTIQUE_SANS_PRIX — Le poste de grutage n'a aucune source de prix dans le depot : il doit etre saisi par le chiffreur. Il reste VISIBLE a zero quantite jamais, prix null toujours.RESULTAT_NON_OPPOSABLE — Quantitatif indicatif : aucun calcul verifie n'a tourne sur cet ouvrage (bloc `verification` absent). A faire valider avant execution — non opposable.La recette de cloison migrée en base (les 40 ouvrages,
migrations/2026-08-01_materiaux_ouvrages.sql ligne 168) compte les
montants d'ossature avec un ratio plat de 1,67 mètre par m² — exact pour
un mur infiniment long, faux pour un mur court. Nous avons rejoué le même mur
avec ce ratio :
| Ratio v0 (1,67 ml/m²) | 13,36 ml |
| Formule géométrique v1, montants courants | 17,5 ml |
| Écart sur le poste « montants courants » | +31,0 % |
| v1 avec l'encadrement de porte (inexprimable en v0) | 23,33 ml (+74,6 %) |
| Total matériaux du mur : v0 → v1 | 173,9 € → 197,5 € (+13,6 %) |
La mesure documentée dans le dossier (BRIEF-01-AVANCEMENT.md)
annonce 31 % d'erreur sur le poste et 6,5 % sur le prix total —
notre run reproduit exactement les 31 % sur les montants courants, et
mesure +13,6 % sur le total une fois compté
l'encadrement de porte, que la recette v0 ne sait pas exprimer du tout.
L'erreur est maximale entre 2 et 5 mètres : la rénovation courante.
Et la tolérance de ±5 % que nous nous sommes fixée n'a jamais été validée par un professionnel. C'est l'une des trois questions à trancher aujourd'hui.
Le moteur refuse par ailleurs de se déclarer opposable tant qu'aucun calcul vérifié n'a tourné. Avertissements du BOM cloison :
TEMPS_MO_ESTIMES — Les temps de main-d'oeuvre sont des estimations maison, jamais des temps de bibliotheque FR. Ils sont VISIBLES et non bloquants : un chiffrage les affiche avec leur statut PROVISOIRE.CALEPINAGE_APPROCHE — Le calepinage est modelise par une formule 1D (rangees verticales de plaques). Un vrai calepinage 2D (chutes reutilisees, decoupes autour des ouvertures) demande un solveur de placement, absent du depot.RECETTE_HERITEE_V0 — Visserie, bande et enduit conservent les ratios scalaires de la recette v0 (SQL:168) : ils ne sont pas encore fonction de la geometrie.RESULTAT_NON_OPPOSABLE — Quantitatif indicatif : aucun calcul verifie n'a tourne sur cet ouvrage (bloc `verification` absent). A faire valider avant execution — non opposable.cd $SCRATCH/demo-zf/backend && .venv-fabrik/bin/python -m pytest tests/ -q -p no:randomly3333 passed, 3 skipped, 12 warnings in 31.08s
Dont 78 tests pour le moteur d'ouvrages et son
schéma (test_assemblies_moteur.py + test_assemblies_schema.py).
Pour un architecte : c'est la condition d'entrée pour vendre le produit à plus d'un client. Un client B qui connaît l'identifiant d'un bien du client A doit se heurter à un mur, sur toutes les portes, pas seulement sur la porte principale.
FAIT ET VÉRIFIÉ RÉEL
cd $SCRATCH/demo-aq/imagein/backend && .venv_scratch/bin/python -m pytest tests/test_isolation.py -v============================= test session starts ============================== platform linux -- Python 3.12.3, pytest-8.3.4, pluggy-1.6.0 -- /home/arthur/repos/artqad-saas/imagein/backend/.venv_scratch/bin/python cachedir: .pytest_cache rootdir: /tmp/claude-1000/-home-arthur/89b8efba-d18f-4bf4-922d-643f9e3ae3b3/scratchpad/demo-aq/imagein/backend configfile: pytest.ini plugins: anyio-4.14.1, cov-7.1.0 collecting ... collected 15 items tests/test_isolation.py::test_tenant_b_gets_404_on_every_project_surface_of_a PASSED [ 6%] tests/test_isolation.py::test_listing_of_b_contains_no_project_of_a PASSED [ 13%] tests/test_isolation.py::test_owner_sees_own_project PASSED [ 20%] tests/test_isolation.py::test_owner_ref_in_payload_is_ignored_on_create PASSED [ 26%] tests/test_isolation.py::test_owner_ref_in_payload_is_ignored_on_patch PASSED [ 33%] tests/test_isolation.py::test_no_key_keeps_previous_behaviour PASSED [ 40%] tests/test_isolation.py::test_legacy_null_owner_project_is_reclaimed PASSED [ 46%] tests/test_isolation.py::test_require_key_rejects_anonymous PASSED [ 53%] tests/test_isolation.py::test_unknown_or_revoked_key_is_401 PASSED [ 60%] tests/test_isolation.py::test_key_is_never_stored_in_clear PASSED [ 66%] tests/test_isolation.py::test_share_token_reads_its_project_only PASSED [ 73%] tests/test_isolation.py::test_share_token_hides_owner_identity PASSED [ 80%] tests/test_isolation.py::test_share_token_forbids_every_write PASSED [ 86%] tests/test_isolation.py::test_expired_share_token_is_401 PASSED [ 93%] tests/test_isolation.py::test_revoked_share_token_is_401 PASSED [100%] ============================== 15 passed in 0.70s ==============================
Chacune est appelée avec la clé du client B sur un bien du client A, et doit répondre 404. Pas 403 : un 403 dirait « ça existe, mais ce n'est pas à vous ». Un 404 ne dit rien du tout — le client B n'apprend même pas que le bien existe.
surfaces = [
("GET", f"/projects/{pid}", {}),
("PATCH", f"/projects/{pid}", {"json": {"name": "volé"}}),
("GET", f"/projects/{pid}/plan", {}),
("PUT", f"/projects/{pid}/plan", {"json": _PLAN}),
("POST", f"/projects/{pid}/items", {"json": {"catalog_product_id": "x"}}),
("GET", f"/projects/{pid}/items", {}),
("DELETE", f"/projects/{pid}/items/{item_id}", {}),
("GET", f"/projects/{pid}/budget", {}),
("GET", f"/projects/{pid}/renders", {}),
("POST", f"/projects/{pid}/scans", {"json": {}}),
("GET", f"/projects/{pid}/scans", {}),
("GET", f"/projects/{pid}/scans/{sid}", {}),
("POST", f"/projects/{pid}/scans/{sid}/upload",
{"files": {"file": ("x.ply", b"ply", "application/octet-stream")}}),
("POST", f"/projects/{pid}/scans/{sid}/process", {}),
("GET", f"/projects/{pid}/scans/{sid}/splat", {}),
("POST", f"/scans/{sid}/detect", {}),
("GET", f"/scans/{sid}/detections", {}),
("POST", "/renders/photoreal",
{"json": {"image_base64": TINY_PNG_B64, "project_id": pid, "scan_id": sid}}),
("POST", "/renders/photoreal", {"json": {"image_base64": TINY_PNG_B64, "project_id": pid}}),
]
Le test vérifie ensuite que le bien du client A est intact : ni renommé, ni vidé de son mobilier. Les 14 autres tests couvrent le jeton de partage qui ne lit que son seul projet, le jeton expiré ou révoqué qui rend 401, la clé jamais stockée en clair, et l'identifiant de propriétaire envoyé dans le corps de la requête, qui est ignoré à la création comme à la modification.
cd $SCRATCH/demo-aq/imagein/web && npx --offline tsx scripts/check-plan-engine.tsRendu 11 plans (35 niveaux) dans plan-engine-out/ OK — validatePlan (plan-engine) : 0 violation sur 35 niveau(x).
Un des 35 niveaux rendus, inséré ici tel quel (dessin vectoriel, aucune image chargée depuis l'extérieur) :
cd $SCRATCH/demo-aq/imagein/backend && .venv_scratch/bin/python -m pytest tests/ -q284 passed in 3.96s
Pour un gérant d'agence : le logiciel relit tous les jours les projets, les phases, les factures, les paiements et le planning, et sort la liste de ce qui dérape. Huit règles, écrites en dur, sans appel à un modèle de langage : donc sans coût par requête, sans latence, et avec un résultat identique d'un jour à l'autre pour les mêmes données.
FAIT ET VÉRIFIÉ RÉEL
cd $SCRATCH/demo-aq/backend && $SCRATCH/venv-studio/bin/python demo-sorties/demo_studio.py . demo-sorties/Une agence fictive de cinq personnes a été peuplée pour déclencher les huit
règles à la fois (date de référence : 26 août 2026). Sortie réelle de
run_rules() — 11 alertes :
| Règle | Niveau | Message rendu |
|---|---|---|
budget_overrun | RED | Coûts à 150% des honoraires |
overdue_invoice | RED | Facture #F-2026-007 en retard de 12 jours |
invoice_gap | ORANGE | Avancement 100% mais facturé seulement 0% |
phase_late | ORANGE | Phase Phase PRO en retard : échéance 2026-08-11, avancement 40% |
invoice_gap | ORANGE | Avancement 50% mais facturé seulement 0% |
invoice_gap | ORANGE | Avancement 40% mais facturé seulement 0% |
slow_client | ORANGE | Ville de Bordeaux : délai de paiement moyen de 70 jours (seuil 45 jours) |
overload | ORANGE | Marie D. : 6.0 j planifiés pour 5.0 j de capacité (semaine du 2026-08-24) |
margin_decline | ORANGE | Marge en baisse 4 mois consécutifs : 18000 € → -18000 € |
missing_invoice_on_milestone | ORANGE | Jalon atteint sur Phase APD (Projet 2026-008-MAISON-CAUDERAN) mais aucune facture émise |
missing_invoice_on_milestone | ORANGE | Jalon atteint sur Phase PRO (Projet 2026-008-MAISON-CAUDERAN) mais aucune facture émise |
Trois lectures utiles. Une : la marge du mois en cours ressort négative parce que 18 000 € de sous-traitance ont été engagés sans facturation en face — c'est exactement ce que la règle sert à voir. Deux : la phase PRO déclenche « jalon atteint » non parce qu'elle est terminée, mais parce que son échéance est dépassée et qu'aucune facture ne la touche. Trois : les messages sont des gabarits que chaque agence peut réécrire, seuils compris.
Et le résumé quotidien, build_digest(), qui ne garde que les trois
problèmes les plus graves :
: les 3 problemes du jour --- digest_date : 2026-08-26 findings_count : 11 items : 3 11 problème(s) détecté(s) le 2026-08-26. 1. [RED] Coûts à 150% des honoraires 2. [RED] Facture #F-2026-007 en retard de 12 jours 3. [ORANGE] Avancement 100% mais facturé seulement 0%
cd $SCRATCH/demo-aq/backend && $SCRATCH/venv-studio/bin/python -m pytest tests/test_ai_rules.py -q30 passed, 3 warnings in 48.89s
tests/test_ai_rules.py, et c'est le seul chiffre citable pour
Studio OS. La suite complète du backend ne tourne pas hors PostgreSQL : mesurée
aujourd'hui, elle donne 73 échecs, 202 succès et 217 erreurs de collecte, et deux
modules ne se collectent même pas. Aucune affirmation de ce document ne porte sur
cette suite complète.
Ce que c'est : se promener dans le relevé 3D d'un logement existant, depuis un navigateur, sans rien installer.
ÉCRIT, PAS INTÉGRÉ NON DÉMONTRABLE HORS LIGNE
Pourquoi rien n'est montré : la correction d'isolation d'IMAGEin (§3) a fermé l'accès direct au fichier de nuage de points, dont la visite avait besoin. Le correctif est identifié — une URL signée à durée limitée pour ce seul fichier — mais il n'est pas écrit. Montrer une visite aujourd'hui reviendrait à montrer la version d'avant l'isolation, c'est-à-dire une version qu'on ne peut pas vendre.
| Sujet | Statut | Pourquoi rien n'est montré |
|---|---|---|
| Visite virtuelle 3D | ÉCRIT, PAS INTÉGRÉ | Cassée par l'isolation IMAGEin. Correctif identifié : URL signée pour le fichier de nuage de points. Non écrit à ce jour. |
| IA designer, rendus photoréalistes | SPÉCIFIÉ | Passent par une interface payante (fal.ai), interdite dans cette démonstration. Et surtout : aucun architecte d'intérieur n'a encore jugé ces propositions à l'aveugle contre un travail humain. Tant que ce jugement n'existe pas, le module est invendable, quelle que soit la qualité des images. |
| Lecture d'un vrai règlement de PLU par modèle de langage | ÉCRIT, PAS INTÉGRÉ | La démonstration du §1 tourne avec un extracteur de test. Le run réel exige une clé d'API plafonnée à 5 $ — geste administratif non fait. |
| Fiabilité annoncée de PLU+ | PAS COMMENCÉ | Aucun taux ne peut être publié tant qu'un architecte n'a pas rédigé la bonne réponse sur 50 à 100 dossiers réels. C'est la condition de mise en vente du rapport à l'unité comme de l'abonnement (décision D3). |
| Trousseau / atelier-core (briques partagées entre les produits) | ÉCRIT, PAS INTÉGRÉ | Lu, pas exécuté dans cette démonstration. Aucune sortie n'est présentée, et rien ici ne repose dessus. |
| Mise en ligne | PAS COMMENCÉ | Rien de tout ce qui précède n'est déployé. Deux dépôts attendent le feu vert d'Arthur ; tout ce que montre cette page tourne en local. |
| Chiffre | Commande (depuis un clone jetable) |
|---|---|
| PLU+ — 438 passed, 1 skipped | PYTHONPATH=. .venv-plu/bin/python -m pytest tests/test_plu_plus_*.py
tests/test_plu_phase2*.py tests/test_plu_parcelle_reelle.py -q |
| dont 5 états — 39 passed | … -m pytest tests/test_plu_plus_etats.py -q |
| dont raisonnement projet — 27 passed | … -m pytest tests/test_plu_plus_project_reasoner.py -q |
| Ze Fabrik — 3333 passed, 3 skipped | cd backend && .venv-fabrik/bin/python -m pytest tests/ -q -p no:randomly |
| dont moteur d'ouvrages — 78 passed | … -m pytest tests/test_assemblies_moteur.py tests/test_assemblies_schema.py -q -p no:randomly |
| IMAGEin — 284 passed | cd imagein/backend && .venv_scratch/bin/python -m pytest tests/ -q |
| dont isolation — 15 passed | … -m pytest tests/test_isolation.py -v |
| Studio OS — 30 passed (seul chiffre citable) | cd backend && venv-studio/bin/python -m pytest tests/test_ai_rules.py -q |
| BOM cloison — 197,50 € / 7,95 h / 12 lignes | .venv-fabrik/bin/python demo-sorties/demo_fabrik.py backend/ demo-sorties/ |
| Écart du ratio v0 — +31,0 % sur les montants courants | même commande, section DEFAUT CONNU |
| Plans IMAGEin — 11 plans, 35 niveaux, 0 violation | npx --offline tsx scripts/check-plan-engine.ts |
Sur quel code ces chiffres ont été mesurés :
artqad-saas commit 8383c291 augmenté des trois lots livrés
la veille (correctif des fausses contradictions PLU+, raisonnement par projet,
IA opératrice de Studio OS), et ze-fabrik commit d5a0adb.
Les dépôts de travail avancent sous d'autres sessions ; les mesures, elles,
tournent sur des clones figés sur ces deux empreintes, et ne sont donc pas
affectées. Aucun fichier suivi de ces dépôts n'a été modifié :
bash verifier-demo.sh le contrôle aussi.
Sorties brutes complètes, rapports HTML entiers et scripts de démonstration :
dossier demo-sorties/ à côté de cette page.