Compare commits

...

3 Commits

Author SHA1 Message Date
25ce0409aa chore(glossaire): désaturer les defaults de navigation
All checks were successful
SMOKE / smoke (push) Successful in 7s
CI / build-and-anchors (push) Successful in 38s
CI / build-and-anchors (pull_request) Successful in 34s
2026-04-30 11:05:20 +02:00
afa4d84997 chore(glossaire): auditer la convergence effective du graphe
All checks were successful
SMOKE / smoke (push) Successful in 6s
CI / build-and-anchors (push) Successful in 38s
CI / build-and-anchors (pull_request) Successful in 40s
2026-04-30 10:37:07 +02:00
bf0683bbb2 Merge pull request 'docs(glossaire): formaliser la gouvernance du graphe' (#347) from docs/gouvernance-graphe-glossaire into main
All checks were successful
Proposer Apply (Queue) / apply-proposer (push) Successful in 15s
CI / build-and-anchors (push) Successful in 36s
SMOKE / smoke (push) Successful in 9s
Deploy staging+live (annotations) / deploy (push) Successful in 47s
Reviewed-on: #347
2026-04-30 07:53:17 +00:00
3 changed files with 167 additions and 21 deletions

View File

@@ -29,3 +29,93 @@ Un `primaryNext` est bon sil produit au moins lun des effets suivants :
- concrétiser.
Un `primaryNext` est faible sil est seulement voisin, décoratif ou encyclopédique.
---
## Dynamique réelle du graphe (niveau avancé)
### 1. Attracteurs
Laudit de convergence effective met en évidence des nœuds fortement attractifs :
* dispositifs méthodologiques (audit, cartographie)
* concepts fondamentaux (co-viabilité, tension, archicration)
Ces nœuds structurent la circulation globale du glossaire.
---
### 2. Bassins de convergence
Le graphe ne se distribue pas uniformément.
Il tend à sorganiser en bassins :
* bassin conceptuel central
* bassin méthodologique
* bassins secondaires (paradigmes, pathologies)
Un bassin est défini comme un ensemble de parcours convergeant vers un même noyau.
---
### 3. Risque de surconvergence
Lorsque trop de parcours convergent vers les mêmes nœuds :
* les parcours deviennent redondants
* la navigation perd en différenciation
* lexpérience de lecture devient monotone
Ce phénomène ne constitue pas une erreur technique, mais un déséquilibre structurel.
---
### 4. Bifurcation effective
Les nœuds à forte bifurcation jouent un rôle clé :
* ils ouvrent des trajectoires multiples
* ils structurent la diversité des parcours
Ils doivent être préservés comme points dexpansion.
---
### 5. Principe de régulation avancée
Lobjectif nest pas de supprimer les attracteurs, mais de :
* limiter leur domination excessive
* maintenir plusieurs bassins actifs
* garantir des trajectoires réellement distinctes
---
### 6. Règle pratique
Avant toute modification :
* vérifier limpact sur les convergences effectives
* éviter dajouter un lien vers un nœud déjà dominant
* privilégier louverture de nouvelles zones de circulation
---
### 7. Nature du système
Le glossaire ne doit pas être compris comme :
* un index
* ni un arbre
mais comme :
→ un graphe dynamique de circulation conceptuelle
dont la structure influence directement la pensée du lecteur.
# la première désaturation a déplacé les attracteurs vers scene-depreuve, journal-de-justification, regime-de-co-viabilite

View File

@@ -5,29 +5,43 @@ import yaml from "js-yaml";
const ROOT = "src/content/glossaire";
const DEFAULTS_FILE = "src/lib/glossary-navigation-defaults.ts";
const HUB_LIMIT = 5;
const EFFECTIVE_TOP_LIMIT = 10;
const PATH_KEYS = ["understand", "deepen", "compare", "apply"];
const defaultsRaw = fs.readFileSync(DEFAULTS_FILE, "utf-8");
const defaultFamilies = new Set(
[...defaultsRaw.matchAll(/^\s{4}"?([a-z0-9-]+)"?\s*:/gm)].map((m) => m[1]),
);
const defaultPathKeysByFamily = new Map();
for (const match of defaultsRaw.matchAll(/^\s{4}"?([a-z0-9-]+)"?\s*:\s*\{([\s\S]*?)^\s{4}\},/gm)) {
const family = match[1];
const body = match[2];
const keys = new Set();
for (const key of ["understand", "deepen", "compare", "apply"]) {
if (new RegExp(`\\b${key}\\s*:\\s*\\[[^\\]]+\\]`).test(body)) {
keys.add(key);
}
}
defaultPathKeysByFamily.set(family, keys);
[...defaultsRaw.matchAll(/^\s{4}"?([a-z0-9-]+)"?\s*:/gm)].map((m) => m[1]),
);
const defaultPathKeysByFamily = new Map();
const defaultTargetsByFamily = new Map();
for (const match of defaultsRaw.matchAll(
/^\s{4}"?([a-z0-9-]+)"?\s*:\s*\{([\s\S]*?)^\s{4}\},/gm,
)) {
const family = match[1];
const body = match[2];
const keys = new Set();
const targetsByKey = new Map();
for (const key of PATH_KEYS) {
const pathMatch = body.match(new RegExp(`\\b${key}\\s*:\\s*\\[([^\\]]*)\\]`));
const targets = pathMatch
? pathMatch[1]
.split(",")
.map((x) => x.trim().replace(/^["']|["']$/g, ""))
.filter(Boolean)
: [];
if (targets.length > 0) keys.add(key);
targetsByKey.set(key, targets);
}
defaultPathKeysByFamily.set(family, keys);
defaultTargetsByFamily.set(family, targetsByKey);
}
const files = fs.readdirSync(ROOT).filter((f) => f.endsWith(".md"));
const slugs = new Set(files.map((f) => f.replace(".md", "")));
@@ -58,6 +72,19 @@ const edges = {};
const incoming = {};
const families = new Set();
const effectiveOutgoing = new Map();
const effectiveIncoming = new Map();
function addEffectiveEdge(from, to) {
if (!from || !to || from === to || !slugs.has(to)) return;
if (!effectiveOutgoing.has(from)) effectiveOutgoing.set(from, new Set());
if (!effectiveIncoming.has(to)) effectiveIncoming.set(to, new Set());
effectiveOutgoing.get(from).add(to);
effectiveIncoming.get(to).add(from);
}
for (const { slug, data, noFrontmatter } of entries) {
if (noFrontmatter) continue;
@@ -75,6 +102,7 @@ for (const { slug, data, noFrontmatter } of entries) {
if (next) {
edges[slug] = next;
incoming[next] = (incoming[next] || 0) + 1;
addEffectiveEdge(slug, next);
if (next === slug) selfLoops.push(slug);
if (!slugs.has(next)) deadPrimaryNext.push(`${slug}${next}`);
@@ -84,14 +112,24 @@ for (const { slug, data, noFrontmatter } of entries) {
const explicitPaths = nav.paths || {};
const familyDefaults = defaultPathKeysByFamily.get(data.family) || new Set();
const familyDefaultTargets = defaultTargetsByFamily.get(data.family) || new Map();
const pathCount = ["understand", "deepen", "compare", "apply"].filter((key) => {
const pathCount = PATH_KEYS.filter((key) => {
const explicit = Array.isArray(explicitPaths[key]) && explicitPaths[key].length > 0;
const fromDefault = familyDefaults.has(key);
return explicit || fromDefault;
}).length;
if (pathCount < 2) weakPaths.push(slug);
for (const key of PATH_KEYS) {
const explicitTargets = Array.isArray(explicitPaths[key]) ? explicitPaths[key] : [];
const defaultTargets = familyDefaultTargets.get(key) || [];
for (const target of [...explicitTargets, ...defaultTargets]) {
addEffectiveEdge(slug, target);
}
}
}
const seenPairs = new Set();
@@ -161,6 +199,24 @@ if (selfLoops.length) {
selfLoops.forEach((s) => console.log(" -", s));
}
console.log(`\n📊 Effective convergence top ${EFFECTIVE_TOP_LIMIT}:`);
[...effectiveIncoming.entries()]
.map(([slug, sources]) => [slug, sources.size])
.sort((a, b) => b[1] - a[1])
.slice(0, EFFECTIVE_TOP_LIMIT)
.forEach(([slug, n]) => {
console.log(` ${n} ${slug}`);
});
console.log(`\n📊 Effective branching top ${EFFECTIVE_TOP_LIMIT}:`);
[...effectiveOutgoing.entries()]
.map(([slug, targets]) => [slug, targets.size])
.sort((a, b) => b[1] - a[1])
.slice(0, EFFECTIVE_TOP_LIMIT)
.forEach(([slug, n]) => {
console.log(` ${n} ${slug}`);
});
const hardFailures =
missingNavigation.length +
directCycles.length +

View File

@@ -38,7 +38,7 @@ export type GlossaryDefaultNavigation = {
understand: ["meta-regime", "regime-de-co-viabilite", "synchrotopie"],
deepen: ["hypotopie", "hypertopie", "atopie", "archicrations-differentielles-et-formes-hybrides"],
compare: ["scene-depreuve", "institution-invisible", "monde-instituable"],
apply: ["cartographie-des-scenes-manquantes", "archidiagnostic", "audit-archicratique"],
apply: ["archidiagnostic", "regime-de-co-viabilite", "scene-depreuve"],
},
"meta-regime": {
@@ -52,7 +52,7 @@ export type GlossaryDefaultNavigation = {
understand: ["archicratie", "co-viabilite", "tension"],
deepen: ["configuration-et-interdependance", "pensee-complexe", "theorie-de-la-justification"],
compare: ["decisionnisme-souverain", "domination-legale-rationnelle", "agencement-machinique", "democratie-deliberative"],
apply: ["audit-archicratique", "cartographie-des-scenes-manquantes"],
apply: ["journal-de-justification", "scene-depreuve"],
},
doctrine: {
@@ -87,7 +87,7 @@ export type GlossaryDefaultNavigation = {
understand: ["tension", "co-viabilite", "archicration"],
deepen: ["coexistence-ontologique-et-necessite-regulatrice", "formes-de-vie-et-cadres-dhabitabilite", "souverainetes-territoriales-et-interdependances-globales"],
compare: ["regulation-technique-et-legitimation-democratique", "memoire-symbolique-et-instantaneite-computationnelle", "travail-vivant-et-abstraction-de-la-valeur"],
apply: ["scene-depreuve", "audit-archicratique", "cartographie-des-scenes-manquantes"],
apply: ["scene-depreuve", "journal-de-justification", "regime-de-co-viabilite"],
},
figure: {