Files

7.8 KiB
Raw Permalink Blame History

name, description, version, author, platforms
name description version author platforms
web-feature-iteration Web-Features bauen, Revert bei Ablehnung. 1.0.0 Agent A (Deployer)
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.

.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.