---
doc_type: developer_guide
audience: developer
scope: workflow, testing, architecture, modules
status: active
version: 2.6
context: "Umfassender Guide für Entwickler: Architektur, Modul-Interna (Deep Dive), Setup, Git-Workflow und Erweiterungs-Anleitungen."
---
# Mindnet Developer Guide & Workflow
**Quellen:** `developer_guide.md`, `dev_workflow.md`, `Architecture_Audit_v2.6`
Dieser Guide ist die zentrale technische Referenz für Mindnet v2.6. Er vereint das technische Verständnis der Module mit dem operativen Workflow zwischen Windows (Dev) und Linux (Runtime).
---
## 1. Einführung & Systemüberblick
### Was ist Mindnet?
Mindnet ist ein **Hybrides Knowledge Management System**, das klassische Notizen (Markdown) mit KI-gestützter Analyse verbindet. Es kombiniert **RAG** (Retrieval Augmented Generation) mit einer **Graphen-Datenbank** (Qdrant), um Wissen nicht nur semantisch zu finden, sondern auch strukturell zu vernetzen.
### Kern-Philosophie
1. **Filesystem First:** Die Wahrheit liegt immer auf der Festplatte (Markdown-Dateien). Die Datenbank ist ein abgeleiteter Index.
2. **Hybrid Retrieval:** Relevanz entsteht aus Textähnlichkeit (Semantik) + Graphen-Verbindungen (Edges) + Wichtigkeit (Centrality).
3. **Active Intelligence:** Das System wartet nicht nur auf Anfragen, sondern schlägt beim Schreiben proaktiv Verbindungen vor ("Matrix Logic").
4. **Local Privacy:** Alle KI-Berechnungen (Ollama) laufen lokal. Keine Cloud-Abhängigkeit für Inference.
---
## 2. Architektur
### 2.1 High-Level Übersicht
Das System folgt einer strikten Trennung zwischen Frontend (Streamlit) und Backend (FastAPI), wobei bestimmte Performance-Pfade (Graph-Visualisierung) optimiert wurden.
```mermaid
graph TD
User((User))
subgraph "Frontend Layer (Streamlit)"
UI["ui.py Router"]
ViewChat["Chat View"]
ViewGraph["Graph View"]
ViewEditor["Editor View"]
Logic["Callbacks & State"]
end
subgraph "Backend Layer (FastAPI)"
API["main.py"]
RouterChat["Chat / RAG"]
RouterIngest["Ingest / Write"]
CoreRet["Retriever Engine"]
CoreIngest["Ingestion Pipeline"]
end
subgraph "Infrastructure & Services"
LLM["Ollama (Phi3/Nomic)"]
DB[("Qdrant Vector DB")]
FS["File System (.md)"]
end
User <--> UI
UI -- "REST (Chat, Save, Feedback)" --> API
UI -. "Direct Read (Graph Viz Performance)" .-> DB
API -- "Embeddings & Completion" --> LLM
API -- "Read/Write" --> DB
API -- "Read/Write (Source of Truth)" --> FS
```
### 2.2 Datenfluss-Muster
1. **Ingestion (Write):**
`Markdown` -> `Parser` -> `Chunker` -> `SemanticAnalyzer (LLM)` -> `Embedder` -> `Qdrant (Points)`
2. **Retrieval (Read):**
`Query` -> `Embedding` -> `Hybrid Search (Vector + Graph)` -> `Re-Ranking` -> `LLM Context`
3. **Visualisierung (Graph):**
`UI` -> `GraphService` -> `Qdrant (Edges Collection)` -> `Cytoscape`
---
## 3. Physische Architektur
Mindnet läuft in einer verteilten Umgebung (Post-WP15 Setup).
* **Windows 11 (VS Code):** Entwicklungsumgebung. **Nie** direkt auf `main` arbeiten!
* **Beelink (Runtime):** Der Server hostet zwei Instanzen via Systemd:
* **PROD:** API (Port 8001) + UI (Port 8501). Home: `~/mindnet`.
* **DEV:** API (Port 8002) + UI (Port 8502). Home: `~/mindnet_dev`.
* **Gitea (Raspberry Pi):** Versionskontrolle ("Safe"). Speichert den Code.
---
## 4. Projektstruktur & Modul-Referenz (Deep Dive)
Das System ist modular aufgebaut. Hier ist die detaillierte Analyse aller Komponenten.
### 4.1 Verzeichnisbaum
```text
mindnet/
├── app/
│ ├── core/ # Business Logic & Algorithms
│ ├── routers/ # API Interface (FastAPI)
│ ├── services/ # External Integrations (LLM, DB)
│ ├── models/ # Pydantic DTOs
│ └── frontend/ # UI Logic (Streamlit)
├── config/ # Configuration Files (YAML)
├── scripts/ # CLI Tools (Ops & Maintenance)
└── vault/ # Local Content Storage
```
### 4.2 Frontend Architecture (`app/frontend/`)
Das Frontend ist eine Streamlit-App, die sich wie eine Single-Page-Application (SPA) verhält.
| Modul | Status | Verantwortung |
| :--- | :--- | :--- |
| **`ui.py`** | 🟢 Core | **Main Router.** Initialisiert Session-State und entscheidet anhand der Sidebar-Auswahl, welche View gerendert wird. |
| **`ui_config.py`** | 🟢 Config | **Constants.** Zentraler Ort für Farben (`GRAPH_COLORS`), API-URLs und Timeouts. Änderungen am Look & Feel passieren hier. |
| **`ui_chat.py`** | 🟢 View | **Chat UI.** Rendert Nachrichtenverlauf, Intent-Badges, Quellen-Expanders und Feedback-Buttons. |
| **`ui_editor.py`** | 🟢 View | **Editor UI.** Markdown-Editor mit Live-Vorschau. Integriert "Intelligence" (KI-Link-Vorschläge). |
| **`ui_graph_cytoscape.py`**| 🟢 View | **Modern Graph.** Interaktiver Graph basierend auf Cytoscape.js (COSE Layout). |
| **`ui_graph.py`** | 🟡 Legacy | **Graph UI (Fallback).** Alte Implementierung mittels `streamlit-agraph`. |
| **`ui_callbacks.py`** | 🟢 Logic | **State Controller.** Handhabt komplexe State-Übergänge (z.B. Graph -> Editor). |
| **`ui_utils.py`** | 🟢 Logic | **Helper.** Enthält den **Healing Parser** (`parse_markdown_draft`), der defektes JSON/YAML von LLMs repariert. |
| **`ui_api.py`** | 🟢 Data | **API Client.** Wrapper für Backend REST-Calls. |
| **`ui_graph_service.py`** | 🟢 Data | **Performance Hack.** Greift direkt auf Qdrant zu (bypass API), um Graphen schnell zu laden. |
#### Frontend Design Patterns (Wichtig!)
1. **Active Inspector Pattern (`ui_graph_cytoscape.py`)**
Um Re-Renders im Graphen zu vermeiden, nutzen wir CSS-Klassen. Wird ein Knoten angeklickt, ändert sich nur die CSS-Klasse (`.inspected`), aber die Physik-Simulation startet nicht neu. Das sorgt für ein stabiles UI-Gefühl.
2. **Resurrection Pattern (`ui_editor.py`)**
Streamlit neigt dazu, Eingaben bei Re-Runs zu "vergessen". Der Editor synchronisiert seinen Inhalt aggressiv in den `session_state`.
* Logik: `if widget_key not in session_state: restore_from_data_key()`.
* Ergebnis: Texteingaben überleben Tab-Wechsel.
3. **Filesystem First (`ui_callbacks.py`)**
Wenn man im Graphen auf "Bearbeiten" klickt:
1. Versucht das System, die **echte Datei** von der Festplatte zu lesen.
2. Nur wenn das fehlschlägt, wird der Text aus den Datenbank-Chunks rekonstruiert ("Stitching").
Dies verhindert, dass veraltete Datenbank-Stände die echten Dateien überschreiben.
---
### 4.3 Backend Architecture (`app/`)
Das Backend stellt die Logik via REST-API bereit.
| Modul | Typ | Verantwortung |
| :--- | :--- | :--- |
| **Core Engine** | | |
| `core/ingestion.py` | Engine | **Pipeline Controller.** Koordiniert den 13-Schritte-Import, Parsing, Hash-Check und DB-Upserts. |
| `core/retriever.py` | Engine | **Search Engine.** Berechnet Hybrid-Score: `(Semantic * W) + (Edge Bonus * 0.25) + (Centrality * 0.05)`. |
| `core/chunker.py` | Engine | **Segmentation.** Zerlegt Text intelligent. Orchestriert `SemanticAnalyzer` für Smart Edges. |
| `core/derive_edges.py`| Engine | **Link Extractor.** Findet Wikilinks, Callouts und Typed Relations im Text. |
| `core/qdrant_points.py`| Mapper | **Object Mapper.** Wandelt Payloads in Qdrant `PointStruct`s um. |
| `core/graph_adapter.py` | Algo | **Graph Logic.** Baut In-Memory Graphen für Re-Ranking und Pfad-Analysen. |
| **Router (API)** | | |
| `routers/chat.py` | Router | **Hybrid Router.** Entscheidet: RAG-Antwort vs. Interview-Modus. |
| `routers/ingest.py` | Router | **Write API.** Nimmt Markdown entgegen, steuert Ingestion und Discovery-Analyse. |
| `routers/query.py` | Router | **Search API.** Klassischer Hybrid-Retriever Endpunkt. |
| `routers/graph.py` | Router | **Viz API.** Liefert Knoten/Kanten für Frontend. |
| **Services** | | |
| `services/llm_service.py`| Service | **Traffic Control.** Async Client für Ollama. Nutzt **Semaphore**, um Hintergrund-Jobs (Import) zu drosseln. |
| `services/discovery.py`| Service | **Intelligence.** "Matrix Logic" für Link-Vorschläge (WP-11). |
| `services/semantic_analyzer.py`| Service | **Filter.** KI-Validierung von Kanten im Hintergrund. |
| `services/feedback_service.py`| Service | **Logging.** Schreibt Interaktions-Logs (JSONL). |
---
### 4.4 Scripts & Tooling (Die Admin-Toolbox)
Der Ordner `scripts/` enthält verifizierte Werkzeuge für den Betrieb.
#### 1. Script-Übersicht
| Skript | Status | Zweck | Argumente & Parameter | Beispielaufruf |
| :--- | :--- | :--- | :--- | :--- |
| **`import_markdown.py`** | 🟢 **Core** | **Ingestion.** Scannt den Vault und importiert Dateien asynchron in Qdrant. Beachtet Hashes. | `--vault PATH` (Quellordner)
`--prefix TEXT` (Collection Prefix)
`--force` (Erzwingt Re-Index)
`--apply` (Schreibt in DB; sonst Dry-Run) | `python3 scripts/import_markdown.py --vault ./vault --apply` |
| **`reset_qdrant.py`** | 🟢 **Core** | **DB-Reset.** Löscht Collections (`wipe`) oder leert sie (`truncate`). Legt Indizes neu an. | `--mode {wipe,truncate}`
`--prefix TEXT`
`--yes` (Keine Rückfrage)
`--no-indexes` (Skip Index-Erstellung) | `python3 -m scripts.reset_qdrant --mode wipe --yes` |
| **`health_check_mindnet.py`** | 🟢 **Ops** | **Monitoring.** Prüft API-Verfügbarkeit (`/query`) und Antwortqualität. Standalone (keine Imports). | `--url URL`
`--query TEXT`
`--top-k INT`
`--strict` (Exit-Code 1 bei Warnings) | `python3 scripts/health_check_mindnet.py --strict` |
| **`payload_dryrun.py`** | 🟡 **Dev** | **Debugger.** Simuliert die JSON-Erstellung (Payloads) ohne DB-Schreibzugriff. Prüft `types.yaml`. | `--vault PATH`
`--note-id ID` (Filter)
`--with-edges` (Zeigt Kanten) | `python3 -m scripts.payload_dryrun --vault ./vault --note-id "projekt-alpha"` |
| **`edges_full_check.py`** | 🟡 **Audit** | **Integritäts-Check.** Zählt Kanten in der DB und prüft logische Konsistenz (z.B. Chunk-Reihenfolge). | Keine (Liest Konfiguration nur aus Umgebungsvariablen `.env`) | `python3 -m scripts.edges_full_check` |
| **`resolve_unresolved_references.py`** | 🔵 **Maint** | **Link-Healer.** Repariert "tote" Links in der DB nachträglich und erzeugt Backlinks. | `--prefix TEXT`
`--limit INT`
`--apply` (Schreibt Änderungen) | `python3 -m scripts.resolve_unresolved_references --apply` |
| **`export_markdown.py`** | ⚪ **Utility** | **Reverse ETL.** Exportiert den Datenbank-Inhalt zurück in Markdown-Dateien (Backup/Recovery). | `--out PATH` (Ziel)
`--note-id ID`
`--include-edges {yaml,footer}`
`--flatten-paths` | `python3 -m scripts.export_markdown --out ./backup` |
---
#### 2. Einsatzszenarien & Bewertung
### 🟢 Essentiell für den Betrieb (Must-Have)
* **`import_markdown.py`**: Das Arbeitspferd. Ohne dieses Skript kommen keine Daten ins System (außer man nutzt die API einzeln). Es ist für Cronjobs optimiert.
* **`reset_qdrant.py`**: Zwingend notwendig für CI/CD-Pipelines oder saubere Neustarts bei Schema-Änderungen.
* **`health_check_mindnet.py`**: Ideal für Docker-Healthchecks oder Monitoring-Tools (Nagios, Uptime Kuma), da es keine Python-Abhängigkeiten zur App hat.
### 🟡 Hilfreich für Entwicklung & Debugging (Should-Have)
* **`payload_dryrun.py`**: Sehr wertvoll, wenn man an der `config/types.yaml` oder dem `chunker.py` arbeitet. Man sieht sofort, wie das JSON aussieht, ohne die Datenbank "zuzumüllen".
* **`edges_full_check.py`**: Wichtiges Diagnose-Tool, wenn der Graph im Frontend "komisch" aussieht oder Kanten fehlen.
### 🔵 Wartung & Spezialfälle (Nice-to-Have)
* **`resolve_unresolved_references.py`**: Sinnvoll in einem "Knowledge Garden", wo oft Links auf noch nicht existierende Notizen gesetzt werden ("Red Links"). Dieses Skript "heilt" den Graphen nachträglich.
* **`export_markdown.py`**: Ein Notfall-Tool. Da Mindnet nach dem Prinzip "Filesystem First" arbeitet, ist ein Export aus der DB selten nötig, kann aber bei versehentlichem Löschen von Dateien lebensrettend sein.
---
## 5. Maintenance & "Kill List"
Folgende Dateien wurden im Audit v2.6 als veraltet, redundant oder "Zombie-Code" identifiziert und sollten entfernt werden.
| Datei | Diagnose | Empfohlene Aktion |
| :--- | :--- | :--- |
| `app/embed_server.py` | **Zombie.** Alter Standalone-Server. | 🗑️ Löschen |
| `app/embeddings.py` | **Zombie.** Veraltete lokale Lib. | 🗑️ Löschen |
| `app/core/edges.py` | **Redundant.** Ersetzt durch `derive_edges.py`. | 🗑️ Löschen |
| `app/core/ranking.py` | **Redundant.** Logik in `retriever.py` integriert. | 🗑️ Löschen |
| `app/core/type_registry.py` | **Redundant.** Logik in `ingestion.py` integriert. | 🗑️ Löschen |
| `app/core/env_vars.py` | **Veraltet.** Ersetzt durch `config.py`. | 🗑️ Löschen |
| `app/routers/qdrant_router.py`| **Deprecated.** Keine Logik, nur CRUD. | 📂 Verschieben nach `scripts/archive/` |
---
## 6. Lokales Setup (Development)
**Voraussetzungen:** Python 3.10+, Docker, Ollama.
**Installation:**
```bash
# 1. Repo & Venv
git clone mindnet
cd mindnet
python3 -m venv .venv
source .venv/bin/activate
# 2. Dependencies
pip install -r requirements.txt
# 3. Ollama (Nomic ist Pflicht!)
ollama pull phi3:mini
ollama pull nomic-embed-text
```
**Konfiguration (`.env`):**
```ini
QDRANT_URL="http://localhost:6333"
MINDNET_OLLAMA_URL="http://localhost:11434"
MINDNET_LLM_MODEL="phi3:mini"
MINDNET_EMBEDDING_MODEL="nomic-embed-text"
COLLECTION_PREFIX="mindnet_dev"
VECTOR_DIM=768
MINDNET_LLM_BACKGROUND_LIMIT=2
MINDNET_API_URL="http://localhost:8002"
```
---
## 7. Der Entwicklungs-Zyklus (Workflow)
### Phase 1: Windows (Code)
1. **Basis aktualisieren:** `git checkout main && git pull`.
2. **Branch erstellen:** `git checkout -b feature/mein-feature`.
3. **Coden & Committen.**
4. **Push:** `git push origin feature/mein-feature`.
### Phase 2: Beelink (Test / Dev)
Hier prüfst du, ob dein Code auf Linux läuft.
1. **Einloggen:** `ssh user@beelink`.
2. **Ordner:** `cd ~/mindnet_dev`.
3. **Code holen:** `git fetch && git checkout feature/mein-feature && git pull`.
4. **Dependencies:** `pip install -r requirements.txt`.
5. **Restart:** `sudo systemctl restart mindnet-dev`.
6. **Validierung (Smoke Tests):**
* **Last-Test:** Starte `python3 -m scripts.import_markdown ...` im Terminal und chatte gleichzeitig im UI (Port 8502).
* **API Check:** `curl -X POST "http://localhost:8002/ingest/analyze" ...`
### Phase 3: Release & Deployment (Prod)
Wenn alles getestet ist:
1. **Gitea:** Pull Request erstellen und mergen.
2. **Deploy auf Prod (Beelink):**
```bash
cd ~/mindnet
git pull origin main
# Sicherstellen, dass Prod-Dependencies aktuell sind
source .venv/bin/activate
pip install -r requirements.txt
ollama pull nomic-embed-text # Falls neue Modelle nötig sind
# Restart
sudo systemctl restart mindnet-prod
sudo systemctl restart mindnet-ui-prod
```
3. **Cleanup:** Branch löschen (lokal und remote).
---
## 8. Erweiterungs-Guide: "Teach-the-AI"
Mindnet lernt nicht durch Training (Fine-Tuning), sondern durch **Konfiguration** und **Vernetzung**.
### Workflow A: Neuen Typ implementieren (z. B. `type: risk`)
1. **Physik (`config/types.yaml`):**
```yaml
risk:
chunk_profile: sliding_short
retriever_weight: 0.90 # Sehr wichtig
edge_defaults: ["blocks"] # Automatische Kante
detection_keywords: ["gefahr", "risiko"]
```
2. **Strategie (`config/decision_engine.yaml`):**
```yaml
DECISION:
inject_types: ["value", "risk"] # <--- "risk" hinzufügen
```
*Ergebnis:* Wenn der Intent `DECISION` erkannt wird, sucht das System nun auch aktiv nach Risiken.
### Workflow B: Graph-Farben ändern
1. Öffne `app/frontend/ui_config.py`.
2. Bearbeite das Dictionary `GRAPH_COLORS`.
```python
GRAPH_COLORS = {
"project": "#FF4B4B",
"risk": "#8B0000" # Neu
}
```
---
## 9. Tests & Debugging
**Unit Tests (Pytest):**
```bash
pytest tests/test_retriever_basic.py
pytest tests/test_chunking.py
```
**Pipeline Tests (Integration):**
```bash
# JSON-Schema prüfen
python3 -m scripts.payload_dryrun --vault ./test_vault
# Graph-Integrität prüfen
python3 -m scripts.edges_full_check
```
**E2E Smoke Tests:**
```bash
# Decision Engine
python tests/test_wp06_decision.py -p 8002 -e DECISION -q "Soll ich X tun?"
# Feedback
python tests/test_feedback_smoke.py --url http://localhost:8002/query
```
---
## 10. Troubleshooting & One-Liners
**DB komplett zurücksetzen (Vorsicht!):**
```bash
# --yes überspringt die Bestätigung
python3 -m scripts.reset_qdrant --mode wipe --prefix "mindnet_dev" --yes
```
**Einen einzelnen File inspizieren (Parser-Sicht):**
```bash
python3 tests/inspect_one_note.py --file ./vault/MeinFile.md
```
**Live-Logs sehen:**
```bash
journalctl -u mindnet-dev -f
journalctl -u mindnet-ui-dev -f
```
**"UnicodeDecodeError in .env":**
* **Ursache:** Umlaute oder Sonderzeichen in der `.env`.
* **Lösung:** Datei bereinigen (nur ASCII) und sicherstellen, dass UTF-8 ohne BOM genutzt wird.
**"Read timed out" im Frontend:**
* **Ursache:** Smart Edges brauchen länger als 60s.
* **Lösung:** `MINDNET_API_TIMEOUT=300.0` in `.env`.