@stephen-netu/design-system 0.1.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 (204) hide show
  1. package/README.md +66 -0
  2. package/package.json +130 -0
  3. package/src/b0-app-shell/clarification-overlay/ClarificationOverlay.svelte +221 -0
  4. package/src/b0-app-shell/clarification-overlay/index.ts +1 -0
  5. package/src/b0-app-shell/command-bar/CommandBar.svelte +565 -0
  6. package/src/b0-app-shell/index.ts +14 -0
  7. package/src/base.css +152 -0
  8. package/src/d0-data-viz/BarChart.svelte +236 -0
  9. package/src/d0-data-viz/CheckpointBar.svelte +574 -0
  10. package/src/d0-data-viz/CheckpointPill.svelte +297 -0
  11. package/src/d0-data-viz/MetricCard.svelte +159 -0
  12. package/src/d0-data-viz/SparkLine.svelte +66 -0
  13. package/src/d0-data-viz/StorageMap.svelte +182 -0
  14. package/src/d0-data-viz/Timeline.svelte +188 -0
  15. package/src/d0-data-viz/checkpoint-types.ts +162 -0
  16. package/src/d0-data-viz/d0-tokens.css +32 -0
  17. package/src/d0-data-viz/index.ts +58 -0
  18. package/src/d0-data-viz/storage-map-types.ts +142 -0
  19. package/src/d0-data-viz/theme-integration.ts +134 -0
  20. package/src/d0-data-viz/types.ts +53 -0
  21. package/src/demos/BspSizingInfographic.svelte +386 -0
  22. package/src/demos/BspZoneDemo.svelte +255 -0
  23. package/src/demos/ControlRoomDemo.svelte +570 -0
  24. package/src/demos/NodepadBlocksShowcase.svelte +189 -0
  25. package/src/demos/index.ts +7 -0
  26. package/src/editor/CodeEditor.svelte +188 -0
  27. package/src/editor/FindReplaceDialog.svelte +516 -0
  28. package/src/editor/MarkdownEditor.svelte +660 -0
  29. package/src/editor/index.ts +2 -0
  30. package/src/entity-graph-view/WorldView.svelte +171 -0
  31. package/src/entity-graph-view/index.ts +6 -0
  32. package/src/entity-graph-view/types.ts +364 -0
  33. package/src/epistemic/index.ts +2 -0
  34. package/src/epistemic/types.ts +134 -0
  35. package/src/epistemic/utils.ts +32 -0
  36. package/src/f0-forms/checkbox/Checkbox.svelte +158 -0
  37. package/src/f0-forms/field/FormField.svelte +91 -0
  38. package/src/f0-forms/index.ts +11 -0
  39. package/src/f0-forms/radio/RadioGroup.svelte +192 -0
  40. package/src/f0-forms/search/SearchBar.svelte +99 -0
  41. package/src/f0-forms/select/Select.svelte +198 -0
  42. package/src/f0-forms/textarea/TextArea.svelte +170 -0
  43. package/src/f0-forms/toggle/FormToggle.svelte +147 -0
  44. package/src/f0-forms/validation/validate.ts +47 -0
  45. package/src/fabric/ai/ChatPanel.svelte +648 -0
  46. package/src/fabric/ai/index.ts +11 -0
  47. package/src/fabric/data/index.ts +21 -0
  48. package/src/fabric/feedback/StatusBar.svelte +274 -0
  49. package/src/fabric/feedback/ToastContainer.svelte +122 -0
  50. package/src/fabric/feedback/index.ts +14 -0
  51. package/src/fabric/index.ts +37 -0
  52. package/src/fabric/input/CommandBar.svelte +79 -0
  53. package/src/fabric/input/KeyboardShortcuts.svelte +388 -0
  54. package/src/fabric/input/index.ts +12 -0
  55. package/src/fabric/layout/GlassBox.svelte +193 -0
  56. package/src/fabric/layout/KanbanBoard.svelte +158 -0
  57. package/src/fabric/layout/KanbanCard.svelte +226 -0
  58. package/src/fabric/layout/KanbanColumn.svelte +278 -0
  59. package/src/fabric/layout/index.ts +17 -0
  60. package/src/fabric/navigation/ActivityRail.svelte +271 -0
  61. package/src/fabric/navigation/index.ts +11 -0
  62. package/src/g0-geo/SovereignMap.svelte +149 -0
  63. package/src/g0-geo/index.ts +2 -0
  64. package/src/index.ts +68 -0
  65. package/src/l0-layout/block-writer/BlockConnectionLines.svelte +98 -0
  66. package/src/l0-layout/block-writer/BlockContent.svelte +213 -0
  67. package/src/l0-layout/block-writer/BlockHeader.svelte +230 -0
  68. package/src/l0-layout/block-writer/BlockItem.svelte +177 -0
  69. package/src/l0-layout/block-writer/BlockWriter.svelte +219 -0
  70. package/src/l0-layout/block-writer/block-writer-types.ts +63 -0
  71. package/src/l0-layout/block-writer/index.ts +24 -0
  72. package/src/l0-layout/block-writer/markdown.ts +110 -0
  73. package/src/l0-layout/chat-view/ChatViewLayout.svelte +61 -0
  74. package/src/l0-layout/epistemic/AllayDetailPanel.svelte +113 -0
  75. package/src/l0-layout/epistemic/AssayDetailPanel.svelte +164 -0
  76. package/src/l0-layout/epistemic/AvenueTrace.svelte +253 -0
  77. package/src/l0-layout/epistemic/KnowledgeDetailPanel.svelte +204 -0
  78. package/src/l0-layout/epistemic/ParadigmLens.svelte +170 -0
  79. package/src/l0-layout/epistemic/ProvenanceChain.svelte +164 -0
  80. package/src/l0-layout/epistemic/TrustView.svelte +195 -0
  81. package/src/l0-layout/epistemic/index.ts +7 -0
  82. package/src/l0-layout/grove/AccordCard.svelte +156 -0
  83. package/src/l0-layout/grove/GroveCard.svelte +197 -0
  84. package/src/l0-layout/grove/MemberBadge.svelte +96 -0
  85. package/src/l0-layout/grove/MemberList.svelte +59 -0
  86. package/src/l0-layout/grove/grove-types.ts +29 -0
  87. package/src/l0-layout/grove/index.ts +14 -0
  88. package/src/l0-layout/index.ts +45 -0
  89. package/src/l0-layout/kanban/KanbanBoard.svelte +71 -0
  90. package/src/l0-layout/kanban/KanbanCard.svelte +276 -0
  91. package/src/l0-layout/kanban/KanbanColumn.svelte +198 -0
  92. package/src/l0-layout/kanban/KanbanViewLayout.svelte +61 -0
  93. package/src/l0-layout/workspace/WorkspaceLayout.svelte +93 -0
  94. package/src/n0-node-graph/GraphEditor.svelte +342 -0
  95. package/src/n0-node-graph/GraphHistory.svelte +122 -0
  96. package/src/n0-node-graph/Node.svelte +269 -0
  97. package/src/n0-node-graph/NodeCanvas.svelte +187 -0
  98. package/src/n0-node-graph/NodeEdge.svelte +152 -0
  99. package/src/n0-node-graph/NodePalette.svelte +318 -0
  100. package/src/n0-node-graph/NodePort.svelte +128 -0
  101. package/src/n0-node-graph/index.ts +33 -0
  102. package/src/n0-node-graph/n0-tokens.css +29 -0
  103. package/src/n0-node-graph/node-port-types.ts +19 -0
  104. package/src/n0-node-graph/types.ts +96 -0
  105. package/src/n0-node-graph/validate.test.ts +722 -0
  106. package/src/n0-node-graph/validate.ts +371 -0
  107. package/src/n1-flow-canvas/FlowCanvas.svelte +202 -0
  108. package/src/n1-flow-canvas/graph-state.svelte.ts +95 -0
  109. package/src/n1-flow-canvas/index.ts +21 -0
  110. package/src/n1-flow-canvas/layout.ts +118 -0
  111. package/src/n1-flow-canvas/layout.worker.ts +128 -0
  112. package/src/n1-flow-canvas/types.ts +102 -0
  113. package/src/n1-flow-canvas/utils.ts +146 -0
  114. package/src/n2-manifold-disk/ManifoldDisk.svelte +314 -0
  115. package/src/n2-manifold-disk/index.ts +6 -0
  116. package/src/n2-manifold-disk/poincare.ts +184 -0
  117. package/src/n3-force-graph/ForceGraph.svelte +180 -0
  118. package/src/n3-force-graph/GraphTooltip.svelte +99 -0
  119. package/src/n3-force-graph/animated-edge.ts +107 -0
  120. package/src/n3-force-graph/health-node.ts +128 -0
  121. package/src/n3-force-graph/index.ts +31 -0
  122. package/src/n3-force-graph/types.ts +94 -0
  123. package/src/n4-adaptive-manifold/AdaptiveManifold.svelte +1165 -0
  124. package/src/n4-adaptive-manifold/DetailCard.svelte +212 -0
  125. package/src/n4-adaptive-manifold/SuggestionIndicator.svelte +91 -0
  126. package/src/n4-adaptive-manifold/classifier.ts +139 -0
  127. package/src/n4-adaptive-manifold/index.ts +45 -0
  128. package/src/n4-adaptive-manifold/n4-tokens.css +155 -0
  129. package/src/n4-adaptive-manifold/orchestrator.ts +301 -0
  130. package/src/n4-adaptive-manifold/phase-theme.ts +92 -0
  131. package/src/n4-adaptive-manifold/pinnacle-events.ts +135 -0
  132. package/src/n4-adaptive-manifold/providers/gravitational-provider.ts +191 -0
  133. package/src/n4-adaptive-manifold/providers/manifold-provider.ts +276 -0
  134. package/src/n4-adaptive-manifold/transition.ts +90 -0
  135. package/src/n4-adaptive-manifold/types.ts +313 -0
  136. package/src/p0-primitives/index.ts +6 -0
  137. package/src/p0-primitives/tokens/control-room.css +309 -0
  138. package/src/p0-primitives/tokens/index.ts +6 -0
  139. package/src/p0-primitives/tokens/tokens.css +140 -0
  140. package/src/p0-primitives/tokens/tokens.json +132 -0
  141. package/src/p0-primitives/types/index.ts +123 -0
  142. package/src/p0-primitives/types/plugin-types.ts +74 -0
  143. package/src/p0-primitives/utils/index.ts +39 -0
  144. package/src/platform/hud-protocol.ts +20 -0
  145. package/src/platform/index.ts +3 -0
  146. package/src/s0-state/create-store.ts +84 -0
  147. package/src/s0-state/derived.ts +41 -0
  148. package/src/s0-state/index.ts +6 -0
  149. package/src/showcase/Showcase.svelte +401 -0
  150. package/src/spatial/BspTilingCanvas.svelte +232 -0
  151. package/src/spatial/ForceCanvas.svelte +289 -0
  152. package/src/spatial/LodRenderer.svelte +334 -0
  153. package/src/spatial/SnapZoomCamera.svelte +185 -0
  154. package/src/spatial/ZoneTiler.svelte +311 -0
  155. package/src/spatial/camera-types.ts +45 -0
  156. package/src/spatial/content-proportional-bsp.ts +253 -0
  157. package/src/spatial/force-canvas-types.ts +102 -0
  158. package/src/spatial/index.ts +15 -0
  159. package/src/spatial/lod-types.ts +70 -0
  160. package/src/spatial/zone-tiler-types.ts +177 -0
  161. package/src/stores/vaultStore.svelte +14 -0
  162. package/src/t0-transport/connection.ts +34 -0
  163. package/src/t0-transport/error.ts +37 -0
  164. package/src/t0-transport/events.ts +50 -0
  165. package/src/t0-transport/index.ts +6 -0
  166. package/src/t0-transport/invoke.ts +30 -0
  167. package/src/tauri/index.ts +13 -0
  168. package/src/u0-primitives/allay-gauge/AllayGauge.svelte +90 -0
  169. package/src/u0-primitives/allay-gauge/index.ts +1 -0
  170. package/src/u0-primitives/animated-icon/AnimatedIcon.svelte +273 -0
  171. package/src/u0-primitives/animated-icon/README.md +53 -0
  172. package/src/u0-primitives/animated-icon/index.ts +31 -0
  173. package/src/u0-primitives/assay-badge/AssayBadge.svelte +121 -0
  174. package/src/u0-primitives/assay-badge/AssaySignalBar.svelte +83 -0
  175. package/src/u0-primitives/assay-badge/index.ts +2 -0
  176. package/src/u0-primitives/avatar/Avatar.svelte +177 -0
  177. package/src/u0-primitives/badge/Badge.svelte +149 -0
  178. package/src/u0-primitives/button/Button.svelte +304 -0
  179. package/src/u0-primitives/card/Card.svelte +182 -0
  180. package/src/u0-primitives/dropdown/Dropdown.svelte +305 -0
  181. package/src/u0-primitives/expert-badge/ExpertBadge.svelte +89 -0
  182. package/src/u0-primitives/expert-badge/index.ts +1 -0
  183. package/src/u0-primitives/index.ts +35 -0
  184. package/src/u0-primitives/input/Input.svelte +237 -0
  185. package/src/u0-primitives/modal/Modal.svelte +331 -0
  186. package/src/u0-primitives/modal/index.ts +1 -0
  187. package/src/u0-primitives/spinner/Spinner.svelte +129 -0
  188. package/src/u0-primitives/tabs/Tabs.svelte +225 -0
  189. package/src/u0-primitives/tabs/tabs-types.ts +11 -0
  190. package/src/u0-primitives/toggle/Toggle.svelte +161 -0
  191. package/src/u0-primitives/tooltip/Tooltip.svelte +234 -0
  192. package/src/v0-diagrams/DiagramPanel.svelte +68 -0
  193. package/src/v0-diagrams/MarkmapDiagram.svelte +56 -0
  194. package/src/v0-diagrams/MermaidDiagram.svelte +53 -0
  195. package/src/v0-diagrams/index.ts +4 -0
  196. package/src/v0-diagrams/types.ts +28 -0
  197. package/src/v0-diagrams/v0-tokens.css +6 -0
  198. package/src/vite-env.d.ts +7 -0
  199. package/src/x0-enchanted-blocks/ENCHANTED_BLOCKS_SPEC.md +457 -0
  200. package/src/x0-enchanted-blocks/components/EnchantedBlock.svelte +485 -0
  201. package/src/x0-enchanted-blocks/components/NodepadBlock.svelte +262 -0
  202. package/src/x0-enchanted-blocks/core/block-layout.ts +211 -0
  203. package/src/x0-enchanted-blocks/core/block-types.ts +227 -0
  204. package/src/x0-enchanted-blocks/index.ts +46 -0
@@ -0,0 +1,212 @@
1
+ <script lang="ts">
2
+ import type { ManifoldNode } from './types.js';
3
+
4
+ interface Props {
5
+ node: ManifoldNode;
6
+ pinned: boolean;
7
+ onclose?: () => void;
8
+ }
9
+
10
+ let { node, pinned, onclose }: Props = $props();
11
+ </script>
12
+
13
+ <div
14
+ class="detail-card"
15
+ class:detail-card--pinned={pinned}
16
+ >
17
+ <header class="detail-card__header">
18
+ <span class="detail-card__kind">{node.kind}</span>
19
+ <span class="detail-card__name">{node.label}</span>
20
+ {#if pinned}
21
+ <button class="detail-card__close" onclick={onclose}>&times;</button>
22
+ {/if}
23
+ </header>
24
+
25
+ <div class="detail-card__body">
26
+ {#if node.kind === 'agent'}
27
+ {@render agentBody(node)}
28
+ {:else if node.kind === 'task'}
29
+ {@render taskBody(node)}
30
+ {:else}
31
+ {@render genericBody(node)}
32
+ {/if}
33
+ </div>
34
+ </div>
35
+
36
+ {#snippet agentBody(n: ManifoldNode)}
37
+ {#if n.metadata?.spark_by_axis}
38
+ {@const axes = n.metadata.spark_by_axis as [number, number, number]}
39
+ {@const ROLE_LABELS = ['Epistemic', 'Worker', 'Coordination'] as const}
40
+ {@const dominant = axes[0] > axes[1] && axes[0] > axes[2] ? 0 : axes[1] > axes[2] ? 1 : 2}
41
+ <div class="detail-card__row">
42
+ <span class="detail-card__label">Role</span>
43
+ <span class="detail-card__value">{ROLE_LABELS[dominant]}</span>
44
+ </div>
45
+ <div class="detail-card__row">
46
+ <span class="detail-card__label">Axes (i/j/k)</span>
47
+ <span class="detail-card__value">{axes[0]} / {axes[1]} / {axes[2]}</span>
48
+ </div>
49
+ {/if}
50
+ {#if n.metadata?.spark_remaining != null}
51
+ <div class="detail-card__row">
52
+ <span class="detail-card__label">Spark</span>
53
+ <span class="detail-card__value">{n.metadata.spark_remaining as number}</span>
54
+ </div>
55
+ {/if}
56
+ {#if n.metadata?.current_task}
57
+ <div class="detail-card__row">
58
+ <span class="detail-card__label">Working</span>
59
+ <span class="detail-card__value">{n.metadata.current_task as string}</span>
60
+ </div>
61
+ {/if}
62
+ {#if n.metadata?.loop_phase}
63
+ <div class="detail-card__row">
64
+ <span class="detail-card__label">Phase</span>
65
+ <span class="detail-card__value">{n.metadata.loop_phase as string}</span>
66
+ </div>
67
+ {/if}
68
+ {/snippet}
69
+
70
+ {#snippet taskBody(n: ManifoldNode)}
71
+ {#if n.metadata?.wt_id}
72
+ <div class="detail-card__row">
73
+ <span class="detail-card__label">ID</span>
74
+ <span class="detail-card__value">{n.metadata.wt_id as string}</span>
75
+ </div>
76
+ {/if}
77
+ {#if n.metadata?.flow_phase}
78
+ <div class="detail-card__row">
79
+ <span class="detail-card__label">Flow</span>
80
+ <span class="detail-card__value">{n.metadata.flow_phase as string}</span>
81
+ </div>
82
+ {/if}
83
+ {#if n.metadata?.claiming_agent}
84
+ <div class="detail-card__row">
85
+ <span class="detail-card__label">Agent</span>
86
+ <span class="detail-card__value">{n.metadata.claiming_agent as string}</span>
87
+ </div>
88
+ {/if}
89
+ {#if n.metadata?.priority}
90
+ <div class="detail-card__row">
91
+ <span class="detail-card__label">Priority</span>
92
+ <span class="detail-card__value">{n.metadata.priority as string}</span>
93
+ </div>
94
+ {/if}
95
+ {#if n.metadata?.description}
96
+ <div class="detail-card__description">{n.metadata.description as string}</div>
97
+ {/if}
98
+ {/snippet}
99
+
100
+ {#snippet genericBody(n: ManifoldNode)}
101
+ <div class="detail-card__row">
102
+ <span class="detail-card__label">Status</span>
103
+ <span class="detail-card__value">{n.status}</span>
104
+ </div>
105
+ {/snippet}
106
+
107
+ <style>
108
+ /* Outer shell: molds to content up to a capped height.
109
+ Positioning handled by the wrapper div in AdaptiveManifold. */
110
+ .detail-card {
111
+ width: 220px;
112
+ max-height: min(420px, calc(100% - 40px));
113
+ display: flex;
114
+ flex-direction: column;
115
+ overflow: hidden;
116
+ background: #1e1e1e;
117
+ border: 1px solid rgba(184, 115, 51, 0.3);
118
+ border-radius: var(--radius-md, 6px);
119
+ font-family: var(--font-mono);
120
+ font-size: 11px;
121
+ color: #e8e0d0;
122
+ pointer-events: none;
123
+ z-index: 10;
124
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6);
125
+ }
126
+
127
+ .detail-card--pinned {
128
+ pointer-events: auto;
129
+ border-color: rgba(184, 115, 51, 0.6);
130
+ }
131
+
132
+ /* Pinned header — never scrolls */
133
+ .detail-card__header {
134
+ flex-shrink: 0;
135
+ display: flex;
136
+ align-items: center;
137
+ gap: 6px;
138
+ padding: 6px 8px;
139
+ border-bottom: 1px solid rgba(184, 115, 51, 0.15);
140
+ }
141
+
142
+ .detail-card__kind {
143
+ color: #b87333;
144
+ text-transform: uppercase;
145
+ font-size: 9px;
146
+ letter-spacing: 0.5px;
147
+ }
148
+
149
+ .detail-card__name {
150
+ flex: 1;
151
+ overflow: hidden;
152
+ text-overflow: ellipsis;
153
+ white-space: nowrap;
154
+ }
155
+
156
+ .detail-card__close {
157
+ background: none;
158
+ border: none;
159
+ color: #a09880;
160
+ cursor: pointer;
161
+ font-size: 14px;
162
+ padding: 0 2px;
163
+ line-height: 1;
164
+ }
165
+
166
+ .detail-card__close:hover {
167
+ color: #e8e0d0;
168
+ }
169
+
170
+ /* Scrollable body — grows to fill, scrolls when content overflows the cap */
171
+ .detail-card__body {
172
+ flex: 1;
173
+ min-height: 0;
174
+ overflow-y: auto;
175
+ padding: 6px 8px;
176
+ display: flex;
177
+ flex-direction: column;
178
+ gap: 3px;
179
+ scrollbar-width: thin;
180
+ scrollbar-color: rgba(184, 115, 51, 0.25) transparent;
181
+ }
182
+
183
+ .detail-card__body::-webkit-scrollbar { width: 3px; }
184
+ .detail-card__body::-webkit-scrollbar-thumb { background: rgba(184, 115, 51, 0.25); border-radius: var(--radius-xs, 2px); }
185
+ .detail-card__body::-webkit-scrollbar-track { background: transparent; }
186
+
187
+ .detail-card__row {
188
+ display: flex;
189
+ justify-content: space-between;
190
+ gap: 8px;
191
+ }
192
+
193
+ .detail-card__label {
194
+ color: #a09880;
195
+ flex-shrink: 0;
196
+ }
197
+
198
+ .detail-card__value {
199
+ color: #e8e0d0;
200
+ text-align: right;
201
+ overflow: hidden;
202
+ text-overflow: ellipsis;
203
+ white-space: nowrap;
204
+ }
205
+
206
+ .detail-card__description {
207
+ color: #a09880;
208
+ margin-top: 4px;
209
+ font-size: 10px;
210
+ line-height: 1.4;
211
+ }
212
+ </style>
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ // N4 SuggestionIndicator — Shows layout suggestion badge
3
+ // Renders a small floating pill when the orchestrator has a stable suggestion.
4
+ // Provides Accept / Dismiss / Pin actions per ADR.
5
+
6
+ import type { LayoutAlgorithm, LayoutSuggestion } from './types.js';
7
+
8
+ interface Props {
9
+ suggestion: LayoutSuggestion | null;
10
+ onaccept?: () => void;
11
+ ondismiss?: () => void;
12
+ onpin?: () => void;
13
+ }
14
+
15
+ let { suggestion, onaccept, ondismiss, onpin }: Props = $props();
16
+
17
+ const LABELS: Record<LayoutAlgorithm, string> = {
18
+ gravitational: 'Garden',
19
+ manifold: 'Manifold',
20
+ };
21
+ </script>
22
+
23
+ {#if suggestion && !suggestion.dismissed}
24
+ <div class="n4-suggestion">
25
+ <span class="n4-suggestion__icon">◈</span>
26
+ <span class="n4-suggestion__label">{LABELS[suggestion.algorithm]}</span>
27
+ <span class="n4-suggestion__reason">{suggestion.reason}</span>
28
+ <button class="n4-suggestion__action n4-suggestion__action--accept" onclick={onaccept} title="Switch layout">
29
+
30
+ </button>
31
+ <button class="n4-suggestion__action" onclick={ondismiss} title="Dismiss">
32
+
33
+ </button>
34
+ <button class="n4-suggestion__action" onclick={onpin} title="Pin current layout">
35
+
36
+ </button>
37
+ </div>
38
+ {/if}
39
+
40
+ <style>
41
+ .n4-suggestion {
42
+ display: inline-flex;
43
+ align-items: center;
44
+ gap: 6px;
45
+ padding: var(--n4-suggestion-padding, 6px 10px);
46
+ background: var(--n4-suggestion-bg, color-mix(in srgb, var(--color-accent, #b87333) 8%, var(--color-bg-panel, #222)));
47
+ border: 1px solid var(--n4-suggestion-border, rgba(184, 115, 51, 0.25));
48
+ border-radius: var(--n4-suggestion-radius, 6px);
49
+ font-size: var(--n4-suggestion-font-size, 11px);
50
+ font-family: var(--font-sans, system-ui);
51
+ color: var(--n4-suggestion-text, #a09880);
52
+ white-space: nowrap;
53
+ }
54
+
55
+ .n4-suggestion__icon {
56
+ color: var(--n4-suggestion-accent, #b87333);
57
+ font-size: 13px;
58
+ line-height: 1;
59
+ }
60
+
61
+ .n4-suggestion__label {
62
+ color: var(--n4-suggestion-accent, #b87333);
63
+ font-weight: 600;
64
+ letter-spacing: 0.02em;
65
+ }
66
+
67
+ .n4-suggestion__reason {
68
+ color: var(--n4-suggestion-text, #a09880);
69
+ opacity: 0.75;
70
+ }
71
+
72
+ .n4-suggestion__action {
73
+ background: none;
74
+ border: 1px solid transparent;
75
+ border-radius: var(--radius-sm, 3px);
76
+ cursor: pointer;
77
+ font-size: 11px;
78
+ padding: 1px 4px;
79
+ color: var(--n4-suggestion-text, #a09880);
80
+ transition: color 120ms, border-color 120ms;
81
+ }
82
+
83
+ .n4-suggestion__action:hover {
84
+ color: var(--n4-suggestion-accent, #b87333);
85
+ border-color: var(--n4-suggestion-border, rgba(184, 115, 51, 0.25));
86
+ }
87
+
88
+ .n4-suggestion__action--accept {
89
+ color: var(--n4-suggestion-accent, #b87333);
90
+ }
91
+ </style>
@@ -0,0 +1,139 @@
1
+ // N4 TopologyClassifier — always returns manifold layout.
2
+ // Pure function, no state. Deterministic given same input.
3
+ // S-02: uses Map (ordered) for adjacency, not Set.
4
+
5
+ import type {
6
+ ManifoldSnapshot,
7
+ LayoutAlgorithm,
8
+ ClassificationResult,
9
+ TopologyMetrics,
10
+ } from './types.js';
11
+
12
+ /** Number of consecutive matching classifications before suggesting. */
13
+ export const STABILITY_TICKS = 3;
14
+
15
+ export function classifyTopology(
16
+ snapshot: ManifoldSnapshot,
17
+ ): ClassificationResult {
18
+ // Manifold is the implemented layout algorithm.
19
+ // computeMetrics() is preserved for topology analysis.
20
+ const nodeCount = snapshot.nodes.length;
21
+ const edgeCount = snapshot.edges.length;
22
+ const edgeDensity = nodeCount > 0 ? edgeCount / nodeCount : 0;
23
+
24
+ return {
25
+ recommended: 'manifold',
26
+ confidence: 1.0,
27
+ reason: edgeCount === 0
28
+ ? 'manifold: sparse (no edges, S³ projection only)'
29
+ : `manifold: ${edgeCount} edges, density ${edgeDensity.toFixed(2)}`,
30
+ ranked: [{ algorithm: 'manifold' as LayoutAlgorithm, fitness: 1.0 }],
31
+ metrics: { nodeCount, edgeCount, edgeDensity, maxDepth: 0, rootCount: 0, cycleCount: 0, componentCount: 0, maxClusterSize: 0 },
32
+ };
33
+ }
34
+
35
+ // === Metrics computation (single pass, O(V+E)) ===
36
+
37
+ export function computeMetrics(snapshot: ManifoldSnapshot): TopologyMetrics {
38
+ const nodeCount = snapshot.nodes.length;
39
+ const edgeCount = snapshot.edges.length;
40
+
41
+ if (nodeCount === 0) {
42
+ return { nodeCount: 0, edgeCount: 0, edgeDensity: 0, maxDepth: 0, rootCount: 0, cycleCount: 0, componentCount: 0, maxClusterSize: 0 };
43
+ }
44
+
45
+ // Note: "edgeDensity" here is edges/nodes (avg out-degree), NOT graph density (edges/(n*(n-1)/2)).
46
+ const edgeDensity = nodeCount > 0 ? edgeCount / nodeCount : 0;
47
+
48
+ // Build adjacency (directed) and undirected adjacency
49
+ // S-02: Map preserves insertion order (deterministic)
50
+ const adj = new Map<string, string[]>();
51
+ const uAdj = new Map<string, string[]>();
52
+ const inDegree = new Map<string, number>();
53
+
54
+ for (const n of snapshot.nodes) {
55
+ adj.set(n.id, []);
56
+ uAdj.set(n.id, []);
57
+ inDegree.set(n.id, 0);
58
+ }
59
+ for (const e of snapshot.edges) {
60
+ adj.get(e.source)?.push(e.target);
61
+ uAdj.get(e.source)?.push(e.target);
62
+ uAdj.get(e.target)?.push(e.source);
63
+ inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);
64
+ }
65
+
66
+ // Roots: in-degree 0
67
+ let rootCount = 0;
68
+ for (const [, deg] of inDegree) {
69
+ if (deg === 0) rootCount++;
70
+ }
71
+
72
+ // Cycle detection via DFS (directed)
73
+ const WHITE = 0, GRAY = 1, BLACK = 2;
74
+ const color = new Map<string, number>();
75
+ for (const n of snapshot.nodes) color.set(n.id, WHITE);
76
+ let cycleCount = 0;
77
+
78
+ function dfs(nodeId: string): void {
79
+ color.set(nodeId, GRAY);
80
+ for (const neighbor of adj.get(nodeId) ?? []) {
81
+ const c = color.get(neighbor) ?? WHITE;
82
+ if (c === GRAY) { cycleCount++; }
83
+ else if (c === WHITE) { dfs(neighbor); }
84
+ }
85
+ color.set(nodeId, BLACK);
86
+ }
87
+
88
+ for (const n of snapshot.nodes) {
89
+ if (color.get(n.id) === WHITE) dfs(n.id);
90
+ }
91
+
92
+ // Max depth via BFS from roots (or all nodes if no roots)
93
+ let maxDepth = 0;
94
+ const depthVisited = new Map<string, boolean>();
95
+ const roots = snapshot.nodes.filter(n => (inDegree.get(n.id) ?? 0) === 0);
96
+ const bfsStart = roots.length > 0 ? roots : [snapshot.nodes[0]];
97
+
98
+ for (const root of bfsStart) {
99
+ if (depthVisited.get(root.id)) continue;
100
+ const queue: Array<{ id: string; depth: number }> = [{ id: root.id, depth: 0 }];
101
+ depthVisited.set(root.id, true);
102
+ while (queue.length > 0) {
103
+ const cur = queue.shift()!;
104
+ if (cur.depth > maxDepth) maxDepth = cur.depth;
105
+ for (const neighbor of adj.get(cur.id) ?? []) {
106
+ if (!depthVisited.get(neighbor)) {
107
+ depthVisited.set(neighbor, true);
108
+ queue.push({ id: neighbor, depth: cur.depth + 1 });
109
+ }
110
+ }
111
+ }
112
+ }
113
+
114
+ // Connected components via BFS on undirected graph
115
+ const compVisited = new Map<string, boolean>();
116
+ let componentCount = 0;
117
+ let maxClusterSize = 0;
118
+
119
+ for (const n of snapshot.nodes) {
120
+ if (compVisited.get(n.id)) continue;
121
+ componentCount++;
122
+ let clusterSize = 0;
123
+ const queue = [n.id];
124
+ compVisited.set(n.id, true);
125
+ while (queue.length > 0) {
126
+ const cur = queue.shift()!;
127
+ clusterSize++;
128
+ for (const nb of uAdj.get(cur) ?? []) {
129
+ if (!compVisited.get(nb)) {
130
+ compVisited.set(nb, true);
131
+ queue.push(nb);
132
+ }
133
+ }
134
+ }
135
+ if (clusterSize > maxClusterSize) maxClusterSize = clusterSize;
136
+ }
137
+
138
+ return { nodeCount, edgeCount, edgeDensity, maxDepth, rootCount, cycleCount, componentCount, maxClusterSize };
139
+ }
@@ -0,0 +1,45 @@
1
+ // N4 Adaptive Manifold — Unified topology-aware graph layout layer
2
+ // Gravitational canvas: GravitationalProvider, classifier, orchestrator, transitions
3
+
4
+ export type {
5
+ LayoutAlgorithm,
6
+ NodeStatus,
7
+ ManifoldNode,
8
+ ManifoldEdge,
9
+ ManifoldSnapshot,
10
+ NodeStyleEntry,
11
+ NodeStyleRegistry,
12
+ LayoutPreferences,
13
+ EasingCurve,
14
+ AlgorithmProvider,
15
+ TopologyMetrics,
16
+ ClassificationResult,
17
+ AnimationMomentKind,
18
+ AnimationFrame,
19
+ EasingFn,
20
+ LayoutSuggestion,
21
+ ResolvedThemeColors,
22
+ NodeLayout,
23
+ LayoutResult,
24
+ LoopPhase,
25
+ PinnacleEvent,
26
+ PhaseVisualParams,
27
+ PhaseTheme,
28
+ GravitationalConfig,
29
+ NodeIndicatorState,
30
+ } from './types.js';
31
+
32
+ export { DEFAULT_LAYOUT_PREFERENCES, DEFAULT_GRAVITATIONAL_CONFIG } from './types.js';
33
+
34
+ export { classifyTopology, computeMetrics, STABILITY_TICKS } from './classifier.js';
35
+ export { LayoutOrchestrator } from './orchestrator.js';
36
+ export { TransitionAnimator, EASING_FUNCTIONS } from './transition.js';
37
+
38
+ export { GravitationalProvider } from './providers/gravitational-provider.js';
39
+
40
+ export { default as AdaptiveManifold } from './AdaptiveManifold.svelte';
41
+ export { default as SuggestionIndicator } from './SuggestionIndicator.svelte';
42
+ export { default as DetailCard } from './DetailCard.svelte';
43
+
44
+ export { PinnacleEventInferrer } from './pinnacle-events.js';
45
+ export { resolvePhaseTheme, DEFAULT_PHASE_THEME } from './phase-theme.js';
@@ -0,0 +1,155 @@
1
+ /* N4 Adaptive Manifold — Design Tokens
2
+ * Prefix: --n4-*
3
+ * Consumed by AdaptiveManifold.svelte and SuggestionIndicator.svelte
4
+ */
5
+
6
+ :root {
7
+ /* ── Node rendering ─────────────────────────────────────────────────────── */
8
+ --n4-node-width: 120px;
9
+ --n4-node-height: 28px;
10
+ --n4-node-radius: 4px;
11
+ --n4-node-bg: #222;
12
+ --n4-node-bg-hover: #2a2a2a;
13
+ --n4-node-bg-selected: color-mix(in srgb, var(--color-accent, #b87333) 12%, #222);
14
+ --n4-node-border: rgba(184, 115, 51, 0.15);
15
+ --n4-node-border-hover: rgba(184, 115, 51, 0.35);
16
+ --n4-node-border-selected: var(--color-accent, #b87333);
17
+ --n4-node-text: var(--color-text-primary, #e8e0d0);
18
+ --n4-node-text-muted: var(--color-text-secondary, #a09880);
19
+ --n4-node-id-font: var(--font-mono, 'JetBrains Mono', monospace);
20
+ --n4-node-id-size: 10px;
21
+ --n4-node-label-size: 11px;
22
+ --n4-node-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
23
+ --n4-node-shadow-hover: 0 2px 8px rgba(0, 0, 0, 0.4);
24
+ --n4-node-shadow-selected: 0 0 12px var(--color-accent-glow, rgba(184, 115, 51, 0.2));
25
+
26
+ /* ── Edge rendering ─────────────────────────────────────────────────────── */
27
+ --n4-edge-width: 1.5px;
28
+ --n4-edge-color: rgba(184, 115, 51, 0.25);
29
+ --n4-edge-color-hover: rgba(184, 115, 51, 0.55);
30
+ --n4-edge-color-active: var(--color-accent, #b87333);
31
+ --n4-edge-dash-length: 6px;
32
+ --n4-edge-dash-gap: 3px;
33
+ --n4-edge-arrow-size: 6px;
34
+
35
+ /* ── Canvas ─────────────────────────────────────────────────────────────── */
36
+ --n4-canvas-bg: var(--color-bg-canvas, #1a1a1a);
37
+ --n4-canvas-grid-color: rgba(184, 115, 51, 0.04);
38
+ --n4-canvas-grid-size: 24px;
39
+ --n4-canvas-padding: 40px;
40
+
41
+ /* ── Scatter grid (fallback topology) ───────────────────────────────────── */
42
+ --n4-scatter-gap: 8px;
43
+ --n4-scatter-chip-bg: var(--color-bg-panel, #222);
44
+ --n4-scatter-chip-border: var(--border-default, rgba(184, 115, 51, 0.15));
45
+ --n4-scatter-chip-accent: var(--color-accent, #b87333);
46
+
47
+ /* ── Suggestion indicator ───────────────────────────────────────────────── */
48
+ --n4-suggestion-bg: color-mix(in srgb, var(--color-accent, #b87333) 8%, var(--color-bg-panel, #222));
49
+ --n4-suggestion-border: rgba(184, 115, 51, 0.25);
50
+ --n4-suggestion-text: var(--color-text-secondary, #a09880);
51
+ --n4-suggestion-accent: var(--color-accent, #b87333);
52
+ --n4-suggestion-radius: var(--radius-md, 6px);
53
+ --n4-suggestion-padding: 6px 10px;
54
+ --n4-suggestion-font-size: var(--text-xs, 11px);
55
+
56
+ /* ── Transition ─────────────────────────────────────────────────────────── */
57
+ --n4-transition-duration: 400ms;
58
+ --n4-transition-easing: cubic-bezier(0.4, 0, 0.2, 1);
59
+
60
+ /* ── Node status accents ─────────────────────────────────────────────────── */
61
+ --n4-node-active: var(--color-accent, #b87333);
62
+ --n4-node-idle: var(--color-text-secondary, #a09880);
63
+ --n4-node-blocked: var(--color-status-warning, #f39c12);
64
+ --n4-node-completed: var(--color-text-secondary, #a09880);
65
+ --n4-node-critical: var(--color-status-error, #c0392b);
66
+
67
+ /* ── Kind accents (overridden by consuming apps) ───────────────────────── */
68
+ --n4-kind-task: var(--color-accent, #b87333);
69
+ --n4-kind-agent: var(--color-expert-sovereign, #b87333);
70
+ --n4-kind-signal: var(--color-status-info, #2980b9);
71
+ --n4-kind-capability: var(--color-accent-secondary, #d4a574);
72
+ --n4-kind-intent: var(--color-expert-atelier, #b87333);
73
+ --n4-kind-subtask: color-mix(in srgb, var(--color-accent, #b87333) 60%, transparent);
74
+ --n4-kind-note: var(--color-text-primary, #e8e0d0);
75
+ --n4-kind-concept: var(--color-accent-secondary, #d4a574);
76
+ --n4-kind-claim: var(--color-status-success, #27ae60);
77
+ --n4-kind-grove: color-mix(in srgb, var(--color-accent, #b87333) 75%, #5a7a3a);
78
+ --n4-kind-member: var(--color-text-secondary, #a09880);
79
+ --n4-kind-daemon: var(--color-accent, #b87333);
80
+ --n4-kind-spark: var(--color-status-warning, #f39c12);
81
+
82
+ /* ── Easing curves ─────────────────────────────────────────────────────── */
83
+ --n4-ease-settle: cubic-bezier(0.0, 0.0, 0.2, 1.0);
84
+ --n4-ease-morph: cubic-bezier(0.34, 1.56, 0.64, 1.0);
85
+ --n4-ease-arrive: cubic-bezier(0.22, 1.0, 0.36, 1.0);
86
+ --n4-ease-pulse: linear;
87
+
88
+ /* ── Animation durations ───────────────────────────────────────────────── */
89
+ --n4-morph-duration: 600ms;
90
+ --n4-arrive-duration: 250ms;
91
+ --n4-depart-duration: 200ms;
92
+ --n4-focus-duration: 150ms;
93
+ --n4-pulse-duration: 400ms;
94
+
95
+ /* ── Phase ambient theming ──────────────────────────────────── */
96
+ --n4-phase-seed-background: #1a1a1a;
97
+ --n4-phase-seed-brightness: 0.4;
98
+ --n4-phase-seed-indicator-intensity: 0.3;
99
+ --n4-phase-seed-pulse-speed: 4s;
100
+ --n4-phase-seed-saturation: 0.6;
101
+
102
+ --n4-phase-sprout-background: #1a1c1a;
103
+ --n4-phase-sprout-brightness: 0.7;
104
+ --n4-phase-sprout-indicator-intensity: 0.7;
105
+ --n4-phase-sprout-pulse-speed: 2.5s;
106
+ --n4-phase-sprout-saturation: 0.85;
107
+
108
+ --n4-phase-go-background: #1c1a18;
109
+ --n4-phase-go-brightness: 1.0;
110
+ --n4-phase-go-indicator-intensity: 1.0;
111
+ --n4-phase-go-pulse-speed: 1.5s;
112
+ --n4-phase-go-saturation: 1.0;
113
+
114
+ --n4-phase-consult-background: #1b1a1c;
115
+ --n4-phase-consult-brightness: 0.85;
116
+ --n4-phase-consult-indicator-intensity: 0.85;
117
+ --n4-phase-consult-pulse-speed: 2s;
118
+ --n4-phase-consult-saturation: 0.9;
119
+
120
+ --n4-phase-weed-background: #1c1b18;
121
+ --n4-phase-weed-brightness: 0.65;
122
+ --n4-phase-weed-indicator-intensity: 0.6;
123
+ --n4-phase-weed-pulse-speed: 2.5s;
124
+ --n4-phase-weed-saturation: 0.75;
125
+
126
+ --n4-phase-freeze-background: #1a1a1e;
127
+ --n4-phase-freeze-brightness: 0.2;
128
+ --n4-phase-freeze-indicator-intensity: 0.1;
129
+ --n4-phase-freeze-pulse-speed: 8s;
130
+ --n4-phase-freeze-saturation: 0.2;
131
+
132
+ --n4-phase-compost-background: #1a1a1a;
133
+ --n4-phase-compost-brightness: 0.25;
134
+ --n4-phase-compost-indicator-intensity: 0.15;
135
+ --n4-phase-compost-pulse-speed: 6s;
136
+ --n4-phase-compost-saturation: 0.3;
137
+
138
+ --n4-phase-prune-background: #1c1a1a;
139
+ --n4-phase-prune-brightness: 0.2;
140
+ --n4-phase-prune-indicator-intensity: 0.1;
141
+ --n4-phase-prune-pulse-speed: 8s;
142
+ --n4-phase-prune-saturation: 0.2;
143
+ }
144
+
145
+ /* ── Accessibility: reduced motion ─────────────────────────────────────── */
146
+ @media (prefers-reduced-motion: reduce) {
147
+ :root {
148
+ --n4-morph-duration: 0ms;
149
+ --n4-arrive-duration: 0ms;
150
+ --n4-depart-duration: 0ms;
151
+ --n4-focus-duration: 0ms;
152
+ --n4-pulse-duration: 0ms;
153
+ --n4-transition-duration: 0ms;
154
+ }
155
+ }