SPEC — Macroscope Rendering Templates
SPEC — Macroscope Rendering Templates
Status: Draft v0.1 Owner: Francois (Framework Specialist) Source request: MET-0008 Authority: TFD-0024 Reference impl:
C:\Users\bockb\OneDrive - STM\agent-ea\clients\transgesco\DAE-0007-trangesco-evaluation-systemes\out\_publish\dae-0007\Canonical taxonomy:C:\Users\bockb\OneDrive - STM\agent-ea\clients\transgesco\DAE-0007-trangesco-evaluation-systemes\MACROSCOPE-STRUCTURE.md
1. Purpose & Scope
Specify the rendering layer of the Macroscope framework — HTML templates + data binding + print/PDF behavior — so that every DAE (Dossier d'Architecture d'Entreprise) reuses the same structure instead of reinventing it.
In scope (this spec):
- Common data contract (D1 →
data.js) - Shared CSS tokens and layout primitives
- Section schema (extensible per A### code)
- A100+A280 jumeau mechanic
- Print/PDF behavior
Out of scope (handled elsewhere):
- D1 schema itself (lives in agent-ea v2, see memory
ea-registre-architecture) - Content templates (markdown scaffolds, siblings under
templates/) - Skill
/toolkit:framework-publish(extracted after templates validated) - Word
.docxexport (lot 2)
1bis. Universal pattern — Landing → Registre → Detail (3 niveaux)
Note terminologique : on dit « Registre » (pas « Registreue ») pour la page intermédiaire, afin d'éviter la collision avec le Registreue d'objets EA (D1, voir memory
ea-registre-architecture). Synonymes acceptables si contexte le justifie : Répertoire, Index, Liste. Jamais « Registreue ».
Règle transverse : tout livrable navigable suit le pattern à trois étages :
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ LANDING PAGE │ │ REGISTRE PAGE │ │ DETAIL PAGE │
│ (DAE home page) │───▶│ (intermediate list)│───▶│ (single article) │
├─────────────────────┤ ├─────────────────────┤ ├─────────────────────┤
│ • Présente le DAE │ │ • Grille de tous │ │ • Contenu complet │
│ • Liens vers chaque │ │ les items d'UNE │ │ • Chapter nav │
│ registreue/article │ │ catégorie │ │ • Toutes sections │
│ • KPI / sommaire │ │ • Recherche + filtres│ │ • Drawer / détails │
│ • Carte du DAE │ │ • Tri + compteur │ │ • Prêt PDF/print │
│ • Statut global │ │ • Lien vers détail │ │ • Retour vers │
│ │ │ • Retour vers │ │ registreue │
│ │ │ landing │ │ │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
index.html *-registreue.html *-detail.html
(ou *-architecture.html)
Exemples appliqués DAE-0007 :
| Niveau | Page | Rôle |
|---|---|---|
| Landing | index.html |
Accueil DAE, présente le dossier et liens vers tous les registreues/livrables |
| Registre | 230-orientations-architecture.html |
Liste de toutes les ORI avec recherche/filtres/tri |
| Detail | 230-ori-001-yoffix.html |
Article complet d'une orientation (Yoffix) |
| Registre | 14-processus-registreue.html |
Liste de tous les processus (FLOWS) |
| Detail | 14-p01-fermeture-mensuelle.html |
Fiche complète d'un processus |
| Registre | registreue-changements.html |
Liste des changements (CHG) |
| Detail | fiche-changement.html?id=CHG-1 |
Détail d'une initiative |
| Registre | 100-solution-globale.html |
Vue solution + sommaire (hybride A100/A280) |
Capacités minimales d'une CATALOG page (vocabulaire fermé) :
- Recherche libre (input texte, filtre cartes par
nm + desc + ctx) - Filtres multi-critères (catégorie, statut, phase, direction — selon la donnée)
- Tri (par défaut sur ID ; alternatives : statut, phase, alphabétique)
- Compteur dynamique (
X / Yaffichés) - État vide géré (placeholder si filtre vide ou data manquante)
- Lien vers detail sur chaque carte (si une page detail existe)
- Pas de mélange de catégories — un registre = UNE catégorie. Ne JAMAIS mêler CHG et ORI sur le même registre.
- Retour vers landing (breadcrumb ou lien
← Accueil)
Capacités minimales d'une LANDING page :
- Présente le DAE (titre, deck, métadonnées, statut global)
- Liens nommés vers chaque registre (
Voir le registreue des orientations →) - Aucune liste détaillée d'items individuels (c'est le rôle du registre)
- KPI/sommaire optionnel (nombre de changements, phases, etc.)
Capacités minimales d'une DETAIL page :
- Contenu complet d'UN seul item
- Breadcrumb :
Landing → Registre → Detail - Lien
← Registreen mast - Optimisée pour PDF/print (single-document focus)
Anti-patterns explicites :
- ✗ Page qui mélange "orientations" + "changements" + "projets" sur une seule grille
- ✗ Detail page accessible uniquement par URL directe (toujours partir du registre)
- ✗ Filtres absents sur un registre dépassant ~5 items
- ✗ Registre page sans lien vers landing
- ✗ Landing page qui détaille individuellement les items (c'est le rôle du registre)
Le skill /toolkit:framework-publish enforce ce pattern à 3 étages lors du scaffold de toute nouvelle catégorie de livrables.
2. Architecture overview
D1 (per-client EA DB)
│ export
▼
data.js ──┐ (single source of truth, per DAE)
│
▼
HTML template (rendering layer, this spec)
│
├─ Screen view (interactive: filters, drawers, tabs)
└─ Print view (_print.css: expanded, paginated)
│
▼
PDF (Playwright headless, _shared/exporters/html-to-pdf.js)
Invariants:
- A template never contains client data — only structure + binding.
- All client data flows through
data.js(loaded via<script src="data.js">). - A template is identified by one or more Macroscope A### codes (a "jumeau" template carries 2+).
- Two templates referencing the same A### code = error (single home per code, see
MACROSCOPE-STRUCTURE.md§"une seule maison").
3. Data contract
3.1 Top-level objects in data.js
Borrowed from DAE-0007 (proven), extensible. All optional except META.
| Object | Shape | Used by | Notes |
|---|---|---|---|
META |
{client, dae, publishedDate, basePath} |
all | required, drives footer + crumbs |
MAP |
[{l1, nom, caps:[{nm, sub, dec, decL, crit, critL, pro[], org, role[], app[], cmp[], vendor, op, opStm, opex, vol, src, change_type?, change_desc?}]}] |
A100, A280, A219, A200, A250 | LeanIX v4 (Capacité→Processus→App→Composant→Opérateur). Optional change_type + change_desc populate A280 overlay. |
SVC |
[{nm, dec, decL, crit, cov, cons, opex, dec2}] |
A100, A280, A400 | services partenaires/STM |
PROJ |
[{id, nm, cap, org, st, stL, capex, opexD, fund, why, type, impact, impactDesc, change, owner, deadline, depends, sow?}] |
A100, A280, A270 | projets, CapEx, change détaillé |
CHG |
[{id, code, nm, dir, desc, ph, phEnd, projets[]}] |
A100 sommaire, A310-A360 | initiatives (regroupe ≥1 PROJ) |
PHASES, PHWIN, JALONS |
timeline | A100, A270 | feuille de route |
DATA |
{subjects:[{id, nm, dom, apps[], own, d}], rel[], flows[]} |
A100 (vues données/flot), A150 | modèle conceptuel + flux |
FLOWS |
{<process-id>:{...}} |
A251, A100 (process refs) | processus, SIPOC, BPMN |
PROC_LINKS |
{<process-name>: <url>} |
cross-page links | navigation processus |
ORI |
[{id, nm, cat, catL, st, stL, q, ctx, href?, phase?}] |
A230, A100 (orient. transverses) | Orientations d'architecture. cat ∈ collab|infra|fin|gov. st ∈ cours|att|diff. Schéma DAE-0007 canonique. |
3.2 The change_type / change_desc overlay (A280 mechanic)
Any object that participates in an A280 view exposes optional fields:
| Field | Type | Values | Meaning |
|---|---|---|---|
change_type |
enum | NEW, MOD, EXIST, OUT |
Nature du changement de l'objet entre AS-IS et cible |
change_desc |
string | text | Description courte (≤200 char), affichée en tooltip/drawer |
change_phase |
enum | 0, 1, 2, x |
Phase de livraison (filtre Macroscope, optionnel) |
change_chg |
string | CHG-N id |
Rattache l'objet à une initiative (filtre, optionnel) |
Règle : un objet sans change_type est traité comme EXIST par défaut. Aucune donnée client n'est jamais codée en dur dans le template.
3.3 D1 → data.js binding
Le mapping D1 → data.js est porté par le pipeline existant (memory d1-datajs-html-pipeline). Cette spec contraint uniquement la forme de data.js, pas comment il est produit. Aligné TFD-0010 (interface contract).
4. CSS tokens & layout primitives
Source canonique : _jct-editorial.css + _jct-harmonize.css + _print.css (DAE-0007). Copiés dans templates/rendering/_shared-css/.
4.1 Color tokens
:root{
/* STM/Transgesco navy (override per client via META) */
--navy:#002B5C; --navy-700:#003D7A; --navy-50:#EAF0F8;
--green:#009A44; --green-700:#007A35; --green-50:#E8F7EE;
--yellow:#FFE400; --yellow-700:#8A7600; --yellow-50:#FFFBE6;
--blue:#009EE0; --blue-50:#E0F5FC; --teal:#007489;
--red:#B91C1C; --red-50:#FEE2E2;
/* Editorial ink scale */
--ink:#0B1220; --ink-2:#1F2937; --ink-3:#4B5563; --ink-4:#6B7280;
/* Paper (cream) — editorial signature */
--paper:#F7F4EC; --paper-2:#FBF8F0; --white:#fff;
--rule:#B8B19E; --rule-2:#E5E0D1;
/* Change-type swatches (A280) */
--chg-new:#0066CC; --chg-mod:#D4A800; --chg-exist:#5A9B6A; --chg-out:#999;
/* Typography */
--serif:"Fraunces","Cormorant Garamond",Georgia,serif;
--sans:"Inter","Söhne","Segoe UI",system-ui,sans-serif;
--mono:"JetBrains Mono",Consolas,monospace;
}
4.2 Layout primitives
| Class | Purpose |
|---|---|
header.mast + .stripe |
Masthead navy → green gradient + yellow/green/blue stripe |
.container (max-width:1280px) |
Page container |
.crumb |
Breadcrumb (mono, small) |
h1 (serif, italic accent en <em> jaune) |
Page title |
.deck |
Subtitle (serif italic, light navy) |
h2.sec |
Section heading (serif, navy, underline) |
.intro-text |
Section intro paragraph |
.callout |
Highlighted box (green left-border) |
.grid |
Card grid (auto-fill min 380px) |
.chg-card, .chg-head, .chg-body |
Change card (used in A100 sommaire et A230) |
.chg-status + .st-actif/.st-cond/.st-out/.st-phase |
Status pills |
.diag-tab, .diag-pane, .diag-bar, .diag-stage |
Interactive diagram framing |
.tg-card (variants [data-impact="..."]) |
Object cards in diagrams, colored by change_type |
.diag-drawer + .scrim |
Side drawer for object detail |
4.3 Print rules (_print.css)
- All interactive panes expanded.
- Drawers inlined as appendix sections.
- Tabs collapsed to sequential sections (each pane visible).
- Page breaks before each
h2.sec. - Color preserved (
-webkit-print-color-adjust: exact).
5. Section schema (extensible registre)
Each A### code declares its rendering recipe. Registre format:
// templates/rendering/_registre.js (generated alongside the templates)
const CATALOG = {
"LANDING": {
title: "Accueil DAE (landing)",
crumbLabel: "00 · Accueil",
twinned: false,
file: "index.html",
sections: [
{ id:"masthead", h:"Masthead", kind:"prose", binding:"LANDING.{badge,rule,title,sub,meta}" },
{ id:"intro", h:"Intro éditoriale", kind:"prose", binding:"LANDING.intro" },
{ id:"sections", h:"Ledger sections (cartes vers registres)", kind:"card-grid",
binding:"LANDING.sections[].tiles[]",
// LOI : un tile.href pointe TOUJOURS un registre ou un detail. Jamais un item enumeré ici.
contract:"no item enumeration on landing — point to registers only" }
]
},
"A100+A280": {
title: "Solution d'entreprise & analyse d'impact",
crumbLabel: "01 · A100 · A280",
twinned: true,
file: "A100-A280-solution-impacts.html",
sections: [
{ id:"archi-cible", h:"Architecture cible — 4 vues",
kind:"interactive-tabs",
tabs:[
{id:"logi", label:"Logicielle · A219", binding:"MAP+app/cmp"},
{id:"data", label:"Données · A150", binding:"DATA.subjects+rel"},
{id:"flot", label:"Flot de données", binding:"DATA.flows"},
{id:"infra", label:"Infrastructure · A370", binding:"MAP+infra"}
],
filters:["phase","chg","impact"],
drawer:"object-detail"
},
{ id:"sommaire-chg", h:"Sommaire des changements",
kind:"card-grid",
binding:"CHG",
linkPattern:"fiche-changement.html?id={id}"
},
{ id:"orientations", h:"Orientations transverses à valider",
kind:"card-grid",
binding:"ORIENT (filtered by CHG=CHG-1)"
}
]
},
"A230": {
title: "Orientations d'architecture",
crumbLabel: "02 · A230",
twinned: false,
file: "A230-orientations-architecture.html",
sections: [
{ id:"orient-list", h:"Orientations", kind:"card-grid",
binding:"ORIENT", linkPattern:"230-ori-{id}.html" }
]
}
// Future codes (A140, A200, A251, ...) plug in here via /toolkit:framework-publish
};
Section kinds (vocabulaire fermé, étendre seulement si besoin réel) :
interactive-tabs— pane tabs + filters + drawer (A100, A219, A150)card-grid— grid of.chg-card(sommaire, orientations)static-mermaid— Mermaid diagram block (A251, A270)data-table— sortable/filterable table (registreues, inventaires)prose— h2 + intro-text + body sections (A140, A230 detail pages)impact-matrix— matrice couche × option avec changements typés (A230-ORI detail).Définitions canoniques des couches (LOI : ne jamais mélanger ces couches, chaque objet va dans UNE couche unique) :
Couche Définition stricte Exemples d'objets NE PAS mettre ici Stratégie / orientations Principes directeurs et choix de cap. Pas des objets concrets. « Orientation SaaS-first », « Cloud-only », « Multi-fournisseur autorisé » Apps, rôles, processus Organisation Structure organisationnelle : directions, départements, équipes, comités. Entités collectives nommées dans l'organigramme. « Direction Finance », « Comité de gérance SEC », « Équipe TI Transgesco » Rôles individuels (→ Rôles), processus (→ Processus) Processus d'affaires Flux de travail métier, séquences d'activités, procédures opérationnelles. « Fermeture mensuelle », « Démarche de marché », « Réservation de poste » Apps qui supportent le processus (→ Applications), rôles qui l'exécutent (→ Rôles) Rôles et compétences Fonctions individuelles : postes nommés, profils de compétences, rôles dans l'organigramme. C'est ici que vivent « administrateur X », « gestionnaire Y », « analyste Z ». « Comptable principale », « Administrateur M365 », « Administrateur Yoffix » Départements (→ Organisation), équipes (→ Organisation) Applications Logiciels métiers identifiables : apps SaaS, modules ERP, plateformes. Un nom commercial unique. « Sage Vision33 », « CaseWare », « Yoffix », « Microsoft Teams » Composantes techniques sous-jacentes (→ Composante TI), hébergement (→ Composante TI) Composante TI Infrastructure et services techniques : connecteurs, intégrations, stockage, identité, réseau, hébergement. « Tenant M365 », « Connexion SSO SAML », « Provisionnement SCIM », « Hébergement EU Yoffix » Apps (→ Applications) Tests de la couche (à appliquer mentalement avant d'écrire un objet dans le matrix) :
- Si je peux le pointer dans un organigramme et c'est une boîte avec ≥2 personnes → Organisation
- Si je peux le pointer dans un organigramme et c'est une fonction individuelle → Rôles
- Si c'est un nom commercial de logiciel → Applications
- Si c'est un câble, un protocole, un stockage, une intégration → Composante TI
- Si c'est un verbe d'action métier (« faire X ») → Processus
- Si c'est un principe de cap → Stratégie
Format canonique :
// In data.js for a A230-ORI detail page
const ORI_DETAIL = {
ref:"A230-ORI-001",
title:"Plateforme de gestion des espaces de bureau",
deck:"Yoffix · Microsoft Places · M365 natif",
meta:[ /* metadata bar rows */ ],
options:[
{ id:"A", label:"Yoffix", color:"opt-a" },
{ id:"B", label:"Microsoft Places", color:"opt-b" },
{ id:"C", label:"M365 natif", color:"opt-c", recommended:true }
],
// Layers — vocabulaire LeanIX v4 étendu (Stratégie + Org + Rôles ajoutés)
layers:[
{ id:"strat", nm:"Stratégie / orientations" },
{ id:"org", nm:"Organisation" },
{ id:"proc", nm:"Processus d'affaires" },
{ id:"role", nm:"Rôles et compétences" },
{ id:"app", nm:"Applications" },
{ id:"cmp", nm:"Composante TI" },
{ id:"data", nm:"Données" }, // optionnel
{ id:"sec", nm:"Sécurité & conformité" } // optionnel
],
// Matrix indexed by "<layer>.<option>" → structured cell
matrix:{
"strat.A":{ level:"NONE", objects:[],
rationale:"Aligné orientation SaaS-first. Pas de tension stratégique." },
"org.A": { level:"NEW", objects:[
{type:"NEW", nm:"Rôle administrateur Yoffix", desc:"Cumulé avec admin M365"}],
rationale:"Pas d'embauche. Admin Yoffix = admin M365 (PRJ-08)." },
"app.A": { level:"NEW", objects:[
{type:"NEW", nm:"Yoffix (SaaS)", desc:"Add-in Teams + portail"}],
rationale:"Nouveau fournisseur SaaS, intégration Teams native." },
// ... etc pour chaque combinaison couche×option
}
};
Vocabulaire fermé :
level∈NEW | MOD | OUT | NONE(jamais autre chose).NONE= aucun impact sur cette couche pour cette option.objects[].type∈NEW | MOD | OUT. Pas de typeNONEau niveau objet — un objet sans changement n'est simplement pas listé.leveldoit être la synthèse cohérente desobjects[]: si tout estNONE⇒level:"NONE"etobjects:[]. Si ≥1 NEW et ≥1 MOD ⇒level:"NEW"(priorité décroissante NEW > MOD > OUT > NONE).
Rendu visuel (cellule) :
┌──────────────────────────────────────┐
│ [pill NEW] │ ← level pill (color-coded)
│ │
│ • [NEW] Yoffix (SaaS) │ ← objects with type badges
│ Add-in Teams + portail │
│ │
│ Nouveau fournisseur SaaS, │ ← rationale (italic, ink-3)
│ intégration Teams native. │
└──────────────────────────────────────┘
Colonne option recommandée (recommended:true) : fond --paper-2 + bordure verte gauche.
5.1 A100+A280 jumeau mechanic
Une seule page HTML, mode toggle en haut (sticky, mono-font pill) :
[ Cible · A100 ] [ Impacts · A280 ] [ Tableau sommaire ]
- Mode "Cible" : tg-cards rendues sans
data-impactattribute → bordure neutre, légende impact masquée. - Mode "Impacts" : tg-cards rendues avec
data-impact={change_type}→ bordure colorée + légende visible + filtrechange_typeactif. - Tableau sommaire : remplace le stage diag par une
data-table(objets ×change_type×change_desc×change_phase×change_chg). Tri/filtre côté client. Pas d'overlay visuel — c'est la version "exécutive" du A280.
Impl note : un seul <main>, trois <section data-mode="..."> masquées/affichées par aria-hidden. Pas de re-render — toggle de classe sur <body>.
5.2 PDF rendering du jumeau (résout R2 du request)
À l'impression, les 3 modes sont rendus séquentiellement : Cible → Impacts → Tableau. Page break entre chaque. Le toggle est masqué (@media print { .mode-toggle{display:none} }). Aucun choix utilisateur à l'impression — un PDF unique contient tout.
6. File layout (canonical)
production-lines/digital-talent/frameworks/
enterprise-architecture/
macroscope/
framework-guide.md (existing, content layer doc)
overview.md (existing, content layer doc)
templates/ (Francois owns)
enterprise-solution-template.md (existing, content scaffold)
enterprise-context-template.md (existing)
architecture-orientation-template.md (existing)
architecture-evaluation-template.md (existing)
rendering/ (THIS SPEC)
SPEC.md (← this file)
README.md (usage for Remy/Elena)
_registre.js (section registre, extensible)
_shared-css/
_jct-editorial.css
_jct-harmonize.css
_print.css
index.html (LANDING gabarit, niveau 1 du 3-tier)
index-data.example.js (DAE-0007 echo for regression)
A100-A280-solution-impacts.html
A100-A280-data.example.js (skeleton + DAE-0007 echo for regression)
A230-orientations-architecture.html
A230-data.example.js
A230-ORI-detail.html
A230-ORI-detail-data.example.js
_shared/
exporters/
html-to-pdf.js (Playwright, all frameworks)
README.md
7. Validation criteria
A template is "ready" when:
- Renders cleanly with empty data (skeleton navigable, no JS errors).
- Renders cleanly with DAE-0007 echo (
A100-A280-data.example.jsreuses DAE-0007data.jsas a regression fixture). - PDF export reproduces screen layout, all interactive content expanded, clean page breaks.
- Cloneable to a new DAE in ≤5 min (copy folder + swap
data.js+ adjustMETA+ done). - No client data hardcoded in HTML — every visible string in templates is a placeholder or comes from
data.js.
8. Open questions for board review
- OQ-1 — Tokens client-specific (navy override per client) : currently hardcoded in
:root. Move toMETA.theme = {primary, accent}and apply via CSS variables? Reco : oui, mais lot 2 — pour DAE-0007 le navy STM reste bon. - OQ-2 —
CATALOGextensible : doit-il être 1 fichier global ou 1 fichier par framework ? Reco : 1 par framework (_registre.jssous chaque framework folder), agrégé par le skill/toolkit:framework-publish. - OQ-3 — Mermaid (utilisé par A251 dans DAE-0007) : on garde le bundle
mermaid.min.jsshared ou per-template ? Reco :_shared/lib/mermaid.min.jsà côté des exporteurs. - OQ-4 — A140 (Contexte d'entreprise), A270 (Stratégie de livraison) — pas dans MET-0008 mais à scaffolder via skill plus tard. Section kinds
prose+data-tablesuffisent ? À valider quand on les fera.
9. Next steps (post-spec approval)
- Board review spec (this file) → ajustements
- Implement
A100-A280-solution-impacts.html+A230-orientations-architecture.html(task #3) - Copy DAE-0007
data.jsas*-data.example.jsfixtures (regression) - Build
html-to-pdf.jsPlaywright (task #4) - Regression test : régénérer DAE-0007 A100 + A230 depuis les gabarits
- Extract
/toolkit:framework-publishskill du pattern (task #5) - Notif Pablo (N-023a) + Ada (N-050) à la publication