@micheeeeel/yinyangapp 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/bundle.js +1 -1
  2. package/dist/types/adapters/yasuniCauseAdapter.d.ts +31 -5
  3. package/dist/types/api.d.ts +5 -1
  4. package/dist/types/components/controller/YinYangController.d.ts +63 -679
  5. package/dist/types/components/controller/action-stack/ActionStackController.d.ts +35 -0
  6. package/dist/types/components/controller/action-stack/ActionStackManager.d.ts +9 -0
  7. package/dist/types/components/controller/action-stack/StackFocusController.d.ts +105 -0
  8. package/dist/types/components/controller/actions/ActionProjectionService.d.ts +32 -3
  9. package/dist/types/components/controller/actions/ChildActionMenuController.d.ts +8 -4
  10. package/dist/types/components/controller/actions/CoreEventMenuController.d.ts +13 -13
  11. package/dist/types/components/controller/actions/KeyEventController.d.ts +192 -0
  12. package/dist/types/components/controller/actions/radialItemMenu.d.ts +0 -9
  13. package/dist/types/components/controller/children/ChildrenBuilder.d.ts +95 -0
  14. package/dist/types/components/controller/children/ComponentSwitchCoordinator.d.ts +80 -0
  15. package/dist/types/components/controller/debug/ControllerDebugTools.d.ts +81 -0
  16. package/dist/types/components/controller/force-field/ForceFieldComputationService.d.ts +3 -15
  17. package/dist/types/components/controller/force-field/ForceFieldDetailsPanel.d.ts +120 -66
  18. package/dist/types/components/controller/force-field/ForceFieldDetailsPresenter.d.ts +139 -0
  19. package/dist/types/components/controller/force-field/ForceFieldRenderer.d.ts +0 -8
  20. package/dist/types/components/controller/force-field/IncomingForceFieldService.d.ts +53 -0
  21. package/dist/types/components/controller/force-field/PropagationAnimator.d.ts +56 -0
  22. package/dist/types/components/controller/force-field/edgeIdentity.d.ts +28 -0
  23. package/dist/types/components/controller/force-field/incomingContinuation.d.ts +22 -0
  24. package/dist/types/components/controller/force-field/propagation-viz/PropagationCometPlayer.d.ts +60 -0
  25. package/dist/types/components/controller/force-field/propagation-viz/propagationVizLists.d.ts +51 -0
  26. package/dist/types/components/controller/force-field/propagation-viz/propagationVizModel.d.ts +60 -0
  27. package/dist/types/components/controller/force-field/propagationTree.d.ts +32 -0
  28. package/dist/types/components/controller/force-field/shieldViewModel.d.ts +79 -0
  29. package/dist/types/components/controller/force-field/types.d.ts +37 -10
  30. package/dist/types/components/controller/labels/ComponentTitlePresenter.d.ts +99 -0
  31. package/dist/types/components/controller/navigation/DiagramNavigator.d.ts +64 -0
  32. package/dist/types/components/controller/odd/OddViewManager.d.ts +1 -1
  33. package/dist/types/components/controller/search/SearchPanelSynchronizer.d.ts +9 -0
  34. package/dist/types/components/controller/state/ControllerSession.d.ts +107 -0
  35. package/dist/types/components/controller/state/ControllerUiCallbacks.d.ts +60 -0
  36. package/dist/types/components/controller/state/YinYangControllerState.d.ts +4 -5
  37. package/dist/types/components/controller/types.d.ts +103 -0
  38. package/dist/types/components/controller/utils/actionCatalog.d.ts +15 -0
  39. package/dist/types/components/controller/utils/forceFieldPresentation.d.ts +14 -8
  40. package/dist/types/components/search/GlobalSearchController.d.ts +68 -9
  41. package/dist/types/components/view/BorderDrawer.d.ts +5 -0
  42. package/dist/types/components/workspace/workspaceTemplate.d.ts +1 -1
  43. package/dist/types/config/propagationCometConfig.d.ts +9 -36
  44. package/dist/types/config/propagationCometVizConfig.d.ts +34 -0
  45. package/dist/types/data/activeDiagram.d.ts +4 -6
  46. package/dist/types/data/adverse-action-planner.d.ts +22 -0
  47. package/dist/types/data/catalogue-coverage.d.ts +26 -0
  48. package/dist/types/data/combo-engine.d.ts +76 -21
  49. package/dist/types/data/contacts/buildContactSphere.d.ts +23 -4
  50. package/dist/types/data/contacts/index.d.ts +6 -3
  51. package/dist/types/data/propagation-graph.d.ts +16 -0
  52. package/dist/types/data/stability-shield.d.ts +21 -0
  53. package/dist/types/data/yasuni_actions.d.ts +38 -5
  54. package/dist/types/data/yasuni_cause.d.ts +7 -0
  55. package/dist/types/data/yasuni_key_events.d.ts +3 -2
  56. package/dist/types/interfaces/IPropagationGraph.d.ts +39 -0
  57. package/dist/types/interfaces/IYinYangController.d.ts +2 -2
  58. package/dist/types/utils/actionPropagation.d.ts +104 -32
  59. package/dist/types/utils/adverseMode.d.ts +14 -0
  60. package/package.json +4 -2
  61. package/dist/types/components/controller/utils/forceFieldMetadata.d.ts +0 -4
  62. package/dist/types/data/yasuni_graph.d.ts +0 -22
  63. package/dist/types/data/yasuni_propagation_layers.d.ts +0 -3
  64. package/dist/types/interfaces/ICauseGraph.d.ts +0 -9
  65. package/dist/types/interfaces/IPropagationLayers.d.ts +0 -27
  66. package/dist/types/utils/causeGraph.d.ts +0 -6
@@ -1,41 +1,14 @@
1
+ import type { PropagationCometVizConfig } from "./propagationCometVizConfig";
1
2
  /**
2
- * Réglages (mutables, panneau Debug « Comète de propagation ») de l'animation
3
- * de propagation : une comète qui parcourt les champs de force de la source
4
- * jusqu'aux feuilles, avec une queue fondue, un halo doux et des anneaux
5
- * discrets à chaque satellite atteint. Jouée en boucle sur l'action en focus
6
- * (YinYangController.flashSourcePropagationTree) et au clic sur une ligne du
7
- * panneau (flashChildCuttings). Lue à chaque frame : un changement de valeur
8
- * s'applique à la passe en cours.
3
+ * Réglages (mutables, panneau Debug « Comète de l'action en focus ») de la
4
+ * comète rejouée en boucle sur l'action en focus (FocusPropagationLoop).
5
+ * Même lecteur et mêmes trajets que la comète des listes Source / Bilan
6
+ * (PropagationCometPlayer, propagationVizModel) ; seuls le rythme et
7
+ * l'aspect diffèrent : plus calme, et d'une autre couleur pour qu'on ne la
8
+ * confonde pas avec celle d'un clic.
9
9
  */
10
- export declare const propagationCometConfig: {
11
- /** Pause entre deux passes de la boucle de l'action en focus. */
10
+ export declare const propagationCometConfig: PropagationCometVizConfig & {
11
+ /** Pause entre deux passes de la boucle. */
12
12
  loopGapMs: number;
13
- /** Vitesse de croisière de la comète le long du chemin (px/s). Le chemin
14
- * entier est joué d'un seul mouvement (accélération/décélération douces
15
- * aux deux bouts, pas d'arrêt aux étapes intermédiaires). */
16
- speedPxPerSec: number;
17
- /** Durée minimale d'une traversée, pour qu'un chemin très court reste
18
- * lisible. */
19
- minTravelMs: number;
20
- /** Rayon du noyau de la comète (px). */
21
- dotRadius: number;
22
- /** Opacité maximale de l'ensemble (noyau, queue, halo). */
23
- opacity: number;
24
- /** Longueur de la queue, exprimée en temps de trajet (ms) : la queue est
25
- * l'ombre des positions récentes, elle suit donc les virages aux étapes. */
26
- tailMs: number;
27
- /** Épaisseur de la queue à sa base (px), décroissante vers la pointe. */
28
- tailWidth: number;
29
- /** Intensité du halo flouté et du glow (0 = aucun, 1 = nominal). */
30
- glow: number;
31
- /** Fondu d'apparition au départ et d'extinction à l'arrivée (ms). */
32
- fadeMs: number;
33
- /** Opacité de départ des anneaux à chaque satellite atteint (0 = aucun). */
34
- ringOpacity: number;
35
- /** true : la comète prend la couleur de l'action (item de la pile) ; false :
36
- * couleur fixe ci-dessous. */
37
- useItemColor: boolean;
38
- /** Couleur fixe (et couleur de repli quand aucune action n'est identifiable). */
39
- color: string;
40
13
  };
41
14
  export type PropagationCometConfig = typeof propagationCometConfig;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Réglages (mutables, panneau Debug « Comète des listes Source / Bilan ») de
3
+ * la comète jouée au clic sur une ligne ou un en-tête de liste des cartes
4
+ * Source et Bilan (PROP-VIZ-01, PropagationCometPlayer). Le rythme (vitesse,
5
+ * durée minimale d'un saut, rafale) est lu au lancement ; l'aspect à chaque
6
+ * frame. Indépendants des réglages de la boucle de l'action en focus
7
+ * (propagationCometConfig.ts).
8
+ */
9
+ export declare const propagationCometVizConfig: {
10
+ /** Vitesse de la tête le long des sauts (px/s), constante : les branches
11
+ * issues d'un même embranchement repartent ensemble. */
12
+ speedPxPerSec: number;
13
+ /** Durée minimale d'un saut, pour qu'un saut très court reste visible. */
14
+ minHopMs: number;
15
+ /** Intervalle entre deux départs d'une rafale (clic sur l'en-tête). */
16
+ burstGapMs: number;
17
+ /** Rayon du noyau (px). */
18
+ dotRadius: number;
19
+ /** Longueur de la queue, en temps de trajet (ms). */
20
+ tailMs: number;
21
+ /** Épaisseur de la queue à sa base (px). */
22
+ tailWidth: number;
23
+ /** Intensité du halo (0 = aucun). */
24
+ glow: number;
25
+ /** Extinction de la tête à l'arrivée sur le dernier satellite (ms). */
26
+ fadeMs: number;
27
+ /** Opacité des anneaux à chaque satellite atteint (0 = aucun). */
28
+ ringOpacity: number;
29
+ /** true : couleur de l'action du bloc (item de la pile) quand elle existe ;
30
+ * false : couleur fixe ci-dessous. */
31
+ useBlockColor: boolean;
32
+ color: string;
33
+ };
34
+ export type PropagationCometVizConfig = typeof propagationCometVizConfig;
@@ -1,8 +1,7 @@
1
1
  import { type Composante, type Sphere } from "./yasuni_cause";
2
2
  import { type ActionDefinition } from "./yasuni_actions";
3
3
  import { type KeyEventDefinition } from "./yasuni_key_events";
4
- import type { CauseGraph } from "../interfaces/ICauseGraph";
5
- import type { PropagationLayersConfig } from "../interfaces/IPropagationLayers";
4
+ import type { CompiledPropagationGraph } from "../interfaces/IPropagationGraph";
6
5
  export declare const YASUNI_DIAGRAM_ID = "yasuni";
7
6
  /** Paramètre d'URL qui choisit le diagramme dans la page standalone. */
8
7
  export declare const DIAGRAM_URL_PARAM = "diagram";
@@ -19,8 +18,8 @@ export interface DiagramData {
19
18
  /** Événements Clés ET adverses, par id. */
20
19
  keyEventMap: Map<string, KeyEventDefinition>;
21
20
  adverseKeyEvents: KeyEventDefinition[];
22
- interconnectionGraph: CauseGraph;
23
- propagationLayers: PropagationLayersConfig;
21
+ /** Graphe unifié de propagation, compilé depuis les satellites. */
22
+ propagationGraph: CompiledPropagationGraph;
24
23
  }
25
24
  export interface DiagramOption {
26
25
  id: string;
@@ -56,5 +55,4 @@ export declare const activeActions: ActionDefinition[];
56
55
  export declare const activeKeyEvents: KeyEventDefinition[];
57
56
  export declare const activeKeyEventMap: Map<string, KeyEventDefinition>;
58
57
  export declare const activeAdverseKeyEvents: KeyEventDefinition[];
59
- export declare const activeInterconnectionGraph: CauseGraph;
60
- export declare const activePropagationLayers: PropagationLayersConfig;
58
+ export declare const activePropagationGraph: CompiledPropagationGraph;
@@ -7,6 +7,16 @@ import type { ComboSlot } from "./yasuni_actions";
7
7
  * `{ id, delayedEffect: keyEvent }` (elle porte directement
8
8
  * targetedActionIds/withinNextN).
9
9
  */
10
+ /** Satellite éligible à une menace — la définition de catalogue d'une
11
+ * menace générique (adv_gen_*) en déclare plusieurs, une menace spécifique
12
+ * (adv_spec_*) un seul ; l'instance insérée n'en garde toujours qu'un. */
13
+ export interface AdverseTarget {
14
+ componentId: string;
15
+ oddId: string;
16
+ cuttingIndex: number;
17
+ }
18
+ /** Identifiant stable d'un satellite cible : composante::odd::index. */
19
+ export declare function adverseTargetId(target: AdverseTarget): string;
10
20
  export interface AdverseCandidate {
11
21
  id: string;
12
22
  combos?: ComboSlot[];
@@ -14,6 +24,11 @@ export interface AdverseCandidate {
14
24
  targetedActionIds: string[];
15
25
  withinNextN?: number;
16
26
  };
27
+ /** Satellites sur lesquels cette menace peut être insérée. Absent pour un
28
+ * Événement adverse (pas de satellite). Une action adverse SANS cible
29
+ * éligible (liste vide) n'est jamais sélectionnée : elle ne pourrait
30
+ * produire aucun delta direct. */
31
+ eligibleTargets?: AdverseTarget[];
17
32
  }
18
33
  export interface PlannerStackItem {
19
34
  actionId: string;
@@ -24,6 +39,13 @@ export interface AdversePlacement {
24
39
  /** Slot d'insertion au moment où cette insertion est appliquée (les
25
40
  * précédentes du plan étant déjà faites) — pas un slot final. */
26
41
  slotIndex: number;
42
+ /** Cible résolue, choisie parmi `eligibleTargets` au moment de
43
+ * l'insertion (tirage déterministe via rng) — une seule par instance,
44
+ * donc un seul delta direct. Absente pour un Événement adverse. */
45
+ target?: AdverseTarget;
46
+ /** `adverseTargetId(target)` — stocké explicitement pour la
47
+ * journalisation et les tests. */
48
+ targetSatelliteId?: string;
27
49
  }
28
50
  export interface PlanAdverseInsertionsParams {
29
51
  /** Items adverses disponibles (pas encore dans la pile). */
@@ -0,0 +1,26 @@
1
+ import type { ActionDefinition } from "./yasuni_actions";
2
+ export interface SatelliteCoverage {
3
+ componentId: string;
4
+ componentName: string;
5
+ oddId: string;
6
+ cuttingId: number;
7
+ name: string;
8
+ protective: string[];
9
+ adverse: string[];
10
+ unknown: string[];
11
+ }
12
+ /** Fenêtres temporelles admises (bandes normalisées, voir ComboCondition). */
13
+ export declare const ALLOWED_WINDOWS: readonly [4, 5, 6, 8, 9, 10, 12, 13, 14];
14
+ export declare function buildCoverageMatrix(): SatelliteCoverage[];
15
+ export declare function actionUsage(): Map<string, string[]>;
16
+ /**
17
+ * Toutes les violations du catalogue, sous forme de messages lisibles —
18
+ * vide si la configuration est acceptable. Reprend les contrôles de
19
+ * démarrage de main.ts et y ajoute les règles de l'audit : pas de
20
+ * satellite orphelin (ni action protectrice ni menace directe), une relation causale par interprétation, aucun
21
+ * combo réciproque, fenêtres normalisées, identifiants de combo uniques.
22
+ */
23
+ export declare function catalogueViolations(): string[];
24
+ /** Rendu texte de la matrice, une ligne par satellite. */
25
+ export declare function renderCoverageMatrix(): string;
26
+ export declare function protectiveActions(): ActionDefinition[];
@@ -1,4 +1,4 @@
1
- import type { ActionDefinition } from "./yasuni_actions";
1
+ import type { ActionDefinition, ComboEffect } from "./yasuni_actions";
2
2
  /**
3
3
  * Intervalles du multiplicateur combo.
4
4
  *
@@ -7,22 +7,35 @@ import type { ActionDefinition } from "./yasuni_actions";
7
7
  *
8
8
  * m = plancher + (plafond − plancher) × prereqAvgRatio
9
9
  *
10
- * Les deux types partagent la même largeur d'intervalle (1) et se touchent en
11
- * ×1, le point neutre "rien de spécial ne se passe" :
10
+ * Tous les intervalles se touchent en ×1, le point neutre "rien de spécial
11
+ * ne se passe", et chaque famille a sa propre temporalité de jeu :
12
12
  *
13
- * - bonus [1, 2] → m = 1 + avgRatio
14
- * Les requires sont des DÉCLENCHEURS. Aucun joué → ×1 (neutre, pas de
15
- * malus) ; tous parfaits et bien placés → ×2.
16
- * - dangereux [0, 1] → m = avgRatio
13
+ * - preparation [1, 2] → m = 1 + avgRatio
14
+ * Les requires sont des DÉCLENCHEURS. Investir tôt pour ouvrir une
15
+ * suite plus forte. Jamais éligible aux chaînes non plafonnées.
16
+ * - exploitation [1, 2] → m = 1 + avgRatio
17
+ * Choisir le bon moment pour encaisser la valeur accumulée. Seule
18
+ * famille pouvant recevoir une performance chaînée supérieure à 1
19
+ * (slots marqués uncappedEligible) : m n'a alors plus de plafond.
20
+ * - securisation [0, 1] → m = avgRatio
17
21
  * Les requires sont des PROTECTEURS et le risque est permanent
18
22
  * (triggered = true en continu). Protection parfaite → ×1 (risque
19
23
  * annulé) ; aucune protection → ×0 (l'action ne rapporte plus rien).
24
+ * Avec le réglage dédié, une surperformance des protecteurs peut
25
+ * produire un léger dividende, plafonné à ×1,25.
26
+ * - stabilisation → m = 1, toujours
27
+ * Les requires sont des DÉCLENCHEURS mais le slot ne multiplie rien :
28
+ * déclenché, il crée un BOUCLIER de stabilité persistant sur le
29
+ * satellite ciblé (voir stability-shield.ts), appliqué après la
30
+ * propagation aux résolutions négatives ultérieures.
20
31
  *
21
- * Largeurs égales de part et d'autre : un bonus et un risque de qualité égale
22
- * s'annulent exactement dans composeEffectiveDelta, ce qui rend l'arbitrage
23
- * lisible sans avoir à connaître un barème. Le multiplicateur affiché EST
24
- * l'avgRatio (au décalage de plancher près) — aucune traduction mentale.
32
+ * Le multiplicateur affiché reste une lecture directe de l'avgRatio (au
33
+ * plancher de la famille près) ; composeEffectiveDelta
34
+ * additionne ensuite les écarts à 1 de chaque slot.
25
35
  */
36
+ /** Plafond du multiplicateur d'une sécurisation dont les protecteurs
37
+ * surperforment (réglage dangerousComboCanBecomeBonus actif). */
38
+ export declare const SECURISATION_OVERPERFORMANCE_CAP = 1.25;
26
39
  /** Détail de la contribution d'un prérequis au multiplicateur combo. */
27
40
  export interface PrereqBreakdown {
28
41
  id: string;
@@ -35,31 +48,60 @@ export interface PrereqBreakdown {
35
48
  * (ratio/positional = 0 par convention, sans signification réelle) d'un
36
49
  * prérequis réellement joué mais sous-performant. */
37
50
  played: boolean;
51
+ /** Protecteur d'une sécurisation SUPPOSÉ joué (mode RECHERCHE, voir
52
+ * EvaluateComboOptions.assumeSecurisationProtected) : ratio, position et
53
+ * facteur valent 1 par convention, sans que l'action ait été jouée. */
54
+ assumed?: boolean;
38
55
  }
39
56
  /** Réglages "Combos" du panneau de contrôle — voir YinYangControllerState.combos.
40
57
  * Bornés (false) par défaut : comportement actuel. */
41
58
  export interface ComboEngineSettings {
42
- /** Lève le plafond à 1 sur le ratio des prérequis DÉCLENCHEURS (non
43
- * dangereux), autorisant une cascade de combos à dépasser ×2. */
59
+ /** Lève le plafond à 1 sur le ratio des prérequis DÉCLENCHEURS — mais
60
+ * uniquement pour les slots `exploitation` explicitement marqués
61
+ * `uncappedEligible` : ce sont les seules chaînes autorisées à dépasser
62
+ * ×2. Les préparations et les stabilisations restent maîtrisées. */
44
63
  uncappedChainedPerformance?: boolean;
45
- /** Lève le plafond à 1 sur le ratio des prérequis PROTECTEURS d'un combo
46
- * dangereux, permettant à m = avgRatio de dépasser ×1. */
64
+ /** Lève le plafond à 1 sur le ratio des PROTECTEURS d'une sécurisation,
65
+ * permettant à m = avgRatio de dépasser ×1 — jusqu'à
66
+ * SECURISATION_OVERPERFORMANCE_CAP. */
47
67
  dangerousComboCanBecomeBonus?: boolean;
48
68
  }
69
+ /** Options d'évaluation hors réglages du panneau de contrôle. */
70
+ export interface EvaluateComboOptions {
71
+ /** Mode RECHERCHE : l'action est montrée hors pile, sans historique. Une
72
+ * sécurisation y serait toujours à ×0 (aucun protecteur joué) et
73
+ * masquerait toute propagation ; on suppose donc ses protecteurs joués
74
+ * à leur nominal (m = 1, risque annulé). Les autres familles restent
75
+ * évaluées sur l'historique réel. */
76
+ assumeSecurisationProtected?: boolean;
77
+ }
49
78
  export interface ComboResult {
50
79
  triggered: boolean;
51
80
  name?: string;
52
81
  comboId?: string;
53
82
  description?: string;
54
- type?: string;
83
+ type?: ComboEffect["type"];
55
84
  effectiveDelta: number;
56
85
  baseDelta: number;
57
86
  deltaMultiplier: number;
58
87
  maxDeltaMultiplier: number;
88
+ /** Exploitation uncappedEligible avec le réglage uncappedChainedPerformance
89
+ * actif : la performance chaînée des déclencheurs n'est plus plafonnée à 1,
90
+ * m peut dépasser maxDeltaMultiplier — qui n'est alors plus un plafond. */
91
+ uncapped?: boolean;
59
92
  prereqAvgRatio?: number;
60
93
  prereqBreakdowns?: PrereqBreakdown[];
61
94
  requires?: string[];
62
95
  withinLastN?: number;
96
+ /** Stabilisation déclenchée : points de bouclier créés sur le satellite
97
+ * ciblé, actifs jusqu'à la fin de la mission (voir stability-shield.ts). */
98
+ shield?: number;
99
+ /** Sécurisation évaluée avec ses protecteurs supposés joués
100
+ * (EvaluateComboOptions.assumeSecurisationProtected). */
101
+ assumedProtected?: boolean;
102
+ /** Recopie de ComboEffect.backfire : ce slot autorise un retournement
103
+ * négatif du multiplicateur composé (voir composeEffectiveDelta). */
104
+ backfire?: boolean;
63
105
  }
64
106
  /**
65
107
  * Évalue tous les slots combo d'une action et retourne ceux qui sont déclenchés.
@@ -70,23 +112,36 @@ export interface ComboResult {
70
112
  * @param prereqRatioMap (optionnel) actionId → ratio de performance (actualDelta / baseDelta,
71
113
  * clampé dans [0, 1]). Si fourni, le multiplicateur est pondéré par la
72
114
  * performance réelle des prérequis :
73
- * effectiveDm = (dangereux ? 0 : 1) + avg(ratio × Beta(t))
115
+ * effectiveDm = plancher + avg(ratio × Beta(t))
74
116
  * où t est la position normalisée du prérequis dans la fenêtre.
75
117
  * @returns Tableau de ComboResult pour chaque slot (vide si aucun combo défini)
76
118
  */
77
- export declare function evaluateCombo(action: ActionDefinition, playedHistory: string[], prereqRatioMap?: Map<string, number>, settings?: ComboEngineSettings): ComboResult[];
119
+ export declare function evaluateCombo(action: ActionDefinition, playedHistory: string[], prereqRatioMap?: Map<string, number>, settings?: ComboEngineSettings, options?: EvaluateComboOptions): ComboResult[];
78
120
  /**
79
121
  * Compose le delta effectif à partir de plusieurs résultats combo (formule additive centrée).
80
122
  * Chaque multiplicateur exprime un écart par rapport à 1 (neutre).
81
123
  *
82
- * Formule : baseDelta × (Σ multiplicateurs − (n − 1))
124
+ * Formule : baseDelta × (1 + Σ (mᵢ − 1))
83
125
  *
84
126
  * Exemples :
85
127
  * - 1 combo ×1.4 → baseDelta × 1.4
86
- * - 2 combos ×1.4 + ×-0.5 → baseDelta × (1.4 + (−0.5)) = baseDelta × 0.9
87
- * - aucun combo → baseDelta × 1 = baseDelta
128
+ * - 2 combos ×1.4 + ×0.5 → baseDelta × (1 + 0.4 − 0.5) = baseDelta × 0.9
129
+ * - bonus parfait ×2 + sécurisation sans protection ×0 → baseDelta × 1
130
+ * - aucun combo → baseDelta × 1 = baseDelta
131
+ *
132
+ * Le multiplicateur composé est borné à 0 : une convergence de sécurisations
133
+ * faibles ne transforme jamais silencieusement une action protectrice en
134
+ * menace. Seul un slot déclaré `backfire: true` (annoncé au joueur comme un
135
+ * effet pervers possible) autorise un retournement négatif.
88
136
  */
89
137
  export declare function composeEffectiveDelta(baseDelta: number, results: ComboResult[]): number;
138
+ /**
139
+ * Bouclier de stabilité créé par une action à partir de ses résultats combo :
140
+ * le plus fort de ses slots de stabilisation déclenchés, 0 sinon. Un seul
141
+ * bouclier par satellite — c'est la projection qui arbitre ensuite entre
142
+ * plusieurs actions ciblant le même satellite (voir stability-shield.ts).
143
+ */
144
+ export declare function stabilityShieldFromResults(results: ComboResult[] | undefined): number;
90
145
  /**
91
146
  * Retourne true si l'action donnée est requise par au moins
92
147
  * une autre action dans le catalogue.
@@ -6,22 +6,41 @@ export interface ContactSatelliteValue {
6
6
  /** Prédominance du trait dans le profil, entier 0–10. */
7
7
  weight: number;
8
8
  }
9
- export interface ContactProfile {
9
+ /**
10
+ * Profil d'un contact tel que l'APPLICATION HÔTE le fournit (yvy-frontend le
11
+ * lit sur l'API de yvy-backend, seule source des profils) : la lib n'y
12
+ * ajoute que la grille universelle. Ni rôle ni organisme : le texte présenté
13
+ * sous le nom est `description`, composé par l'hôte.
14
+ */
15
+ export interface ContactProfileData {
10
16
  /** Identifiant stable, utilisé par le frontend pour sélectionner le graphe. */
11
17
  id: string;
12
18
  name: string;
13
- role: string;
14
- organisation: string;
15
19
  /** Profil sans identité/biographie définitive : calibration à revoir. */
16
20
  provisional?: boolean;
21
+ /** Présentation du contact (titre au repos, panneau de détails). */
17
22
  description?: string;
23
+ /** Une valeur par satellite de la grille universelle, ni plus ni moins. */
18
24
  values: Record<SatelliteKey, ContactSatelliteValue>;
19
25
  }
26
+ /** Profil EMBARQUÉ (fixtures `profiles/<id>.ts`, page standalone et
27
+ * `getContactCause` dépréciée) : identité complète de la calibration. */
28
+ export interface ContactProfile extends ContactProfileData {
29
+ role: string;
30
+ organisation: string;
31
+ }
32
+ /**
33
+ * Vérifie un profil reçu de l'hôte AVANT de construire sa sphère : une clé
34
+ * de satellite manquante ou inconnue, un score ou un poids non fini ou hors
35
+ * bornes lèvent une erreur qui nomme le contact et la clé — jamais de valeur
36
+ * par défaut silencieuse.
37
+ */
38
+ export declare function validateContactProfile(profile: ContactProfileData): void;
20
39
  /**
21
40
  * Le moteur lit `score` comme une tension (affichage = (1 − score) × 100 %) :
22
41
  * un satellite de qualité 72 % est donc stocké 0.28.
23
42
  */
24
43
  export declare function qualityPercentToTension(percent: number): number;
25
- export declare function buildContactSphere(profile: ContactProfile): Sphere;
44
+ export declare function buildContactSphere(profile: ContactProfileData): Sphere;
26
45
  /** Valeurs identiques pour les 38 satellites — gabarit de profil non calibré. */
27
46
  export declare function uniformContactValues(score: number, weight: number): Record<SatelliteKey, ContactSatelliteValue>;
@@ -1,11 +1,14 @@
1
1
  import type { Sphere } from "../yasuni_cause";
2
- import { type ContactProfile } from "./buildContactSphere";
2
+ import { type ContactProfile, type ContactProfileData } from "./buildContactSphere";
3
3
  export declare const contactProfiles: readonly ContactProfile[];
4
4
  export declare const CONTACT_IDS: readonly string[];
5
5
  export declare function getContactProfile(contactId: string): ContactProfile | undefined;
6
+ /** Le profil embarqué `contactId` au format injectable, présenté comme
7
+ * avant 2.6.0 (« rôle — organisme ») ; lève une erreur si l'id est inconnu. */
8
+ export declare function getEmbeddedContactProfileData(contactId: string): ContactProfileData;
6
9
  /** Sphere fraîchement construite du contact ; lève une erreur si l'id est inconnu. */
7
10
  export declare function getContactSphere(contactId: string): Sphere;
8
- export { buildContactSphere, qualityPercentToTension } from "./buildContactSphere";
9
- export type { ContactProfile, ContactSatelliteValue } from "./buildContactSphere";
11
+ export { buildContactSphere, qualityPercentToTension, validateContactProfile, } from "./buildContactSphere";
12
+ export type { ContactProfile, ContactProfileData, ContactSatelliteValue, } from "./buildContactSphere";
10
13
  export { UNIVERSAL_FACETS, CONTACT_CATEGORIES } from "./universalFacets";
11
14
  export type { SatelliteKey, ContactFacetId, ContactCategoryId } from "./universalFacets";
@@ -0,0 +1,16 @@
1
+ import { type CompiledEdge, type CompiledPropagationGraph, type PropagationGraphDiagnostic, type SatelliteKey } from "../interfaces/IPropagationGraph";
2
+ import { type Composante } from "./yasuni_cause";
3
+ /** Gain maximal d'un saut hors poids : absorption 1,2 × gap 1,2
4
+ * (absorptionMultiplier / gapMultiplier de utils/actionPropagation.ts). */
5
+ export declare const MAX_HOP_GAIN = 1.44;
6
+ /** Cycles élémentaires du graphe (sources ordonnées, chaque cycle énuméré
7
+ * une seule fois depuis son plus petit nœud). Taille du catalogue : quelques
8
+ * dizaines de satellites, énumération directe. Utilisé par V7 et par
9
+ * l'audit d'équilibrage (scripts/propagation-cycles-audit.ts). */
10
+ export declare function elementaryCycles(outgoing: ReadonlyMap<SatelliteKey, readonly CompiledEdge[]>): CompiledEdge[][];
11
+ export declare function compilePropagationGraph(cause: Composante[]): CompiledPropagationGraph;
12
+ export declare function formatPropagationGraphDiagnostics(diagnostics: readonly PropagationGraphDiagnostic[]): string;
13
+ /** Graphe du catalogue Yasuní. Les diagnostics sont signalés sans bloquer le
14
+ * démarrage : les arêtes en erreur sont déjà exclues ; un test exige zéro
15
+ * diagnostic sur le catalogue. */
16
+ export declare const yasuniPropagationGraph: CompiledPropagationGraph;
@@ -0,0 +1,21 @@
1
+ /** Coefficient de conversion du delta de l'action en points de bouclier. */
2
+ export declare const STABILITY_SHIELD_FACTOR = 0.5;
3
+ /**
4
+ * Valeur du bouclier créé par une stabilisation déclenchée :
5
+ * bouclier = max(1, arrondi(baseDelta × r × 0,5))
6
+ * où r est la performance moyenne des prérequis, plafonnée à 1. Un
7
+ * baseDelta négatif ou nul (action adverse, action sans effet) ne crée
8
+ * jamais de bouclier — une menace ne protège pas.
9
+ */
10
+ export declare function computeStabilityShield(baseDelta: number, prereqAvgRatio: number): number;
11
+ /**
12
+ * Réduction unique d'un total négatif par le bouclier. Un total positif
13
+ * ou nul est rendu tel quel ; un total négatif remonte d'au plus
14
+ * `shield` points, borné à 0 (jamais transformé en bonus).
15
+ */
16
+ export declare function applyStabilityShield(aggregatedDelta: number, shield: number): number;
17
+ /**
18
+ * Un seul bouclier par satellite : le plus fort remplace le précédent, un
19
+ * bouclier plus faible ne dégrade jamais celui déjà en place.
20
+ */
21
+ export declare function mergeStabilityShield(current: number | undefined, incoming: number): number;
@@ -1,18 +1,51 @@
1
1
  export interface ComboCondition {
2
2
  requires?: string[];
3
+ /**
4
+ * Fenêtre temporelle (undefined = session entière). Bandes normalisées :
5
+ * 4 à 6 → enchaînement opérationnel immédiat ;
6
+ * 8 à 10 → préparation tactique ou institutionnelle ;
7
+ * 12 à 14 → transformation structurelle longue, réservée aux chaînes majeures.
8
+ */
3
9
  withinLastN?: number;
4
10
  }
11
+ /**
12
+ * Une relation causale = une seule interprétation. Si le prérequis
13
+ * conditionne la réussite de l'action courante, la relation est une
14
+ * `securisation` ; s'il consolide un gain obtenu contre une menace future,
15
+ * c'est une `stabilisation`. Une même relation ne figure jamais dans les
16
+ * deux familles, ni dans les deux sens chronologiques : c'est la seconde
17
+ * action, celle qui complète réellement la séquence, qui porte le combo.
18
+ */
5
19
  export interface ComboEffect {
6
20
  /**
7
- * Seul `type` décide de l'amplitude : "dangereux" parcourt [0, 1] (les
8
- * requires sont des protecteurs), les autres [1, 2] (les requires sont des
9
- * déclencheurs). Le curseur dans l'intervalle est la performance réelle des
10
- * prérequis — voir combo-engine.ts. Pas de palier à choisir au cas par cas.
21
+ * Seul `type` décide de l'amplitude — voir combo-engine.ts :
22
+ * - "preparation" / "exploitation" : [1, 2], les requires sont des
23
+ * déclencheurs ;
24
+ * - "securisation" : [0, 1], les requires sont des protecteurs évalués
25
+ * en continu (l'action conserve de 0 à 100 % de son effet) ;
26
+ * - "stabilisation" : ×1, et un bouclier persistant sur le satellite
27
+ * ciblé (voir stability-shield.ts) à la place du multiplicateur.
28
+ * Le curseur dans l'intervalle est la performance réelle des prérequis.
29
+ * Pas de palier à choisir au cas par cas.
11
30
  */
12
- type: "preparation" | "exploitation" | "stabilisation" | "dangereux";
31
+ type: "preparation" | "exploitation" | "stabilisation" | "securisation";
13
32
  name: string;
14
33
  comboId: string;
15
34
  description: string;
35
+ /**
36
+ * Autorise ce slot à retourner le multiplicateur composé en négatif
37
+ * (effet pervers annoncé au joueur). Par défaut le composé est borné à 0 :
38
+ * une convergence de sécurisations faibles ne transforme jamais une action
39
+ * protectrice en menace.
40
+ */
41
+ backfire?: boolean;
42
+ /**
43
+ * Exploitation explicitement éligible aux performances chaînées non
44
+ * plafonnées (réglage uncappedChainedPerformance) : seuls ces slots
45
+ * transmettent un ratio de prérequis supérieur à 1. Sans effet sur les
46
+ * autres types.
47
+ */
48
+ uncappedEligible?: boolean;
16
49
  }
17
50
  export interface ComboSlot {
18
51
  condition: ComboCondition;
@@ -1,3 +1,4 @@
1
+ import type { PropagationTarget } from "../interfaces/IPropagationGraph";
1
2
  export interface Cutting {
2
3
  id: number;
3
4
  name: string;
@@ -7,6 +8,12 @@ export interface Cutting {
7
8
  /** Présentation succincte du problème ou enjeu représenté par ce cutting. */
8
9
  description?: string;
9
10
  actionIds: string[];
11
+ /**
12
+ * PROP-GRAPH — sorties pondérées de ce satellite vers d'autres satellites,
13
+ * quelle que soit leur portée (même ODD, autre ODD, autre facette). Absent
14
+ * = feuille. Compilées et validées par data/propagation-graph.ts.
15
+ */
16
+ propagationTargets?: PropagationTarget[];
10
17
  }
11
18
  export interface ODD {
12
19
  id: string;
@@ -1,7 +1,8 @@
1
1
  export interface KeyEventEffect {
2
2
  /**
3
- * Bonus ADDITIF de score (en points), au pic de la fenêtre positionnelle —
4
- * réduit vers 0 aux bords, voir positionalBonus (amplifier-engine.ts).
3
+ * Bonus additif nominal au pic de la fenêtre. Pour un slot occupé éligible,
4
+ * pondération positionnelle avec plancher 0,15 ; aucun effet si la cible est
5
+ * absente ou hors fenêtre. Voir positionalBonus (amplifier-engine.ts).
5
6
  * Appliqué dans la direction du delta effectif de l'action (après combos),
6
7
  * jamais sur une action au delta nul. Additif et non multiplicatif : un
7
8
  * ratio réduit par la position devenait fractionnaire et se faisait
@@ -0,0 +1,39 @@
1
+ /** Référence complète d'un satellite du catalogue. */
2
+ export type SatelliteRef = {
3
+ componentId: string;
4
+ oddId: string;
5
+ cuttingId: number;
6
+ };
7
+ /** Clé canonique `componentId::oddId::cuttingId`, seule clé de résolution. */
8
+ export type SatelliteKey = string;
9
+ export declare function satelliteRefKey(ref: SatelliteRef): SatelliteKey;
10
+ /** Sortie pondérée d'un satellite. */
11
+ export interface PropagationTarget {
12
+ /** Destination complète, toujours explicite : pas de composante implicite. */
13
+ to: SatelliteRef;
14
+ /** Influence signée, finie, 0 < |w| ≤ 1. Propre à l'arête, jamais héritée
15
+ * du nœud cible. */
16
+ w: number;
17
+ rationale: string;
18
+ }
19
+ /** Portée dérivée de from/to, pour l'affichage seulement — jamais stockée,
20
+ * jamais lue par le calcul. */
21
+ export type PropagationScope = "local" | "inter-odd" | "inter-facette";
22
+ export type CompiledEdge = PropagationTarget & {
23
+ from: SatelliteRef;
24
+ scope: PropagationScope;
25
+ };
26
+ export type PropagationGraphRule = "V1" | "V2" | "V3" | "V4" | "V5" | "V6" | "V7";
27
+ export type PropagationGraphDiagnostic = {
28
+ severity: "error" | "warning";
29
+ rule: PropagationGraphRule;
30
+ from: SatelliteKey;
31
+ to?: SatelliteKey;
32
+ message: string;
33
+ };
34
+ export type CompiledPropagationGraph = {
35
+ /** Sorties valides par satellite source. Une arête en erreur n'y figure
36
+ * pas : aucune contribution, aucun repli, aucune redirection. */
37
+ outgoing: ReadonlyMap<SatelliteKey, readonly CompiledEdge[]>;
38
+ diagnostics: readonly PropagationGraphDiagnostic[];
39
+ };
@@ -70,12 +70,12 @@ export interface IYinYangController {
70
70
  setChildrenContextLabelsVisible(isVisible: boolean): void;
71
71
  /**
72
72
  * Lève le plafond à 1 sur le ratio de performance des prérequis
73
- * déclencheurs (combos non dangereux), autorisant une cascade de combos à
73
+ * déclencheurs (exploitations éligibles), autorisant une cascade de combos à
74
74
  * dépasser ×2.
75
75
  */
76
76
  setComboUncappedChainedPerformance(isEnabled: boolean): void;
77
77
  /**
78
- * Permet à un combo dangereux de devenir un bonus net : lève le plafond à
78
+ * Permet à un sécurisation de devenir un bonus net : lève le plafond à
79
79
  * 1 sur le ratio de performance des prérequis protecteurs, autorisant
80
80
  * m = avgRatio à dépasser ×1.
81
81
  */