Hier ist eine fertige `README_indexing.md`, die du direkt in dein Repo legen kannst. Sie beschreibt genau den Ablauf “Markdown rein ⇒ Qdrant ⇒ Eule/Vector finden’s”, inkl. Tests & Troubleshooting.

---

# Crumbforest – Markdown → Qdrant Indexierung

Ziel: **Neue/aktualisierte `.md`-Dateien** aus diesem Repo in **Qdrant** indizieren, sodass

* `vector search "…" …` sinnvolle Treffer liefert und
* `eule "…" …` Antworten aus dem Kontext ziehen kann.

Minimal-pragmatischer Ablauf — **ohne** unnötiges Git-/Sudo-/Cache-Chaos.

---

## 0) Voraussetzungen (einmalig)

Diese Umgebung wird erwartet (ist bei uns bereits so eingerichtet):

* Python venv: `/opt/venvs/crumbforest/bin/python3`
* Qdrant läuft lokal, Collection: `md_files`
* Wrapper/Tools:

  * `vector` → `/opt/vector/cli.py`
  * `vector-index` → `/opt/gitea-md/index_md_qdrant.py`
  * `eule` → `/opt/eule/eule_rag.py`
* Logging:

  * `/var/log/crumb/vector.jsonl`
  * `/var/log/crumb/eule.jsonl`
* Caches (les-/schreibbar für `vectorbot`):

  * `HF_HOME=/opt/cache/hf`
  * `SENTENCE_TRANSFORMERS_HOME=/opt/cache/st`
  * `TORCH_HOME=/opt/cache/torch`

> Falls du auf einem frischen System bist, lies **Troubleshooting** unten.

---

## 1) Markdown hinzufügen / ändern

Im Repo (dieses Verzeichnis):

```bash
# Beispiel: neue Datei
echo -e "# Eule war tanzen (2025-08-16)\n\nKurzbericht + Medien." > eule_war_tanzen_2025-08-16.md

# optional: Medien unter media/<…>/ ablegen
mkdir -p media/eule_tanzt_2025-08-16
# (Bilder etc. hineinkopieren)

git add eule_war_tanzen_2025-08-16.md media/eule_tanzt_2025-08-16/
git commit -m "Add: Eule war tanzen (2025-08-16)"
git push   # nur nötig, wenn das Repo einen Remote nutzt
```

> Wenn du direkt **auf dem Server-Clone** arbeitest und der Clone keine Pulls braucht, reicht `git add/commit`.

---

## 2) Index aktualisieren (Qdrant)

**Ohne Git-Pull**, nur lokale Dateien indizieren:

```bash
vector-index
```

Ausgabe endet typischerweise mit:

```
🎉 Fertig. <N> Dateien, ~<M> Chunks, <X> geändert, in <t>s.
```

---

## 3) Testen

### Vector-Suche

```bash
vector info
vector search "Eule tanzen" --k 5
```

Du solltest deine neue Datei unter den Treffern sehen (Dateiname + Snippet).

### Eule (ohne LLM, nur Kontext)

```bash
eule --no-llm "Was ist in 'Eule war tanzen' dokumentiert?"
```

Eule zeigt die Top-Quellen inkl. deiner neuen `.md`.

---

## 4) Optional: Snapshot (Backup)

```bash
vector snapshot create --collection md_files
vector snapshot list   --collection md_files
```

---

## 5) (Optional) Cron für Auto-Reindex

Wenn du **regelmäßig** indizieren willst (ohne Pull):

```bash
( crontab -l 2>/dev/null | sed '/index_md_qdrant\.py/d'; \
  echo '*/30 * * * * sudo -n -u vectorbot env HF_HOME=/opt/cache/hf SENTENCE_TRANSFORMERS_HOME=/opt/cache/st TORCH_HOME=/opt/cache/torch GIT_PULL=0 /opt/venvs/crumbforest/bin/python3 /opt/gitea-md/index_md_qdrant.py >>/var/log/crumb/vector.jsonl 2>&1' ) | crontab -
```

---

## Troubleshooting (kurz & knackig)

### A) `Permission denied: sentence-transformers/.../modules.json`

Embedding-Cache gehört „falschem“ User. Fix:

```bash
sudo install -d -m 775 -o vectorbot -g crumblog /opt/cache/hf /opt/cache/st /opt/cache/torch
sudo chown -R vectorbot:crumblog /opt/cache
```

Die Wrapper rufen bereits mit:

```
HF_HOME=/opt/cache/hf
SENTENCE_TRANSFORMERS_HOME=/opt/cache/st
TORCH_HOME=/opt/cache/torch
```

auf.

### B) `sudo: a password is required`

Der Wrapper muss **genau** dem Eintrag in `/etc/sudoers.d/crumbforest-tools` entsprechen.
Beispiel (so ist’s korrekt):

```
# Wrapper: /usr/local/bin/vector-index
exec sudo -n -u vectorbot env HF_HOME=... SENTENCE_TRANSFORMERS_HOME=... TORCH_HOME=... GIT_PULL=0 /opt/venvs/crumbforest/bin/python3 /opt/gitea-md/index_md_qdrant.py "$@"
```

Sudoers (exakte Pfade!):

```
tty ALL=(vectorbot) NOPASSWD: /opt/venvs/crumbforest/bin/python3 /opt/gitea-md/index_md_qdrant.py *
```

Prüfen:

```bash
sudo visudo -cf /etc/sudoers.d/crumbforest-tools
which vector vector-index eule
```

### C) Indexer will `git pull` / fragt nach Credentials

Wir indexieren **lokal**. Entweder:

* im Wrapper `GIT_PULL=0` setzen (siehe oben), **oder**
* im Script die `git pull`-Zeile entfernen/absichern.

### D) `.state`-Ordner nicht beschreibbar

Der Indexer speichert seinen Stand unter `/opt/gitea-md/.state`.
Fix:

```bash
sudo install -d -m 2775 -o vectorbot -g crumblog /opt/gitea-md/.state
```

### E) Doctor

Schnellcheck:

```bash
eule-doctor
vector-doctor
```

Beide sollten ✅ zeigen.

---

## Zusammenfassung

1. **Markdown schreiben** → `git add/commit/push` (optional).
2. **Index aktualisieren** → `vector-index` (ohne Pull).
3. **Testen** → `vector search …`, `eule --no-llm …`.

Fertig. Kein Overhead, nur Wald. 🌲🦉

---

Wenn das so passt, speicher die Datei:

```bash
cat > README_indexing.md <<'MD'
[OBIGER INHALT HIER REINKOPIEREN]
MD

git add README_indexing.md
git commit -m "Docs: README_indexing – Markdown→Qdrant Workflow"
git push
```

Sag Bescheid, wenn du noch eine **README\_blockly.md** für die CrumBlocks möchtest – dann dokumentiere ich dort den Wasserkocher-Flow (Variablen, Schleifen, Bedingungen) genau so schlank.
