@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,6 +1,5 @@
1
- import { CauseGraph } from "../interfaces/ICauseGraph";
1
+ import { type CompiledPropagationGraph, type PropagationScope, type SatelliteKey } from "../interfaces/IPropagationGraph";
2
2
  import { YinYangComponentNode } from "../interfaces/IYinYangInternalModel";
3
- import { LocalCuttingEdge, PropagationLayersConfig } from "../interfaces/IPropagationLayers";
4
3
  export type Action = {
5
4
  id: string;
6
5
  name: string;
@@ -9,25 +8,39 @@ export type Action = {
9
8
  category: string;
10
9
  cost: number;
11
10
  };
11
+ /**
12
+ * Saut de propagation appliqué : une arrivée sur un satellite, le long d'une
13
+ * arête du graphe unifié (PROP-GRAPH). Toutes les portées — même ODD, autre
14
+ * ODD, autre facette — sont produites par le même parcours.
15
+ */
12
16
  export type PropagatedActionEdge = {
13
- layerType: "inter" | "intra" | "bridge";
17
+ scope: PropagationScope;
14
18
  fromComponentId: string;
15
19
  toComponentId: string;
16
20
  fromOddId: string;
17
21
  toOddId: string;
18
- fromCuttingId?: number;
19
- toCuttingId?: number;
22
+ fromCuttingId: number;
23
+ toCuttingId: number;
20
24
  weight: number;
21
25
  deltaTo: number;
26
+ /** Budget porté par l'arrivée précédente (le delta direct pour une sortie
27
+ * de la cible directe). */
22
28
  baseDelta: number;
23
- propagationFactor: number;
29
+ /** État de la cible directe dans l'instantané : référence du gap (D4). */
24
30
  fromState: number;
25
31
  toState: number;
26
32
  absorption: number;
27
33
  gap: number;
28
34
  rationale?: string;
29
- /** Entry-point cutting carried from the inter-ODD graph edge (used by Phase 6+7). */
30
- targetedCutting?: number;
35
+ /** Index, dans la liste d'arêtes de la résolution, de l'arrivée qui a porté
36
+ * le budget de ce saut. Absent pour une sortie du point de départ. Interne
37
+ * à une résolution : l'affichage travaille sur des identifiants stables
38
+ * (voir controller/force-field/edgeIdentity.ts). */
39
+ parentEdgeIndex?: number;
40
+ /** Chemin causal de l'arrivée : satellites traversés depuis le point de
41
+ * départ de la résolution, satellite d'arrivée compris. Aucun satellite
42
+ * n'y figure deux fois (guard par chemin, PROP-GRAPH-01 révisé). */
43
+ path: readonly SatelliteKey[];
31
44
  };
32
45
  export type ProjectedActionStateDetails = {
33
46
  oddStates: Record<string, number>;
@@ -36,39 +49,98 @@ export type ProjectedActionStateDetails = {
36
49
  type CuttingStateMap = Record<string, Record<number, number>>;
37
50
  export declare function clampState(state: number): number;
38
51
  export declare function tensionFromState(state: number): number;
52
+ /**
53
+ * Seuil, en points d'état (échelle 0-100), sous lequel un saut de
54
+ * propagation n'est ni appliqué ni poursuivi. Il arrête les cascades
55
+ * atténuées (les cycles, eux, sont coupés par le guard par chemin) et ne
56
+ * s'applique jamais au delta direct de l'action.
57
+ *
58
+ * Calibrage sur le catalogue Yasuní (137 résolutions, 372 sauts locaux) :
59
+ * le plus petit premier saut vaut 0,45 (delta 2 × w 0,45 × abs 0,5) et le
60
+ * plus petit deuxième saut 0,21 ; un dixième de point est donc sous tout
61
+ * saut porteur de sens, et sous la résolution d'affichage (états entiers).
62
+ * À ce seuil, 17 % des sauts du catalogue sont coupés, tous des queues de
63
+ * chaîne inférieures à 0,1 point.
64
+ */
65
+ export declare const MIN_PROPAGATED_DELTA = 0.1;
66
+ /**
67
+ * Nombre maximal de sauts évalués par résolution (PROP-GRAPH-01, D9). Le
68
+ * guard par chemin interdit déjà tout cycle : cette borne n'est qu'un filet
69
+ * contre l'explosion combinatoire d'un graphe très branché. Elle interrompt
70
+ * le parcours et le signale (voir PropagationTruncation). Une résolution du
71
+ * catalogue évalue au plus quelques dizaines de sauts.
72
+ */
73
+ export declare const MAX_HOPS_PER_RESOLUTION = 1000;
74
+ /** Vrai si le saut doit être appliqué et poursuivi : |delta| ≥ seuil, même
75
+ * règle pour les deux signes ; un delta nul ou NaN est arrêté. Testé avant
76
+ * tout arrondi d'affichage. */
77
+ export declare function isSignificantPropagatedDelta(delta: number): boolean;
78
+ /**
79
+ * Résolution interrompue par MAX_HOPS_PER_RESOLUTION. Son résultat est alors
80
+ * partiel : les appelants ne doivent pas le présenter comme complet. Émis
81
+ * aussi en console.warn.
82
+ */
83
+ export type PropagationTruncation = {
84
+ /** Satellite de départ du parcours, `componentId::oddId::cuttingId`. */
85
+ sourceKey: string;
86
+ /** Sauts évalués avant l'arrêt (significatifs ou non). */
87
+ hopsProcessed: number;
88
+ /** Sauts encore en file, jamais évalués. */
89
+ hopsPending: number;
90
+ limit: number;
91
+ };
39
92
  export declare function absorptionMultiplier(state: number): number;
40
93
  export declare function gapMultiplier(sourceState: number, targetState: number): number;
41
94
  export declare function absorptionRuleExplanation(state: number): string;
42
95
  export declare function gapRuleExplanation(sourceState: number, targetState: number): string;
43
96
  export declare function deriveOddStates(component: YinYangComponentNode): Record<string, number>;
44
97
  export declare function deriveCuttingStates(component: YinYangComponentNode): CuttingStateMap;
45
- /** Find a node in the intra-ODD flat array by toCuttingId (to start AT it). */
46
- export declare function findNodeInTree(edges: LocalCuttingEdge[], targetId: number): LocalCuttingEdge | null;
47
- export declare function propagateActionInComponent(component: YinYangComponentNode, graph: CauseGraph, sourceOddId: string, delta: number, k: number): PropagatedActionEdge[];
48
98
  export type ActionPropagationDetails = ProjectedActionStateDetails & {
99
+ /** Sauts appliqués, toutes composantes confondues, dans l'ordre du
100
+ * parcours. */
101
+ edges: PropagatedActionEdge[];
102
+ /** Résolution interrompue par la garde technique (vide si complète). */
103
+ truncations: PropagationTruncation[];
104
+ };
105
+ /**
106
+ * Résolution d'une action : delta direct sur sa cible, puis parcours unique
107
+ * du graphe unifié (contrat PROP-GRAPH-01 §6).
108
+ *
109
+ * Les états retournés sont ceux de `component` (la facette jouée) : les
110
+ * arêtes vers d'autres facettes sont parcourues et retournées dans `edges`,
111
+ * mais leurs deltas ne modifient pas l'état de ces facettes (D7).
112
+ * `allComponents` fournit l'état de base des autres facettes ; sans lui, les
113
+ * sauts qui sortent de `component` sont ignorés.
114
+ */
115
+ export declare function computeActionPropagationDetails(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): ActionPropagationDetails;
116
+ /**
117
+ * Arrivée dans `component` d'une arête venue d'une autre composante, déjà
118
+ * calculée par la résolution de l'action (voir computeActionPropagationDetails).
119
+ */
120
+ export type IncomingPropagationEntry = Pick<PropagatedActionEdge, "toOddId" | "deltaTo" | "fromState"> & {
121
+ toCuttingId?: number;
122
+ /** Chemin causal de l'arrivée (voir PropagatedActionEdge.path). Absent : le
123
+ * chemin se réduit au satellite d'arrivée. */
124
+ path?: readonly SatelliteKey[];
125
+ };
126
+ export type IncomingLocalContinuation = {
127
+ /** Sauts dans la composante cible, dans l'ordre du parcours. L'arrivée
128
+ * elle-même n'y figure pas : c'est l'arête entrante. */
49
129
  edges: PropagatedActionEdge[];
130
+ truncations: PropagationTruncation[];
50
131
  };
51
132
  /**
52
- * Canonical single-pass propagation: runs the 8 phases once and returns both
53
- * the collected edges AND the final states. propagateForceFieldActionInComponent
54
- * and projectActionStateDetailsInComponent below are thin wrappers over this —
55
- * having them as two independently-maintained twins previously let the
56
- * state-only path silently drift from the edge path: it never passed
57
- * `allComponents` into the Phase 5 inter-ODD call (so cross-component edges
58
- * were absent from its internal `interEdges` — with real data this happened
59
- * to have no effect on the RETURNED states, since Phase 6/7 already only
60
- * ever applies same-component budgets, but it meant edges/rationale for ~150
61
- * real cross-component synergies were unavailable to any caller built on top
62
- * of the state-only path), and it never threaded the Phase 6/7 "global mode"
63
- * tracking (`targetedOddsWithGlobalMode`) that the edge path has — inert with
64
- * today's graph/layers data (no same-component edge without a targetedCutting
65
- * currently targets an ODD that has its own intra chain) but a silent
66
- * divergence waiting for the next graph data change. One implementation
67
- * makes both classes of bug structurally impossible instead of just
68
- * currently-inert.
133
+ * Suite, dans la composante cible, d'une arête venue d'une autre composante.
134
+ * Même parcours que la résolution complète, repris depuis le satellite
135
+ * d'arrivée avec son delta pour budget, la même référence de gap (`fromState`
136
+ * de l'arrivée, l'état de la cible directe) et l'état de base de la cible ;
137
+ * il s'arrête au bord de la composante, et le guard part du chemin de
138
+ * l'arrivée. Le résultat coïncide donc avec les
139
+ * sauts que la résolution complète produit dans cette composante à la suite
140
+ * de cette arrivée. Le graphe ne dépend pas de la portée : une arête vers un
141
+ * autre ODD de la même composante est poursuivie comme une arête locale.
69
142
  */
70
- export declare function computeActionPropagationDetails(component: YinYangComponentNode, graph: CauseGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, k: number, layers?: PropagationLayersConfig, allComponents?: YinYangComponentNode[]): ActionPropagationDetails;
71
- export declare function propagateForceFieldActionInComponent(component: YinYangComponentNode, graph: CauseGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, k: number, layers?: PropagationLayersConfig, allComponents?: YinYangComponentNode[]): PropagatedActionEdge[];
72
- export declare function projectActionStateDetailsInComponent(component: YinYangComponentNode, graph: CauseGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, k: number, layers?: PropagationLayersConfig, allComponents?: YinYangComponentNode[]): ProjectedActionStateDetails;
73
- export declare function projectActionStatesInComponent(component: YinYangComponentNode, graph: CauseGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, k: number, layers?: PropagationLayersConfig, allComponents?: YinYangComponentNode[]): Record<string, number>;
143
+ export declare function computeIncomingLocalContinuation(component: YinYangComponentNode, entry: IncomingPropagationEntry, graph: CompiledPropagationGraph): IncomingLocalContinuation;
144
+ export declare function propagateForceFieldActionInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): PropagatedActionEdge[];
145
+ export declare function projectActionStateDetailsInComponent(component: YinYangComponentNode, graph: CompiledPropagationGraph, sourceOddId: string, sourceCuttingId: number | undefined, delta: number, allComponents?: readonly YinYangComponentNode[]): ProjectedActionStateDetails;
74
146
  export {};
@@ -0,0 +1,14 @@
1
+ import { type ActionDefinition } from "../data/yasuni_actions";
2
+ import { type KeyEventDefinition } from "../data/yasuni_key_events";
3
+ export declare function isAdverseModeActive(): boolean;
4
+ export declare function setAdverseModeActive(active: boolean): void;
5
+ /** Abonnement aux bascules du mode ; renvoie la fonction de désabonnement. */
6
+ export declare function onAdverseModeChange(listener: (active: boolean) => void): () => void;
7
+ /** L'action a-t-elle une surface (bulle, ligne d'arbre) dans le mode courant ? */
8
+ export declare function isActionShownInMode(action: ActionDefinition): boolean;
9
+ /** L'événement a-t-il une surface (bulle du cœur, ligne d'arbre) dans le
10
+ * mode courant ? */
11
+ export declare function isKeyEventShownInMode(keyEvent: KeyEventDefinition): boolean;
12
+ /** Catalogue des événements montrés dans le mode courant : Événements Clés
13
+ * ordinaires, ou Événements adverses en mode adverse. */
14
+ export declare function keyEventsForMode(): KeyEventDefinition[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micheeeeel/yinyangapp",
3
- "version": "2.5.1",
3
+ "version": "2.6.0",
4
4
  "description": "A program to visualize human activity balance to reach Sustainable Development Objectives",
5
5
  "main": "dist/bundle.js",
6
6
  "types": "dist/types/main.d.ts",
@@ -12,7 +12,9 @@
12
12
  "check:file-lines": "node scripts/check-file-lines.mjs",
13
13
  "ci:guard": "npm run check:file-lines",
14
14
  "analyze": "ANALYZE=true webpack --mode production && tsc -p tsconfig.types.json",
15
- "benchmark:compare": "node benchmarks/compare.js"
15
+ "benchmark:compare": "node benchmarks/compare.js",
16
+ "catalogue:matrix": "npx tsx scripts/catalogue-matrix.ts",
17
+ "propagation:cycles-audit": "npx tsx scripts/propagation-cycles-audit.ts"
16
18
  },
17
19
  "author": "Thomas MICHEL",
18
20
  "license": "UNLICENSED",
@@ -1,4 +0,0 @@
1
- export declare function getInterOddRationale(componentId: string, fromOddId: string, toOddId: string): string | null;
2
- export declare function getLayersInvolved(componentId: string, fromOddId: string, toOddId: string): string[];
3
- export declare function getLocalLayerWeightSummary(componentId: string, fromOddId: string, toOddId: string): string | null;
4
- export declare function getBridgeLayerWeightSummary(componentId: string, fromOddId: string, toOddId: string): string | null;
@@ -1,22 +0,0 @@
1
- import { CauseGraph } from "../interfaces/ICauseGraph";
2
- /**
3
- * Yasuní sparse interconnection matrix W (adjacency list form) — SIGNED.
4
- *
5
- * Node format: componentId::oddId (contextualized SDG node).
6
- * w in [-1..+1], expert-driven bands (absolute value):
7
- * - 0.2 weak
8
- * - 0.4 moderate
9
- * - 0.6 strong
10
- * - 0.8 structuring
11
- *
12
- * Sign convention:
13
- * - w > 0 : A↑ causes B↑ (same direction)
14
- * - w < 0 : A↑ causes B↓ (opposite direction)
15
- *
16
- * NOTE: This file intentionally includes a few additional contextualized nodes (e.g.,
17
- * biodiversity_habitat_fragmentation::ODD_2, indigenous_rights::ODD_3/4/11) to show that
18
- * the node count is not constrained to 17. If your engine builds node state strictly from
19
- * yasuni_cause.ts, add these nodes there (or have the engine lazily init missing nodes).
20
- */
21
- export declare const yasuniInterconnectionGraph: CauseGraph;
22
- export default yasuniInterconnectionGraph;
@@ -1,3 +0,0 @@
1
- import { PropagationLayersConfig } from "../interfaces/IPropagationLayers";
2
- export declare const yasuniPropagationLayers: PropagationLayersConfig;
3
- export default yasuniPropagationLayers;
@@ -1,9 +0,0 @@
1
- export type CauseNodeId = `${string}::${string}`;
2
- export interface CauseEdge {
3
- to: CauseNodeId;
4
- w: number;
5
- rationale?: string;
6
- /** Entry-point cutting in the target ODD's intra chain (Phase 6+7 / incoming-mode entry). */
7
- targetedCutting?: number;
8
- }
9
- export type CauseGraph = Record<CauseNodeId, CauseEdge[]>;
@@ -1,27 +0,0 @@
1
- export interface LocalCuttingEdgeRef {
2
- cuttingId: number;
3
- rationale?: string;
4
- }
5
- export interface LocalCuttingEdge {
6
- toCuttingId: number;
7
- w: number;
8
- rationale?: string;
9
- /** Pointers to next cuttings in the causal chain — resolved from the same flat array. */
10
- targetedCuttings?: LocalCuttingEdgeRef[];
11
- }
12
- export interface BridgeCuttingEdge {
13
- fromComponentId?: string;
14
- fromOddId: string;
15
- fromCuttingId: number;
16
- toComponentId?: string;
17
- toOddId: string;
18
- toCuttingId: number;
19
- w: number;
20
- rationale?: string;
21
- }
22
- export interface PropagationLayersConfig {
23
- intraOddByComponent: Record<string, Record<string, LocalCuttingEdge[]>>;
24
- bridgeEdgesByComponent: Record<string, BridgeCuttingEdge[]>;
25
- localK?: number;
26
- bridgeK?: number;
27
- }
@@ -1,6 +0,0 @@
1
- import { Cause } from "../interfaces/ICauseModel";
2
- import { CauseGraph, CauseNodeId } from "../interfaces/ICauseGraph";
3
- export declare function makeCauseNodeId(componentId: string, oddId: string): CauseNodeId;
4
- export declare function listCauseNodeIds(cause: Cause): CauseNodeId[];
5
- export declare function validateCauseGraph(cause: Cause, graph: CauseGraph): string[];
6
- export declare function countEdges(graph: CauseGraph): number;