Initial: Mesh-Skills, Configs, Scripts
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: web-feature-iteration
|
||||
description: "Web-Features bauen, Revert bei Ablehnung."
|
||||
version: 1.0.0
|
||||
author: Agent A (Deployer)
|
||||
platforms: [linux]
|
||||
---
|
||||
|
||||
# Web-Feature-Iteration (inkrementell für diesen Nutzer)
|
||||
|
||||
Governs how to extend or feature-up an existing interactive web page/app for this
|
||||
user. Learnt the hard way 2026-08-04 on TicTacToe (3D-Relaunch 3× rejected, full revert).
|
||||
|
||||
## Trigger
|
||||
|
||||
- "Neue Funktion einbauen" / "Erweiterung" / "Mach mal 3D / Animation / X dazu"
|
||||
- Erweitern einer **laufenden, bereits spielbaren/nutzbaren** Seite
|
||||
|
||||
---
|
||||
|
||||
## Kerngesetz: lieber klein + funktionierend als schick + kaputt
|
||||
|
||||
Aus der TicTacToe-Session (Nutzer lehnte 3-Mal ab):
|
||||
1. **Minimaler Eingriff zuerst.** Wenn eine Seite funktioniert (z. B. spielbares
|
||||
TicTacToe mit Minimax), baue eine kleine, isolierte Erweiterung — nicht einen
|
||||
glänzenden Redesign (3D-Canvas, neue Engine). Der Nutzer bevorzugt funktionierend vor flashy.
|
||||
2. **Kritik ist wertvoll — Match auf Nutzer-Mehrwert.** Gegen einen perfekten
|
||||
Minimax-Gegner ist "Wer beginnt (X/O)" (≈5 Zeilen, 0 Risiko) mehr wert als
|
||||
Schwierigkeitsstufen, die die perfekte Engine anfassen. Frag: "Was ist die kleinste
|
||||
Änderung mit dem größten echten Nutzen?"
|
||||
3. **Sauberer Revert erwartet.** Wenn der Nutzer "Komplett zurück" / "Geht gar nicht"
|
||||
sagt: sofort den letzten bekannten funktionierenden Stand wiederherstellen (Backup
|
||||
`index-original.html.bak`), tote Assets (geladene lib/) entfernen, über HTTPS verifizieren.
|
||||
Erwartung: Was nichts bringt, wird zurückgenommen, nicht "repariert bis es gefällt".
|
||||
|
||||
## Effektiver 3D/Visual-Anstupser (aus TicTacToe)
|
||||
|
||||
- Hat der Nutzer 3D/Visual-Wunsch, aber die **Interaktion bleibt die Wahrheit**:
|
||||
Wenn ein 3D-Canvas das präzise Klicken unmöglich macht (perspektivisches Klick-Mapping),
|
||||
lehnt der Nutzer ab. Behalte die **präzise 2D-/Affordance-Schicht** (echte anklickbare
|
||||
Zellen statt Canvas-Koordinaten) und rendere die Deko (3D-Steine) DARUNTER/separat.
|
||||
- Pauschale "Glanz"-Erweiterungen (permanente Board-Rotation) machen Spiele unspielbar — vermeiden.
|
||||
|
||||
## Reusable Technik-Pitfalls (Three.js)
|
||||
|
||||
- **`BoxGeometry` hat KEINE `.rotation`-Eigenschaft** (nur `Object3D`: Mesh/Group).
|
||||
`geometry.rotation.z = x` → `TypeError: Cannot set properties of undefined (setting 'z')`.
|
||||
Fix: `geometry.rotateZ(angle)` (BufferGeometry-Methode) oder die Geometrie in ein Mesh
|
||||
packen und das Mesh rotation zulassen.
|
||||
- **Diagnose:** isoliert im Browser `new THREE.X()` testen; den größten Fehler in kleine
|
||||
Schritte zerlegen (Material vs. Geometrie vs. Group) statt die ganze Funktion zu raten.
|
||||
|
||||
### ⚠️ Chart.js/CDN-Abhängigkeit vermeiden — statisches CSS statt JS-Diagramm
|
||||
|
||||
Chart.js von CDN (cdn.jsdelivr.net) lädt auf mobilen Browsern oft nicht oder
|
||||
verzögert. Die `canvas` bleibt dann leer — die Seite sieht aus wie ein
|
||||
dunkles Nichts. Sub-Agenten können nicht prüfen ob das Chart lädt (kein
|
||||
Browser-Zugriff).
|
||||
|
||||
**Fix: Chart.js durch statische CSS-Balken ersetzen.**
|
||||
```css
|
||||
.chart-bar { background: linear-gradient(to top, #4ade80, rgba(74,222,128,0.2)); height: 100%; }
|
||||
```
|
||||
- Kein JS, kein CDN, kein Fallback nötig → immer sichtbar
|
||||
- Keine mobilen Lade-Probleme
|
||||
- Null zusätzliche Ladezeit
|
||||
- Sub-Agenten können den Code im Review sehen
|
||||
|
||||
**Entscheidungsregel:** Wenn ein Diagramm nur Daten-Status zeigt (keine
|
||||
Interaktion nötig), ist CSS die bessere Wahl. Nur wenn der Nutzer aktiv
|
||||
zoomen/filtern/hovern muss, lohnt sich Chart.js/Canvas.
|
||||
|
||||
## Verifikation (immer)
|
||||
|
||||
1. Erst SELBST im echten Browser testen (Seite laden, 1 Spielzug, KI-Antwort, `js_errors` leer),
|
||||
nicht nur `curl` Status 200 behaupten.
|
||||
2. **Kontrast-Check auf der Live-URL:** `curl` allein erkennt keine CSS-Fehler.
|
||||
Prüfe: Sind alle Texte auf hellen Hintergründen lesbar? `--muted` auf `--surface` kann
|
||||
wie schwarz auf schwarz wirken (WCAG-AA 4.5:1 erforderlich). Wenn Browser nicht verfügbar:
|
||||
Hex-Farben gegeneinander halten oder Sub-Agenten den Code visuell prüfen lassen.
|
||||
3. **Nach Deploy: Team-Review über die LIVE-Seite per Sub-Agent, nicht nur den Code.**
|
||||
Nutzer-Vorgabe (hart): "Ihr müsst euch wieder gegengecheckt haben." Nach bestandenem
|
||||
technischen Check (HTTP 200 + nginx-t) einen Review-Task mit **eingebettetem Seiteninhalt**
|
||||
(HTML + CSS) an einen Sub-Agenten schicken. Sub-Agenten können keine externen URLs laden.
|
||||
4. **Nach Revert:** gleicher Browser-Test, damit die wiederhergestellte Seite wirklich läuft.
|
||||
|
||||
## Team-Gegenprüfung ist PFLICHT — nie solo bauen (Nutzer-Grundsatz, 2026-08-09)
|
||||
|
||||
Der Nutzer verlangt es hart (für Alle Ebenen der Arbeit, nicht nur Code): **"Ihr müsst euch wieder gegengecheckt haben; manche Dinge findet man nur im Team."** Mehrfach baute ich ein Backend/Daten-Gerüst allein → der Nutzer fand jedes Mal echte Fehler, die ein Review gefunden hätte. Lektionen:
|
||||
|
||||
- **Daten UND Backend review-en lassen, nicht nur Roh-Daten vom Team holen.** Reine "Schätzwerte einholen" ist kein Gegenchenken. Code, Logik, URL-Formate und Generierung gehören dem Team zum Review vorgelegt.
|
||||
- Sub-Agenten-Review ist wertvoll, aber **nicht immer live-verifiziert**: Ein Sub-Agent bestätigte mir das tote `reiseauskunft.bahn.de`-Format aus "Wissen", ohne es zu testen → shippen gab `DNS_PROBE_FAILED`. **Jede URL-/Endpoint-Empfehlung eines Sub-Agenten vor dem Einbau selbst mit curl/browser prüfen** (DNS + HTTP + ob Parameter wirklich wirken), nicht nur dem Format-Urteil vertrauen.
|
||||
- Wenn der Nutzer systematisch Fehler findet, stoppe und führe eine Review-Runde durch, statt einzeln weiterzubauen.
|
||||
|
||||
## Daten-Generierungs-Pitfalls (mehrstufige Listen/Filter)
|
||||
|
||||
Aus der 3-Ebenen-Zugsuche (urlaub.perfekt-ohne-en.de, Flask+SQLite):
|
||||
|
||||
- **Sortier-Filter schneidet sichtbare Kategorien ab.** Sortiert man Ziele nach Distanz und nimmt `[:N]`, bleiben NUR die nächsten (z. B. nur "unter 5h") — ferne 5-7h/>7h-Ziele "verschwinden". Fix: **je Kategorie** (unter5h / 5-7h / über7h) separat die repräsentativsten N Ziele nehmen, damit alle Kategorien in jeder Liste vertreten bleiben.
|
||||
- **Kategorie aus dem berechneten Wert ableiten, nicht aus einer geplanten Bandbreite.** Wenn Label und berechnete Zeit auseinanderlaufen (z. B. Kategorie "5-7h" aber Zeit ~3h), ist das ein Review-findbarer Inkonsistenz-Bug. Einheit: `kategorie = f(berechne_zeit)`.
|
||||
- **Platzhalter vermeiden.** Pauschale Dummy-Werte (z. B. alle Einwohner=150000) sind Datenfehler — der Nutzer merkt, dass keine echten kleinen Städte drin sind. Entweder echte Werte oder NULL/"k.A.", nie plausible Dummy-Zahl.
|
||||
- Wenn eine Städte-/Ziel-Datenbank auf viele Einträge skaliert (190+ Städte, 10000+ Verbindungen): **generiere deterministisch** aus einer Referenzliste + Distanz-Logik, statt manuell jede Zuordnung zu erfinden. Mit klarer Kategorie- und Zeit-Ableitung.
|
||||
|
||||
## Flask+SQLite für dynamische, user-gepflegte Daten (statt statischer Seiten)
|
||||
|
||||
Bei mehrstufiger Navigation (Ebenen, Klick-Weiterleitung mit `/2/<slug>`-URLs) und vielen Datensätzen: **Backend + SQLite** schlägt statische Generierung.
|
||||
- Eine Datenänderung = eine DB-UPDATE, alle abhängigen Seiten/PDFs aktualisieren sich — statisch wäre ein Full-Rebuild von tausenden Dateien.
|
||||
- Isolate Semantik: URL-Route `/2/<slug>` zuverlässig machen (Bindestriche↔Umlaute: `osnabrueck`, auch `koln`-Formen, mit mehrstufiger Kandidaten-Rücktranskription).
|
||||
- PDF on-demand (wkhtmltopdf) statt vorab für jede Kombination.
|
||||
- Deploy: systemd-Service + nginx reverse_proxy auf `127.0.0.1:<port>` (Muster wie das sshportal-Backend); statische/Server-Reload-Cache: **nach Template-/Code-Änderung Restart**, sonst rendert die laufende App veraltete Templates (äußerte sich als "Kategorie fehlt trotz Fix").
|
||||
|
||||
## Support-Dateien
|
||||
- `references/tic-tac-toe-revert-2026-08-04.md` — Revert-Chronologie + 3D-Gotcha-Detail.
|
||||
- `references/urlaub-3-ebenen-zugsuche-2026-08-09.md` — Mehrstufige Zugsuche: DB-Deep-Link-Deadends, 25k/10k-Schwellen-Umbau, Kategorien-Generator-Prinzip.
|
||||
@@ -0,0 +1,49 @@
|
||||
# TicTacToe 3D-Relaunch → kompletter Revert (2026-08-04)
|
||||
|
||||
Chronologie einer über-engineert-Erweiterung, die der Nutzer 3× ablehnte, und
|
||||
der saubere Revert — als Muster, warum "minimal + funktionierend" gilt.
|
||||
|
||||
## Ablauf
|
||||
|
||||
1. **Ausgangslage:** tictactoe.perfekt-ohne-en.de, statisches HTML/JS, Player (X) gegen
|
||||
KI (O), Minimax (unschlagbar), Flip-Coin-Animation, helles Glas-Design. Funktioniert.
|
||||
2. **Mesh-Brainstorming (Rechen-Agenten):** UnraidHermes empfahl Schwierigkeitsstufen,
|
||||
SwitchHermes (KRITIK) empfahl stattdessen "Wer beginnt (X/O)" — kleinster Eingriff mit
|
||||
größtem Nutzen, weil gegen perfekte KI nur der Startende Remis erzwingen kann.
|
||||
→ Entscheidung: X/O-Wahl als Punkt 3.
|
||||
3. **Umsetzung zu grob:** Statt nur X/O-Wahl wurde ein kompletter 3D-Relaunch gebaut
|
||||
(Three.js, 3D-X aus gekreuzten Balken, 3D-O als Torus, rotierendes 3D-Board).
|
||||
4. **Ablehnung Runde 1:** Nutzer: "Sieht schön aus aber ist wegen der Drehung unspielbar."
|
||||
→ Nur Rotation entfernt.
|
||||
5. **Ablehnung Runde 2:** Nutzer: "Ich klicke blind und verliere" (perspektivisches
|
||||
Canvas-Klick-Mapping ungenau). → 2D-Grid, CSS-3D-Steine.
|
||||
6. **Ablehnung Runde 3:** "Schade ... X und o selbst sollte 3D bleiben." → Three.js echte
|
||||
3D-Steine + unsichtbares 2D-Grid-Overlay für präzise Klicks.
|
||||
7. **Finales "Komplett zurück":** Nutzer zufrieden nur mit der ORIGINAL-Version.
|
||||
→ `cp index-original.html.bak index.html`, `rm -rf lib/`, chown, Re-verify im Browser.
|
||||
|
||||
## Kernlektion
|
||||
|
||||
- Der Nutzer will **funktionierend + vertraut**, nicht **schick + neu**. Eine laufende
|
||||
Seite mit einer blassen Erweiterung anzufassen ist riskant; ein full 3D-Redesign
|
||||
bei einem simplen Spiel war die falsche Hebelgröße.
|
||||
- Die Interaktion (präzises Klicken) ist unverhandelbar. Deko (3D) darf nie die
|
||||
Bedienbarkeit brechen.
|
||||
- Beim ersten "zurück / unspielbar" früh auf minimalen Stand zurück (nicht "reparieren
|
||||
bis es gefällt") — spart · die 3 Wiederversuche.
|
||||
|
||||
## Was gut war & bleibt
|
||||
|
||||
- **Mesh-Brainstorming lief gut:** beide Rechen-Agenten (UnraidHermes + SwitchHermes)
|
||||
lieferten substantielle, kritisch geprüfte Ideen mit eingebettetem Kontext in die
|
||||
Task-Beschreibung (Briefing-Pitfall: NIE externe Datei — Agenten sehen nur /srv/work/tasks/).
|
||||
- **Gegenprüfung:** LaptopHermes offline → KRITIK-Task an SwitchHermes umgeleitet, lief sauber.
|
||||
|
||||
## Three.js-Gotcha (Detail)
|
||||
|
||||
`BoxGeometry`/`BufferGeometry` haben KEINE `.rotation`-Eigenschaft — nur `Object3D`
|
||||
(Mesh, Group) haben das. `g1.rotation.z = Math.PI/4` wirft
|
||||
`TypeError: Cannot set properties of undefined (setting 'z')`.
|
||||
Fix: `g1.rotateZ(Math.PI/4)` (Geometrie-Methode) oder Geometrie in ein Mesh packen.
|
||||
Isolierter Browser-Test (`new THREE.BoxGeometry(...)`, `new THREE.MeshPhysicalMaterial(...)`)
|
||||
half, den Fehler auf die Geometrie-Zeile einzugrenzen.
|
||||
@@ -0,0 +1,43 @@
|
||||
# urlaub.perfekt-ohne-en.de — 3-Ebenen-Zugsuche (2026-08-09)
|
||||
|
||||
Referenz für mehrstufige, DB-gestützte Navigations-Web-App. Gelernt beim Bau einer
|
||||
3-Ebenen-Zugziele-Suche (Radevormwald → 100k → 50k/25k → 25k/10k).
|
||||
|
||||
## Architektur (endgültig)
|
||||
- Flask + SQLite (`/opt/urlaub/urlaub.db`), Routen: `/`, `/2/<slug>`, `/3/<slug>`, `/pdf/<stadt>`, `/dbauskunft/<von>/<nach>`
|
||||
- Templates: `ebene.html` (Kategorien als `selectattr`), `pdf.html`, `leer.html`
|
||||
- systemd `urlaub.service` + nginx reverse_proxy auf `127.0.0.1:8040`
|
||||
- PDF on-demand via `wkhtmltopdf` (ein `/tmp/urlaub-html/*.html` je Stadt)
|
||||
|
||||
## DB-Deep-Link — DEAD ENDS (wichtig, verifiziert 08.08)
|
||||
Nutzer-Wunsch: ein Button, der bahn.de mit vorbefüllter Suche öffnet.
|
||||
**Alle Deep-Link-Formate sind kaputt/nicht zuverlässig:**
|
||||
- `reiseauskunft.bahn.de` → **toter DNS** (`DNS_PROBE_FAILED_NXDOMAIN`). Sub-Agent "bestätigte" dieses Format aus altem Wissen — **musste live getestet werden**.
|
||||
- `reiseauskunft.de/bin/query.exe/dn?...` → toter Pfad ("Seite existiert nicht mehr")
|
||||
- `www.bahn.de/buchung/fahrplan/suche?von=..&nach=..&..` → SPA übernimmt Query-Parameter NICHT
|
||||
- `#query=start:X;destination:Y` → fragil, übernimmt nicht zuverlässig
|
||||
|
||||
**Lösung:** ehrliche Zwischenseite — zeigt Start/Ziel (readonly), Button + Fallback-Link auf
|
||||
`https://www.bahn.de/buchung/fahrplan/suche` (verifiziert HTTP 200). Nutzer trägt Start/Ziel
|
||||
manuell ein (paar Sekunden). Kein fabrizierter zuverlässiger Deep-Link.
|
||||
|
||||
## Daten-Pitfalls
|
||||
- **Sortier-Filter-Bug:** `sorted(nach Distanz)[:N]` → nur nächste Ziele, alle fernen
|
||||
5-7h/>7h-Kategorien "verschwinden". Fix: je Kategorie (unter5h/5-7h/über7h) die nächsten N.
|
||||
- **Kategorie aus berechneter Zeit** ableiten (`h=d/70`, kategorisiere auf h), nicht aus
|
||||
Distanz-Bandbreite — sonst Label widerspricht Zeit.
|
||||
- **Platzhalter-Einwohner (alle 150000)** waren als "keine echten kleinen Städte" erkennbar.
|
||||
Fix: echte Werte aus Referenzliste.
|
||||
- Schwellen-Umbau im Nutzer-Konsens: E2 = 25k, E3 = 10k (nicht 50k/25k). Anzahl Städte ~
|
||||
≥100k:80, ≥50k:~180-200, ≥25k:~400-450, ≥10k:~900-1100. Diese "mehr Städte bei tieferer
|
||||
Schwelle"-Erwartung des Nutzers war korrekt.
|
||||
|
||||
## Abdeckung/Deep-Links
|
||||
- Jede Ebene-Ziel sollte klickbar zur nächsten Ebene sein; bei finaler Ebene (z.B. 3) dürfen
|
||||
Links nicht auf nicht-existente `/4/` zeigen (wäre 404-Dangling) — Endpunkt als `(final)` markieren.
|
||||
- Umlaute in URLs: slug erzeugt `osnabrueck` via ae/oe/ue/ss-Transkription; Route muss
|
||||
MEHRERE Kandidaten durchprobieren (`wuerzburg`, `würzburg`, `wurzburg`) inkl. umgekehrte
|
||||
Richtung (`koln` → `Köln`). Wir praxis: `LOWER(replace(nach,' ',''))`-Vergleich.
|
||||
|
||||
## Mengen (zur Orientierung)
|
||||
- Ebene1: 33 Ziele (100k+). Ebene2 (25k): ~1946. Ebene3 (10k): ~10222. (Nach Kategorien-Balance.)
|
||||
Reference in New Issue
Block a user