@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,457 @@
1
+ # Enchanted Blocks — Unified Spatial Content System
2
+
3
+ ## Problem Statement
4
+
5
+ Three KOS apps hit the same wall: **content doesn't fit**, and **enrichment is one-way**.
6
+
7
+ - **Ryu**: Task descriptions, daemon logs, and epistemic assay results overflow their containers. We gave up on rich task content.
8
+ - **Atelier**: Notes can't display KVE bidirectional enrichment. The canvas is static, not living.
9
+ - **Nodepad** (external research): Proved spatial research works—auto-classification, inferred connections, synthesis emergence—but we never integrated it.
10
+
11
+ ## Core Insight
12
+
13
+ Content fitting is a **measurement problem**. Enrichment is a **rendering problem**. Both need:
14
+ 1. **Deterministic text layout** without DOM reflow (Pretext)
15
+ 2. **Adaptive card sizing** that grows/shrinks with content
16
+ 3. **Bidirectional value flow** between cards and the KVE
17
+ 4. **Three canonical views** for different cognitive modes
18
+
19
+ ## Architecture
20
+
21
+ ### New Module: `x0-enchanted-blocks`
22
+
23
+ Location: `LEAP/design-system/src/x0-enchanted-blocks/`
24
+
25
+ Exports:
26
+ - `EnchantedBlock` — adaptive card component
27
+ - `EnchantedCanvas` — spatial canvas with three view modes
28
+ - `useBlockEnrichment` — KVE bidirectional hook
29
+ - `BlockClassifier` — auto-type detection (14 types from nodepad)
30
+ - `SynthesisEngine` — emergent bridging sentences
31
+
32
+ ### 1. Adaptive Block Sizing (Pretext Integration)
33
+
34
+ ```typescript
35
+ // block-layout.ts — DOM-free measurement
36
+ import { prepare, layout } from '@chenglou/pretext';
37
+
38
+ export interface BlockMetrics {
39
+ minWidth: number; // shrink-wrap width
40
+ idealWidth: number; // optimal reading width (~65ch)
41
+ height: number; // measured at target width
42
+ lineCount: number; // for virtualization
43
+ hasOverflow: boolean; // content exceeds max constraints
44
+ }
45
+
46
+ export function measureBlock(
47
+ content: string,
48
+ font: string,
49
+ maxWidth: number,
50
+ options?: { whiteSpace?: 'normal' | 'pre-wrap'; wordBreak?: 'normal' | 'keep-all' }
51
+ ): BlockMetrics {
52
+ const prepared = prepare(content, font, options);
53
+ const { height, lineCount } = layout(prepared, maxWidth, 1.6 /* lineHeight */);
54
+
55
+ // Shrink-wrap: find tightest width that doesn't increase line count
56
+ const minWidth = measureNaturalWidth(prepared);
57
+
58
+ return { minWidth, idealWidth: Math.min(520, maxWidth), height, lineCount, hasOverflow: height > 400 };
59
+ }
60
+ ```
61
+
62
+ **Used by:**
63
+ - `EnchantedBlock.svelte` — auto-height cards with overflow indicators
64
+ - `VirtualCanvas.svelte` — accurate scrollbar/track sizing
65
+ - `KanbanColumn.svelte` — column height pre-calculation
66
+
67
+ ### 2. The 14 Block Types (Nodepad Classification)
68
+
69
+ ```typescript
70
+ export type BlockType =
71
+ | 'claim' // Asserted truth
72
+ | 'question' // Open inquiry
73
+ | 'idea' // Proposed concept
74
+ | 'task' // Action item (Ryu integration)
75
+ | 'entity' // Named thing (person, org, concept)
76
+ | 'quote' // External citation
77
+ | 'reference' // Link/pointer
78
+ | 'definition' // Term explanation
79
+ | 'opinion' // Subjective stance
80
+ | 'reflection' // Self-aware musing
81
+ | 'narrative' // Story/time sequence
82
+ | 'comparison' // Side-by-side analysis
83
+ | 'thesis' // Synthesized position
84
+ | 'general'; // Unclassified
85
+
86
+ export interface EnchantedBlockData {
87
+ id: string;
88
+ type: BlockType;
89
+ content: string; // Raw user input
90
+ annotation?: string; // AI enrichment (what the note doesn't say)
91
+ provenance: ProvenanceChain; // From Ryu's epistemic system
92
+ connections: BlockConnection[]; // Inferred from content + KVE
93
+ createdAt: number;
94
+ modifiedAt: number;
95
+ // Spatial state (canvas view)
96
+ x?: number;
97
+ y?: number;
98
+ width?: number;
99
+ height?: number;
100
+ }
101
+ ```
102
+
103
+ **Visual encoding:**
104
+ - Color border by type (brass/copper palette)
105
+ - Icon badge (top-left)
106
+ - Annotation appears on hover/focus (subtle expansion)
107
+ - Connections shown as faint lines (opacity ∝ relevance)
108
+
109
+ ### 3. Three Canonical Views
110
+
111
+ ```typescript
112
+ export type CanvasView = 'tiling' | 'kanban' | 'graph';
113
+
114
+ // Tiling: BSP spatial layout (ZoneTiler)
115
+ // - Blocks auto-size to content
116
+ // - Drag dividers to resize zones
117
+ // - Blocks reflow within zones
118
+
119
+ // Kanban: Columnar by type
120
+ // - Columns: [Unsorted | Claim | Question | Idea | Task | ...]
121
+ // - Drag between columns = reclassify
122
+ // - Column height = sum of measured block heights
123
+
124
+ // Graph: Force-directed (N3 Force Graph)
125
+ // - Nodes = blocks (sized by content)
126
+ // - Edges = inferred connections
127
+ // - Synthesis nodes emerge at high centrality
128
+ ```
129
+
130
+ ### 4. Bidirectional KVE Enrichment
131
+
132
+ ```typescript
133
+ // useBlockEnrichment.ts — Svelte 5 runes
134
+ import { prepareWithSegments, walkLineRanges } from '@chenglou/pretext';
135
+
136
+ export function useBlockEnrichment(blockId: string) {
137
+ const enrichment = $state<EnrichmentState>({ status: 'idle' });
138
+
139
+ // Outbound: Block content → KVE
140
+ async function contributeToKVE(content: string, type: BlockType) {
141
+ enrichment.status = 'contributing';
142
+ await ryu_knowledge_ingest({
143
+ content,
144
+ type,
145
+ provenance: { source: 'atelier', blockId }
146
+ });
147
+ enrichment.status = 'idle';
148
+ }
149
+
150
+ // Inbound: KVE → Block annotation
151
+ async function fetchEnrichment(content: string) {
152
+ enrichment.status = 'enriching';
153
+ const result = await ryu_knowledge_epistemic_detail({ content });
154
+
155
+ // Annotation = "something the note doesn't already say"
156
+ enrichment.annotation = result.insights
157
+ .filter(i => !content.toLowerCase().includes(i.text.toLowerCase()))
158
+ .map(i => i.text)
159
+ .join(' · ');
160
+
161
+ // Inferred connections to other blocks
162
+ enrichment.connections = result.related.map(r => ({
163
+ targetId: r.blockId,
164
+ strength: r.relevance,
165
+ type: r.relationType // 'supports', 'contradicts', 'extends', 'similar'
166
+ }));
167
+
168
+ enrichment.status = 'idle';
169
+ }
170
+
171
+ return { enrichment, contributeToKVE, fetchEnrichment };
172
+ }
173
+ ```
174
+
175
+ ### 5. Synthesis Emergence
176
+
177
+ When enough blocks accumulate (threshold: 5+ with connection density > 0.3), the canvas offers a **synthesis**:
178
+
179
+ ```typescript
180
+ export interface Synthesis {
181
+ id: string;
182
+ type: 'thesis';
183
+ content: string; // Single sentence bridging tensions
184
+ bridges: string[]; // Block IDs that this synthesizes
185
+ confidence: number;
186
+ }
187
+
188
+ // Triggered by: canvas block count change + connection density check
189
+ // Source: ryu_think({ context: blockIds, mode: 'synthesize' })
190
+ // Presentation: Floating pill at canvas center, dismissable
191
+ // Solidify: Click → creates new 'thesis' block, auto-connected to bridged blocks
192
+ ```
193
+
194
+ ### 6. Component: EnchantedBlock
195
+
196
+ ```svelte
197
+ <!-- EnchantedBlock.svelte -->
198
+ <script lang="ts">
199
+ import { measureBlock } from './block-layout.js';
200
+ import { useBlockEnrichment } from './useBlockEnrichment.svelte.js';
201
+
202
+ interface Props {
203
+ block: EnchantedBlockData;
204
+ editable?: boolean;
205
+ maxWidth?: number;
206
+ onChange?: (block: EnchantedBlockData) => void;
207
+ onTypeChange?: (type: BlockType) => void;
208
+ }
209
+
210
+ let { block, editable = false, maxWidth = 400, onChange, onTypeChange }: Props = $props();
211
+
212
+ // DOM-free measurement
213
+ const metrics = $derived(measureBlock(
214
+ block.content,
215
+ '14px "Sovereign Sans"',
216
+ maxWidth,
217
+ { whiteSpace: 'pre-wrap' }
218
+ ));
219
+
220
+ // KVE enrichment
221
+ const { enrichment, contributeToKVE, fetchEnrichment } = useBlockEnrichment(block.id);
222
+
223
+ // Debounced enrichment on content change
224
+ $effect(() => {
225
+ if (block.content.length > 10) {
226
+ const timer = setTimeout(() => fetchEnrichment(block.content), 500);
227
+ return () => clearTimeout(timer);
228
+ }
229
+ });
230
+
231
+ let isEditing = $state(false);
232
+ let isExpanded = $state(false);
233
+ </script>
234
+
235
+ <div
236
+ class="enchanted-block type-{block.type}"
237
+ style:width="{metrics.idealWidth}px"
238
+ style:min-height="{Math.min(metrics.height, 200)}px"
239
+ class:expanded={isExpanded}
240
+ class:has-annotation={!!enrichment.annotation}
241
+ >
242
+ <!-- Type badge (click to reclassify) -->
243
+ <button class="type-badge" onclick={() => onTypeChange?.(nextType(block.type))}>
244
+ <Icon name={typeIcons[block.type]} />
245
+ <span class="type-label">{block.type}</span>
246
+ </button>
247
+
248
+ <!-- Content -->
249
+ {#if isEditing}
250
+ <div
251
+ contenteditable="true"
252
+ class="block-content editable"
253
+ bind:innerText={block.content}
254
+ onblur={() => { isEditing = false; contributeToKVE(block.content, block.type); }}
255
+ />
256
+ {:else}
257
+ <div
258
+ class="block-content"
259
+ ondblclick={() => editable && (isEditing = true)}
260
+ >
261
+ {@html renderMarkdown(block.content)}
262
+ </div>
263
+ {/if}
264
+
265
+ <!-- Annotation (appears on hover/focus) -->
266
+ {#if enrichment.annotation}
267
+ <div class="annotation" class:visible={isExpanded}>
268
+ <Icon name="Sparkles" />
269
+ <span>{enrichment.annotation}</span>
270
+ </div>
271
+ {/if}
272
+
273
+ <!-- Overflow indicator -->
274
+ {#if metrics.hasOverflow}
275
+ <button class="expand-hint" onclick={() => isExpanded = !isExpanded}>
276
+ {isExpanded ? 'Collapse' : 'Expand'} ({metrics.lineCount} lines)
277
+ </button>
278
+ {/if}
279
+
280
+ <!-- Connection handles (graph view only) -->
281
+ <div class="connection-handles">
282
+ {#each enrichment.connections as conn}
283
+ <div class="connection-handle" style="--strength: {conn.strength}">
284
+ <Icon name={relationIcons[conn.type]} />
285
+ </div>
286
+ {/each}
287
+ </div>
288
+ </div>
289
+
290
+ <style>
291
+ .enchanted-block {
292
+ position: relative;
293
+ background: var(--color-bg-elevated, #2a2a2a);
294
+ border-left: 3px solid var(--type-color, #b87333);
295
+ border-radius: var(--radius-md, 8px);
296
+ padding: var(--space-3, 12px);
297
+ transition: all 0.2s ease;
298
+ }
299
+
300
+ .type-claim { --type-color: #d4943a; }
301
+ .type-question { --type-color: #6b8ce6; }
302
+ .type-idea { --type-color: #7cb97a; }
303
+ .type-task { --type-color: #b87333; }
304
+ /* ... etc for all 14 types */
305
+
306
+ .annotation {
307
+ opacity: 0;
308
+ max-height: 0;
309
+ overflow: hidden;
310
+ transition: all 0.3s ease;
311
+ font-size: var(--text-xs, 11px);
312
+ color: var(--color-text-muted, #a09880);
313
+ font-style: italic;
314
+ }
315
+
316
+ .enchanted-block:hover .annotation,
317
+ .annotation.visible {
318
+ opacity: 1;
319
+ max-height: 100px;
320
+ margin-top: var(--space-2, 8px);
321
+ }
322
+
323
+ .expanded {
324
+ max-height: none;
325
+ }
326
+ </style>
327
+ ```
328
+
329
+ ## Integration Points
330
+
331
+ ### Ryu Tasks
332
+
333
+ Current: Task list with truncated descriptions.
334
+
335
+ With Enchanted Blocks:
336
+ - Tasks become `type: 'task'` blocks
337
+ - Full descriptions visible via measured height
338
+ - Epistemic assay results shown as annotations
339
+ - Task connections = dependencies (inferred from content)
340
+
341
+ ### Atelier Notes
342
+
343
+ Current: Static markdown notes.
344
+
345
+ With Enchanted Blocks:
346
+ - Notes auto-classify into 14 types
347
+ - KVE enrichment appears as annotations
348
+ - Bidirectional: notes contribute to KVE, KVE enriches notes
349
+ - Three views: tiling (BSP), kanban (by type), graph (connections)
350
+
351
+ ### BlockWriter
352
+
353
+ Current: Visual block-based writing with BSP zones.
354
+
355
+ With Enchanted Blocks:
356
+ - Each writing block is an EnchantedBlock
357
+ - Content measurement prevents overflow
358
+ - Synthesis emerges from connected blocks
359
+ - Export to thesis/node with full provenance
360
+
361
+ ## Implementation Roadmap
362
+
363
+ ### Phase 1: Foundation (Week 1)
364
+ - [ ] Add `@chenglou/pretext` dependency to design-system
365
+ - [ ] Create `block-layout.ts` with measurement primitives
366
+ - [ ] Create `EnchantedBlock.svelte` with auto-sizing
367
+
368
+ ### Phase 2: Classification (Week 2)
369
+ - [ ] Implement 14-type classifier (local regex + LLM fallback)
370
+ - [ ] Type badge UI with click-to-reclassify
371
+ - [ ] Color palette per type (brass/copper variants)
372
+
373
+ ### Phase 3: Enrichment (Week 3)
374
+ - [ ] `useBlockEnrichment` hook with KVE integration
375
+ - [ ] Annotation display (hover/focus expansion)
376
+ - [ ] Connection inference from `ryu_knowledge_epistemic_detail`
377
+
378
+ ### Phase 4: Canvas (Week 4)
379
+ - [ ] `EnchantedCanvas.svelte` with three view modes
380
+ - [ ] Tiling: integrate with existing ZoneTiler
381
+ - [ ] Kanban: columnar layout with drag-to-reclassify
382
+ - [ ] Graph: integrate with N3 Force Graph
383
+
384
+ ### Phase 5: Synthesis (Week 5)
385
+ - [ ] Synthesis engine (density detection + `ryu_think`)
386
+ - [ ] Floating thesis pill UI
387
+ - [ ] Solidify flow (thesis block creation)
388
+
389
+ ## File Structure
390
+
391
+ ```
392
+ src/x0-enchanted-blocks/
393
+ ├── index.ts # Public exports
394
+ ├── ENCHANTED_BLOCKS_SPEC.md # This document
395
+ ├──
396
+ ├── core/
397
+ │ ├── block-layout.ts # Pretext measurement
398
+ │ ├── block-types.ts # 14 types + icons
399
+ │ ├── classifier.ts # Auto-type detection
400
+ │ └── synthesis.ts # Emergence detection
401
+
402
+ ├── components/
403
+ │ ├── EnchantedBlock.svelte # Adaptive card
404
+ │ ├── EnchantedCanvas.svelte # Three-view canvas
405
+ │ ├── TypeBadge.svelte # Clickable type indicator
406
+ │ ├── Annotation.svelte # Enrichment display
407
+ │ └── ConnectionLine.svelte # SVG connection
408
+
409
+ ├── hooks/
410
+ │ └── useBlockEnrichment.svelte.ts # KVE bidirectional
411
+
412
+ └── views/
413
+ ├── TilingView.svelte # BSP spatial (ZoneTiler)
414
+ ├── KanbanView.svelte # Columnar by type
415
+ └── GraphView.svelte # Force-directed (N3)
416
+ ```
417
+
418
+ ## Dependencies
419
+
420
+ ```json
421
+ {
422
+ "dependencies": {
423
+ "@chenglou/pretext": "^1.0.0"
424
+ },
425
+ "peerDependencies": {
426
+ "svelte": "^5.0.0"
427
+ }
428
+ }
429
+ ```
430
+
431
+ ## Success Metrics
432
+
433
+ 1. **No overflow**: 100% of blocks display full content without truncation
434
+ 2. **Enrichment coverage**: 80%+ of blocks have KVE annotations within 2s of edit
435
+ 3. **Synthesis quality**: User accepts 50%+ of suggested thesis statements
436
+ 4. **View switching**: <100ms to switch between tiling/kanban/graph
437
+ 5. **Measurement speed**: <16ms for blocks up to 1000 characters
438
+
439
+ ## KVE Integration Commands
440
+
441
+ Leverages existing Ryu commands:
442
+ - `ryu_knowledge_ingest` — outbound contribution
443
+ - `ryu_knowledge_epistemic_detail` — inbound enrichment
444
+ - `ryu_think` — synthesis generation
445
+ - `ryu_knowledge_provenance_chain` — provenance display
446
+
447
+ ## Open Questions
448
+
449
+ 1. Should synthesis be automatic or user-triggered?
450
+ 2. How to handle very long content (>10k chars) in blocks?
451
+ 3. Should connections be editable or purely inferred?
452
+ 4. Export format: `.nodepad` JSON, `.md`, or KOS-native?
453
+
454
+ ---
455
+
456
+ *Spec version: 2026-04-09*
457
+ *Status: Draft for review*