Files

307 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: mesh-file-task-queue
description: >
Multi-Agent-Koordination ueber geteiltes Dateisystem stat.
---
# Mesh File-Based Task Queue
Kooperative Aufgabenbearbeitung zwischen Hermes-Agents über einen gemeinsamen
Datei-Share — der zuverlässigste Kanal, wenn Webhook-Antworten leer bleiben
und Nutzer keinen manuellen Relay spielen wollen (Nutzer-Präferenz).
## Kernidee
Status = **Ordner**, nicht Feld in der Datei. Verschieben per `mv` ist atomar
und konfliktfrei zwischen Agents (auf NFS zuverlässig atomar; über SSH/scp wird
der atomare `mv` **remote auf dem Master** ausgeführt und ist ebenso konfliktfrei).
Kein Locking-Konflikt, kein Lost Update.
**Blueprint-v1-Struktur (ab 02.08.2026):**
```
/srv/work/tasks/
├── offen/ # offene Aufgaben (JSON, Dateiname = <task_id>.json)
├── in_arbeit/ # wird bearbeitet (Dateiname erhält Präfix <C.D>_ , letzte 2 IP-Oktette)
├── fertig/ # erledigt, verifiziert
├── bugfix/ # Ergebnis passt nicht — NUR Master entscheidet
└── archiv/ # wirklich abgeschlossen — NUR Master entscheidet
```
> ⚠️ Ältere Struktur (`todo/inProgress/finished/bugged/completed` mit Markdown)
> wurde durch die Blueprint-v1-Struktur abgelöst.
## Task-Dateiformat (JSON, Blueprint v1)
```json
{
"task_id": "T20260802_1785703372",
"ziel_agent": "LaptopHermes",
"original_ziel_agent": "LaptopHermes",
"aufgabentyp": "html",
"prioritaet": "mid",
"budget_limit_eur": 1.0,
"status": "offen",
"ergebnis_pfad": null,
"beschreibung": "...",
"anlage_ts": "1785703372",
"in_arbeit_ts": null,
"fertig_ts": null
}
```
Pflicht-Felder: `task_id, ziel_agent, aufgabentyp, priorität, budget_limit_eur,
status, ergebnis_pfad, original_ziel_agent`.
## Rollen & Regeln
### Executor (Sub-Agent)
1. **Pollt alle 10s** `tasks/offen/`, zeitversetzt pro Agent (z.B. Sek. 10/20/40/50)
2. Greift nur Tasks, deren `ziel_agent` seine Agent-ID/IP trägt
3. `offen/` → `in_arbeit/` (vor Bearbeitung; Dateiname erhält Präfix aus den
**letzten zwei ZT-IP-Oktetten**, z.B. `34.142_T2026....json`, für Log-Nachvollziehbarkeit)
4. Ergebnis schreiben, dann `in_arbeit/` → `fertig/` (Erfolg) oder → `bugfix/`?
**NEIN** — Executor archiviert/entscheidet NIE über `bugfix/` oder `archiv/`;
nur Master entscheidet final. Bei eigenem Fehler meldet er über die Datei/Log.
### Master (Hub)
- **Polling/Ausfall-Fallback:** **WIEDER AKTIV seit 2026-08-06**, aber im **sanften `nur_alarm`-Modus**
(KEIN Auto-Relabel auf `"beliebig"` mehr). Parametrisiert: `VERPASST=180s` (3× Polling-Zyklus 30–60s),
**Ping-Check** (Alarm nur wenn Ziel-Agent wirklich `down`, sonst still bei busy/slow), Cron alle 60s
(`* * * * * /usr/local/bin/mesh-master-poller.sh`), Alarm → Event-Log `AUSFALL_ALARM`, Master entscheidet
manuell. Historie + Begründung: `references/failover-poller-2026-08-06.md`.
- **Retry:** Ergebnisse in `fertig/` prüfen; passt nichts → `bugfix/`; wirklich
abgeschlossen → `archiv/`.
- `bugged/finished/…`-Retry-Counter nach Bedarf (siehe Retry-Logik in blueprint)
> ⚠️ **Nutzergrundregel (2026-08-06): Bevor Betriebs-Zeitparameter geändert werden (Failover-Fenster,
> Polling-Intervalle u.Ä.), IMMER erst den Problemlöser konsultieren** — nicht selber raten/sofort umsetzen.
> Nutzer sagte explizit: „zeiten erfragen noch mit problemlöser vorher" und war verärgert, dass der
> Master Zeiten eigenmächtig setzen wollte. Ablauf: Brainstorming-Skill `brainstorm` an einen online-
> rechenstarken Agenten (UnraidHermes .34.142) senden mit klarer JSON-Abfrage, Ergebnis validieren, DANN
> umsetzen. Der 03.08.-Fehler (30s zu aggressiv) passierte genau durch Setzen ohne Abstimmung.
## Share-Zugriff (SSH/scp — NICHT mehr NFS!)
**Seit 2026-08-03 ist NFS OBSOLET.** Alle Sub-Agenten laden/bearbeiten/verschieben
Tasks über **SSH/scp mit Key-Auth** (verschlüsselt). Grund: NFS überträgt plaintext
(Man-in-the-Middle-fähig); SSH ist Ende-zu-Ende verschlüsselt, zeigt nur eigene Tasks
(Key-Auth) und ist auditierbar.
- `/srv/work/tasks/` bleibt die **zentrale Ablage auf dem Master**; kein Mount nötig.
- Sub-Agent pullt eigene Tasks per `scp` (`offen/<JahrMonatTag>.<C>.<D>.*.json`),
sperrt per remote-`mv` (absolut Pfade), schreibt Ergebnis, push nach `fertig/`.
- Jeder Agent hat eigenen ed25519-Key (`/root/.ssh/<agent>_mesh` auf Master, Public-Key in authorized_keys).
- **SSH_CMD MUSS den Host enthalten**, sonst `hostname contains invalid characters` → endlose SKIPs.
- Daemon: systemd-user-service (Loop alle 10s) — NICHT nohup/Cron-@reboot (stirbt bei SSH-Session-Ende).
- **Wichtigster Fix überhaupt:** Task-Dateien mit `chmod 0666` anlegen UND nach jedem `mv` setzen —
vom Master (root) erstellte/mit `mv` bewegte Dateien sind sonst für Sub-Agenten (uid 1000) unschreibbar
→ `PermissionError [Errno 13]` / Polling „funktioniert nie".
- **fail2ban-Whitelist:** `ignoreip = <alle ZT-IPs>` in `[sshd]`-Sektion von jail.local, sonst bannt
fail2ban die Mesh-IPs bei scp-Fehlschlägen → „Connection refused" trotz Ping ok.
- NFS-Server auf dem Master ist **deaktiviert** (`systemctl disable nfs-kernel-server rpcbind`),
NFS-Ports (2049/111/20048) aus UFW entfernt.
> ⚠️ _Nur falls doch NFS nötig:_ Export auf die **4 bekannten IPs** statt `/16` zur defense-in-depth,
> und UFW + Export konsistent halten. Details: `references/ssh-scp-task-polling-2026-08-03.md`.
## Workflow-Beispiel
1. Master legt Task in `offen/` ab (JSON) — `mesh-task-create.sh <ziel> <auftrag> <typ> <prio>`
2. Sub-Agent pollt alle 10s (systemd-user-service), pullt eigene Task per scp,
sperrt per remote-`mv` → `in_arbeit/`, bearbeitet via `hermes chat`, schreibt `result`
3. Pusht nach `fertig/` (remote-`mv`)
4. Master verifiziert `fertig/`; nur Master entscheidet über `bugfix/` oder `archiv/`
5. Optional: Artefakte auf Dokumentations-Website spiegeln (`dokumentationen.perfekt-ohne-en.de`)
— `mesh-master-report.sh` generiert die HTML-Doku live aus /srv/work/tasks
## Brainstorming verteilen (Multi-Perspektive, bewährt 2026-08-04)
Nutzerliebling-Ansatz: **zwei Rechen-Agenten bekommen DIESELBE Aufgabe aus unterschiedlichen**
Perspektiven, Master synthetisiert. Bewährte Kombination (TicTacToe & PersoEnt):
- **UnraidHermes** (34.142, Entwickler) → `brainstorm`: 2-3 Ausbau-/Lösungs-Optionen + Empfehlung
- **SwitchHermes** (20.26, Cockpit) ODER **LaptopHermes** (178.202) → `brainstorm` mit
**KRITIK-Perspektive**: Annahmen angreifen, größtes Risiko, robustere MVP-Version
Abwechselndes Ergebnis ist der Mehrwert: Der „Ausbau"-Agent liefert die naive/ambitionierte
Idee, der „KRITIK"-Agent falsifikiert sie gegen reale Beschränkungen (z.B. TicTacToe:
Minimax unspielbar → Schwierigkeitsstufen vs. KRITIK: zu viele Stufen schlecht, X/O-Wahl
kleiner + risikofrei). Master = Entscheider nach Verifikation.
## Skripte (Master, auf dem Hub/VPS) — Präfix `mesh-` (seit 2026-08-03 umbenannt von `duo-`)
- `scripts/master-task-handler.sh` — (älterer) Master-Cron mit Lock, Validierung, Retry
- `mesh-task-create.sh <ziel> <auftrag> <typ> <prio>` — legt JSON-Task ab (Dateiname `JahrMonatTag.C.D.Auftrag.json`, setzt 0666)
- `mesh-master-poller.sh` — Ausfall-Erkennung; **AKTIV seit 2026-08-06** (`nur_alarm`-Modus, `VERPASST=180s`,
Ping-Check; Flag `AUSFALL_FALLBACK_AKTIV=1`), setzt NICHT auf "beliebig"
- `mesh-master-report.sh` — generiert Doku-Website live aus den Task-Ordnern
- `mesh-agent-poller.sh <meine-ip> <meine-id> [master] [keyfile]` — Sub-Agent-Poller (Pull/scp + remote-mv-Lock + hermes chat + push)
- `mesh-poller-daemon.sh` — Loop alle 10s als systemd-user-service (robust, überlebt SSH-Session-Ende)
- `mesh-daily-archive.sh` — Tages-Archiv (23:50), `mesh-log.sh` — Ereignis-Log
## Dokumentation (Nutzer-Präferenz: IMMER sichtbar)
Der Nutzer verlangt, dass **jede Aktion automatisch dokumentiert und jederzeit
einsehbar** ist. Betreibe das Doku-Subsystem aktiv:
- `mesh-log.sh <aktion> <detail> [agent] [kosten]` bei **jeder** Aktion aufrufen
(appendet an `/srv/work/log/events.jsonl`)
- Live-Panel: `Dokumentationen.perfekt-ohne-en.de` (Tasks, Agenten, Kosten, 40 Events)
- Tages-Archiv: `Archiv.perfekt-ohne-en.de` (täglich 23:50 Zusammenfassung)
Details, Skripte & Pitfalls: `references/dokumentation-archiv-2026-08-03.md`
## References
- `references/file-task-queue-srv-work.md` — ausführliche Doku + Samba/Pitfalls
- `references/ssh-scp-task-polling-2026-08-03.md` — 🔑 SSH/scp-Umbau: NFS obsolet, Key-Auth,
systemd-daemon, alle Pitfalls (SSH_CMD-Host, chmod 0666, fail2ban-Whitelist, Doppel-Daemon)
- `references/failover-poller-2026-08-06.md` — 🔑 Failover-Poller-Reaktivierung (`nur_alarm`, 180s,
Ping-Check) + Nutzerregel \"Zeiten erst mit Problemlöser abstimmen\" + Update-Cadence (wöchentlich)
- `references/persoent-google-health-2026-08-07.md` — 🔑 PersoEnt: Google Fit REST ist deprecated, Health
Connect hat KEINE Server-REST-API → PersoEnt muss native App werden (Android Health-Connect-SDK + iOS
HealthKit) statt Website. Entscheidung: erst Android-APK (Nutzer testet am Handy), iOS später. Toolchain-
Status auf VPS/LaptopHermes + Baustraßen-Optionen A/B.
- Der konkrete APK-Build-Workflow (Flutter-SDK-Setup auf headless VPS, git safe.directory-Fix,
AGP-namespace-Pitfall, Webroot-Download) liegt im Skill **`mobile-apk-flutter-build`** (devops).
- `references/ssh-key-distribution-master-control.md` — 🔑 SSH-Key-Verteilung an Sub-Agenten (Workaround
wenn Tasks nicht ziehen), Master Control Suite (Notfall-Tools + Budget-Report), OS-Update via SSH,
Gateway-Auto-Start nach Reboot, Budget-Report-Format (Bullet-Liste für Handy).**Füge ein `# Sub-Agent Task Format: Executable vs Analysis (2026-08-28)`**
**Critical lesson:** Sub-Agenten fuehren Aufgaben NUR aus, wenn der Task eine einzige,
klare Befehls-Instruktion enthaelt. Lange Beschreibungen fuehren zu Analyse statt Aktion.
| Format | Ergebnis |
|--------|----------|
| Lange Beschreibung (5+ Saetze, Kontext) | Sub-Agent analysiert, bricht ab ❌ |
| Kurzer Befehl mit `befehl`-Feld | Fuehrt aus, meldet Ergebnis ✅ |
Regel: **Nur `befehl`- und `ansage`-Feld. KEINE Analyse, kein Kontext.**
### SSH-Key-Verteilung per Task (Henne-Ei-Problem)
Master braucht SSH zu Sub-Agenten (Kill-Switch, Notfall), hat aber keinen Key dort.
Key per Task verteilen scheitert, weil Sub-Agenten kein Terminal fuer `echo pubkey >>
authorized_keys` haben (nur `execute_code`/Python).
**Sofortloesung:** Manuell auf jedem Sub-Agenten ausfuehren:
```
mkdir -p ~/.ssh && echo '<master-pubkey>' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
```
## Master Control Suite (Notfall-Tools, 2026-08-28)
| Skript | Funktion | Cron |
|--------|----------|------|
| `/usr/local/bin/mesh-kill-all.sh` | Notfall: Alle auf Ollama | Manuell |
| `/usr/local/bin/mesh-budget-watch.sh` | Guthaben prüfen, Auto-Switch | `*/30 * * * *` |
| `/usr/local/bin/mesh-model-broadcast.sh` | Modell auf allen setzen | Manuell |
| `/usr/local/bin/mesh-status-monitor.sh` | Task-Antworten + SSH tracken | `*/30 * * * *` |
| `/usr/local/bin/mesh-model-scout.py` | Modelle scouten (alle 3 Tage) | `0 6 */3 * *` |
**Budget-Schwellen:** <$1 Warnung | <$0.50 Auto-Ollama | <$0.10 Stopp
## Pitfalls
- **Nutzer akzeptiert KEINEN manuellen Relay.** Agents müssen sich über den
Share direkt verständigen; der Nutzer ist nur für kostenpflichtige Aktionen
(Essen bestellen, Token-Kauf) involviert.
- **Task in `todo/` reicht NICHT** ohne Master/Executor-Cron auf der Gegenseite
— sonst liegt die Aufgabe ewig (wie Message Bus ohne Poll-Cron).
- **Verwaistes Ergebnis-Slot:** Aufgabenliste auf einer Webseite zeigt den
Status live aus dem Share; immer den passenden Render-Pfad `/completed/` anlegen.
- **`ls /path/*.json` unter `set -euo pipefail` bricht mit Exit 2 ab** bei
leerem Glob (kein Match → Skript endet still, Datei wird nie erzeugt).
Fix: `shopt -s nullglob` um die Zähl-Loops in `mesh-master-report.sh` und
`mesh-daily-archive.sh`. Symptom: curl auf die Site = 403/404, obwohl der
vhost existiert.
- **Netzwerk konsolidieren:** nur EIN aktives ZeroTier-Netzwerk im Mesh —
alte Netzwerk-IDs/Subnetze vollständig aus Skills, Config und UFW entfernen.
- **`SSH_CMD` ohne Host** → `hostname contains invalid characters` + leerer Lock-Output
(endet als SKIP-Schleife, obwohl der manuelle mv klappt). Host IMMER in `SSH_CMD` einfügen.
- **root-eigene Task-Dateien unschreibbar für Sub-Agenten** (uid 1000): `PermissionError [Errno 13]`
selbst bei 0777-Dir. Fix: `chmod 0666` bei Task-Erstellung und nach jedem `mv` (in_arbeit + fertig).
- **fail2ban bannt Mesh-IPs** → `Connection refused` auf :22 obwohl Ping klappt. Fix: `ignoreip`
mit allen ZT-IPs in `[sshd]`-Sektion von `/etc/fail2ban/jail.local`.
- **Kontext für Sub-Agenten IMMER in die Task-Beschreibung einbetten — nie als externe Datei.**
Agenten sehen per SSH/scp NUR `/srv/work/tasks/`, nicht `/srv/work/` oder `/root/`. Ein
„Briefing pfad" wie `/srv/work/briefing_x.md` ist für den Agenten unsichtbar → er weiß den
Projektkontext nicht und halluziniert (diagnostiziert 2026-08-04: LaptopHermes erfand „HR-Kausal-KI",
weil er nicht wusste, dass PersoEnt eine Gesundheitsplattform ist). Fix: vollen Kontext als
Detail-Parameter 6 in die Task-Beschreibung (`mesh-task-create.sh <ziel> <auftrag> <typ> <prio>
<budget> \\\"Kontext: ... Aufgabe: ...\\\"`). Erst dann ist ein Verteil-Task zuverlässig.
- **Sub-Agent-Review per URL scheitert → IMMER Seiteninhalt einbetten!**
URLs allein reichen nicht. Sub-Agenten (besonders SwitchHermes auf ARM64) laden oft keine externen
URLs oder stoßen an Tool-Limits. `curl -s "https://domain.de/"` liefert leeres Resultat.
**Fix:** HTML + CSS + relevante Textauszüge DIREKT in die Task-Beschreibung. Nie: "Prüfe die URL".
Sondern: "Hier der HTML-Code: <...>. Prüfe Kontrast/Lesbarkeit."
- **Kurzwort "Briefing" (Nutzerwunsch 2026-08-06):** = das standardisierte Kontext-Übergabe-Dokument
(Ziel / Entscheidungen / Begriffe / offene Fragen / Grenzen / nächste Schritte — wie ein Session-Handoff).
Ein Wort, große Wirkung. Sagt der Nutzer "Briefing" (z.B. beim Start eines neuen Chats oder als Vorgabe
für einen Agenten-Task), IST genau diese Struktur gemeint — als Master jeweils prüfen: vollständig?
Dann arbeiten; fehlt Kontext → max. 5 Rückfragen.
- **Ziel-Agent offline beim Verteilen → Task auf einen ANDEREN online-Agenten umleiten.**
Der Ziel-Agent kann zwischen Task-Anlage und Poll-Takt ausfallen (z.B. Laptop offline,
„No route to host"). Der Task bleibt dann ewig in `offen/` (Poller greift nicht, da
falsche IP). Fix: Master entfernt den verwaisten `offen/`-Task und legt ihn **manuell neu**
für einen online-Agenten an (z.B. Laptop→SwitchHermes). Den Offline-Task VOLLSTÄNDIG löschen
(kein Doppel-Artefakt in offen + in_arbeit), Ziel-Agent + Dateinamen-Schema (C.D-Oktette) im
neuen Task entsprechend anpassen. Erst das Line-of-Ownership-Log (`mesh-log.sh`) aktualisieren.
- **Sub-Agent hängt in Skill/File-Lade-Schleife statt zu antworten (2026-08-08):** Bei komplexen
Review-/Brainstorm-Tasks (z.B. „Code-Bremse prüfen", „Städte-Liste gegenprüfen") geraten
Rechen-Agenten in einen Loop aus `skill_view(...)`/Dateisuche und stoßen an ihr
Iterationslimit („Reached maximum iterations (3). Requesting summary..."), wobei **kein
verwertbares `# Ergebnis`** ankommt — nur Reasoning-Spur, der Task sieht fälschlich „fertig"
aus. Symptom-Erkennung: `result` enthält die Aufgabe reproduziert/umformuliert statt zu
analysieren; ein `# Ergebnis`-Check im Code ist trügerisch, weil der Marker auch im
Aufgaben-Prompt-Text vorkommt (echtes Ergebnis = Text NACH dem letzten `# Ergebnis`).
**Fix: einfacher + konkreter Prompt, der Skill-Laden explizit verbietet** — z.B.
„Beantworte NUR aus deinem Wissen, LADE KEINE Skills/Dateien, antworte sofort. FRAGE: <konkret>.
UNTER '# Ergebnis'. Deutsch." Ein solcher fokussierter Prompt lieferte zuverlässig saubere
Antworten (2× verifiziert), während der ausführliche „GRUNDGERÜST ... evaluiere ..." die Schleife
auslöste. Master-Rechnung/APIs sowieso als Master selbst ausführen, da Sub-Agenten keinen Zugriff
auf VPS-Dateien/APIs haben — für deren Bestätigung nur minimale, eindimensionale Fragen stellen.
- **Task-Datei-Größen-LLM-Fehlschläge abfangen:** Wenn ein fertiger Task kein echtes Resultat
hat, → `bugfix/` und einfacher neu stellen (nicht denselben komplexen Prompt wiederholen).
- **Master muss Agenten-Ergebnis GEGEN das echte System verifizieren, bevor er darauf baut.**
Sub-Agenten (besonders schwache Modelle) produzieren überzeugend klingende, aber teils
halluzinierte Claims (z.B. „85+ Felder / Form-Builder gebaut", „Backend läuft"). Vor der
Übernahme/Synthese IMMER gegen reale Quellen prüfen: `curl` auf die Live-Domain (Statuscode),
`ls` auf den echten Datei-/Code-Pfad, Schema/Collections per API ansehen, `ss`/`systemctl`
für Services. So zeigte sich z.B. „85+ Felder" nie gebaut (Migration hatte nur `health_records`),
während „PocketBase läuft" stimmte. Baue auf dem **nachgewiesenen Ist-Stand** auf, nicht auf
dem Agenten-Claim. Beide Rechen-Agenten konvergierend = guter Hinweis, aber KEIN Ersatz für
die eigene Master-Verifikation.
- **GENEREITER, NUTZERGEPRÜFT (2026-08-08): Auch der MASTER-eigene Code/Backend gehört durch
Team-Gegenprüfung.** Beim Bau des Flask-Backends lieferten zwar die DATEN vom Team, aber der
Code wurde solo gebaut — der Nutzer fragte zu Recht „Habt ihr euch gegengecheckt?" und eine
kurze Review-Runde fand sofort 2 echte Bugs (DB-Deep-Link-Falschformat + Einwohner-Platzhalter).
**Regel: „Verteilen > Einzelkämpfer" gilt auch für den Master-Selbstbau.** Nach dem Bau einer
eigenständigen Komponente (Backend, Skript, Config) EINEN kompakten Review-Task an ein
Rechen-Agent schicken (mit eingebettetem Kontext, einfachem Prompt — nicht in die
Skill-Lade-Schleife fallen lassen), dann die benannten Fixes prüfen. Spart langfristig mehr,
als der eine Review-Aufruf kostet.
Signatur: `<ziel> <auftrag> <typ> <prio> <budget> <detail>`. Wer den langen Kontext-Prompt
direkt hinter `<prio>` setzt, schreibt ihn in `budget_limit_eur` (Position 5) statt in
`beschreibung` → Task-JSON wird **ungültig** (JSONDecodeError beim Parsen, Poller kann ihn
nicht bearbeiten bzw. legt den Volltext in das Zahl-Feld). Symptom: `beschreibung` bleibt der
reine Auftragsname 2 Zeichen kurz, `budget_limit_eur` enthält den ganzen String. Fix: Budget
explizit angeben und Kontext an Position 6: `mesh-task-create.sh <ziel> <auftrag> <typ> <prio>
1.0 \"<kompletter Kontext + Aufgabe>\"`. Nach Anlage immer JSON validieren
(`python3 -c "import json;json.load(open(...))"`) und `beschreibung`-Länge gegenprüfen.
## Referenzen
- `references/file-task-queue-srv-work.md` — ausführliche Doku + Samba/Pitfalls
- `references/ssh-scp-task-polling-2026-08-03.md` — 🔑 SSH/scp-Umbau: NFS obsolet, Key-Auth,
systemd-daemon, alle Pitfalls (SSH_CMD-Host, chmod 0666, fail2ban-Whitelist, Doppel-Daemon)
- `references/failover-poller-2026-08-06.md` — 🔑 Failover-Poller-Reaktivierung (`nur_alarm`, 180s,
Ping-Check) + Nutzerregel "Zeiten erst mit Problemlöser abstimmen" + Update-Cadence (wöchentlich)
- `references/persoent-google-health-2026-08-07.md` — 🔑 PersoEnt: Google Fit REST ist deprecated, Health
Connect hat KEINE Server-REST-API → PersoEnt muss native App werden (Android Health-Connect-SDK + iOS
HealthKit) statt Website. Entscheidung: erst Android-APK (Nutzer testet am Handy), iOS später. Toolchain-
Status auf VPS/LaptopHermes + Baustraßen-Optionen A/B.
- Der konkrete APK-Build-Workflow (Flutter-SDK-Setup auf headless VPS, git safe.directory-Fix,
AGP-namespace-Pitfall, Webroot-Download) liegt im Skill **`mobile-apk-flutter-build`** (devops).