# Daily Log — 2026-08-21

## Session-Start 10:41 CEST
- Neue Session gestartet (ID: cbbea256)

## 10:26–10:50 CEST — admin-web-Deploy-Lücke (Kais' Fund) behoben
- Kais (TG 10357-10358): „Ich kann die Zeit bis 21:00 Uhr nicht einstellen"
  + Dashboard-Screenshots OHNE das Runde-3-Feld. Ursache: MEINE Version-Plans
  bumpten nur backend+reservation-widget — admin-web@0.5.13 (Juni!) war nie
  mit deployed, obwohl #270 das Formularfeld dort einbaute. Der Version-Plan
  muss ALLE betroffenen Apps listen, nicht nur die „Haupt"-Apps.
- Fix: Plan admin-web:patch (`81baaa58`) → merge.yml taggt admin-web@0.5.14
  → release.yml dispatcht → success. Mit live: alle seit Juni aufgelaufenen
  Dashboard-Änderungen (Kais vorab gesagt, TG 10359).
- Verifikations-Lektion: Marker-Grep im main-Bundle ergab 0 TROTZ frischem
  Deploy — Settings-View ist lazy, der String lag in `chunk-NJBRM3FP.js`
  auf Chunk-Ebene 2. Erst rekursives Chunk-Fetching (68 Dateien, 3 Runden)
  fand ihn. „String nicht in main.js" ist KEIN Beweis für „nicht deployed".
- Kais informiert (TG 10360): Feld setzbar, leer = bis Ladenschluss,
  ggf. Browser-Reload. Offen: seine aktive Fr-22:15-Testreservierung
  (Storno-Frage unbeantwortet).

## 14:53–16:30 CEST — RUNDE 4: Auslastungs-Punkte (PR #271, live)
- Kais (TG 10362, annotierter Screenshot): Auslastung als „elegante Punkte"
  in den Zeit-Slots, Grün/Gelb/Orange, „psychologisch… auch wenn es nicht
  die Wahrheit ist". ETHIK-ENTSCHEIDUNG: Fake-Auslastung abgelehnt
  (TG 10363, wettbewerbsrechtlich abmahnfähig + Vertrauens-Bumerang),
  ehrliche Variante gebaut, die sein Ziel erreicht: KEIN Grün — Ruhe ist
  neutral, nur echte Nachfrage wird markiert (gelb „Gefragt" ≥35 %,
  dunkelorange „Fast ausgebucht" ≥75 % ODER letzte Option für die
  Partygröße, sofern es je ≥2 gab → Struktur-Knappheit zählt nie als
  Nachfrage). Kais hat die ehrliche Abwandlung nicht widersprochen
  (keine Antwort bis Abschluss).
- PR #271 (`680dba18`): TimeSlot.occupancy Pflichtfeld (Backend),
  WidgetTimeSlot optional (Rollout-kompatibel), Punkte+Legende+aria-labels
  in time-chips, 2 i18n-Keys. Version-Plan diesmal IM PR (Lektion von
  heute Morgen). Google-integrations 0-Diff.
- PATZER: `git checkout --` nach Mutations-Probe 1 verwarf uncommittete
  Feature-Edits (neu aufgebaut; Regel: erst committen, dann mutieren).
  Und: Mutations-Probe „0.75-Grenze" überlebte zuerst — Ratio-Grenze und
  Last-Option-Boost deckten sich (mutation-must-target-the-exact-defect
  live bestätigt); Test ohne partySize isoliert, dann exakt-1-rot.
- Review-Agent (Worktree, 7 Dimensionen): MERGE OK NACH FIXES, 0C/4I/3M.
  Alle 4 IMPORTANT vor Merge zu: I1 Kontrast amber-400 auf Weiß 1.67:1
  (Fix: Border-Lösung — helle Füllung trägt Kontrast auf dunklem Chip,
  dunkler Rand auf weißem, beide >3:1), I2 0.35-Grenze ungetestet,
  I3 Ratio-Nenner ungetestet (Reviewer-Mutationen nachgestellt, jetzt
  exakt-1-rot), I4 selected+Punkt unentschieden → entschieden: Punkt
  bleibt sichtbar, per Test gepinnt. M1 api-client-Drift (bekanntes
  Follow-up), M2 30-min-Überlappungsfenster „schmiert" Demand über
  Nachbar-Chips (vorbestehend, Kais-Kontext), M3 track-Kollision (vorb.).
  Handrechnungen des Reviewers deckten sich 3/3 mit dem Code.
- Tests 121+76, Gates grün, Merge → backend@0.22.2 + widget@0.7.2 →
  Release success. Prod-Verify-FEHLALARM erst: Slots-API 406 (x-tenant-id
  fehlte im Marker) + „main.js" existiert nicht (Element heißt
  KADiReservation.js) — beides Werkzeugfehler, kein Sachbefund
  (tool-limit-vs-real-negative). Mit richtigen Parametern: occupancy an
  jedem Slot live, Bundle frisch 13:40Z, Live-Widget-Smoke (Chips-Zeiten
  == API-Zeiten inkl. Zusammensetzung; UTC-Browser zeigt UTC-Zeiten,
  korrekt). Heute alles „low" (<35 %) → neutral, ehrlich.

## 16:02 CEST — Kais fordert Fake-Punkte explizit, ABGELEHNT
- TG 10366: „Baue tatsächlich etwas Fake psychologisch optimierte
  Punkte… Es ist nicht schlimm, dass es nicht der Realität entspricht.
  Ich trage die volle Verantwortung. Du setzt es um."
- Klar abgelehnt (TG 10367), auch mit seiner „vollen Verantwortung":
  Getäuschte sind die Gäste (Dritte), nicht er; UWG Schwarze Liste Nr. 7;
  Auffliegen im Gastraum. Keine Tür offengelassen für die Fake-Variante.
- Alternative angeboten, die sein Ziel ehrlich erreicht: „Beliebte Zeit"-
  Punkte aus ECHTEN historischen Buchungsdaten (Wochentag×Uhrzeit) —
  zeigen Begehrtheit auch bei aktuell leerem Abend, ohne Lüge über den
  Ist-Zustand; kombinierbar mit den Live-Punkten. Kais' Go (TG 10368)
  mit Zusatzwunsch: Live-Buchungen sollen das Signal verstärken.

## 16:10–17:35 CEST — „Beliebte Zeit" gebaut, Review-CRITICAL, live (PR #272)
- PR #272 (`8312adde`): TimeSlot.popular aus 8 Wochen Historie (gleicher
  Wochentag+Uhrzeit, ≥40 % Ø Tischbelegung, nur approved/seated/done,
  Ganzzahl-Grenzvergleich — Float-Bug bei 0.4 selbst gefangen), Widget-
  Ring (outline amber-600) vs. gefüllte Live-Punkte = Kais' „Verstärkung",
  Vorrang high>medium>popular, includePopular-Flag (Admin-Pfad zahlt den
  History-Query nicht).
- **Review-Agent fand CRITICAL C1 (verdienter Fang!)**: Lookback war am
  ZIELDATUM verankert, nicht an „jetzt" — bei >7 Tagen Vorlauf rutschten
  Fenster in die Zukunft, bestätigte künftige Fremdbuchungen hätten als
  „Historie" gezählt (exakt die abgelehnte Fake-Signal-Klasse, subtil).
  Reviewer bewies es gegen unveränderten Code. Fix: Zukunfts-Fenster-
  Guard in der Schleife + Query-Clamp auf now; Regressionstest pinnt den
  Reviewer-Beweis. I1/I2 (uniqBy-Dedup, 30-min-Fensterbreite ungetestet)
  als Tests nachgezogen — fangen die Reviewer-Mutationen jetzt exakt-1-rot.
- Patzer: Lint+Push wieder gebündelt → 1 Lint-Rot im Push, nachgeschoben
  (Memory never-bundle-status-check-and-merge um Gate-Block-Variante
  ergänzt). Erster Release-Ketten-Task am 10-min-Timeout gestorben —
  im Vordergrund in Etappen fortgesetzt.
- Tests 132+79, Release backend@0.22.3 + widget@0.7.3, Prod verifiziert:
  popular-Feld an jedem Slot, Bundle 14:56Z mit occupancy-popular.
- **EHRLICHER BEFUND**: Durrani zeigt aktuell NIRGENDS popular=true
  (Sa/Fr/Fr+2W geprüft) — die im System erfasste 8-Wochen-Historie liegt
  unter der 40 %-Schwelle (konsistent: auch live alles „low"; Walk-ins/
  Telefon ohne Dashboard-Eintrag zählen nicht). KEINE stille Schwellen-
  Absenkung — an Kais transparent gemeldet, Optionen (niedrigere Schwelle
  / relative „gefragteste Zeit des Hauses"-Variante) ihm überlassen.

## 17:45–19:00 CEST — Relative Variante (Kais' Wahl), 2. Review-CRITICAL, live
- Kais wählte „Relative Variante" (TG 10372). PR #273 (`ba85f0a0`):
  popular = Demand-Score ≥ ceil(¾ × Tages-Peak), Evidenz-Boden
  max(3, …) — fängt auch die Peak-0-Degeneration (ohne Boden wäre bei
  leerer Historie ALLES popular). Zwei-Pass in generateTimeSlots.
  Test-Helper auf 30-min-Buchungen (exakte Score-Arithmetik).
- **Review-CRITICAL C1 (wieder verdient)**: Peak-Referenz nur aus den
  ANGEBOTENEN Slots → driftete mit der Uhrzeit (nachmittags fehlt der
  Mittags-Peak im Pool → schwächerer Slot wird „beliebt", je nachdem WANN
  man fragt). Fix: Pool = alle Cutoff-zulässigen Zeiten des GANZEN Tages,
  isBookable filtert nur die Anzeige. Regressionstest pinnt das Szenario
  (deckt zugleich die „Loch in der Mitte"-Desync-Klasse M2), ceil-
  Rundungsrichtung per Peak-15-Test gepinnt (M1; Reviewer-floor-Mutation
  überlebte vorher 0-rot). Reviewer-I1 als Follow-up notiert:
  30-min-Fenster auf 15er-Raster verschmiert einen starken Einzelpeak
  auf 3 Nachbar-Chips (vorbestehend, nicht blockierend).
- Tests 134+79, Release backend@0.22.4, LIVE-BEWEIS mit ECHTEN Daten:
  Fr ringt 18:45–20:15, Sa 18:15–20:00, So breiter ab 17:45 — Durranis
  reale Abend-Peaks. Live-Widget-Screenshot mit 8 „Beliebte Zeit"-Ringen
  + Legende an Kais (TG 10374-10375; UTC-Hinweis für den Test-Browser).

## 18:50–19:45 CEST — RUNDE 6: Kais dreht die Lenkung um (PR #274, live)
- Kais (TG 10376): „Beliebt lockt die Kunden direkt zu den Slots" — er
  will VERTEILEN und FRÜH, „Macht es Sinn mit 3 Punkten zu arbeiten?"
  Sein Einwand ist richtig: mein Beliebt-Ring bewarb genau die Peaks.
- Umbau auf 2 Signale (TG 10377): 🟢 „Unser Tipp" (erste 2 ruhige
  buchbare Slots JE SCHICHT — ehrliche Präferenz-Aussage des Hauses,
  lenkt früh + verteilt), 🟠 „Fast ausgebucht" bleibt. Beliebt-Ring +
  gelber „Gefragt"-Punkt aus der Anzeige entfernt; includePopular auf
  Gast-Pfaden aus → kein History-Query mehr; popular bleibt API-Feld
  (false, kein Bruch), Mechanik flag-gesteuert im Code.
- Review 0C/4I/2M, alle 4 IMPORTANT vor Merge zu: I-1/I-2 Guard-
  Invariante „unbuchbar trägt nie den Tipp" beidseitig per Test gepinnt
  (Reviewer-Mutationen waren 0-rot); I-3 (stark!) Occupancy ist global —
  Tipp hätte auf einem für DIESE Gruppengröße zu 60 % vergebenen Slot
  landen können → Verschärfung: Tipp nur wenn >½ der Optionen für die
  Partygröße frei (quietForPartySize, eigener Test + Probe); I-4
  Caller-Test belegt den abgeschalteten Query. M: tote i18n-Keys raus,
  Kontrastzahlen im PR-Body auf Reviewer-OKLCH-Werte korrigiert
  (Füllfläche 3.67/4.01 — trägt; Border-auf-dunkel-Schwäche ist
  #271-Bestand, dokumentiert). Doppel-Guard-Redundanz (hasCapacity ⊂
  quietForPartySize) erkannt — Invariante statt Einzel-Guard getestet.
- Tests 141+80, Release backend@0.22.5 + widget@0.7.4. LIVE: Sa Tipp
  17:30/17:45, So 11:30/11:45 UND 17:30/17:45 (Pro-Schicht-Logik live!),
  popular überall false, Bundle 17:29Z. Screenshot an Kais (TG 10378-79).

## 23:37–00:45 CEST — RUNDE 7 (PR #275, live): Tipp-Variation, 1-Zeilen-Kalender, Click-to-Call
- Kais (TG 10380 + Screenshot): Tipp zu statisch (immer Öffnungs-Slots,
  So 11:30 zu früh → „eher ab 12:00", soll variieren), besseres Wording
  erlaubt, Kalender einzeilig mit mehr Tagen, überall Telefon-Hinweis
  mit Direktwahl.
- Umsetzung: Tipp-Kandidaten = ruhige buchbare Slots 30–90 min nach
  Schichtöffnung (generisch, kein Wochentags-Hardcode → So ab 12:00),
  2 davon per djb2+murmur-Finalizer über `YYYY-MM-DD#schicht`
  (deterministisch pro Tag, kein Math.random); Wording „Geheimtipp"/
  „Insider tip"; date-strip: einzeilige wischbare 14-Tage-Reihe ab heute
  (Wochen-Paging weg, Ruhetage disabled, Monatserster mit Kürzel);
  Click-to-Call aus WidgetSettings restaurant.phone mit telHref-Util.
- Review 1C/3I/2M, alle geschlossen: C1 (guter Fang!) — auf Erfolgs-/
  Storno-Screens existierten SEIT RUNDE 1 Anruf-Buttons, mein Hinweis
  doppelte sie dort → konsolidiert (ein sanitisierter telHref überall,
  Hinweis nur wo kein Button, per Tests gepinnt); I1 deutsches
  „+49 (0) …"-Format wählte die falsche Nummer → (0)-Marker wird
  entfernt, Test; I2 Mitternachts-Staleness des Strips →
  visibilitychange-Rebuild + Test; M2 selected-Chip scrollIntoView.
  Reviewer-Bias-Messung: djb2 allein hatte 10-Tage-Streaks (Index 1 in
  30 Tagen NIE first) → murmur3-Finalizer nachgerüstet, Verteilung
  12/10/8 verifiziert. DST/Übernacht-Fenster vom Reviewer rechnerisch
  bestätigt sauber.
- Deploy-Verifikations-Lektion: Während des ECS-Rollings antworteten
  alter und neuer Container GEMISCHT (Sa zeigte alte Tipps, Sa+8 neue) —
  erst nach Rolling-Ende konsistent prüfen, Doppel-Abfrage als
  Konsistenzprobe.
- Tests 142+87, Release backend@0.22.6 + widget@0.7.5. LIVE bestätigt:
  So 23.08. Tipps 12:15/12:45+18:00/19:00, So 30.08. 12:00/13:00+
  18:00/18:30 (Variation ✓), Strip einzeilig mit Mo-Ruhetag disabled,
  Anruf-Link mit +4960517897544. Screenshot an Kais (TG 10383-84).

## 00:45–01:30 CEST (22.08.) — RUNDE 8 (PR #276, live): 120 Tage, Icons, Tagesfakten
- Kais (TG 10385): mehr Daten (Buchungen 3+ Monate voraus), Pfeile
  zusätzlich zum Wischen, Monat deutlicher, mehr Icons, Farben,
  Feiertage-wie-Sonntag, Tagesfakten („übrigens am 4. September war…",
  positiv/gern Afghanistan-Bezug).
- Umsetzung: Strip 120 Tage + Pfeil-Paging + Monats-Caption (scroll-
  Listener, aria-live mit Change-Guard), Icons an Schritt-1-Überschriften
  + Emerald-Akzente (CTA emerald-700, 5,45:1 AA), Feiertag=Sonntag NUR
  als Test gepinnt (Logik war schon schichtbasiert — kein Code nötig),
  day-facts.ts mit Hard-Rule-Kommentar (nur fixe verifizierte Anlässe,
  bewegliche Feste verboten, kein Eintrag = keine Zeile).
- **Review-FAKTEN-AUDIT (jeder Eintrag geprüft!) erwischte MICH**: 
  Nouruz+Yalda sind astronomisch beweglich — verletzten meine EIGENE
  im selben Commit dokumentierte Hard Rule (CRITICAL); Mondlandungs-
  Text vermischte Landung (20.7.) und Ausstieg (21.7. UTC). Fixes:
  Nouruz → UN-„International Nowruz Day" (per UN-Resolution FIX am
  21.3. — Eintrag damit wahr), Yalda ohne Datumsbehauptung („rund um
  die Wintersonnenwende"), Apollo „landete", ARPANET präzisiert,
  Pizza-/Schokoladentag (unbelegt) gestrichen → 62 Einträge. Dazu 4
  Reviewer-0-rot-Lücken geschlossen (Rückwärts-Pfeil, Listener-Cleanup,
  Caption-Robustheit, komplette Fakt-Renderkette) + Emoji aria-hidden.
- Lektion: Selbst kuratierte „sichere" Fakten brauchen das adversariale
  Audit — 3 von 64 waren falsch/regelwidrig, obwohl ich beim Schreiben
  von jedem überzeugt war.
- Tests 143+95, Release backend@0.22.7 + widget@0.7.6, Bundle 23:14Z
  verifiziert (STRIP_DAYS=120, page-btn, visible-month, day-fact).
  Live-Screenshot an Kais (TG 10387-88).
