← w3yh.xyz

journal day

Dienstag, 28. April 2026

Tagesansicht des öffentlichen Journals: konkrete Changelog-Outputs, Incidents und kuratierte Notes, ohne dass der Index alles auf einmal rendert.

Aktivität an diesem Tag: hoch

Dienstag, 28. April 2026

claude-opus-4.7w3yh

W3YH-102 Cross-Subdomain-Shell für terminal.w3yh.xyz

added

  • **`tyrone-terminal/src/components/cross-shell/back-to-w3yh-badge.tsx`** und **`tyrone-terminal/src/components/cross-shell/cross-shell-footer.tsx`** — 1:1 aus `w3yh.xyz/src/components/cross-shell/` übernommen. Badge in default-Variante mit `placement="sticky"`, weil Tyrone keine echte Top-Bar hat — die `<StatusBar />` ist eine 8px-Bottom-Bar im Bloomberg-Stil.

changed

  • **`tyrone-terminal/src/app/layout.tsx`** — globaler Stylesheet-Link auf `https://w3yh.xyz/cross-shell/cross-shell.css` im `<head>`. `<BackToW3yhBadge />` als erstes Body-Kind vor `<main>`, `<CrossShellFooter />` als letztes Body-Kind nach der existierenden `<StatusBar />`. Browser-Tab-Title gehoben auf `Tyrone Terminal · w3yh.xyz`.
  • **`/etc/nginx/sites-available/terminal.w3yh.xyz`** — vier neue `add_header`-Direktiven (X-Content-Type-Options nosniff, X-Frame-Options DENY, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy ohne camera/mic/geo/topics/cohort) im HTTPS-Server-Block ergänzt. Bestehender HSTS-Header auf strengere Variante mit `includeSubDomains; preload` aktualisiert (vorher nur `max-age=31536000`).

deployed

  • `sudo nginx -t` grün, `sudo systemctl reload nginx` (non-destructive, alte Worker bleiben bis fertig).
  • `npm run build` im Tyrone-Tree grün, alle 11 Routes generiert (inkl. /, /login, /auth/callback, /auth/handoff, /api/auth/magic-link, /api/chart, /api/economic-events, /api/feed, /api/insights, /api/universe).
  • `pm2 restart [process] durch (PID 2535842 neu).
  • `curl -sI https://terminal.w3yh.xyz/` zeigt alle 5 Cross-Shell-Header live, HTTP/2 307 → /login wie erwartet (kein eingeloggter Zustand).

notes

  • **Tyrone ist nicht git-versioniert** — keine Branch-/PR-Strategie wie bei gym/stocktracker, dafür Backup angelegt: `src/app/layout.tsx.bak-cross-shell` und `/etc/nginx/sites-available/terminal.w3yh.xyz.bak-cross-shell`. Rollback via `cp` falls nötig.
  • **Cookies sicher:** Layout-Änderungen + Nginx-Header-Baseline berühren keine Cookie-Logik. Tyrone-Sessions bleiben weiterhin auf `terminal.w3yh.xyz`-Scope, nicht `.w3yh.xyz`.
  • **Power-User-Subdomain-Scope von W3YH-102 ist damit komplett:** stocktracker (live seit 2026-04-25), gym (live heute), terminal (live heute). Spielplatz/Spielgenerator/Carpark wandern unter Spielgenerator-Dach (W3YH-116, eigene Familien-/Kinder-Strategie).
claude-opus-4.7w3yh

W3YH-102 Cross-Subdomain-Shell für gym.w3yh.xyz

added

  • **`gym-tracker/src/components/cross-shell/back-to-w3yh-badge.tsx`** und **`gym-tracker/src/components/cross-shell/cross-shell-footer.tsx`** — 1:1 aus `w3yh.xyz/src/components/cross-shell/` übernommen. Default-Variante des Back-Badges (sticky), Footer mit `appName="Gym Tracker"`, `appDomain="gym.w3yh.xyz"`.

changed

  • **`gym-tracker/src/app/layout.tsx`** — globaler Stylesheet-Link auf `https://w3yh.xyz/cross-shell/cross-shell.css` im `<head>`. `<BackToW3yhBadge />` als erstes Body-Kind, `<CrossShellFooter />` als letztes. Browser-Tab-Title gehoben auf `Gym Tracker · w3yh.xyz`.
  • **`gym-tracker/next.config.ts`** — neuer `headers()`-Hook mit Variante-A-Security-Baseline (HSTS preload, X-Content-Type-Options nosniff, X-Frame-Options DENY, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy ohne camera/mic/geo/topics/cohort).

verified

  • Build im gym-Repo grün (alle 9 Static/Dynamic-Routes generiert: /, /one-shot, /private, /auth/callback, /auth/handoff, /api/auth/magic-link).
  • Branch `cross-shell/gym` (Commit `d228595`) als Fast-Forward in `main` gemergt und nach `origin/main` gepusht.
  • Vercel-Auto-Deploy nach 5 Sekunden live (`x-vercel-id: fra1::cdtwg-...`). `curl -sI https://gym.w3yh.xyz/` zeigt alle 5 Cross-Shell-Header korrekt: HSTS preload, X-Content-Type-Options nosniff, X-Frame-Options DENY, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy ohne camera/mic/geo/topics/cohort.

notes

  • **Scope-Anpassung W3YH-102:** Spielplatz, Spielgenerator und Carpark sind aus dem Cross-Shell-Rollout rausgenommen — eigene Familien-/Kinder-Zielgruppe braucht eine andere Lösung. Plan dort: Spielplatzcheck ans Spielgenerator-Design angleichen und ins Burger-Menü integrieren. Neues Ticket **W3YH-116** im todo.md.
  • **Reihenfolge:** gym als Aufwärmer zuerst (kleinster Cross-Shell-Einbau, Vercel-Hosting), terminal.w3yh.xyz folgt (Tyrone-Repo, Nginx-Header-Variante).
  • **Uncommitted Files im gym-Repo unangetastet:** Dominiks 4 Auth-Copy-Anpassungen (`page.tsx`, `README.md`, `SUPABASE_SETUP.md`, `CHANGELOG.md`) bleiben im Working Tree und gehen separat.
antigravityw3yh

W3YH-101 Spielplatzcheck Mobile-Optimierung & Map-Fokus

added

  • **`spielplatzcheck-canonical/spielplatzcheck/components/PlaygroundMap.tsx`** — Integration von `leaflet.markercluster` ergänzt. Die 271 Einzelmarker werden nun dynamisch gruppiert, was die Karten-Fokuslast um >90% reduziert.

changed

  • **`spielplatzcheck-canonical/spielplatzcheck/components/HomePageClient.tsx`** — Mobile-Layout: Die Sidebar-Liste wird auf mobilen Viewports (`< lg`) via `hidden lg:block` komplett aus dem DOM entfernt. Dies beseitigt den Overflow und reduziert die Fokus-Last um ca. 424 Elemente. Initialer View-Modus wird über Hook `useResponsiveDefaultView` auf mobilen Endgeräten auf "Liste" (List-First) erzwungen.
  • **`spielplatzcheck-canonical/spielplatzcheck/components/Header.tsx`** — Mobile-UX: Header-Menü-Toggle implementiert (Slide-Down-Panel, X-Icon, korrekte `aria`-Attribute).
  • **`spielplatzcheck-canonical/spielplatzcheck/app/globals.css`** — CSS-Hardening: `overflow-x: hidden` auf `html/body` gesetzt, um den persistierenden 75px-Overflow final zu stoppen. Marker-Cluster-Icons CSS-bereinigt, um mit dem Design zu harmonieren.

verified

  • `npm run build` grün, gepusht und live auf Vercel nach Build.
antigravityw3yh

W3YH-115 X-Sentiment Datenquelle refactored

changed

  • **`w3yh.xyz/scripts/lib/pressespiegel.mjs`** — Refactor der Funktion `fetchXTweetsForWeek()`. Greift nun direkt auf die `x_tweets`-Tabelle zu statt auf die alte RAG-Layer-RPC `kg_portfolio_sentiment`, welche eine Engagement-Schwelle (>100 Likes) nutzte und Mid-Cap-Ticker komplett aus dem Feed filterte.
  • **Query-Logik in `fetchXTweetsForWeek()`** — Filtern erfolgt jetzt präzise mittels `.contains("cashtags", [ticker])` und wochenscharfer Datums-Range auf `x_tweets.created_at`.
  • **Cleanup** — Veraltete Datums-Regex-Logik aus der `pressespiegel.mjs` entfernt.

added

  • **Cron-Härtung** — Der `cashtag-portfolio` Scraper wurde als Cronjob in die System-Crontab aufgenommen (`0 3 * * *`), um die Datenbasis täglich zuverlässig um zu aktualisieren.

verified

  • Cronjob aktiv, Skripte funktional, `npm run build` im W3YH-Repo grün.
claude-opus-4.7w3yh

W3YH-114 Pressespiegel-Sentiment Phase 2 — X-Tweets als Briefing-Block

added

  • **`scripts/lib/pressespiegel.mjs::fetchXTweetsForWeek(supabase, tickers, start, end)`** — neue Funktion. Ruft pro Recap-Ticker die existierende RPC `kg_portfolio_sentiment(ticker_symbol, match_limit: 15)`. Parsed das echte Tweet-Datum per Regex `/\((\d{4}-\d{2}-\d{2})\):/` direkt aus dem `content`-String — `kg_chunks.created_at` ist Crawl-Zeit (alle 200 Rows haben den gleichen Timestamp), `metadata->>'created_at'` existiert nicht. Filtert clientseitig auf `[start, end)`, sortiert nach Engagement (likes + retweets aus `metadata`, fallback auf `engagement_score`-Spalte) und liefert top 5 pro Ticker als `Map<ticker, [{handle, date, headline, likes, retweets, url, engagement}]>`.
  • **Helper:** `parseTweetDate`, `parseTweetHandle` (extrahiert `@user` aus `section_title`), `extractHeadline` (erste content-Zeile ohne `@user (date):` Prefix), `parseMetadata` (RPC liefert `metadata` als JSON-String).
  • **Konstanten:** `X_TWEET_TOP_N=5`, `X_RPC_MATCH_LIMIT=15` als `X_SENTIMENT_CONSTANTS` exportiert.

changed

  • **`scripts/portfolio-draft.mjs`** — `xTweetsByTicker` parallel zu `pressespiegelByTicker` in `main()` geholt (eigener `try/catch`, gleiche Failure-Semantik). An `buildMdx()` und durch zu `renderTickerBlock()` weitergereicht.
  • **`renderTickerBlock()`** — neuer `renderXSentimentBlock()`-Aufruf zwischen `<Pressespiegel />` und dem TODO-Block. Fehlende Tweets: HTML-Kommentar `<!-- X-Sentiment: keine ${ticker}-Tweets ... -->`. Vorhandene Tweets: `X-Sentiment (nicht im Output lassen, nur für den Schreib-Kontext):` + Liste ` - 2026-04-22 · @KobeissiLetter (4250 Likes · 521 RTs): BREAKING: Tesla stock, $TSLA, surges +5% ...`.
  • **TODO-Hinweis pro Ticker** um X-Tweet-Interpretations-Hint erweitert: „Engagement zeigt Aufmerksamkeits-Niveau, Inhalt zeigt Tonalität".

verified

  • Smoke-Test isoliert: `fetchXTweetsForWeek` für KW17 mit `[NVDA, TSLA, MSFT, GOOG, META, AMZN]` über extended range (2026-04-12 bis 2026-04-27) liefert 5 Tickers mit je einem Top-Tweet, alle mit korrekten Likes/RTs (z.B. NVDA 5262/807, MSFT 7088/1038).
  • `node scripts/portfolio-draft.mjs --year 2026 --week 17 --force` läuft durch. Block A hat UNH/HIMS/NVO/SE/ZETA/ZVRA — keine matchen die Watchlist-Tweets, also korrekt 6× HTML-Kommentar.
  • `npm run build` grün.

notes

  • **Architektur-Pivot vs. todo:** Der ursprüngliche todo-Eintrag plante X als zweite Sektion in der `<Pressespiegel />`-Komponente plus mögliche SQL-Migration. Tatsächlich wollten wir aber das Briefing-Pattern: X-Tweets gehen wie TLI als unsichtbarer Schreib-Kontext ins Draft, weil Engagement-Zahlen ohne Tweet-Inhalt im Output nichtssagend wären. Das LLM (Mensch oder spaeter Qwen) liest TLI + News + X in einem Rutsch und schreibt im TODO-Block den Take.
  • **Sentiment offen:** Phase 2 hat bewusst kein Sentiment-Signal für X (im Gegensatz zu News). Begründung: `metadata->>'sentiment'` existiert nicht, Heuristik aus content wäre unzuverlässig („BREAKING: Nvidia hits new record" — pos? neg? mixed?), LLM-Klassifikation wäre eigene Phase. Phase 2.1 könnte das nachziehen wenn nötig.
  • **Datenstand:** `kg_chunks` hat aktuell 200 x_tweets total (Top-Engagement-Snapshot, nicht Vollarchiv), Tweet-Datums-Verteilung 2026-04-12 bis 2026-04-27. Crawler überschreibt scheinbar daily, alle `created_at` zeigen heute .

Incidents

W3YH / Cross-Shell für terminal.w3yh.xyz [autonomous]
~45 minclaude-opus-4.7

Problem: terminal.w3yh.xyz hatte als einzige Power-User-Subdomain noch keine Cross-Shell — kein Back-Badge, kein einheitlicher Footer, Nginx-Header-Baseline schwächer als bei Vercel-Apps (nur HSTS ohne includeSubDomains/preload, keine X-Content-Type-Options/X-Frame-Options/Referrer-Policy/Permissions-Policy)

Ursache: W3YH-102-Rollout hatte Stocktracker (25.04) und gym (heute Abend) abgehakt, terminal stand noch offen weil Tyrone-Tree (`~/.openclaw/workspace/projects/tyrone-terminal/`) nicht git-versioniert ist und Nginx-Header-Variante (statt next.config.ts) einen anderen Pfad braucht

Fix: Cross-Shell-Komponenten 1:1 ins Tyrone-Repo kopiert; layout.tsx mit Badge (sticky default — keine Top-Bar in Tyrone, StatusBar ist 8px-Bottom) + Footer + CSS-Link erweitert. Nginx-Config um 4 Cross-Shell-Header ergänzt, HSTS auf preload+includeSubDomains gehoben. Backups (`layout.tsx.bak-cross-shell`, Nginx-`bak-cross-shell`). `nginx -t` grün, `systemctl reload nginx` non-destructive, `npm run build` grün (11 Routes), `pm2 restart [process] Verify: alle 5 Header per `curl -sI https://terminal.w3yh.xyz/` live, HTTP/2 307 → /login wie erwartet

W3YH / Cross-Shell für gym.w3yh.xyz [autonomous]
~30 minclaude-opus-4.7

Problem: gym.w3yh.xyz hatte keine Cross-Shell und kein `headers()`-Hook in `next.config.ts` (komplett leere Default-Config) — Sicherheits-Header über Vercel-Default hinaus fehlten, kein Back-Anker zu w3yh.xyz

Ursache: W3YH-102-Rollout: stocktracker bereits live, gym als kleinster Aufwand-Aufwärmer geplant. Repo unter `gym-tracker/` mit 4 uncommitted Auth-Copy-Files von Dominik, die nicht mit dem Cross-Shell-Scope vermischt werden sollten

Fix: Branch `cross-shell/gym` von `main`, 2 Komponenten 1:1 kopiert, layout.tsx mit CSS-Link + Badge + Footer + Tab-Title-Update, `next.config.ts` mit 5-Header-Baseline. Selektiver Commit (`d228595`) ohne Dominiks uncommitted Files, Push, Fast-Forward in main, Vercel-Auto-Deploy nach 5s live, alle 5 Header via `curl` verifiziert

W3YH / Spielplatzcheck Mobile-Fokuslast & Map [autonomous]
~45 minantigravity (gemini-3.1-pro-high)

Problem: spielplatz.w3yh.xyz war auf Mobile praktisch unbenutzbar: 877 fokussierbare Elemente im Map-Modus (Tab-Navigation hoffnungslos), 75px Mobile-Overflow (horizontaler Scroll permanent), Mobile-Menübutton war ein nicht-funktionaler Stub

Ursache: Sidebar-Liste blieb auf Mobile im DOM (parallel zur Karte) → 424 zusätzliche Fokus-Elemente; Karte rendert 271 Einzelmarker ohne Clustering; UI/UX-Review-Befund vom 24.04 stand offen

Fix: Mobile list-first via `useResponsiveDefaultView()`-Hook erzwungen, Compact-Liste auf `< lg` aus dem DOM (`hidden lg:block`); Leaflet `MarkerClusterGroup` integriert → ~25 Cluster statt 271 Marker; Mobile-Header-Menü als Slide-Down-Panel mit X-Icon und korrekten aria-Attributen; `overflow-x: hidden` auf html/body als CSS-Hardening. `npm run build` grün, gepusht und live auf Vercel nach Build

W3YH / X-Sentiment Datenquelle Refactor [autonomous]
~30 minantigravity (gemini-3.1-pro-high)

Problem: W3YH-114 Pressespiegel-Sentiment Phase 2 lief über die RPC `kg_portfolio_sentiment` aus `kg_chunks`, aber für das tatsächliche Mid-Cap-Portfolio (ASTS, HIMS, UNH, NVO, SE, ZETA, ZVRA) waren null Treffer — der KW17-Smoke zeigte 6× HTML-Kommentar im Draft

Ursache: `kg-embed.py` filtert `x_tweets` mit hartem `TWEET_MIN_LIKES = 100` für `kg_chunks`. Mid-Cap-Tweets haben aber meist <30 Likes, fielen komplett durchs Sieb. Big-Cap-Macro-Tweets (NVDA/TSLA/MSFT) von Macro-Influencern dominieren stattdessen den RAG-Snapshot

Fix: `fetchXTweetsForWeek()` direkt auf `x_tweets` umgebaut: `.contains("cashtags", [ticker])` + `.gte("created_at", start).lt("created_at", end)`, Sortierung nach `likes` in der DB, top 5 pro Ticker. Tweet-Datums-Regex und Helper aus 114 entfernt (`x_tweets.created_at` ist echtes Tweet-Datum). Native Cron `0 3 * * *` für `cashtag-portfolio` als Cron-Härtung. Coverage-Sprung: 0 → 285/332/258/245/120/164/11 KW17-Tweets pro Portfolio-Ticker

W3YH / Pressespiegel-X-Briefing-Block [autonomous]
~75 minclaude-opus-4.7

Problem: KW18-Recap-Draft brauchte X-Sentiment pro Ticker, aber Engagement-Zahlen ohne Tweet-Inhalt im Output sind nichtssagend; das ausführende LLM (Mensch oder später Tyrone-Qwen) braucht die Tweets als Schreib-Kontext, nicht als sichtbares Sentiment-Widget

Ursache: W3YH-114 ursprüngliche Skizze hatte X als zweite Sektion in der `<Pressespiegel />`-Komponente mit pos/neg/neutral-Färbung; Praxis-Test zeigte: Sentiment-Heuristik aus content unzuverlässig („BREAKING: Nvidia hits new record" — pos? neg? mixed?), `metadata->>'sentiment'` existiert nicht, LLM-Klassifikation wäre eigene Phase

Fix: Pivot zum Briefing-Pattern: X-Tweets gehen wie TLI als unsichtbarer „X-Sentiment (nicht im Output lassen)"-Block ins Draft-MDX. `fetchXTweetsForWeek()` neue Funktion, Tweet-Datum aus `content` via Regex (kg_chunks.created_at = Crawl-Zeit), Top 5 pro Ticker nach Engagement (likes + retweets aus metadata). `renderXSentimentBlock()` zwischen Pressespiegel und TODO-Block. Build grün, KW17-Smoke korrekt (6× HTML-Kommentar weil Mid-Caps in kg_chunks fehlen — gefixt in W3YH-115). Folge-Ticket `W3YH-116` für Familien-Apps unter Spielgenerator-Dach angelegt

TLI / Gmail Auth
~5 minantigravity

Problem: TLI-Mails kamen nicht mehr durch, da der GWS Token abgelaufen oder revoziert war (`invalid_grant` / `expired or revoked`)

Ursache: Der Authentifizierungs-Token für Google Workspace (gws) verlor seine Gültigkeit

Fix: Komplett neue Authentifizierung via `gws auth login --force` durchgeführt (durch Dominik per CLI-Aufruf)

Persönliches Build-Journal. Aufgaben werden über ein Agentensystem (OpenClaw, verschiedene LLMs) per Cron- und Telegram-Trigger ausgeführt; die Heatmap zeigt eine relative Compute-Aktivität in fünf Stufen.