docs: update database schema, websocket protocol, workspace outliner spec, flaws backlog, and readme to match current architecture
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
This commit is contained in:
1 parent
634195b629
commit
1776e87029
5 files changed
+160
-124
No files matched your search
+44
-32
@@ -1,12 +1,12 @@
|
||||
# 📝 Kernmodul 3: Workspace Outliner-Engine, Wiki-Links & Pure-DB Storage
|
||||
|
||||
Der MindSift Workspace ([`WorkspaceView.tsx`](../../frontend/src/features/workspace/WorkspaceView.tsx)) kombiniert ein **hierarchisches Bullet-Point Notizsystem (inspiriert von Logseq)** mit einem **persönlichen Wiki** und einem **globalen To-Do Rollup Dashboard**.
|
||||
Der MindSift Workspace ([`WorkspaceView.tsx`](../../frontend/src/features/workspace/WorkspaceView.tsx)) kombiniert ein **hierarchisches Bullet-Point Notizsystem (inspiriert von Logseq)** mit einem **persönlichen Wiki**, **Live-Kollaboration** und einem **globalen To-Do Rollup Dashboard**.
|
||||
|
||||
---
|
||||
|
||||
## 🌳 1. Die Logseq-Outliner-Engine
|
||||
|
||||
Im Gegensatz zu klassischen Fließtext-Editoren basiert der MindSift Workspace auf **Blöcken** (`document_blocks` in SQLite). Jeder Block ist ein gedanklicher Knotenpunkt mit einer flexiblen Einrückungsebene (`level: 0, 1, 2, ...`).
|
||||
Im Gegensatz zu klassischen Fließtext-Editoren basiert der MindSift Workspace auf einer **flachen, relationalen Liste von Blöcken** (`blocks`-Tabelle in SQLite). Jeder Block ist ein gedanklicher Knotenpunkt mit einer flexiblen Einrückungsebene (`level: 0, 1, 2, ...`) und einer fortlaufenden Fließkommaposition (`position`):
|
||||
|
||||
```
|
||||
• Projekt MindSift v2.0 (level 0)
|
||||
@@ -22,12 +22,20 @@ Im Gegensatz zu klassischen Fließtext-Editoren basiert der MindSift Workspace a
|
||||
- `Tab`: Rückt den aktuellen Block ein (wird Kindknoten des vorherigen Blocks).
|
||||
- `Shift + Tab`: Rückt den Block um eine Ebene aus (verringert die Tiefe).
|
||||
- `Shift + Enter`: Weicher Zeilenumbruch innerhalb desselben Blocks (z.B. für mehrzeilige Notizen oder Code).
|
||||
- `Backspace` (auf leerem Block): Rückt den Block aus oder löscht ihn, wenn er auf Level 0 ist.
|
||||
- `/` (Slash-Commands): Öffnet das Umwandlungsmenü (`/todo`, `/h1`, `/h2`, `/h3`, `/code`, `/callout`, `/quote`, `/divider`).
|
||||
- `Backspace` (auf leerem Block): Löscht den Block sofort. Das Ausrücken erfolgt strikt und kontrolliert über `Shift + Tab`.
|
||||
- `/` (Slash-Commands): Öffnet das Umwandlungsmenü (`/todo`, `/link`, `/h1`, `/h2`, `/h3`, `/code`, `/callout`, `/quote`, `/divider`).
|
||||
- **Markdown-Tastatur-Kürzel:** Tippen von `[] ` oder `[ ] ` wandelt den Block sofort in ein Todo um; `# `, `## `, `### ` erzeugt Überschriften.
|
||||
|
||||
### Eingabestabilität & Zombie-Fokus-Schutz (`OutlinerBlock.tsx`)
|
||||
1. **Echter Fokus-Check:** Remote-Updates (`block_updated`) werden nur dann abgewehrt, wenn der Block tatsächlich aktiv im Betriebssystem editiert wird:
|
||||
`isFocusedRef.current === true && document.hasFocus()`.
|
||||
2. **Sofort-Flush bei Fensterwechsel:** Sobald das Browser-Fenster den Fokus verliert (`window.addEventListener('blur', ...)`), wird ein offener 150ms-Debounce sofort gecancelt und der Text augenblicklich per WebSocket übertragen.
|
||||
3. **Stale Closures eliminiert:** Alle Callbacks werden in `useRef` gehalten, sodass asynchrone Debounce-Timer garantiert die aktuellste Komponenten-Referenz verwenden.
|
||||
|
||||
### Zoom-In Hoisting (Fokus-Modus)
|
||||
Klickt der Benutzer auf den Bullet-Dot (`•`) eines Blocks, blendet der Editor alle übergeordneten und benachbarten Blöcke aus und zoomt **ausschließlich in diesen Ast** hinein.
|
||||
- Eine dezente Breadcrumb-Leiste oben zeigt den Pfad an (z.B. `Workspace / Projekte / MindSift / Architektur`).
|
||||
Klickt der Benutzer auf den Bullet-Dot (`•`) eines Blocks, blendet der Editor alle übergeordneten und benachbarten Blöcke aus und zoomt **ausschließlich in diesen Ast** hinein:
|
||||
- Der gewählte Punkt wird zur prominenten Überschrift im Fokus-Modus.
|
||||
- Eine klickbare Breadcrumb-Leiste oben zeigt den Pfad an (z.B. `Workspace / Projekte / MindSift / Architektur`).
|
||||
- Ein Klick auf ein beliebiges Breadcrumb-Element zoomt sofort auf die jeweilige Ebene zurück.
|
||||
|
||||
### Drag & Drop von Blöcken
|
||||
@@ -35,51 +43,55 @@ Der Bullet-Dot dient gleichzeitig als Drag-Anfasser. Wird ein Block verschoben,
|
||||
|
||||
---
|
||||
|
||||
## 🔗 2. Wiki-Links (`[[Link]]`) & Hashtags
|
||||
## 🔗 2. Wiki-Links (`[[Link]]`), Web-Links (`/link`) & Hashtags
|
||||
|
||||
1. **Interne Wiki-Links:**
|
||||
- Text in doppelten eckigen Klammern (z.B. `[[Reiseplanung 2026]]`) wird automatisch als klickbarer Link gerendert.
|
||||
- Ein Klick darauf durchsucht die Notizen des Benutzers und öffnet das Ziel-Dokument direkt im Editor.
|
||||
2. **Hashtags (`#tag`):**
|
||||
- Hashtags im Fließtext werden automatisch indiziert (`doc_block_tags`-Tabelle).
|
||||
- Text in doppelten eckigen Klammern (z.B. `[[Reiseplanung 2026]]`) wird automatisch als klickbare Notiz-Pille gerendert.
|
||||
- Klick darauf öffnet die verknüpfte Notiz direkt im Editor.
|
||||
2. **Slash-Befehl `/link` & Link-Modal:**
|
||||
- `/link` öffnet ein Modal mit zwei Modi:
|
||||
- **Notiz verknüpfen:** Durchsucht bestehende Notizen und fügt `[[Titel]]` ein.
|
||||
- **Web-Link:** Eingabe von Titel und URL, fügt Standard-Markdown `[Titel](url)` ein.
|
||||
3. **Hashtags (`#tag`):**
|
||||
- Hashtags im Fließtext werden automatisch indiziert (`block_tags`-Tabelle).
|
||||
- In der linken Leiste listet der Tag-Explorer alle verwendeten Schlagworte auf. Klick auf ein Tag filtert alle Dokumente und Blöcke, die dieses Tag enthalten.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
## ⚡ 3. Echtzeit-Kollaboration & Automatische Markdown-Kompilierung
|
||||
|
||||
## ⚡ 3. Yjs CRDT Real-Time Engine & Dual-Persistence
|
||||
|
||||
Ab MindSift v2.1 setzt der Workspace auf ein **konfliktfreies Replicated Data Type (CRDT) Modell** auf Basis von [Yjs](https://yjs.dev/):
|
||||
MindSift setzt auf eine latenzfreie In-Memory Kollaborations-Architektur ([`internal/ws/docroom.go`](../../internal/ws/docroom.go)):
|
||||
|
||||
### Funktionsweise
|
||||
1. **CRDT-Struktur im Client:**
|
||||
- Ein `Y.Doc` pro geöffnetem Dokument.
|
||||
- `Y.Array<string>` (`blocks`): Führt die Block-IDs in korrekter Reihenfolge. Der YATA-Algorithmus garantiert, dass simultanes Einfügen, Verschieben oder Löschen von Blöcken durch mehrere Nutzer deterministisch und konfliktfrei konvergiert.
|
||||
- `Y.Map` (`block:<id>`): Speichert Inhalt (`content`), Einrückung (`level`), Erledigungsstatus (`checked`) und Faltungsstatus (`collapsed`).
|
||||
2. **Kollaborative Bearbeitung ohne Sperren:**
|
||||
- Nutzer können simultan dieselbe Notiz bearbeiten.
|
||||
- Fokus- und Cursor-Positionen werden via `CRDT_AWARENESS` übertragen und als farbige Benutzer-Pillen direkt am jeweiligen Block visualisiert.
|
||||
1. **In-Memory DocRoom pro geöffnetem Dokument:**
|
||||
- Hält den synchronen Zustand von `title` und `blocks[]` im RAM.
|
||||
- Granulare Mutations-Events (`block_updated`, `block_created`, `block_deleted`, `block_moved`, `title_updated`).
|
||||
- Ephemeres Presence-Tracking (`cursor_moved`, `client_left`) zeigt farbige Benutzer-Avatare im Header und Cursors am aktiven Block an.
|
||||
2. **Echo-Schutz:**
|
||||
- Jeder Client identifiziert sich mit einer eindeutigen `clientId`.
|
||||
- Der Server sendet Mutations-Events ausschließlich an andere Clients im selben Raum (`clientId != senderClientId`), um Cursor-Springen und Selbstechos zu verhindern.
|
||||
|
||||
### Dual-Persistence in SQLite
|
||||
### Automatische Markdown-Kompilierung & SQLite Debounce-Flush
|
||||
```
|
||||
Client (Y.Doc Mutation)
|
||||
Eingabe im OutlinerBlock
|
||||
│
|
||||
├──▶ WebSocket (CRDT_UPDATE Base64 Delta)
|
||||
├──▶ WebSocket (block_updated Event)
|
||||
│ │
|
||||
│ ▼
|
||||
│ SQLite: document_crdt_updates / document_crdt_state
|
||||
│ (Mathematisch exakte CRDT-Konvergenz)
|
||||
│ Go DocRoom: In-Memory Mutation & Broadcast an Peers
|
||||
│
|
||||
└──▶ Periodischer Snapshot / Flush
|
||||
└──▶ 1.5s Inaktivitäts-Debounce (oder Raum-Exit)
|
||||
│
|
||||
▼
|
||||
SQLite: document_blocks
|
||||
(Relationale Indizes für Global To-Dos, Tag-Explorer & FTS)
|
||||
SQLite Transaktion:
|
||||
1. Persistiert Blöcke in `blocks`
|
||||
2. Regex-Extraktion von #tags in `block_tags`
|
||||
3. Kompiliert Block-Hierarchie zu Standard-Markdown
|
||||
und speichert Cache in `documents.markdown_cache`
|
||||
```
|
||||
|
||||
1. **Mathematische CRDT-Garantie:** Binäre Yjs-Updates werden in `document_crdt_updates` und periodisch als Snapshot in `document_crdt_state` gesichert. Auch nach einem Server-Neustart oder Offline-Phasen konvergieren alle Clients verlustfrei.
|
||||
2. **Relationale Query-Fähigkeit:** Um schnelle SQL-Abfragen für das globale To-Do Rollup Dashboard und Hashtags zu ermöglichen, werden die Blöcke parallel in `document_blocks` materialisiert. Es existieren **keine Markdown-Dateien auf der Festplatte**.
|
||||
1. **Kompiliertes Markdown:** Jeder Block wird gemäß seiner `level`-Tiefe mit 2 Leerzeichen pro Einrückungsebene als sauberes Markdown formatiert (`documents.markdown_cache`).
|
||||
2. **Pure Database Architecture:** Alle Daten liegen transaktional und sicher in SQLite. Es werden keine unkontrollierten Dateien auf der Festplatte abgelegt; Notizen können jederzeit per Klick als `.md`-Datei exportiert werden.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in new issue
Block a user