Commit Graph
100 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 2270f0de91 Der „Anpassen"-Knopf war nur an EINEM der beiden Bretter geprueft
Beim Nachsehen zu VanVans Meldung #6 aufgefallen, nicht beim Bauen:
Der Knopf haengt an ZWEI Kartenarten -- an den Creator-Vorlagen
(vorlagenbrett.js:459) und am Team-Katalog (:1220). Im Browser
gemessen war nur die erste.

UND DIE ZWEITE IST DIE, DIE VANVAN BENUTZT. Die Creator-Vorlagen
stehen auf „Aufgaben" und richten sich an Betreuer; der Katalog
steht auf „Eure Aufgaben", und dort verteilt die rechte Hand an die
Modis. Genau das war ihre Meldung.

Dass man diese beiden Bretter verwechselt, ist in diesem Haus schon
passiert: In pruef-bewerbung-aufgaben steht es seit dem 30.09. als
Messfehler notiert, „der wie ein Befund aussieht". Diesmal waere es
andersherum gewesen -- ein gruener Haken ueber einem Weg, den
niemand geprueft hat.

GEMESSEN HAT ES NICHTS KAPUTTES GEFUNDEN: Der Katalogzweig
funktioniert. Aber er war unbewiesen, und das ist derselbe Zustand
wie „ungeprueft" -- nur mit besserem Gefuehl.

DIE GEGENPROBE ZUM ANDEREN BRETT STECKT JETZT DRIN. Ein Creator
bekommt den „dauerhaft"-Haken NICHT (geprueft in
pruef-aufgaben-vorlagen), die Leitung MUSS ihn bekommen (geprueft
hier). Zwei Pruefungen, die denselben Unterschied von beiden Seiten
messen -- erst dann ist es eine Regel und nicht ein Zufall.

GEPRUEFT -- pruef-modi-katalog 150 -> 159 ok

  jede Katalogkarte hat einen „Anpassen …"-Knopf (12 von 12)
  das Fenster hat Frist und Anmerkung
  und die Leitung bekommt den „dauerhaft"-Haken
  die Frist der Vorlage steht als Vorgabe drin (2026-10-05,
    fruehestens 2026-10-03)
  mit Haken wird die Frist gesperrt
  die angepasste Aufgabe liegt in ihrer Liste (3 -> 4)
  sie ist wirklich dauerhaft · und hat keine Frist
  die Anmerkung steht als Notiz dabei

  Die letzten drei fragen die DATENBANK, nicht den Bildschirm. Was
  auf dem Brett steht, ist eine Darstellung; was in der Aufgabe
  steht, gilt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 11:04:03 +02:00
DogFatherGitandClaude Opus 5 3d859cbed5 Eine untaugliche Zweitfassung erkennt der Server selbst
NACHGEMESSEN AN DEN SECHS, DIE HEUTE NACHT LIVE ENTSTANDEN SIND --
vier tragen das Loch am Anfang, weil sie gebaut wurden, bevor es
bekannt war:

    387,6 s Zeitachse fuer wenige Sekunden Ton
    164,2 s
    134,1 s
     63,8 s
      9,7 s  (in Ordnung)
      3,3 s  (in Ordnung)

Sie gehoeren dem Dienstbenutzer; von aussen sind sie nicht
wegzuraeumen. Und mit „gibt es schon, dann weiter" waeren sie fuer
immer so geblieben.

EIN SCHALTER „alles neu ab Fassung 2" WAERE DIE BEQUEME LOESUNG und
die falsche: eine Zahl, die jemand hochzaehlen muss, wird beim
naechsten Mal vergessen. Gefragt wird deshalb die DATEI SELBST --
nach dem, was schiefgehen kann: Passt ihre Zeitachse zu der
Tonmenge, die sie traegt? AAC packt 1024 Abtastwerte in einen
Rahmen; Rahmenzahl mal 1024 durch die Abtastrate ist die echte
Laenge. Mehr als anderthalb Sekunden darueber heisst: Loch.

Was nicht passt, wird beim naechsten Nachruestlauf weggeraeumt und
neu gebaut -- einmal, denn danach passt es.

ZWEI FEHLER IN DIESER FUNKTION, BEIDE VON DER GEGENPROBE GEFUNDEN

Und beide waeren still geblieben:

 1. ffprobe GIBT DIE WERTE IN SEINER REIHENFOLGE AUS, nicht in
    meiner: erst `sample_rate`, dann `nb_frames`. Ich hatte
    `[rahmen, rate, dauer]` destrukturiert und damit 48000 Rahmen
    bei 95 Hz gerechnet -- eine „echte Laenge" von einer halben
    Million Sekunden. Die Funktion haette JEDE Datei fuer tauglich
    erklaert, immer. Gelesen wird jetzt mit Namen.

 2. DER DATEINAME FEHLTE IM AUFRUF. ffprobe antwortete „You have to
    specify one input file", der `catch` machte daraus ein
    freundliches „taugt" -- und wieder sagte die Funktion zu allem
    ja.

Das ist zweimal dieselbe Sorte: gruen und wertlos. Gefunden hat es
nicht das Lesen, sondern die Frage „kann sie ueberhaupt NEIN
sagen?". Genau dafuer gibt es die Gegenprobe.

WIE MAN EINE DATEI MIT LOCH NACHSTELLT -- UND WIE NICHT

`-itsoffset 40` war der naheliegende Weg und ergab 2,5 s: Der
MP4-Baukasten rechnet einen reinen Anfangsversatz wieder heraus.
Dasselbe mit `-copyts`, `-output_ts_offset` und `-muxdelay`. Was
bleibt, ist eine Zeitachse, die laenger ist als ihr Ton -- und das
stellt eine stumme Bildspur von 40 Sekunden her. Der Weg dorthin
ist ein anderer als bei `MediaRecorder`; die ZAHLEN, die die
Funktion liest, sind dieselben.

GEPRUEFT -- pruef-chat-anhaenge 164 -> 168 ok

  eine Fassung mit zu langer Zeitachse nachgestellt (40,0 s)
  und sie wird als untauglich erkannt
  der Nachruestlauf ersetzt sie (40,0 s → 2,5 s)
  und die neue gilt als tauglich — er wandelt sie nicht ewig weiter

Die letzte Zeile ist die zweite Gegenprobe: Ein Lauf, der bei jedem
Durchgang alles neu wandelt, waere eine Warnung, die immer kommt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 02:04:23 +02:00
DogFatherGitandClaude Opus 5 ff48a0a6ef Das Loch am Anfang der Sprachnachrichten -- und ein halb fertiges Stueck
NACHGEMESSEN AN EINER ECHTEN NACHRICHT AUS DEM HAUS, nachdem die
Zweitfassungen heute Nacht live entstanden waren. `mumqbw6v….webm`
vom 29.09., 46 Pakete:

    Paket 1 bei   0,000 s
    Paket 2 bei  61,116 s
    ...
    Paket 46 bei 63,756 s

2,76 Sekunden Ton, verteilt ueber eine Zeitachse von 63,8 Sekunden.
Dazwischen ein Loch von einer Minute. `MediaRecorder` setzt diesen
Versatz selbst; die Datenbank kennt ihn nicht (dort steht die Angabe
des Absenders: 2910 ms).

WAS DAS FUER DEN HOERER HEISST: Das Abspielgeraet zeigt 1:03,
springt beim Antippen in eine Minute Stille und faengt erst danach
an. Auf einem Handy ueber Mobilfunk sieht genau das aus wie „laedt
die ganze Zeit" -- Miss' Satz aus Runde 5, woertlich.

Das war also nicht nur der Behaelter. Die Umwandlung von heute Nacht
hat das Loch brav mituebernommen: 63,8 s Zeitachse, 32 KB Inhalt.

GEAENDERT: `-af asetpts=N/SR/TB` vergibt die Zeitstempel neu,
fortlaufend ab null. An der echten Datei nachgemessen -- der
Toninhalt bleibt unveraendert (260 KiB dekodiert vorher wie
nachher), nur die Laenge geht von 63,8 s auf 2,76 s. Es wird nichts
abgeschnitten, sondern ein Loch geschlossen.

UND EIN ZWEITER FUND, von der Pruefung und nicht vom Nachdenken

Sie holte die zweite Fassung ab und bekam 44 BYTES. ffmpeg legt die
Zieldatei sofort an und fuellt sie danach -- bei `+faststart`
schreibt es sie am Ende noch einmal um. Die Stelle, die fragt „gibt
es die zweite Fassung?", sah in dieser Zeit eine Datei, die es gibt
und die nichts enthaelt. Wer dann zuhoert, bekommt ein Bruchstueck.

Jetzt entsteht sie unter `….m4a.teil` und wird erst am Ende
umbenannt. Umbenennen im selben Ordner ist EIN Schritt: entweder
vollstaendig da oder gar nicht. Der Bruchstuecknamen endet
ausdruecklich NICHT auf `.m4a`, sonst waere die Luecke nur
umbenannt -- und deshalb muss `-f mp4` dabeistehen, weil ffmpeg das
Format sonst an der Endung waehlt und `.teil` nicht kennt. Auch das
hat die Pruefung gefunden: Der erste Versuch mit Umbenennen erzeugte
gar keine Datei mehr.

WAS DIE PRUEFUNG JETZT MISST -- UND WAS NICHT

Sie vergleicht NICHT mehr die Zeitachsen beider Dateien. Genau das
war mein erster Anlauf, und er haette das Loch durchgewunken: Wenn
es mitwandert, sind beide Zeitachsen gleich lang und alles ist
gruen. Gefragt wird jetzt nach dem TON -- wie viele Bytes
herauskommen, wenn man beide dekodiert (231 KiB zu 231 KiB) -- und
danach, ob die Zeitachse zu dieser Tonmenge passt (2,46 s fuer
2,46 s Ton).

Ein dritter kleiner: `tonBytes` las die Rueckgabe von
`execFileSync`. ffmpeg schreibt seine Zusammenfassung aber auf
stderr -- die Messung meldete fuer beide Dateien 0 KiB. Rot, und zu
Recht: Sie hat nichts gemessen.

WAS BEWUSST OFFEN BLEIBT: Eine Aufnahme, die schon als MP4
hereinkommt (seit dem 02.10. der Normalfall), wird nicht
umgewandelt -- und traegt ein solches Loch, falls sie eines hat,
weiter. Dass sie eines haette, ist nicht gemessen: Seit der
Umstellung gibt es keine einzige neue Aufnahme. AAC noch einmal nach
AAC zu wandeln kostet Qualitaet fuer ein Problem, das ich nicht
beobachtet habe. Faellt es auf, ist die Stelle bekannt.

GEPRUEFT -- pruef-chat-anhaenge 163 -> 164 ok

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 01:55:46 +02:00
DogFatherGitandClaude Opus 5 d70d00cedc Jede Sprachnachricht in einer Fassung, die JEDES Geraet abspielt
Miss im Support, Meldung #12 -- fuenf Runden seit dem 23.09.: „Bei
mir laesst sich die Nachricht nicht abspielen." Zuletzt: „Jetzt laedt
es die ganze Zeit." Bei allen anderen ging es.

GEMESSEN, BEVOR GEBAUT WURDE

  · Alle sechs Sprachnachrichten im Haus sind audio/webm (Opus).
  · Miss' Geraet: iPhone, iOS 18.7, WebKit.
  · Seit der Umstellung am 02.10. (neue Aufnahmen bevorzugen MP4)
    wurde KEINE EINZIGE neue aufgenommen. Ihr Problem betrifft also
    ausschliesslich die sechs alten Dateien -- und jede kuenftige aus
    einem Firefox, der nichts anderes kann.

WAS ICH NICHT MESSEN KONNTE, und das gehoert dazu: Ob WebKit
WebM/Opus abspielen kann, laesst sich auf diesem Rechner nicht
nachsehen -- Playwrights WebKit startet hier nicht (libegl.dll
fehlt). Die Vermutung „iPhones koennen kein WebM" ist begruendet,
aber von mir nicht gemessen.

GENAU DESHALB STELLT DIE LOESUNG DIE FRAGE NICHT. Statt zu raten,
welches Geraet welchen Behaelter kann, legt der Server neben jede
Sprachnachricht eine zweite Fassung in dem Format, bei dem sich seit
zwanzig Jahren alle einig sind: AAC in MP4. Gibt es sie, wird sie
abgespielt -- bei jedem, nicht nur auf iPhones. Kein Geraetename im
Code, keine Liste, die altert.

  helfer-ffmpeg.mjs     ffmpeg finden, umwandeln, drei Ausgaenge
  beim Hochladen        nebenher, nicht davor: Die Nachricht wartet
                        nicht auf ffmpeg
  toeneNachruesten()    das Netz darunter -- fuer die sechs von
                        frueher und fuer den Fall, dass eine
                        Umwandlung einmal nicht geklappt hat
  ?form=mp4             dieselbe Route, dieselben Rechte; eine
                        zweite haette dieselbe Sichtbarkeitspruefung
                        ein zweites Mal gebraucht

ffmpeg IST ABGESPROCHEN INSTALLIERT (Debian 7.1.5, auf Nachfrage
freigegeben). Fehlt es, passiert nichts Schlimmes: Die
Sprachnachricht geht wie bisher im Originalformat hinaus, und es
steht EINMAL eine Zeile im Protokoll -- nicht bei jedem Hochladen.

DREI ENTSCHEIDUNGEN, DIE NICHT NAHELIEGEND WAREN

 1. `-movflags +faststart` IST NICHT KOSMETIK. Ohne es steht die
    Inhaltsuebersicht einer MP4 am ENDE. Das Abspielgeraet muss dann
    erst bis ans Ende lesen, bevor es anfangen kann -- genau das
    „laedt die ganze Zeit" aus Miss' Runde 5. Geprueft wird die
    Reihenfolge der Kaesten in der Datei, nicht die Zeile im Aufruf.

 2. DAS ORIGINAL BLEIBT LIEGEN. Ohne `?form=mp4` kommt weiter die
    WebM. Sie ist das, was aufgenommen wurde; sie durch eine
    Umrechnung zu ersetzen hiesse, das Original wegzuwerfen.

 3. EIN GEMEINSAMER LOESCHER. Zwei Stellen entfernen Anhaenge
    (Gespraech wegraeumen, Nachricht zuruecknehmen). Beide nahmen
    genau eine Datei -- ab heute waere bei jeder geloeschten
    Sprachnachricht eine m4a liegengeblieben, ohne Zeile, die auf
    sie zeigt. Dieselbe Luecke hatte ich gestern bei den
    Supportbildern gefunden; hier steht sie von Anfang an an EINER
    Stelle.

ZWEI FUNDE DER PRUEFUNG, BEIDE MEINE EIGENEN

 · `anhang_datei` STAND NICHT IN DER ABFRAGE der Nachrichtenliste.
   Die Funktion, die auf der Platte nachsieht, bekam deshalb nichts
   und sagte brav „gibt es keine zweite Fassung" -- fuer JEDE
   Nachricht. Alles war gebaut, nichts kam an. Gefunden hat das die
   Pruefung, nicht das Lesen.
 · Mein erster Anlauf mass die Aufnahme ueber den Knopf -- und die
   ist seit dem 02.10. schon MP4, braucht also gar keine zweite
   Fassung. Die Pruefung wurde rot und hatte recht: Gemessen werden
   muss der Fall, den es bei Miss gibt. Jetzt nimmt sie ausdruecklich
   eine WebM auf.

Dazu zweimal derselbe alte Tritt: ein Gegen-Apostroph in einem
Kommentar INNERHALB eines Template-Literals. Der Server startet dann
gar nicht. Steht jetzt als Warnung an beiden Stellen.

GEPRUEFT -- pruef-chat-anhaenge 146 -> 163 ok

  Eine echte WebM/Opus-Aufnahme (31 972 Bytes) wird hochgeladen; die
  zweite Fassung entsteht von selbst und kommt als audio/mp4 heraus,
  mit „ftyp"-Marke, mit Accept-Ranges. ffprobe sagt: Original Opus,
  Zweitfassung AAC, 2,40 s gegen 2,46 s. Die Inhaltsuebersicht steht
  bei Byte 32, die Tondaten ab 1270 -- also vorne. Beim Loeschen
  gehen beide Dateien. Gegenproben: ein Bild bekommt keine zweite
  Fassung; eine halbierte Laenge waere aufgefallen; das Original
  bleibt unter seiner eigenen Adresse abrufbar.

  Der dritte Ausgang hat einen eigenen Zaehler: Fehlt ffmpeg, steht
  „KONNTE NICHT NACHSEHEN" mit Anleitung da -- nicht gruen und nicht
  rot. Und der Block raeumt hinter sich auf: Mein Probebild liess
  eine spaetere Pruefung rot werden, weil es die Gespraechsliste
  veraendert hatte. Eine Pruefung, die den Stand fuer die naechste
  verschiebt, ist schlimmer als keine.

  Dazu gruen: pruef-struktur 102 (92 Module) · pruef-ports 10 ·
  pruef-gifs 17 · pruef-treffchat 114 · pruef-chat-optik ·
  pruef-aufbewahrung 45.

NUR DAS AGENTURHAUS? NEIN -- der Chat gehoert beiden Haeusern, und
die Aenderung gilt fuer beide gleich. Sie aendert nichts an
Sichtbarkeit oder Rechten: Wer eine Nachricht hoeren darf, hoert sie
jetzt in einem Format, das sein Geraet kann.

OFFEN BLEIBT DIE ANTWORT VON MISS. Ob es bei ihr jetzt laeuft, weiss
nur sie -- deshalb steht ihre Meldung weiter offen und nicht auf
erledigt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 01:41:34 +02:00
DogFatherGitandClaude Opus 5 1ce2c3785e Der Hinweis an der Anmeldung sagte seit dem 01.10. das Gegenteil
VanVan im Support, Meldung #5, zweite Runde: „Man kann sich jetzt nur
noch über die richtige Schaltfläche anmelden. Das funktioniert jetzt.
Aber wenn man sich 2x versucht über den falschen Button anzumelden,
dann kommt ein irreführender Text wo steht, dass die Auswahl oben
nicht schuld ist."

SIE HAT RECHT -- UND DER GRUND IST MEINE EIGENE AENDERUNG

Auf der Crew-Wand stand ab dem zweiten Fehlversuch: „Zugangscode
stimmt nicht. Achte auf die Bindestriche -- die Auswahl oben ist
nicht schuld."

Das war am 20.09.2026 richtig. Dort gab es den STILLEN ZUGANG: Die
rechte Hand und die Modis kamen ueber die Codekennung herein, egal
welche Kachel sie antippten. Der Satz „Stimmt die Auswahl oben?"
haette sie in eine Schleife geschickt -- alle Kacheln durchprobieren,
acht Fehlversuche, Adresse gesperrt. Ein Hinweis, der die Sperre
herbeifuehrt, gegen die er helfen soll.

Mit VanVans ERSTER Runde derselben Meldung ist der stille Zugang
weggefallen („es soll fest sein"). Nachgemessen in workspace.js: Die
Kandidaten kommen seither aus `WHERE rolle = ?`, auf beiden Waenden.
Die Kachel entscheidet ueberall -- und der Satz sagte ab diesem Tag
das Gegenteil der Wahrheit, genau an der Stelle, an der jemand
feststeckt.

DAS IST DIE SORTE FEHLER, DIE EIN UMBAU HINTERLAESST: Nicht der neue
Code war falsch, sondern ein Satz drei Dateien weiter, dessen
Voraussetzung er entfernt hat. Er stand sogar ausfuehrlich begruendet
da -- und die Begruendung las sich beim Umbau wie eine Bestaetigung,
weil sie von einem Zustand sprach, den es nicht mehr gab. Gefunden
hat ihn kein Prueflauf, sondern VanVan beim Benutzen.

GEAENDERT: Ein Satz fuer beide Waende. Die Fallunterscheidung nach
Wand ist weg -- es gibt nur noch eine Regel, also auch nur noch eine
Auskunft. Der Hinweis auf die Bindestriche bleibt; er galt nie nur
fuer eine Wand.

  „Zugangscode stimmt nicht. Stimmt die Auswahl oben? Ein Code
   gehört immer zu genau einer davon – und achte auf die
   Bindestriche."

GEPRUEFT -- pruef-modi-verborgen 87 -> 94 ok

  Im echten Browser, beide Waende (crew-index.html und index.html),
  je zweimal mit einem falschen Code:
    · die Waende sind wirklich verschieden (gate--crew true/false)
    · „nicht schuld" steht nirgends mehr
    · stattdessen die Frage nach der Auswahl -- die dort seit dem
      01.10. wirklich gilt (Abschnitt 1 derselben Datei misst das)
    · derselbe Satz auf beiden Waenden
    · Gegenprobe: nach dem ERSTEN Versuch steht er noch nicht da,
      dort steht die kurze Absage. Ein Hinweis, der immer kommt,
      waere keiner.

  DIE VERSUCHSSPERRE WIRD VOR DER MESSUNG GELEERT. Acht Fehlversuche
  je Adresse in zehn Minuten -- die Abschnitte davor verbrauchen
  welche, und ab dem neunten stuende „Zu viele Versuche" statt des
  Satzes. Das waere ein roter Haken ueber die Messumgebung gewesen,
  nicht ueber das Programm.

  Dazu: pruef-struktur 102 ok.

BEIDE HAEUSER BETROFFEN, und das ist hier richtig: Es ist dieselbe
Anmeldung mit derselben Regel. Nachgewiesen wird genau das -- der
Satz ist auf beiden Waenden derselbe, und er stimmt auf beiden.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 00:16:05 +02:00
DogFatherGitandClaude Opus 5 f2f11e8091 Gelesene Antworten rutschen zur Seite -- statt sich zu stapeln
VanVan im Support, Meldung #15: „Die Modis können die Antworten auf
die Bewerbungen im Bereich eure Aufgaben noch nicht einklappen. Das
wird mit der Zeit unübersichtlich."

WARUM ES NICHT EINFACH EIN SCHALTER GEWORDEN IST

Am 30.09. habe ich diesen Kasten absichtlich NICHT einklappbar
gebaut, und die Begruendung steht woertlich im Quelltext: „Eine
Antwort, die man erst aufklappen muss, ist wieder keine." Sie ist
richtig -- fuer eine Antwort, die man noch nicht gelesen hat. Danach
ist sie falsch herum, und genau das meldet VanVan.

Ein Schalter, der alles wegklappt, haette die naechste Absage
mitversteckt: die Zeile, derentwegen der Kasten ueberhaupt
entstanden ist. Deshalb nicht „einklappbar", sondern GELESEN:

  · Was noch niemand quittiert hat, steht offen da -- wie bisher.
  · „Verstanden" schiebt eine Zeile hinter „N ältere Antworten",
    zugeklappt, jederzeit wieder aufzumachen. Nichts wird geloescht;
    eine Absage samt Begruendung wegzuwerfen, weil jemand sie einmal
    gelesen hat, waere das Gegenteil des Umbaus vom 30.09.
  · Ab zwei offenen Antworten gibt es „Alle N verstanden" -- wer nach
    dem Urlaub sieben vorfindet, soll nicht siebenmal tippen, und
    sieben Anfragen waeren sieben Gelegenheiten, dass eine verloren
    geht.

AM MENSCHEN, NICHT AM GERAET

`gesehen_am` steht in `vorlagen_bewerbungen`, nicht im
Browserspeicher. „Habe ich das gelesen?" ist eine Frage ueber die
Person: Sonst waere dieselbe Antwort auf dem Handy wieder neu,
nachdem man sie am Rechner gelesen hat -- und das waere genau die
Unuebersichtlichkeit, die gemeldet wurde, nur eine Tuer weiter.

Das AUFKLAPPEN der aelteren bleibt dagegen im Augenblick: kein
Zustand, den man mitschleppt. Nach dem Neuladen ist wieder zu.

GEGEN FREMDE ZEILEN GESCHUETZT: Nur die eigenen, nur die
beantworteten, 404 statt 403 -- wie ueberall im Haus. Ein zweites
„Verstanden" zaehlt nicht noch einmal, sonst wanderte die Zeile bei
jedem Klick ans Ende und man saehe nicht mehr, wann man sie wirklich
gelesen hat.

WAS ICH FALSCH ERWARTET HATTE: Meine erste Pruefung verlangte, dass
nach einem „Verstanden" OBEN NICHTS mehr steht. Sie wurde rot --
Frida hatte zwei Antworten, und der Knopf gilt je Zeile. Die
Pruefung hatte recht; dass er nur seine eigene Zeile nimmt, ist das
gewollte Verhalten und steht jetzt als Aussage dort.

NEBENBEI: Ein 11,2-px-Pfeil (gemeldet von pruef-css-klassen). Unter
11,5 px faengt im Haus die Grenze an, ab der man zusammenkneift --
dass es „nur ein Zeichen" ist, aendert daran nichts.

GEPRUEFT

  pruef-bewerbung-aufgaben  164 -> 178 ok
    Im echten Browser, am Handy (390 px): die ungelesene Antwort
    steht offen mit „Verstanden", danach ist genau diese eine Zeile
    weg (2 -> 1), sie liegt hinter „1 ältere Antwort", zugeklappt
    wird sie gar nicht erst gebaut, aufgeklappt steht sie samt
    Begruendung wieder da, „Alle verstanden" raeumt den Rest, nach
    dem Neuladen gilt beides weiter als gelesen und ist wieder zu.
    Am Server: fremde Antwort 404, erfundene Nummer 404, zweites
    „Verstanden" zaehlt 0.
  pruef-struktur 102 ok, 414 Routen (eine neue) ·
  pruef-css-klassen · pruef-zeichen 7 · pruef-modi-katalog 150 ·
  pruef-vorlagen 24 · pruef-aufgaben-vorlagen 60

NUR DAS AGENTURHAUS. „Eure Aufgaben" liegt unter `/workspace`; am
Crew-Haus aendert sich keine Zeile.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-03 00:10:15 +02:00
DogFatherGitandClaude Opus 5 018d02c3b8 Vorlagen anpassen: Frist, dauerhaft und eine Anmerkung
VanVan im Support, Meldung #6, zweite Haelfte -- der Rest, der heute
frueh ausdruecklich offen stehen blieb: „Bei den Vorlagen laesst sich
weder die Frist anpassen noch ‚dauerhaft' einstellen, und eine
Anmerkung fehlt auch."

EIN ZWEITER KNOPF, NICHT EIN FENSTER FUER ALLE

„An alle" verteilt zwoelf Aufgaben mit einem Druck. Haette jedes
Uebernehmen jetzt ein Fenster geoeffnet, waere der haeufige Weg
langsamer geworden, um den seltenen moeglich zu machen. Neben
„Uebernehmen" steht deshalb „Anpassen …" -- an den Creator-Vorlagen
und am Katalog, aus derselben Funktion.

DAS FENSTER IST DAS DES HAUSES

`frageNach` kann seit heute ein DATUM und einen HAKEN, die Anmerkung
konnte es als `grund` schon. Ein eigener kleiner Dialog in
vorlagenbrett.js waere der zweite im Haus gewesen -- und der, in dem
beim naechsten Mal Esc, Fokusfalle oder der Abbruch fehlen. Beide
Felder sind standardmaessig aus; fuer die dreissig anderen Aufrufe
aendert sich nichts.

DREI ENTSCHEIDUNGEN, DIE NICHT NAHELIEGEND WAREN

 1. DIE ANMERKUNG WIRD EINE NOTIZ (`aufgaben_notizen`), kein Anhang
    an der Beschreibung. Sie traegt damit, von wem sie stammt, und
    die Aufgabe zeigt sie ohnehin an. In die Beschreibung geschrieben
    waere sie von der Vorlage nicht mehr zu unterscheiden -- und
    dieselbe Vorlage haette beim naechsten Mal einen anderen Text.

 2. EINE DAUERHAFTE AUFGABE BEKOMMT KEINE FRIST, auch wenn eine
    mitgeschickt wird. Sie waere ab dem naechsten Tag fuer immer
    ueberfaellig, und eine Warnung, die immer kommt, ist keine mehr.
    Dieselbe Regel steht seit Langem im Aenderungsweg; haette sie
    hier gefehlt, gaebe es zwei Antworten auf dieselbe Frage.
    Im Fenster wird das Datum deshalb GRAU, sobald der Haken sitzt --
    ein Datum, das dasteht und nicht gilt, ist schlimmer als keins.

 3. „DAUERHAFT" DARF NUR, WER VERTEILEN DARF. Eine dauerhafte Aufgabe
    laesst sich nicht abhaken (Commit von heute frueh); wer sie sich
    selbst anlegen koennte, haette etwas, das er nie wieder loswird.
    Der Haken fehlt deshalb im Fenster eines Creators -- und
    abgelehnt wird trotzdem am Server, nicht nur ausgeblendet.

EIN FUND, DEN DIE PRUEFUNG GEMACHT HAT

`Number(tage) || 7` -- die Untergrenze des Datumsfeldes lag dadurch
sieben Tage in der Zukunft statt heute, weil Null in JavaScript
unwahr ist. Die VORGABE („in 1 Tag") lag damit UNTER der erlaubten
Grenze: Wer das Fenster oeffnete und einfach „Uebernehmen" drueckte,
bekam eine Absage. `Number.isFinite` fragt, ob eine Zahl da ist, und
nicht, ob sie wahr ist -- derselbe Unterschied wie bei `kill -0`.

NEBENBEI BEHOBEN: Ein gerades Anfuehrungszeichen in einem deutschen
Fehlersatz (gemeldet von pruef-struktur).

GEPRUEFT

  pruef-aufgaben-vorlagen   46 -> 60 ok
    eigene Frist kommt an (und die Vorlage saehe 5 Tage vor -- die
    Angabe hat also wirklich gewirkt), Anmerkung wird woertlich zur
    Notiz mit Namen, ohne Angabe bleibt alles wie bisher, Scout 403
    und es entsteht auch nichts, DogFather 200 und KEINE Frist,
    „morgen" 400, der 45.13. 400, Vergangenheit 400, und als
    Gegenprobe dieselbe Vorlage ohne Frist 200.
    Im Browser: der Knopf, das Fenster, die Vorgabe, kein Haken fuer
    einen Creator, die Aufgabe traegt danach genau die eingetragene
    Frist samt Notiz -- und Abbrechen legt nichts an.
  pruef-nachfrage           74 -> 89 ok
    Datum mit Vorgabe und Untergrenze, Haken 44 px hoch mit 22-px-
    Kaestchen (nicht ueber die ganze Zeile), Sperre und Gegenprobe,
    beide Schranken fuer ein zu fruehes Datum einzeln.
  pruef-struktur 102 · pruef-css-klassen · pruef-modi-katalog 150 ·
  pruef-aufgabenbrett · pruef-vorlagen 24 ·
  pruef-bewerbung-aufgaben 164 · pruef-zuteilung

NUR DAS AGENTURHAUS. Vorlagenbrett und Aufgaben liegen unter
`/workspace`; am Crew-Haus aendert sich keine Zeile.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 23:57:41 +02:00
DogFatherGitandClaude Opus 5 b31bd9b515 Zwei bis drei Bilder je Supportmeldung -- und zwei Funde unterwegs
VanVan im Support, Meldung #11, VIERMAL gemeldet: „Hier im
Supportbereich kann man immer nur ein Bild hinzufuegen bei einer
Meldung. 2-3 waeren besser." Und in der zweiten Runde der Satz, auf
den es ankommt: „wenn man es nacheinander versucht hinzuzufuegen wird
das Bild immer nur ersetzt."

EINE TABELLE STATT NEUER SPALTEN

`support_bilder` haelt ab jetzt JEDES Supportbild -- das der Meldung
(`runde_nr` NULL) und das einer Antwort (`runde_nr` = Runde). Die
Alternative waere `bild2_datei`, `bild3_datei` gewesen, und beim
vierten Bild wieder. Eine Zeile je Bild kennt keine Obergrenze im
Schema; die Grenze steht an EINER Stelle im Code (`BILDER_MAX = 3`)
und kommt von dort in die Oberflaeche, statt dort ein zweites Mal
zu stehen.

DIE ACHT VORHANDENEN BILDER WANDERN MIT. Ohne diesen Schritt haette
die neue Tabelle ab heute recht und die alten Bilder waeren
unsichtbar -- ohne Fehler, ohne rote Zeile, nur acht leere Karten.
Der Umzug steht NACH der Spaltennachruestung: Er liest
`urteil_bild_datei`, und die gibt es in einer bestehenden Datenbank
erst, nachdem sie ergaenzt wurde. Stuende er davor, scheiterte er
genau dort, wo es darauf ankommt -- live, waehrend lokal alles gruen
bliebe, weil jede Pruefung ihre Datenbank frisch anlegt.

DREI BILDER IN EINER ANFRAGE

`x-bilder: 20481,15320` sagt, wo zu schneiden ist, der Rumpf ist die
Aneinanderreihung. `multipart/form-data` haette einen Zerleger
gebraucht, den dieses Haus nicht hat; drei Anfragen nacheinander
haetten den Zustand „Meldung da, Bild zwei laedt noch" erzeugt --
genau den, gegen den die Kommentare an dieser Route schon vorher
argumentieren. Die Summe muss auf das Byte stimmen, und jedes Stueck
wird einzeln an seinen ersten Bytes erkannt: Wer falsch schneidet,
bekommt eine Absage, kein verfaelschtes Bild. Ohne den Kopf gilt der
ganze Rumpf als ein Bild -- derselbe Satz mit einer Laenge, damit
eine Seite aus dem Zwischenspeicher weiterlaeuft.

EINE ROUTE STATT DREI. `/:id/bild` und `/:id/runde/:nr/bild` sind
weg; es gibt `/:id/bild/:bid`. Wohin ein Bild gehoert, steht in
seiner Zeile -- der Weg muss es nicht wiederholen. Die
Meldungsnummer bleibt trotzdem im Pfad: Sie ist die
Sichtbarkeitsfrage, und beides muss zusammenpassen (gemessen).

ZWEI FUNDE, DIE DIE PRUEFUNG GEMACHT HAT UND NICHT ICH

 1. UEBER DIE SEITE KAM GAR KEIN BILD MEHR AN. Beim Melden stand
    kein `Content-Type`. Das ging gut, solange der Rumpf eine
    einzelne Datei war -- ein `File` bringt seinen Typ mit. Ein
    `Blob` aus mehreren hat keinen, `fetch` schickt die Zeile dann
    gar nicht, `express.raw` fuehlt sich nicht zustaendig, und der
    Server bekam einen leeren Rumpf. Die Meldung waere durchgegangen,
    der Text angekommen, die Bilder weg -- ohne Fehlermeldung. Alle
    Pruefungen am Server waren dabei gruen; gefunden hat es erst der
    echte Browser.

 2. DAS KREUZ DES DRITTEN BILDES LAG AUF DEM ZWEITEN. Der
    Entfernen-Knopf ist 44 px breit und absolut gesetzt, der Kasten
    aber nur so breit wie sein Bild. Bei einem schmalen Bild ragt er
    darueber hinaus -- wer „das zweite weg" antippt, loescht das
    dritte. `min-width`/`min-height` loesen das an der Ursache: Ein
    Kasten ist nie schmaler als der Knopf in ihm.

WAS ICH FALSCH ANGENOMMEN HATTE: Ich hatte eingebaut, dass ein
Nachtrag in derselben Runde die Bilder ersetzt. Die Pruefung dazu
wurde rot -- zu Recht: Eine zweite Antwort in derselben Runde kann
es nicht geben, die erste verlaesst den Stand „wartet". Der Code
waere nie gelaufen und damit nie pruefbar gewesen. Er ist weg; an
seiner Stelle steht der Beweis, dass er nicht fehlt.

DREI WEITERE ROTE ZEILEN, DIE NICHT ZU DIESEM UMBAU GEHOERTEN

 * `manager-ziele.js` hatte einen ZWEITEN Notnagel
   (`frageNach ? … : confirm(…)`). `nachfrage.js` hat denselben
   laengst, und zwar mit dem vollstaendigen Text; der hiesige war
   der kuerzere und haette gewonnen. Zwei Antworten auf dieselbe
   Frage -- gemeldet von `pruef-nachfrage`.
 * Zwei Mittelpunkte in `reaktion.css` standen woertlich im
   `content`. Sie liegen im Latin-1-Block, wo `pruef-zeichen` die
   Truemmer einer verunglueckten Kodierung sucht. Jetzt als Escape
   -- im Browser nachgemessen, es steht Zeichen fuer Zeichen
   dasselbe da.
 * Das Aufraeumen nach 90 Tagen loeschte nur das EINE Bild der
   Meldung; die Bilder aus den Antwortrunden blieben ohne Zeile auf
   der Platte liegen. Die Liste kommt jetzt aus einer Abfrage statt
   aus einer Spalte und kann deshalb nicht wieder unvollstaendig
   sein.

GEPRUEFT

  pruef-support            78 -> 104 ok
    darunter: der Umzug der alten Bilder auf einer eigenen
    Wegwerf-Datenbank -- zweimal und dreimal gestartet, nichts
    verdoppelt, Datum von damals erhalten
  pruef-support-bilder     NEU, 36 ok (echter Browser)
    dreimal nacheinander waehlen ergibt drei, das vierte wird mit
    einem Satz abgelehnt, dasselbe zaehlt nicht doppelt, einzeln
    entfernen laesst die anderen stehen, alle drei laden wirklich
    (naturalWidth), Kreuze 44x44 und keines verdeckt (mit Gegenprobe
    per Deckel), nichts ragt auf 390 px heraus
  pruef-nachfrage          69 -> 74 ok
  pruef-struktur          102 ok, 413 Routen (vorher 414: zwei weg,
                          eine neu)
  pruef-zeichen             7 ok (vorher 1 Fehler)
  pruef-aufbewahrung       45 ok
  pruef-manager-ziele     216 ok
  pruef-ports              10 ok · pruef-portnummern 41 ok
    (die neue Pruefdatei verschiebt die abgeleiteten Nummern)

NUR DAS AGENTURHAUS IST BETROFFEN. Die Supportseite liegt unter
`/workspace`; am Crew-Haus aendert sich keine Zeile.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 23:38:03 +02:00
DogFatherGitandClaude Opus 5 3ab69d36a5 Eine dauerhafte Aufgabe wird nicht abgehakt -- auch nicht ueber den Status
VanVan im Support, Meldung #6: „Der Modi kann die dauerhafte Aufgabe
immer noch auf erledigt setzen."

DIE SPERRE GAB ES SEIT DEM 30.09. -- ABER NUR AN EINER TUER.

`/mein-stand` lehnt „erledigt" bei einer dauerhaften Aufgabe seither
ab. Der STATUSWEG (`PATCH /workspace/api/aufgaben/:id`) kannte
`dauerhaft` ueberhaupt nicht. Wer die Aufgabe ohnehin aendern durfte --
etwa weil das Uebernehmen aus dem Pool ihn verantwortlich macht --
hakte sie damit einfach ab. Zwei Tueren, eine Regel, und die Regel
hing nur an einer.

UND ICH HABE DAS LOCH HEUTE FRUEH VERBREITERT. Mit dem Commit davor
darf eine Modi den Status ihrer Aufgabe setzen (damit VanVans Satz
„es gibt darüber ja den button starten" fuer sie ueberhaupt stimmt).
Damit stand ihr genau der Weg offen, der ihr an der anderen Tuer
ausdruecklich verwehrt ist. Gefunden habe ich es nicht beim Bauen,
sondern beim Lesen der offenen Supportmeldungen -- ihr Satz stand seit
dem 28.09. da und passte ploetzlich auf meine eigene Aenderung.

GEAENDERT

 1. Der Statusweg lehnt „erledigt" bei einer dauerhaften Aufgabe ab,
    wenn die Person nicht verteilen darf. DERSELBE Fehlercode wie in
    `/mein-stand` (`dauerhafte_aufgabe`) -- die Oberflaeche uebersetzt
    ihn schon, und ein zweiter Code fuer dieselbe Sache waere der, den
    beim naechsten Mal jemand uebersetzt und der andere nicht.

 2. Der Knopf faellt weg, der die Absage holen wuerde (`darf_beenden`
    vom Server). Dieselbe Ueberlegung wie bei „Fertig" auf der
    Zuteilungskarte, die seit dem 30.09. daneben steht: Ein Knopf, der
    eine Absage holt, ist schlimmer als keiner.

    NUR DER LETZTE SCHRITT faellt weg. „starten" und „zur Freigabe"
    bleiben -- auch eine stehende Aufgabe hat einen Anfang, und der
    Unterschied zwischen „offen" und „in Arbeit" sagt etwas.

 3. BEENDET WIRD SIE VON DER LEITUNG. Das stand seit dem 30.09. als
    Satz im Kommentar von `/mein-stand`; jetzt stimmt er auch.

GEPRUEFT -- UND ZWAR BEIDE TUEREN, sonst wandert der Fehler nur:

    eine dauerhafte Aufgabe (#3)
    Tuer 1 (mein-stand) ist zu (409 dauerhafte_aufgabe)
    Tuer 2 (Status) jetzt auch (409 dauerhafte_aufgabe)
      anfangen darf sie trotzdem (200)
      und die Leitung beendet sie (200)
    und die Oberflaeche erfaehrt es (darf_beenden false)

Die dritte Zeile ist die Gegenprobe gegen zu viel Sperre: „gesperrt"
darf nicht heissen, dass gar nichts mehr geht.

GEPRUEFT: pruef-zuteilung 90 -> 96 ok · pruef-bewerbung-aufgaben 164 ·
pruef-aufgabenbrett 49 · pruef-aufgaben-vorlagen 46 · pruef-struktur 102.

WAS AUS DERSELBEN MELDUNG NOCH OFFEN IST (VanVan, #6): Bei den
VORLAGEN laesst sich weder die Frist anpassen noch „dauerhaft"
einstellen, und eine Anmerkung fehlt auch. Das ist ein eigener Umbau
und steht hier nur, damit es nicht untergeht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 19:26:55 +02:00
DogFatherGitandClaude Opus 5 2fb92f86f3 Die Routenwache war unvollstaendig -- 13 Routen waren ihr unsichtbar
GEFUNDEN ALS FEHLALARM, GEBLIEBEN IST EIN ECHTER FUND.

pruef-struktur meldete:

    assets/js/manager-ziele.js: Schnittstelle gibt es nicht
      -> /workspace/api/manager-ziele

Nachgesehen statt geglaubt: Die Seite ruft diese Adresse NIE auf. In
Zeile 31 steht `const BASIS = '/workspace/api/manager-ziele'`, benutzt
wird ausschliesslich `${BASIS}/stand`, `${BASIS}/eintraege`,
`${BASIS}/eintrag/${id}`.

DER EIGENTLICHE FUND LAG EINE EBENE TIEFER. Der SERVER registriert
seine Routen genauso:

    const BASIS = "/workspace/api/manager-ziele";
    managerZieleRouter.get(`${BASIS}/stand`, ...)

Die Sammelregel verlangte aber, dass ein Routenpfad direkt mit
`/workspace/` beginnt. ALLE DREIZEHN Routen dieses Moduls fehlten
damit in der Liste -- gemessen, nicht geschaetzt. Die Wache war also
nicht zu streng, sie war UNVOLLSTAENDIG: Zu diesen Routen konnte sie
gar nichts sagen, weder dass es sie gibt noch dass es sie nicht gibt.
Und weil die Aufrufe dorthin ebenfalls zusammengesetzt sind, ist es
nie aufgefallen -- ausser an dieser einen nackten Konstanten.

    Server-Routen eingelesen:  401 -> 414

GEAENDERT

 1. Einfache Praefix-Konstanten werden je Datei aufgeloest. Mehr
    nicht: Wer seinen Pfad aus drei Variablen zusammensetzt, bleibt
    unauffindbar -- und das ist richtig so, denn geraten wird hier
    nicht. Ohne bekannten Wert wird GAR NICHTS eingetragen; eine
    geratene Route waere schlimmer als eine fehlende, weil sie einen
    toten Aufruf als lebendig durchgehen liesse.

 2. Eine nackte Praefix-Konstante im Browser gilt als Praefix, wenn
    es Routen DARUNTER gibt. Abgeleitet, nicht aufgezaehlt -- eine
    Ausnahmeliste mit „manager-ziele" darin waere die naechste, die
    niemand pflegt.

GEGENPROBEN IN BEIDE RICHTUNGEN, weil die neue Regel etwas
durchlaesst:

    eine Praefix-Konstante wird als Praefix erkannt (Routen darunter)
    eine erfundene Adresse OHNE Routen darunter bleibt ein Fund
    und eine echte Route bleibt eine echte Route, kein Praefix

DAZU VIER SCHLUSSZEICHEN. Die Wache fuer das deutsche
Anfuehrungszeichen meldete vier Stellen in denselben zwei Dateien:
`„${was}" löschen?` und drei Geschwister. Berichtigt auf `“`.

UND EINE KORREKTUR AN MIR: Ich habe pruef-struktur heute dreimal als
„99 ok, Exitcode 0" protokolliert und dabei zwei rote Zeilen
uebersehen -- mein Filter zeigte nur die ersten drei FEHL-Zeilen und
die Zahl der gruenen. Gefunden habe ich es erst, als dieselbe Pruefung
spaeter Exitcode 1 meldete. Nachgemessen mit `git stash`: Die zwei
Funde stecken auch in HEAD, sie sind also nicht aus meiner laufenden
Arbeit gekommen. Eine Zusammenfassung, die nur die gruenen Zeilen
zaehlt, ist keine.

GEPRUEFT: pruef-struktur 102 ok, 0 Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 19:25:54 +02:00
DogFatherGitandClaude Opus 5 63e3924a08 Die Erinnerungen wirklich zugestellt -- und eine Zeile, an der alles hing
`pruef-manager-ziele` prueft, was `zielRufe()` ZURUECKGIBT. Eine Liste
ist aber keine Benachrichtigung. Dazwischen liegen noch: der
Fuenf-Minuten-Takt, die Artenliste, der Schalter in der Glocke, die
Ruhezeit, die Verschluesselung und das Merkmal gegen Doppelsendungen.
Dieser Weg war genauso nie gelaufen wie der Monatswechsel -- und er
laeuft zum ersten Mal am 1. November um 00:05 Uhr, von selbst, fuer
alle gleichzeitig.

DIE WICHTIGSTE FRAGE STAND GLEICH AM ANFANG

Am 1. um 00:05 ist RUHEZEIT (Vorgabe 22 bis 7). Die Meldung darf dann
nicht herausgehen -- aber sie darf auch nicht VERFALLEN. Das haengt an
einer einzigen Zeile in `benachrichtige`: Das Merkmal wird erst
geschrieben, NACHDEM wirklich zugestellt wurde. Waere es umgekehrt,
bekaeme am 1. November niemand eine Meldung, und zwar fuer immer --
der Takt haette sie als „schon geschickt" abgehakt, waehrend alle
schliefen. Gemessen: nachts null zugestellt UND null Merkmale, um
09:00 dann zwei. Die Zeile haelt.

GEPRUEFT WIRD DIE ECHTE UHRZEIT, NICHT EINE GEFAELSCHTE RUHEZEIT. Das
Haus kann die Ruhezeit per Umgebungsvariable verstellen; das waere
hier die falsche Frage gewesen. Gefragt ist, was am 1. November um
fuenf nach null passiert -- also wird die Uhr dorthin gestellt.

WAS SONST NOCH BEWIESEN IST (20 Pruefungen, 0 Fehler)

  * Der Takt laeuft 288-mal am Tag. Drei weitere Laeufe direkt
    hintereinander stellen NICHTS mehr zu -- ohne das Merkmal
    bekaeme jeder 288 Meldungen und legte das Handy weg.
  * Der Schalter in der Glocke schlaegt die Erinnerung: Wer die Art
    abgeschaltet hat, bekommt nichts, obwohl bei ihm etwas offen ist.
  * Ein Creator bekommt nichts (er hat diese Pflichten nicht), und
    wer kein Geraet angemeldet hat, erzeugt keine Geisterzustellung.
  * Am 11. ist Ruhe. Ohne diese Gegenprobe hiesse „es kommt an"
    moeglicherweise „es kommt jeden Tag", und der ganze Terminplan
    der Vorlage waere wirkungslos.
  * Der Glueckwunsch kommt genau einmal, und danach ist fuer den
    Fertigen Ruhe -- waehrend der andere am 16. weiter gemahnt wird.

GEMESSEN WERDEN ZUSTAENDE, NICHT ZEITPUNKTE. Der Server startet seinen
eigenen Takt und kann jederzeit in die Pruefung hineinlaufen. Deshalb
steht nirgends „nach meinem Aufruf kamen genau drei dazu", sondern „in
push_verschickt steht jetzt genau eine Zeile je Person".

UND DIE ERSTE PRUEFUNG DER DATEI PRUEFT DIE PRUEFUNG. „Null
zugestellt" ist gleich die erste erwartete Antwort; ohne den Beweis,
dass ueberhaupt etwas ankommen KANN, hiesse sie moeglicherweise „der
Dienst ist gar nicht angeschlossen".

NUR DIESE EINE DATEI IST DRIN. Der erste Anlauf dieses Commits hat
mit `git add -A` drei Dateien mitgenommen, die ich nie angefasst
habe -- sie wurden waehrenddessen von einer anderen Sitzung im selben
Verzeichnis bearbeitet (Zeitstempel: Sekunden alt). Zurueckgenommen,
bevor etwas gepusht wurde; ihre Arbeit liegt unveraendert im
Arbeitsverzeichnis.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 19:18:56 +02:00
DogFatherGitandClaude Opus 5 72e51c57b6 Den Monatswechsel durchgespielt -- und zwei stille Fehler gefunden
Der zentrale Weg dieser Kachel war nie gelaufen: „Am 1. jedes Monats
um 00:00 Uhr starten alle Zaehler automatisch bei 0." Der erste
Oktober lag vor der Auslieferung, der erste November liegt dahinter.
Er laeuft ohne Zutun und betrifft alle gleichzeitig -- waere er
falsch, waere er fuer alle auf einmal falsch, und niemand wuesste
warum.

Dieselbe Lage gab es am 01.09.2026 schon einmal in RunOne (der Umbau
zur Hashkette war seit Tagen live und nie gelaufen). Die Lehre stand
danach in der Projektnotiz, und sie gilt hier woertlich: Was sich
nicht zuruecknehmen laesst, wird vorher auf einer Kopie durchgespielt.

`pruef-monatswechsel.mjs` verstellt dafuer die Uhr -- eine Huelle um
`Date`, ganz oben, vor jedem Import. Damit laeuft der ECHTE Code
durch zwei echte Monatswechsel (20. Oktober -> 1. November, 00:05 ->
3. Dezember), ohne dass eine Zeile dafuer umgebaut werden muesste.
41 Pruefungen, 0 Fehler: Zaehler bei 0, keine Warnung am ersten Tag,
die neuen Zielzahlen greifen, die alten Eintraege stehen unveraendert
da, der Oktober ist zu, der Verlauf misst ihn am OKTOBER-Ziel, und
„Neuer Monat" geht an alle drei -- auch an den, der den Oktober voll
hatte.

WAS DABEI AUFGEFALLEN IST -- zwei Fehler, beide stumm

1. DIE SUCHE NACH DEM ROLLENWECHSEL MASS DIE FALSCHE PERSON.
   `WHERE person_id = ?` im Protokoll findet den, der die Aenderung
   GEMACHT hat -- also DogFather --, nicht den, dessen Rolle sich
   geaendert hat (workspace-personen.js schreibt die betroffene
   Nummer ins `detail`). Fuer den Betroffenen fand die Abfrage
   deshalb nie etwas; bei DogFather schob jede fremde
   Rollenaenderung SEINEN Pflichtbeginn. In der echten Datenbank
   stand bei ihm „grund: rollenwechsel" -- ein plausibler Wert aus
   der falschen Zeile.

   NACHGESEHEN, OB ES SCHADET: Alle sechs Zeilen stehen auf 2026-10,
   und das ist ohnehin der frueheste moegliche Monat. Der Fehler
   hatte noch keine Wirkung -- er haette sie beim naechsten
   Rollenwechsel bekommen.

2. `node:sqlite` BINDET EINE ZAHL ALS REAL.
   Der erste Versuch der Reparatur lautete
   `detail LIKE ('#' || ? || ' %')` und traf NIE -- ohne Fehler, ohne
   Warnung, immer leer. Nachgemessen:

       SELECT ('#' || ? || ' %')  mit der Zahl 42  ->  '#42.0 %'

   Gesucht wurde „#42.0 ", gespeichert ist „#42 ". Mit derselben Zahl
   als Zeichenkette stimmt es sofort. Das Muster wird jetzt in
   JavaScript gebaut; im uebrigen Haus kommt dieselbe Verkettung mit
   einer Zahl nicht vor (nachgesehen).

   Gefunden hat das nicht das Lesen, sondern eine Pruefung, die den
   ECHTEN Weg benutzt (die Route der Personenverwaltung) statt den
   Protokolltext selbst zu schreiben. Haette sie ihn selbst
   geschrieben, haette sie ihre eigene Annahme geprueft und waere
   gruen gewesen.

AUSSERDEM BERICHTIGT

Der Pflichtbeginn wurde EINMAL gesetzt und nie wieder angesehen
(`INSERT OR IGNORE`). Wer die Rolle verliert und spaeter zurueck-
bekommt, haette damit keinen Schonmonat mehr bekommen, obwohl die
Vorlage ihn zusichert. Jetzt wird neu gerechnet, wenn seit der
Festlegung ein Rollenwechsel dazugekommen ist -- und nur dann;
geprueft wird ausdruecklich, dass ein zweiter Abruf nichts bewegt.

GEPRUEFT: 216 + 41 = 257 Pruefungen, 0 Fehler

Mit drei Gegenproben an der neuen Stelle: DogFathers Pflichtbeginn
bewegt sich NICHT, wenn er die Rolle eines anderen aendert; ein
unbeteiligter Scout behaelt seinen Wert; und ein zweiter Abruf
rechnet nichts neu. Ohne die erste waere der Fehler von oben
unentdeckt geblieben, ohne die zweite hiesse „einer hat sich
geaendert" vielleicht „alle".

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 18:02:28 +02:00
DogFatherGitandClaude Opus 5 baf8288433 Korrigieren duerfen jetzt beide: Spicy Media und DogFather
Filipe auf die Rueckfrage, wer fremde Eintraege richtigstellen darf:
„ja spicy und dogfather".

Die Vorlage kannte dort nur DogFather („Vergangene Monate sind
gesperrt ... Ausnahme: DogFather"). Das gilt ab jetzt fuer beide --
und zwar fuer BEIDE Faelle, nicht nur fuer einen:

  * einen fremden Eintrag aendern oder loeschen
  * einen abgeschlossenen Monat dafuer kurz oeffnen

ES IST EINE MENGE UND KEINE ZWEITE LISTE. `darfKorrigieren()` gibt
`siehtAlles()` zurueck -- dieselbe Menge, die schon ueber die
Team-Uebersicht und die Zielzahlen entscheidet. Eine eigene
Aufzaehlung derselben zwei Rollen waere die, die beim naechsten Umbau
auseinanderlaeuft. Und inhaltlich gehoert es zusammen: Wer alle
Zahlen sieht und die Ziele setzt, muss einen Zahlendreher gerade
ruecken koennen; zwei verschiedene Grenzen fuer „darf alles sehen"
und „darf etwas richtigstellen" koennte spaeter niemand mehr
erklaeren.

Der Name der Variablen hiess vorher `istAdmin` -- also die Rechnung
statt ihrer Bedeutung. Jetzt heisst sie, was sie beantwortet.

NACHVOLLZIEHBAR BLEIBT ES UNVERAENDERT: Jede Korrektur an einem
fremden Eintrag und jede Aenderung an einem abgeschlossenen Monat
steht mit Name, Rolle und Zeit im Protokoll -- geprueft wird jetzt
ausdruecklich, dass dort auch `spicy` auftaucht.

GEPRUEFT: 206 Pruefungen, 0 Fehler (vorher 194)

Die Grenze wird in beide Richtungen gemessen, nicht nur in eine:
Spicy aendert wirklich (200, und der neue Wert steht in der
Datenbank), Spicy loescht wirklich -- aber ein Manager und ein
fremder Scout werden weiterhin abgewiesen (403), und danach steht
immer noch der Wert von Spicy da. Ohne diese Gegenproben hiesse
„Spicy darf" moeglicherweise „jeder darf". Loeschen ist eigens
geprueft: PATCH und DELETE sind zwei Routen, und zwei Routen koennen
auseinanderlaufen.

Auch die Freigabe fuer alte Monate wird nach Spicys Korrektur wieder
geschlossen gemessen -- eine geoeffnete Tuer ist kein Erfolg.

EINE MEINER PRUEFUNGEN WAR WIEDER FALSCH, NICHT DER CODE: Ich hatte
erwartet, dass ein Manager mit einer fremden Nummer in der Adresse
„nicht bearbeitbar" bekommt. Er bekommt `true` -- weil er gar keine
fremde Liste bekommt, sondern seine eigene; die Nummer wird fuer ihn
schlicht nicht beachtet. Richtiges Verhalten, falsche Frage. Gemessen
wird jetzt, was zaehlt: dass bei ihm kein einziger fremder Eintrag
ankommt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 17:52:36 +02:00
DogFatherGitandClaude Opus 5 b46f75484f Ein Klick statt eines Formulars -- der Schnell-Eintrag
Filipe mit dem Bildschirmfoto der Zeilen: „ich will das viel perfekter
und geiler. will dass es viel einfacher ist. am besten so wenig wie
moeglich zu tippen. fertige sachen, bereit um ab zu gehen."

GEZAEHLT, WAS EIN EINTRAG VORHER KOSTETE -- das war der Punkt:

    Manager Meeting   Knopf, Dialog, Speichern     2 Klicks + Fenster
    Schulung          dazu die Art waehlen         3 Klicks + Fenster
    Werbung           dazu den Link tippen         2 Klicks + tippen
    Creator           dazu den Namen tippen        2 Klicks + tippen

Ein Fenster fuer die Aussage „ich war heute im Meeting" sind drei
Handgriffe fuer null Angaben. Vier Aufgaben im Monat, acht Klicks,
acht Fenster.

JETZT

    Manager Meeting   EIN Klick  („Heute eingetragen")
    Schulung          EIN Klick  (zwei fertige Knoepfe)
    Werbung           Einfuegen + Eintragen, kein Tippen
    Creator           ein Klick je Lead -- oder mehrere Namen auf
                      einmal einwerfen

Am echten Bildschirm nachgemessen: 0/2 vorher, EIN Klick, 1/2 nachher,
„Rueckgaengig" bringt 0/2 zurueck. Nicht „der Knopf ist da", sondern
„danach steht eine andere Zahl dort".

DREI ENTSCHEIDUNGEN DAHINTER

1. DER WEG NIMMT EINE LISTE. „Drei Creator auf einmal" ist EIN
   Vorgang. Wer drei Namen aus Discord kopiert, hat das Monatsziel in
   einem Zug erledigt -- das ist der eigentliche Gewinn, nicht der
   gesparte Klick.

   JEDER EINTRAG WIRD EINZELN GEPRUEFT UND EINZELN BEANTWORTET. Die
   ganze Liste zurueckzuweisen, weil ein Name schon dasteht, waere
   die bequeme und die falsche Loesung: Dann weiss niemand, welcher
   der drei das Problem war, und tippt alles noch einmal. Geprueft
   wird genau dieser Fall -- zwei gehen durch, einer wird im Klartext
   abgelehnt, mit Namen.

2. KEINE SICHERHEITSABFRAGE VORHER, SONDERN „RUECKGAENGIG" DANACH.
   Eine Nachfrage bei jedem Klick waere der Handgriff, den wir gerade
   abgeschafft haben, in neuer Verkleidung. Sie kostet jeden; das
   Zuruecknehmen kostet nur den, der sich vertippt hat. Acht Sekunden
   statt drei -- lang genug, um es mit einem Daumen zu treffen.

3. DIE ZULETZT GEWAEHLTE ART IST VORGEWAEHLT -- abgeleitet aus dem
   letzten Eintrag, nicht in einer Einstellung gespeichert. Eine
   Spalte „Lieblingsart" waere ein zweiter Bestand, der veralten
   kann; der letzte Eintrag veraltet nie.

WAS MIR DABEI AUFGEFALLEN IST

Ein Ein-Klick-Knopf macht den Doppeltipper zur wahrscheinlichsten
Fehleingabe -- bei „Heute eingetragen" merkt man nichts davon, es gibt
ja keine Angabe. Zwei Meetings an einem Tag zu VERBIETEN waere aber
falsch, sie sind moeglich. Also ein Hinweis statt einer Sperre:
„Fuer diesen Tag stehen jetzt 2. War das Absicht?" -- und das
Zuruecknehmen liegt ohnehin daneben. Mit Gegenprobe, dass beim ERSTEN
keine Warnung kommt; sonst waere sie keine Warnung, sondern ein
Begleittext.

AUSSERDEM

  * Die Zeilen bauen sich beim Eintragen nicht mehr neu, sondern
    ziehen nur die Zahlen nach. Sonst verschwaende das Feld, in dem
    man gerade tippt, unter der Hand.
  * „Einfuegen" holt den Link aus der Zwischenablage -- mit drittem
    Ausgang: Firefox gibt sie ohne Erweiterung nicht her, und dann
    wird das gesagt, statt dass ein Knopf stumm bleibt.
  * Im Dialog drei fertige Tage (Heute / Gestern / Vorgestern) statt
    eines Kalenders. Was nicht mehr in diesen Monat gehoert, wird gar
    nicht erst angeboten -- am 1. und 2. fallen welche weg.
  * Der Dialog heisst jetzt „Mehr Angaben" und ist die Ausnahme fuer
    Notiz oder altes Datum. Dass er fuer etwas Normales gebraucht
    wurde, war sein Fehler.

GEPRUEFT: 194 Pruefungen, 0 Fehler (vorher 168)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 17:48:04 +02:00
DogFatherGitandClaude Opus 5 f6d2437985 Manager-Ziele zu Ende gebaut -- und dabei zwei Loecher gefunden
Filipe: „perfektioniere alles jetzt sofort, es muss ready sein."

Die Vorlage Punkt fuer Punkt gegen das Gebaute gehalten, nicht gegen
meine eigene Liste von heute Mittag. Vier Punkte standen noch offen,
und auf dem Weg dorthin sind zwei Fehler aufgefallen, nach denen
niemand gesucht hat.

DIE ZWEI FEHLER ZUERST -- beide gefunden durch Messen, nicht Denken

1. EINE GELOESCHTE PERSON HAETTE IHRE ZAHLEN MITGENOMMEN.
   `mz_eintrag.person_id` stand auf ON DELETE CASCADE. Die Vorlage
   sagt aber: „Wer die Rolle verliert, sieht die Kachel nicht mehr;
   die Daten bleiben fuer den DogFather erhalten." Mit CASCADE waere
   genau das nicht wahr gewesen -- `DELETE FROM personen` haette den
   Monatsverlauf eines Menschen lautlos mitgenommen.

   Jetzt SET NULL, und Name und Rolle stehen zusaetzlich als Text am
   Eintrag (dieselbe Bauweise wie bei support_meldungen). Die Rolle
   ist nicht Zierde: Ohne sie wuerde ein abgeschlossener Monat
   rueckwirkend an den Zielzahlen einer anderen Rolle gemessen.

   Der Umbau laeuft auf dem Bestand von heute Mittag -- Spaltenliste
   AUS PRAGMA abgeleitet, nicht gepflegt, und geprueft werden Zeilen
   UND Spalten. Am 11.09.2026 hat genau so ein Umbau drei Spalten mit
   Inhalt verloren, ohne Fehlermeldung, bei unveraenderter Zeilenzahl.

2. MEIN EIGENER SPERR-TRIGGER HAETTE DAS LOESCHEN BLOCKIERT.
   ON DELETE SET NULL ist kein Loeschen, sondern ein UPDATE auf
   person_id. Der Trigger sah eine Aenderung an einem abgeschlossenen
   Monat und brach ab -- `DELETE FROM personen` waere damit
   gescheitert, an einer Stelle, die mit Monatszielen nichts zu tun
   hat. Erlaubt ist jetzt genau eine Aenderung an einem alten Monat:
   dem Eintrag seinen Besitzer zu nehmen. Als BEDINGUNG und nicht als
   `UPDATE OF <spaltenliste>` -- eine Liste muesste jemand pflegen.

   Weil `CREATE TRIGGER IF NOT EXISTS` eine geaenderte Fassung nicht
   erneuert, wird die alte am INHALT erkannt und ersetzt. Eine
   Fassungsnummer muesste jemand hochzaehlen, und das wird vergessen.

DIE VIER OFFENEN PUNKTE DER VORLAGE

  04  Jede Aufgabenzeile hat ihr eigenes Zeichen -- aus dem Haus
      (`window.Bereiche`), nicht neu gezeichnet: Trichter, Bildschirm,
      Buch, Rahmen. Das Statuszeichen bleibt daneben; ein eingefaerbtes
      Aufgabenzeichen allein traegt die Stufe nicht.
  05  „Farbiger Rand + Badge": Eine Kachel, an der eine Warnung haengt,
      traegt jetzt einen feinen Saum -- JEDE Kachel, nicht nur diese.
      Eine Regel, die nur an einer Stelle gilt, wird beim naechsten Mal
      vergessen.
  08  Die Team-Tabelle ist sortierbar: jede Spalte ein Knopf (kein
      anklickbares <th> -- das erreicht die Tastatur nicht), mit
      aria-sort, und sortiert wird nach ANTEIL statt nach nackter Zahl.
      Dazu eine Ampel-Spalte mit Wort. Auf dem Handy verschwindet die
      Kopfzeile im Kartenmodus, deshalb steht das Sortieren zusaetzlich
      in der Leiste -- sonst waere es auf einem Telefon nicht
      vorhanden.
  09  Wer die Rolle verliert, steht weiter in der Uebersicht, als
      „nicht mehr dabei" und mit der Rolle von damals. Wer geloescht
      wurde, erscheint als zusammengefasste Zeile unter dem
      mitgeschriebenen Namen.

WAS DER SAUM MICH GELEHRT HAT

Er stand zuerst in start.css und war wirkungslos -- der Browser
lieferte weiter den Faseschatten. Der Grund steht seit dem 25.09.2026
in module.css: `:is()` uebernimmt die Spezifitaet seines staerksten
Arguments, und `.gruppe[data-gruppe]` macht die ganze Modulliste
(0,2,0) -- genau so stark wie `.kachel[data-warn="ja"]`, bei
Gleichstand gewinnt die zuletzt geladene Datei. Dieselbe Falle wie
damals bei den Fokusringen, dieselbe Antwort: Was gegen die Modulform
gewinnen muss, gehoert in die Datei mit der Modulform. Gemerkt habe
ich es nur, weil die Bildmessung den errechneten Schatten AUSGIBT
statt ein Bild zu machen.

Beim Herausschneiden blieb eine Klammer zu viel in start.css stehen --
gefunden von pruef-css-klassen („eine schliessende Klammer ohne
oeffnende"), bevor sie still CSS verschluckt hat.

AUSSERDEM BEHOBEN

  * Spicy Media sah an einer FREMDEN Liste „Bearbeiten" und „Loeschen",
    und der Server antwortete mit 403. Ein Knopf, der nichts tut, ist
    schlimmer als kein Knopf.
  * Klick auf eine Person klappt jetzt alle vier Zeilen auf. Die
    Vorlage verspricht „zeigt deren Eintraege" -- zugeklappt zeigte
    der Klick nur Zahlen.
  * Der CSV-Export kennt drei Staende statt zwei: „pflichtig", „neu,
    noch ohne Pflicht", „nicht mehr dabei". Vorher hiess beides „nein".
  * Das Aufklappen baute die ganze Liste neu und riss den
    angeklickten Knopf weg (Fokus sprang nach oben).

GEPRUEFT: 168 Pruefungen, 0 Fehler (vorher 141)

Neu darunter: der Umbau auf einem echten Alt-Bestand (Zeilen, Spalten,
Inhalt, Indizes, Trigger, und ein zweiter Lauf, der nichts mehr tut),
das Loeschen einer Person mit Eintraegen aus einem abgeschlossenen
Monat -- mit Gegenprobe, dass dieselbe Sperre den INHALT weiterhin
nicht aendern laesst.

Zwei meiner neuen Pruefungen haben zuerst sich selbst gemessen statt
den Code: Eine verglich gegen einen Eintrag, den sie vorher geloescht
hatte (404 sah aus wie ein haltender Riegel), die andere meldete eine
fehlende Spalte, die nur ihr eigener Handeinsatz verursacht hatte.
Beide berichtigt.

Am Bildschirm nachgemessen bei 412 px und 1280 px: kein waagerechtes
Schieben, kein eigenes Beruehrziel unter 40 px, genau EINE Kachel mit
Saum und zwanzig ohne.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 17:34:58 +02:00
DogFatherGitandClaude Opus 5 db656f6e14 Manager-Ziele: vier feste Monatsaufgaben, die sich selbst zuruecksetzen
Filipe mit der Vorlage „Prompt · Kachel Agentur-Aufgaben" (02.10.2026):
Scouts, Manager, DogFather und Spicy Media bekommen vier Pflichten je
Monat -- Creator rekrutieren, Manager-Meeting, Schulung oder Community
Talk, Werbung auf TikTok -- mit Fortschritt, Ampel, Warnungen und
einem Monatsschnitt, der nichts loescht.

DREI ENTSCHEIDUNGEN, DIE VON DER VORLAGE ABWEICHEN -- alle abgestimmt:

1. DIE KACHEL HEISST „Manager-Ziele", nicht „Agentur-Aufgaben".
   Es gibt bereits eine Kachel „Agentur" und eine „Aufgaben". Eine
   dritte mit beiden Woertern im Namen waere auf einem Handy nicht
   mehr auseinanderzuhalten.

2. DIE ZIELZAHLEN GELTEN JE ROLLE, und DogFather UND Spicy Media
   duerfen sie aendern. Ein Scout muss nicht dieselbe Zahl schaffen
   wie die Leitung.

3. DIE SCOUT-PIPELINE IST ANGEBUNDEN, in beide Richtungen: Vorschlaege
   aus uebergebenen Leads, Namensvorschlaege beim Tippen, die
   Verbindung bleibt am Eintrag gespeichert. Aber NICHTS zaehlt von
   selbst -- gezaehlt wird nur, was ein Mensch bestaetigt hat. Ein
   Zaehler, der sich allein fuellt, ist einer, dem niemand glaubt.

WAS ANDERS GEBAUT IST, ALS ES NAHELAG

DAS ZIEL WIRD PRO MONAT EINGEFROREN (`mz_ziel` hat den Monat im
Schluessel). Laege nur ein aktueller Wert in `einstellungen`, schriebe
jede spaetere Aenderung rueckwirkend den ganzen Verlauf um: Ein Monat,
der mit 2/2 abgeschlossen war, staende nach einer Erhoehung auf 4
ploetzlich als „nicht erreicht" da. Ein Verlauf, der sich rueckwirkend
aendert, ist keiner. Es gibt deshalb gar keinen Weg, den laufenden
Monat umzuschreiben -- gespeichert wird immer in den naechsten.

DIE SPERRE VERGANGENER MONATE SITZT IN DER DATENBANK, nicht im Code
(drei Trigger). Die Ausnahme fuer DogFather laesst sich in SQLite
nicht ueber die Sitzung abfragen, also ist sie ein sichtbarer Vorgang:
`mz_freigabe` wird fuer die eine Handlung geoeffnet, im `finally`
wieder geschlossen und verfaellt nach zwei Minuten von selbst. Jede
Korrektur steht mit Name und Zeit im Protokoll.

DER LAUFENDE MONAT STEHT IN EINER TABELLE (`mz_lage`), nicht in
`strftime(...,'localtime')`. Sonst entschiede die Zeitzone des Servers,
und am Monatsersten zwischen 00:00 und 02:00 griffe die Sperre fuer
den falschen Monat. Gerechnet wird durchgehend in Europe/Berlin
(identisch mit dem Europe/Luxembourg der Vorlage, aber dieselbe
Zeitrechnung wie der Rest des Hauses).

KEIN ZWEITER ZAEHLER FUER DIE KACHELWAND. Rand und Abzeichen auf der
Startseite kommen aus `workspace-hinweise.js` und damit aus derselben
Rechnung wie die Seite (`standFuer`). Zwei Rechnungen ueber dieselbe
Sache laufen auseinander, und zwar lautlos.

KEIN IMPORTKREIS ZU workspace-push.js. Die Erinnerungen entstehen hier
als Liste (`zielRufe`), verschickt werden sie im vorhandenen
Fuenf-Minuten-Takt. Der Tag steht im Merkmal -- dadurch geht pro
Person hoechstens EINE Meldung am Tag heraus, obwohl der Lauf
288-mal stattfindet.

GETRENNTE HAEUSER: Auf crew.dogfather-universe.com gibt es diese
Kachel nicht, auch nicht fuer DogFather. Gemessen, nicht angenommen.

GEPRUEFT (141 Pruefungen, 0 Fehler) -- mit Gegenproben zu jeder Sperre

  * Vier Rollen kommen herein, drei bekommen 404 (nicht 403), und die
    ANZAHL steht in der Bedingung. „Alle abgewiesen" waere auf einer
    leeren Liste wahr.
  * Die Ampel wird mit EINGESETZTEN Tagen gemessen, nie gegen die
    Wanduhr -- diese Pruefung sagt am 16. November dasselbe wie heute.
    (gate-oeffnung.mjs im Shop war gruen, bis der Kalender sie
    ueberholte.)
  * Die Datenbank lehnt einen Eintrag im Vormonat selbst ab; danach
    wird nachgewiesen, dass die Freigabe nur EINMAL gewirkt hat.
  * Neun Absagen mit dem jeweils richtigen Grund -- und eine
    Instagram-Adresse, die durchgehen MUSS, weil sonst nur bewiesen
    waere, dass die Pruefung streng ist, nicht dass sie richtig ist.
  * Am 7. des Monats ist Ruhe: Ohne diese Zeile bewiese der
    Erinnerungs-Block nur, dass immer etwas kommt.

ZWEI BEFUNDE KAMEN AUS DER MESSUNG, NICHT AUS DEM NACHDENKEN

  * Beim Aufklappen einer Zeile wurde die ganze Liste neu gebaut --
    der angeklickte Knopf existierte danach nicht mehr, der Fokus
    sprang an den Seitenanfang. Gefunden hat es die Bildmessung, der
    die Schaltflaeche unter der Hand wegbrach.
  * Zwei meiner Messungen waren falsch, nicht der Code: Der
    Haus-Test schickte den Keks nicht mit (401 statt 404), und
    `Response.text()` entfernt ein BOM beim Dekodieren -- der Export
    hatte eines, die Pruefung sah es nur nicht. Jetzt wird in Bytes
    gemessen.

Kachelton 47 (#7368ff) ist mit tools/kachel-farbe-einzeln.mjs gegen
alle 46 vorhandenen gerechnet, nicht ausgesucht: Abstand 0,0899,
Kontrast 4,61:1. Beruehrziele, waagerechtes Schieben und
Schriftgroessen sind am Bildschirm bei 412 px und 1280 px nachgemessen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 16:53:09 +02:00
DogFatherGitandClaude Opus 5 731537b682 Eine Wahrheit statt zwei: Der Status der Aufgabe gilt
VanVan im Support (Runde 1, „Ging noch nicht"): „Das dort steht ich
bewerbe mich ist jetzt weg, aber dafür hat er noch mal 2 Buttons
hinzugefügt mit ich fange an und fertig. Wenn man auf ich fange an
drückt steht dort in Bearbeitung und wenn man auf fertig drückt dann
wird es zu erledigt. Die Aufgabe bleibt aber im status offen stehen.
Die beiden Buttons können entfernt werden, weil es darüber ja den
button starten gibt, der auch korrekt funktioniert."

SIE HAT ETWAS GROESSERES GEFUNDEN ALS ZWEI UEBERFLUESSIGE KNOEPFE.

Es gab ZWEI Zustaende nebeneinander, und sie kannten sich nicht:

    aufgaben.status             offen · arbeit · review · erledigt
    aufgaben_zuteilung.zustand  angenommen · arbeit · erledigt

Die zwei Knoepfe setzten den zweiten (`/mein-stand`), der
Starten-Knopf den ersten. Auf der Karte stand „in Bearbeitung", in der
Liste „offen" -- und beides stimmte. Das ist schlimmer als ein Fehler:
Es gibt nichts, dem man glauben kann. Zwei Antworten auf dieselbe
Frage sind in diesem Haus verboten, und genau das war es.

WAS ICH BEINAHE FALSCH GEMACHT HAETTE

Ihr Wunsch war „entfernt die Knoepfe". Bevor ich das tue, habe ich
gemessen, was danach bliebe -- am Bildschirm einer Modi mit einer
angenommenen Aufgabe:

    Karten-Knoepfe:  []
    Schritt-Knoepfe: []

KEIN EINZIGER. Die Modi sieht den Starten-Knopf NICHT, weil
`darfAendern` fuer sie falsch ist: Sie ist weder Leitung noch
`creator_id`, `verantwortlich_id` oder `erstellt_von` -- die Zuteilung
laeuft ueber eine eigene Tabelle. VanVan ist Leitung und sieht ihn;
deshalb klang „den gibt es doch" selbstverstaendlich.

Haette ich die Knoepfe einfach geloescht, haette ich der Modi die
einzige Handlung weggenommen, die sie hatte -- eine Meldung „behoben",
nach der weniger geht als vorher.

ALSO WIRD IHR SATZ WAHR GEMACHT

 1. Wer eine Aufgabe WIRKLICH hat (angenommen/arbeit/erledigt), darf
    ihren STATUS setzen. Damit sieht die Modi denselben Knopf wie alle
    -- gemessen: „Schritt-Knoepfe: [starten ▶]".

    ENG GEFASST: nur der Status, nur allein in der Anfrage. Die
    Pruefung ist `Object.keys(...).length === 1` und nicht „enthaelt
    status" -- sonst waere die schmale Tuer die breite mit einem
    Zusatzfeld.

 2. Der Statuswechsel zieht die Zuteilung MIT. Ohne das waere das
    Entfernen eine stille Verschlechterung gewesen: Die Zaehler einer
    Person („offen / in Arbeit / erledigt") lesen die ZUTEILUNG, nicht
    die Aufgabe. Jede Zuteilung waere fuer immer auf „angenommen"
    stehen geblieben, und die Zahlen haetten aufgehoert, die
    Wirklichkeit zu zeigen -- ohne dass irgendwo etwas rot wird.

    ABGELEITET, NICHT ZWEIMAL GESCHRIEBEN: `STATUS_ALS_ZUSTAND` gibt
    es seit dem 22.09. Benutzt wird genau sie, mit EINER Abweichung,
    und die steht daneben: Wer zugesagt hat, faellt beim Zurueckdrehen
    auf „angenommen", nicht auf „offen". Eine Zusage verschwindet
    nicht, weil jemand den Status zurueckstellt.

 3. Die zwei Knoepfe sind weg. Der Weg `/mein-stand` bleibt -- er ist
    die Schranke fuer den, der die Schnittstelle direkt anspricht.

GEGENPROBEN ZUM ERWEITERTEN RECHT (ein Recht ohne Gegenprobe ist ein
Loch mit Begruendung):

    Anna hat eine Aufgabe, die ihr NUR zugeteilt ist
      (darf_aendern false, darf_status true)
    sie setzt den Status ihrer Aufgabe (200)
    mit einem zweiten Feld kommt sie nicht durch (403)
    und umschreiben darf sie gar nicht (403)
    der Titel steht unveraendert da („Clips schneiden")
    und wer sie nicht hat, setzt auch keinen Status (404)
    zurueckgedreht steht Anna wieder auf „angenommen"

    eine Bewerbung bleibt eine Bewerbung (abgelehnt -> abgelehnt)

ZWEI EIGENE FEHLER, BEIDE VON DER MESSUNG GEFUNDEN:

 · Mein erster Zeuge war Bea und die Pool-Aufgabe. Die Gegenprobe
   wurde rot: Bea darf sie ohnehin umschreiben, weil das Uebernehmen
   aus dem Pool sie verantwortlich macht. An ihr laesst sich ueber die
   neue, schmale Tuer gar nichts zeigen. Der reine Fall wird jetzt
   GESUCHT (darf_aendern falsch, Zuteilung angenommen) statt
   hingeschrieben -- eine feste Nummer waere die naechste, die beim
   naechsten Umbau nicht mehr stimmt.
 · Mein Abschnitt stellte Annas Aufgabe auf „arbeit" und liess sie so
   stehen; ein spaeterer zaehlte ihre „angenommen" und wurde dadurch
   rot. Eine Pruefung, die den Bestand fuer die naechste veraendert,
   misst ab da etwas anderes als sie glaubt. Jetzt raeumt sie auf --
   und die Rueckfahrt ist selbst eine Messung.

ZWEI PRUEFUNGEN MUSSTEN MITZIEHEN, und das ist richtig so: Beide
verlangten „Ich fange an" -- geschrieben von mir am 30.09. fuer
VanVans ERSTE Meldung. Ihre Absicht bleibt woertlich dieselbe („kann
sie wirklich etwas tun?"), nur ist der Griff jetzt der Statusknopf.
`knoepfeAn` sieht dafuer auch neben den Zuteilungsblock: „kann sie
etwas tun?" laesst sich am Block allein nicht beantworten.

GEPRUEFT: pruef-zuteilung 75 -> 90 ok · pruef-bewerbung-aufgaben
162 -> 164 ok · pruef-struktur 99 · pruef-resuemee 35 ·
pruef-aufgabenbrett 49 · pruef-rechtetafel 19 ·
pruef-aufgaben-vorlagen 46.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 15:11:35 +02:00
DogFatherGitandClaude Opus 5 664b799568 Geprüft: Die Benachrichtigung kommt an, wenn die App ZU ist
Filipe: „mach noch einen check ob alles mit den benachrichtigungen jetzt
perfekt klappt und dass die leute sie auch bekommen wenn die app zu ist."

DREI PRUEFUNGEN GAB ES SCHON -- UND KEINE BEANTWORTET DIE FRAGE

    pruef-push       die Verschluesselung, gegen die Testvektoren aus
                     RFC 8291 und RFC 8292 gerechnet        (24 ok)
    pruef-push-weg   Zustellung, TTL, VAPID-Kopf, 410-Fall  (20 ok)
    pruef-push-ziel  wer was bekommt und wer nicht          (38 ok)

Sie hoeren alle beim Push-Dienst auf. Danach faengt der Teil an, um den
es geht: Der Browser muss den Service Worker AUFWECKEN, obwohl keine
Seite offen ist, und der muss etwas anzeigen.

NEU: pruef-push-zu.mjs (13 Pruefungen)

    1. Seite auf, Service Worker meldet sich an.
    2. ALLE Seiten des Workspace zu -- nachgezaehlt, nicht behauptet.
    3. Ein echter Push ueber das DevTools-Protokoll
       (`ServiceWorker.deliverPushMessage`) -- derselbe Weg, den
       Apple und Google benutzen.
    4. Erst DANACH wieder eine Seite, und gefragt, was dasteht.

Eine Meldung, die in Schritt 4 dasteht, kann nur in Schritt 3
entstanden sein. Gemessen:

    nach dem Push steht 1 Meldung da — bei geschlossener App
      „Neue Nachricht" · „VanVan hat dir geschrieben."
      sie weiss, wohin sie fuehrt (/workspace/chat.html)
      und traegt das Gesicht des richtigen Hauses (crew-192.png)
      mit dem Abzeichen fuer die Statusleiste (abzeichen-96.png)

DAS MESSINSTRUMENT IST EINE LEERE SEITE, und das steht so im Kommentar:
`ServiceWorker.enable` gibt es nur an einer SEITE, nicht am Browser
(nachgemessen -- am Browser antwortet das Protokoll „wasn't found").
Eine Sitzung an der App-Seite stirbt mit ihr. `about:blank` gehoert
nicht zum Haus, und dass KEINE Workspace-Seite mehr offen ist, wird
ausdruecklich gezaehlt.

AUCH EIN PUSH OHNE DATEN ZEIGT ETWAS AN. Das ist kein Schoenheitstest:
Ein Browser, der eine Push-Berechtigung hat und mehrmals schweigt,
ENTZIEHT sie wieder -- ab da kommt gar nichts mehr an. Der Fehler, der
sich selbst verschlimmert. Gemessen: „Creator Workspace · Es gibt
etwas Neues."

DER DRITTE AUSGANG, UND ER WAR NOETIG

Mein erster Lauf meldete „nach dem Push steht 0 Meldungen da" -- das
sah aus wie ein schwerer Befund am Haus. Es war der Browser.
Fuenf Aufbauten gemessen, eine Antwort:

    headless (Vorgabe), grant mit origin       -> denied
    headless (Vorgabe), grant ohne origin      -> denied
    headless (Vorgabe), permissions im Kontext -> denied
    headless=old                               -> denied
    mit Fenster (headless: false)              -> GRANTED

Ein kopfloser Chromium verweigert Benachrichtigungen, egal wie man die
Erlaubnis erteilt. Die Pruefung oeffnet deshalb ein Fenster -- und wenn
die Berechtigung trotzdem fehlt, endet sie mit Rueckgabewert 2 und dem
Satz „konnte nicht nachsehen. Das ist KEIN Befund am Haus." Eine
Pruefung, die ihre Voraussetzung nicht hat, darf nicht rot werden.

WAS DAMIT NICHT BEWIESEN IST, und das gehoert in denselben Absatz: ob
ein bestimmtes Handy sie auch anzeigt. Das haengt an den Einstellungen
des Geraets (Nicht stoeren, Berechtigung entzogen, auf dem iPhone die
Installation auf dem Startbildschirm). Geprueft ist der Weg bis zum
Browser, nicht die Laune des Telefons.

AM LAUFENDEN SYSTEM NACHGESEHEN (nur gelesen)

Zehn Anmeldungen, alle gesund -- `fehler = 0` bei jeder einzelnen, und
`zuletzt_ok` bei vieren auf heute 12:31 Uhr. Der Push-Dienst hat also
heute Zustellungen angenommen, und der laeuft ueber Apple und Google,
nicht ueber eine offene Seite.

    BananaStift  iPhone, Android, Windows   zuletzt ok 01.10. 18:18
    Diene        Android                    heute 12:31
    Dogfather    Android                    heute 09:18
    Ghost        Android                    heute 12:31
    Marina       Android                    heute 09:53
    Miss         iPhone                     heute 12:31
    Tamy         Android                    01.10. 18:18
    VanVan       Android                    heute 12:31

GEPRUEFT: pruef-push-zu 13 ok · pruef-push 24 · pruef-push-weg 20 ·
pruef-push-ziel 38 · pruef-ports 10 · pruef-portnummern 41 ·
pruef-pruefzaehler 7. (Die Portnummern leiten sich aus der
alphabetischen Stelle ab -- eine neue Pruefdatei verschiebt sie.)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 14:53:17 +02:00
DogFatherGitandClaude Opus 5 4c08c8859d Beim Antworten im Support darf jetzt ein Bild mit
VanVan (Support): „Wenn man hier im Support auf deine Frage 'geht es
wieder' reagiert und antwortet, kann man auch kein Bild hinzufügen. Das
müsstest du auch noch hinzufügen, damit man nochmal ein Bild anhängen
kann, wenn das Problem noch besteht oder sich durch die Änderung ein
neues Problem ergeben hat."

Ihr zweiter Halbsatz ist der eigentliche Grund, und ich waere nicht
darauf gekommen: Das Bild beim MELDEN zeigt das ERSTE Problem. Taucht
durch die Aenderung ein neues auf, hilft das alte Bild niemandem.

WO ES LIEGT: AN DER RUNDE, NICHT AN DER MELDUNG

Die Meldung hat schon ein Bild -- das vom ersten Mal. Wuerde es hier
ueberschrieben, waere nach Runde drei nicht mehr zu sehen, womit es
angefangen hat. Genau diese Frage loest einen wiederkehrenden Fehler,
und genau deshalb gibt es die Rundentabelle ueberhaupt (ihre eigene
Begruendung steht seit dem 25.09. darueber).

DERSELBE WEG WIE BEIM MELDEN, NICHT EIN ZWEITER

Text und Urteil reisen im Kopf (`x-text`, `x-geht`), das Bild im
Rumpf, eine Route fuer beides. Die Begruendung stand schon beim
Melden und gilt hier genauso: Zwei Routen haetten einen Zustand
dazwischen -- eine Antwort, die schon zaehlt, waehrend das Bild noch
laedt. Ein leerer Rumpf ist zulaessig; ein Bildschirmfoto ist Hilfe,
keine Huerde.

DIE SPALTEN MUESSEN NACHGETRAGEN WERDEN, und das ist die Stelle, an
der es sonst schiefgeht: Die Tabelle entsteht mit `CREATE TABLE IF NOT
EXISTS`. Auf einer Datenbank, die es schon gibt -- also auf dem Server
-- sieht das den Namen, findet ihn, und ist fertig. Die vier neuen
Spalten kaemen dort NIE an: lokal alles gruen (jede Pruefung legt ihre
Datenbank frisch an), live ein Schreibfehler. Zwanzig Zeilen weiter
oben steht derselbe Fall schon einmal, damals mit einem Index.
Deshalb ein ALTER-Nachtrag, der die Tabelle SELBST fragt
(`PRAGMA table_info`) statt einer gepflegten Liste.

DATENBANK VORHER GESICHERT (Hausregel bei Schemaaenderungen):
`sicherungen/vor-support-rundenbild-20261002-142949.db`, geprueft mit
`integrity_check: ok`, 20 Personen, 16 Runden.

DER DIALOG KANN JETZT EIN BILD -- UND ZWAR NUR, WENN MAN IHN FRAGT

Das Feld ist eine Option von `frageNach` und standardmaessig AUS.
Ohne diese Vorgabe bekaemen die 56 anderen Rueckfragen im Haus ein
Bildfeld, nach dem niemand gefragt hat.

Es steht dort und nicht in support.js, weil Grund und Bild in
DENSELBEN Kasten gehoeren: Zwei Dialoge nacheinander hiessen, dass
jemand beim zweiten abbricht und den ersten umsonst getippt hat --
dieselbe Begruendung, aus der die Anzahl-Zeile dort gelandet ist.

Mit Vorschau. Wer sieht, was er anhaengt, haengt seltener das falsche
Bild an.

IM NOTAUSGANG GIBT ES KEINS, und das wird gesagt statt verschwiegen:
`window.prompt` kann keine Datei. Wer einen Browser ohne `<dialog>`
hat, kann antworten -- nur eben ohne Anhang. `bild: null` sorgt dafuer,
dass die aufrufende Stelle nicht raten muss.

GEPRUEFT

pruef-support 48 -> 78. Fuenf vorhandene Aufrufe mussten auf den neuen
Weg mitgezogen werden -- haette ich das vergessen, haetten sie ab
heute nur noch ihre eigene Veraltung gemessen. Neu dazu:

    die Antwort geht mit Bild durch (200)
    im Verlauf haengt das Bild an Runde 1
      und zwar an DIESER Runde, nicht oben an der Meldung
    der Melder bekommt es wieder (200, 70 von 70 Bytes)
    und ueber den gemeinsamen Ausliefer-Weg (Accept-Ranges)
    die Leitung sieht es auch (200)
    ein Fremder bekommt 404 — nicht 403, sonst waere die Nummer verraten
    ohne Anmeldung gar nichts (401)
    ohne Bild geht es genauso (200)
    eine PDF wird abgelehnt (415)

pruef-nachfrage 53 -> 69, am echten Bildschirm, mit echten Dateien
ueber `DataTransfer`:

    ohne Angabe bleibt die Bildzeile verborgen
    der Knopf ist 44 px hoch (Fingermass)
    nach der Wahl steht der Name da, Vorschau ist da
    ein 300x900 grosses Bild wird auf 160 px gedeckelt
      und der Senden-Knopf steht weiter im Fenster
    Gegenprobe: Abbrechen gibt nichts zurueck, auch kein Bild
    und beim naechsten Oeffnen ist es leer

ZWEI EIGENE FEHLER, BEIDE VON DER MESSUNG GEFUNDEN:
 · Meine erste Fassung las die neue Meldung ueber `.id` statt
   `.meldung.id` und meldete „#undefined". Die Pruefung hatte recht,
   der Fehler war meiner.
 · Die Obergrenze der Vorschau habe ich zuerst an einem 1x1-Bild
   gemessen: „3 px, hoechstens 160" -- gruen und wertlos, ein ein
   Pixel hohes Bild kann keine Grenze ueberschreiten. Jetzt entsteht
   im Browser ein 300x900 grosses, und die Grenze wird wirklich
   geprueft.

Dazu unveraendert gruen: pruef-aufbewahrung 45 · pruef-css-klassen 37 ·
pruef-struktur 99.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 14:30:39 +02:00
DogFatherGitandClaude Opus 5 58911d7c4f Auf dem Handy steht jetzt da, wer reagiert hat
VanVan (Support): „Wenn man auf dem Handy auf die Reaktionen unter einer
Nachricht geht, dann sieht man nicht wer darauf reagiert hat. Auf dem PC
funktioniert es."

DIE URSACHE STAND IM QUELLTEXT, mit Kommentar und allem:

    b.title = `${r.wer.join(', ')} · ...`

Ein `title` erscheint beim UEBERFAHREN MIT DER MAUS. Auf einem Finger
gibt es kein Ueberfahren -- und das Antippen schaltet stattdessen die
eigene Reaktion um. Die Auskunft war also nicht versteckt, sondern an
ein Geraet gebunden, das die Haelfte des Teams nicht benutzt. „Auf dem
PC funktioniert es" war der entscheidende Satz ihrer Meldung.

GEAENDERT: Unter den Kacheln steht auf Fingergeraeten eine Zeile mit
den Namen -- je Zeichen, mit dem Zeichen davor:

    👍 Patrick · ❤️ VanVan, Miss

WARUM EINE ZEILE UND KEIN LANGDRUECKEN. Ein langer Druck ist die
uebliche Antwort und die schlechteste: Man muss wissen, dass es ihn
gibt. Hier sind es Leute aus EINEM Raum, also kurze Listen -- sie
passen hin. Was dasteht, muss niemand finden.

WARUM NUR AUF DEM FINGER. Am Rechner funktioniert das Ueberfahren, und
eine Dauerzeile unter jeder zweiten Nachricht waere dort Unruhe ohne
Gewinn. Der `title` bleibt unveraendert.

ZWEI KLEINIGKEITEN, DIE KEINE SIND:
 · `aria-hidden="true"` an der Zeile. Jede Kachel traegt ihre Namen
   schon im `aria-label`; ohne das hoerte ein Vorleseprogramm alles
   doppelt.
 · Die Farbe ist die der Blase (`--blase-leise`), nicht eine feste.
   Derselbe Grund wie bei der Sprachnachricht: Jede Blase traegt die
   Farbe ihres Absenders, und eine feste Schrift ergaebe auf Babyblau
   wieder 1,91:1.

GEPRUEFT AUF BEIDEN GERAETEN, sonst beweist es nichts (pruef-chat-optik,
62 -> 71). Am Handy MUSS die Zeile da sein, am Rechner MUSS sie fehlen
und der Titel die Namen tragen. Ohne die zweite Haelfte waere eine
Regel, die immer gilt, genauso gruen -- und haette am Rechner eine
Zeile angehaengt, die niemand bestellt hat.

    auf dem Handy steht die Zeile da (true)
      und sie nennt den Namen: „👍 Patrick"
      und ein Vorleseprogramm hoert sie nicht doppelt (aria-hidden)
    am Rechner bleibt sie weg — dort funktioniert das Überfahren
      und die Namen stehen wie bisher im Titel

Gemessen wird mit einem FREMDEN Namen (DogFather schreibt, Patrick
reagiert). Mit der eigenen Reaktion staende „Du" da, und die Pruefung
haette den Fall nicht gemessen, um den es geht.

GEPRUEFT: pruef-chat-optik 71 ok · pruef-chat 63 ok ·
pruef-chat-aufloesen 126 ok.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 14:17:51 +02:00
DogFatherGitandClaude Opus 5 b808171704 Der Kamerahinweis wird wieder sichtbar -- und eine eigene Regression weg
ICH HATTE ES GESTERN FALSCH BEHAUPTET UND HEUTE SELBST VERSCHLIMMERT.
Beides steht hier, weil beides zum Befund gehoert.

WAS ICH GESAGT HATTE: „Auf 390 px ist der Hinweis 0 px hoch und
deshalb nicht zu lesen -- wo er hingehoert, ist eine Gestaltungsfrage
und gehoert Filipe."

Der zweite Halbsatz war eine Ausrede. Im Quelltext stand die ganze
Zeit eine 6-Sekunden-Uhr (reaktion.js, `sagFehler`), die ihn wieder
ausblendet. Statt das nachzusehen, habe ich aus zwei Messungen zu
verschiedenen Zeitpunkten einen Widerspruch gebaut (62 px hier, 0 px
dort) und ihn fuer eine Eigenschaft der Breite gehalten.

ALSO ABGETASTET STATT HERGELEITET (390x844, nach dem Laden):

    nach  500 ms  Text 104 Zeichen · hidden=nein ·   0 px
    nach 5000 ms  Text 104 Zeichen · hidden=nein ·   0 px
    nach 7000 ms  Text 104 Zeichen · hidden=ja   ·   0 px

Die Uhr stimmt also -- und trotzdem ist er die ganzen sechs Sekunden
NULL PIXEL hoch. Ein `role="alert"`, den niemand sehen kann. Das war
auf 390 px schon vorher so.

UND AUF 320 PIXELN HABE ICH ES HEUTE SELBST KAPUTTGEMACHT. Vorher
bekam `#fehler` dort eine stillschweigende fuenfte Rasterzeile mit
71 Pixeln -- sichtbar, aber auf Kosten des Bildes (56 statt 127).
Seit die Regie aus dem Fluss ist, bleibt fuer diese Zeile nichts
uebrig: Der Hinweis kostete nichts mehr und war dafuer unsichtbar.
Von „sichtbar und zu teuer" auf „gratis und wirkungslos" ist keine
Verbesserung.

DIE URSACHE, und sie steht seit dem 30.09. im Haus beschrieben:
`#fehler` ist ein Kind des Saals ohne Platzangabe. Der Saal hat vier
Zeilen; das Feld landet in einer fuenften, die es nicht gibt.

ERSTER REPARATURVERSUCH, GEMESSEN UND ZURUECKGENOMMEN: `grid-row: 2`
ohne `position: absolute`. Damit belegte das Feld die Zelle, der Raum
wich in eine stillschweigende zweite SPALTE aus, und das BILD fiel auf
0 px (320) bzw. 2 px (360). Bei `.raum` steht der gleiche Satz fuer
eine zweite ZEILE -- derselbe Fehler, andere Achse. Ich habe den
Kommentar gelesen, nachdem die Messung ihn mir bestaetigt hatte, nicht
davor.

SO GEHT ES: dasselbe Muster wie beim Pult. `position: absolute` nimmt
das Feld aus dem Fluss -- es belegt keine Zelle und verdraengt nichts.
`grid-row: 2` sagt dann nur noch, WORIN es liegt, `align-self: end`
setzt es an die Unterkante. Keine gerechnete Zahl.

GEMESSEN DANACH:

    320x568   Hinweis 62 px · im Fenster · obenauf · Bild 180 -> 180
    390x844   Hinweis 42 px · im Fenster · obenauf · Bild 219 -> 219
    430x932                                        · Bild 242 -> 242

Sichtbar, wenn er kommt. Nach sechs Sekunden wieder weg. Und er
kostet dem Bild kein Pixel mehr.

DIE PRUEFUNG STELLT DEN ZUSTAND SELBST HER (pruef-reaktion-schmal,
38 -> 44). Im Betrieb erscheint der Hinweis, wenn Kamera oder Mikrofon
fehlen -- auf einem Messrechner immer, auf einem Handy mit Freigabe
nie. Eine Pruefung, die darauf wartet, prueft die Messumgebung. Sie
schreibt den Text jetzt selbst hinein, macht ihn sichtbar, misst Hoehe
UND Bildhoehe, und raeumt wieder auf.

GEPRUEFT: pruef-reaktion-schmal 44 ok · pruef-reaktion 421 ok ·
pruef-css-klassen 37 ok · pruef-community-sicht 10 ok ·
pruef-breiten 23 ok.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 14:04:05 +02:00
DogFatherGitandClaude Opus 5 4a0ddf7d49 Die Regie wird auch auf dem kleinen Handy zur Schublade
Filipe: „auf so apps wie youtube und so geht es doch auch auf dem handy
also perfektionier es endlich."

Er hat recht gehabt, und meine Begruendung von 2026-09 war ueberholt.

WAS AUF 320x568 WIRKLICH PASSIERTE (Regie offen, laufende Sendung):

    Bild 0 px · Pult 1324 px IM RASTER · Transportleiste endet bei
    1567 von 568 Pixeln Fenster

Die Regie stand im Fluss statt darueber und schob alles hinaus. Ab
360 px war genau das laengst geloest -- es war dieselbe Seite, nur
schmaler. In reaktion.css stand dazu eine Sperre `and (min-width:
360px)` mit der Begruendung, der Kopf der Regie brauche 210 Pixel und
es seien nur 190 da. Fuenf Versuche hatten das nicht geloest.

DIE RECHNUNG STIMMTE NICHT MEHR. Seit 2026-09 gibt es einen Block
`@media (pointer: coarse)` ohne Breitengrenze, der den Kopf strafft.
Nachgemessen am 02.10.: 197 px, nicht 210 -- und mit einer weiteren
Straffung 147. Der Platz, der damals fehlte, war inzwischen da. Wer
der alten Begruendung geglaubt haette, haette nie nachgesehen.

VIER VARIANTEN DURCHGEMESSEN STATT DIE SECHSTE ZU RATEN
(320x568, Regie offen):

    heute             Bild   0 · Kopf 197 · Schublade 1324
    nur Sperre weg    Bild 180 · Kopf 197 · Schublade  234 · Inhalt  36
    + Knoepfe enger   Bild 180 · Kopf 147 · Schublade  234 · Inhalt  86
    + 86 % statt 72   Bild 180 · Kopf 147 · Schublade  280 · Inhalt 132

Die dritte Variante (Messwerte einzeilig) brachte gegenueber der
zweiten NULL und ist deshalb nicht eingebaut -- die bestehende
coarse-Regel erledigt das schon. Eine Regel, die nichts aendert, ist
eine, die beim naechsten Mal jemand sucht.

GEAENDERT

 1. Die beiden Sperren `and (min-width: 360px)` sind weg. Die Regie
    liegt jetzt auf JEDEM Fingergeraet ueber dem Bild statt im
    Raster, rollt in sich und hat einen stehenden Kopf.
 2. Neuer Block fuer unter 360 px: die drei grossen Knoepfe in EINE
    Zeile (`nowrap`, weniger Polsterung) und die Schublade darf
    86 statt 72 Prozent hoch werden.

    DIE 44 PIXEL HOEHE BLEIBEN -- das ist die Daumengrenze des
    Hauses. Nur die Breite gibt nach, und nachgemessen wird KEIN
    Knopf abgeschnitten (`scrollWidth <= clientWidth`).
    Die 86 statt 100 Prozent sind derselbe Gedanke wie die
    urspruenglichen 72: Oben bleibt ein Streifen Bild stehen, weil
    man sehen muss, worueber man gerade redet.

NACH DEM UMBAU GEMESSEN:

    320x568   Bild 180 px (war 0) · Kopf 147 (war 197)
              Schublade 280 · sichtbarer Inhalt 132 · Rest rollt 994 px
              Transportleiste endet bei 568 von 568
    360x640   Bild 203 px   unveraendert
    390x844   Bild 219 px   unveraendert

Zu UND auf ist das Bild auf 320 px jetzt gleich hoch -- das Oeffnen
der Regie kostet es nichts mehr.

EIN NEBENBEFUND HAT SICH MITERLEDIGT. Der Hinweis „Kamera oder
Mikrofon sind nicht freigegeben" sass in einer impliziten FUENFTEN
Rasterzeile (der Saal deklariert vier) und kostete das Bild 71 Pixel
(56 statt 127). Weil das Pult nicht mehr im Fluss steht, gibt es
diese Zeile nicht mehr: gemessen kostet der Hinweis jetzt 0 px
(325 -> 325).

WAS ICH DABEI FALSCH GEMACHT UND ZURUECKGENOMMEN HABE: Ich wollte
den Hinweis zusaetzlich mit `grid-row: 2` festnageln. Gemessen fiel
das Bild daraufhin auf 0 px (320) und 2 px (360) -- die explizite
Platzierung verdraengte die automatische des Bildes. Sofort wieder
entfernt. Die Messung hat es gefunden, nicht das Nachdenken; ohne
den Lauf davor haette ich eine Verschlechterung ausgeliefert.

DIE PRUEFUNG WURDE SCHAERFER, NICHT GRUENER (pruef-reaktion-schmal,
24 -> 38). Bis heute protokollierte sie den Mangel unter 360 px nur,
statt ihn zu behaupten -- richtig, solange es keine Reparatur gab,
falsch in dem Moment, in dem es eine gibt. Jetzt gilt auf JEDER
Breite: Bild behaelt seine Hoehe (zu und auf), Transportleiste bleibt
im Fenster, Inhalt der Schublade erreichbar, drei Knoepfe mit 44 px
unbeschnitten und obenauf, Zu-Knopf in jedem Zustand erreichbar.
Die Konstante `AUS_DEM_FLUSS_AB = 360` ist geloescht -- eine
Konstante, die nichts mehr trennt, ist der Anfang einer Erklaerung,
die nicht stimmt.

GEPRUEFT: pruef-reaktion-schmal 38 ok · pruef-reaktion 421 ok ·
pruef-css-klassen 37 ok · pruef-community-sicht 10 ok ·
pruef-breiten 23 ok · pruef-fingermass 5 ok.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 13:43:29 +02:00
DogFatherGitandClaude Opus 5 31437ac0dc Die Reaction auf dem kleinen Handy: gemessen, bewacht -- und ein Befund
MEINE EIGENE MERKLISTE WAR FALSCH.

Dort stand seit dem 01.10.: „320x568 zeigt noch ein 320x75 grosses
Videofeld und eine 1 px schmale Chatleiste." Nachgemessen stimmte davon
keine einzige Zahl. Eine Bestandsliste ist ein Wegweiser, keine
Wahrheit -- auch meine eigene.

WAS WIRKLICH DASTEHT (320x568, laufende Sendung):

    Regie ZU   Bild 127 px · Transportleiste endet bei 568 von 568
    Regie AUF  Bild   0 px · Transportleiste endet bei 1585 von 568
    Regie AUF bei 390/430: Bild unveraendert, Transport am Fensterrand

Die Chatleiste ist auf JEDER Handybreite `display: none` -- sie liegt
dort im Registerstreifen. Absicht, keine 1-px-Leiste.

Dass bei OFFENER Regie auf 320 px das Bild verschwindet, ist der in
reaktion.css dokumentierte Mangel samt sechs gescheiterten Versuchen.
Er wird hier NICHT repariert und auch nicht gruen abgehakt -- sonst
wuerde eine spaetere Reparatur rot.

DIE ENTSCHEIDENDE FRAGE WAR EINE ANDERE: Kommt man wieder heraus?
Gemessen in jedem Zustand und auf jeder Breite: Der Knopf, der die
Regie zumacht, steht im Fenster UND liegt obenauf (`elementFromPoint`,
nicht nur „sichtbar"). Es ist also ein Schoenheitsfehler und keine
Falle. Das war vorher niemandem bekannt, weil es niemand gemessen hat.

NEU: pruef-reaktion-schmal.mjs (24 Pruefungen)

Die Reaction-Seite war im Browser so gut wie unbewacht -- von fuenf
Pruefungen, die reaktion.html erwaehnen, oeffnet sie nur eine
ueberhaupt in einem Browser, und keine auf 320 px. Bewacht wird jetzt
die Grenze:

  1. Mit geschlossener Regie muss das Bild auf jeder Handybreite
     mindestens 100 px hoch sein (heute 127 / 219 / 242).
  2. Ab 360 px -- genau dort verlaeuft `@media (pointer: coarse) and
     (min-width: 360px)` -- muss das Bild seine Hoehe auch bei
     OFFENER Regie behalten.
  3. In JEDEM Zustand muss der Zu-Knopf im Fenster stehen und
     anklickbar sein.

Mit Gegenproben, die beweisen, dass sie rot werden kann: ein auf 0
gedruecktes Bild faellt durch, und ein zugedeckter Knopf gilt nicht
als anklickbar, obwohl er im Fenster steht.

-------------------------------------------------------------------
EIN BEFUND, DER FILIPE GEHOERT UND NICHT MIR

Beim Messen kam etwas heraus, das nicht auf der Liste stand. Die
Seite zeigt ein Hinweisfeld „Kamera oder Mikrofon sind nicht
freigegeben. Im Browser oben in der Adresszeile laesst sich …".
Gemessen, zweimal reproduziert:

    320 px   Das Feld kostet das Bild 71 px: 56 -> 127
             (es landet in einer impliziten FUENFTEN Rasterzeile;
              der Saal deklariert vier)
    390 px   Das Feld kostet 0 px -- weil es dort 0 px HOCH ist

Also: Auf dem kleinen Handy frisst der Hinweis mehr als die Haelfte
des Bildes. Auf dem normalen ist er ueberhaupt nicht zu lesen. Eine
Meldung, die erklaert, wie man die Kamera freigibt, und die man dabei
nicht sehen kann, ist keine.

Wo dieser Hinweis hingehoert, ist eine Gestaltungsfrage und damit
Filipes. Deshalb steht die Messung im Protokoll der Pruefung, aber
nicht als Behauptung im Code.

WIE ES GEMESSEN WIRD, nachdem der erste Anlauf wackelte: Nicht die
Hoehe des Feldes (die hing davon ab, WANN gelesen wurde -- in einem
Lauf 62 px, im naechsten 0), sondern der Unterschied vorher/nachher im
selben Lauf: Bild messen, Meldung leeren, Bild noch einmal messen.
Zweimal hintereinander identisch.

GEPRUEFT: pruef-reaktion-schmal 24 ok · pruef-ports 10 ok ·
pruef-portnummern 41 ok · pruef-pruefzaehler 7 ok · pruef-struktur 99 ok.
Die Portnummern leiten sich aus der alphabetischen Stelle ab, eine neue
Pruefdatei verschiebt sie -- deshalb stehen die beiden Port-Pruefungen
mit dabei. Der Gesamtlaeufer liest das Verzeichnis (`readdirSync`) und
findet die neue Datei von selbst; es gibt keine Liste, die veralten
koennte.

AM PRODUKT IST NICHTS GEAENDERT.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 12:29:54 +02:00
DogFatherGitandClaude Opus 5 ea53d950cd Fingermass: beide Grundlinien auf NULL -- kein blindes Telefonfenster mehr
Seit dem 29.09. haelt pruef-fingermass zwei Zahlen, und beide muessen
GENAU stimmen: waechst eine, ist eine neue blinde Messung dazugekommen;
sinkt sie, deckt sie Platz fuer die naechste. Nach dem Grosscheck von
heute sagte die Pruefung selbst, was zu tun ist:

    FEHL Nur noch 0 blinde Fenster — die Grundlinie steht auf 1.
         Bitte in pruef-fingermass.mjs auf 0 senken.
    FEHL 0 Fenster mit Variable und ohne hasTouch (Grundlinie 2).

Beide Zahlen zaehlten dasselbe: `pruef-grosscheck`. Im Kommentar stand
seit dem 01.10. woertlich, warum sie stehen blieben -- „die Datei zu
aendern waere ein Zweizeiler; sie zu pruefen hiesse, 206 Seiten ueber
vier Rollen laufen zu lassen, und das braucht Filipes Zusage. Eine
Aenderung, die ich nicht pruefen darf, liefere ich nicht aus."

Die Zusage kam heute („mach jetzt den prüf groß check"), der Lauf ist
gruen, also faellt die Ausnahme. Beide Grundlinien stehen auf 0.

DAS IST MEHR ALS EINE KLEINERE ZAHL: Es gibt im ganzen Haus kein
Telefonfenster mehr ohne Finger und keines, bei dem offenbleibt, ob am
Telefon mit Mauszeiger gemessen wird. Jedes neue ist ab jetzt ein
Befund und kein Bestand. 29 Dateien messen am Telefon, 28 Fenster
haben einen Finger, 0 blind.

    pruef-fingermass: 5 Pruefungen, 0 Fehler

-------------------------------------------------------------------
NACHTRAG ZUR ZEITBOMBE VON HEUTE NACHT -- UND EINE KORREKTUR AN MIR

Heute Nacht war pruef-gifs rot, weil sie ins Treff-Gespraech schrieb,
wo zwischen 0 und 6 Uhr die Nachtruhe gilt. Repariert, indem sie sich
ein eigenes Gespraech anlegt.

Danach wollte ich wissen, ob noch andere Pruefungen dieselbe Bombe
tragen, und habe sie gestartet „solange das Fenster offen ist". Es war
NICHT offen: Im Protokoll stand 11:40 Uhr. Der Rechner war zwischendurch
aus, und ich hatte meine eigene, veraltete Zeitnotiz fuer die Gegenwart
gehalten -- genau der Fehler, vor dem in CLAUDE.md steht, dass auch
meine eigenen Notizen altern. Die erste Runde beantwortete die Frage
also gar nicht.

DIE NACHT BRAUCHT MAN DAFUER AUCH NICHT. Das Fenster ist eine
Einstellung (`TREFF_NACHT_AB` / `TREFF_NACHT_BIS`), und pruef-treffchat
macht es laengst so: Fenster verschieben statt Systemuhr. Damit laesst
sich die Nacht um 11:42 Uhr herstellen.

GEMESSEN, STATISCH AUSGEWAEHLT: Von 16 Pruefungen, die in einen Raum
schreiben, legen 13 ihn selbst an; uebrig blieben sechs Kandidaten.
Alle sechs mit kuenstlicher Nachtruhe (Fenster 11-13 Uhr, jetzt 11:42):

    pruef-chat-kanaele    81 ok      pruef-chat-aufloesen  126 ok
    pruef-entwicklung     79 ok      pruef-chatkachel       40 ok
    pruef-loeschen        31 ok      pruef-anruf           132 ok

489 Pruefungen, 0 Fehler. Keine weitere Zeitbombe dieser Art.

UND WEIL GRUEN NUR DANN ETWAS HEISST, WENN ES AUCH ROT WERDEN KANN --
drei Messungen statt einer Behauptung:

    1. Kommt der Schalter an?    istNachtruhe false -> TRUE
    2. ALTE pruef-gifs, Nacht:   2 FEHL  (die Methode findet es)
    3. NEUE pruef-gifs, Nacht:   0 FEHL  (die Reparatur haelt wirklich)

Ohne (2) waere (3) wertlos gewesen: Sechs gruene Laeufe sehen genauso
aus, wenn der Schalter gar nicht ankommt.

AM PRODUKT IST NICHTS GEAENDERT -- eine Pruefdatei, zwei Zahlen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 11:45:16 +02:00
DogFatherGitandClaude Opus 5 7edb9c1bdb Grosscheck: mit Finger messen -- und 0 px ist keine kleine Schrift
AUFTRAG: „mach jetzt den prüf groß check."

ERGEBNIS DES LAUFS: 206 Seiten, 122 551 Elemente, 3 870 bedienbare.
Rechner (1280 px) alle vier Rollen sauber, 33 oeffentliche Seiten auf
beiden Groessen sauber, alle fuenf Gegenproben schlagen an. Vier
Beanstandungen, alle dieselbe Stelle -- und beide Ursachen lagen in der
Pruefung, nicht am Produkt.

1. ER HAT OHNE FINGER GEMESSEN

Die drei Browser-Kontexte setzten nur die Fenstergroesse. Ohne
`hasTouch` meldet Chromium `pointer: fine`, und KEINE Regel aus
`@media (pointer: coarse)` greift -- dort stehen im ganzen Haus die
44-Pixel-Beruehrziele. Ausgerechnet die Zeile `if (breite < 700 &&
r.klein.length)` misst genau diese Beruehrziele. Die Handy-Haelfte
dieses Laufs hat also eine Seite vermessen, die es auf keinem Handy
gibt. Dieselbe Luecke wie am 01.10. bei pruef-breiten, wo von sechs
Befunden nach dem Nachruesten genau einer uebrig blieb; 57 andere
Pruefdateien hatten es laengst, diese nicht.

Jetzt `hasTouch: b <= 860, isMobile: b <= 860` an allen drei Stellen --
gleiche Schwelle, gleiche Schreibweise wie ueberall sonst.

2. „0px" IST KEINE KLEINE SCHRIFT, SONDERN GAR KEINE

Gemeldet wurde viermal (einmal je Rolle) dasselbe:

    kalender.html  zu klein: A.k-pille 0px | A.k-pille 0px
                             | SPAN.k-anlass "🇩🇪 Tag der D" 0px

Am echten Bildschirm nachgemessen statt der Zahl geglaubt:

    Kasten 8x8 · Schrift 0px · Zeilenhoehe 0px
    GEMALTER TEXT: Hoehe 0 -- kein einziger Textkasten
    pointer-events: none · alle Kinder display:none
    title="Tag der Deutschen Einheit — gesetzlicher Feiertag"
    Tagesdialog: „10:00 Uhr Ein absichtlich sehr langer Titel …"

Im schmalen Monatsraster (Zelle 46 px breit) wird ein Termin
absichtlich zu einem farbigen PUNKT. `font-size: 0` ist dort das
Mittel, nicht der Mangel; kalender.css begruendet es ausfuehrlich, und
den Namen nennt der Tagesdialog. Es wird nichts gemalt -- die Frage
„ist dieser Text zu klein zum Lesen?" ist bei 0 px falsch gestellt.

Die Messung fragt jetzt `0 < Groesse < Grenze`. Zwischen 1 und 11,5 px
faellt alles weiterhin auf, und genau dort liegt der echte Mangel.

WAS DAS NICHT IST: ein Freibrief. `font-size: 0` versteckt Text auch
vor dem sehenden Auge -- aber das ist ein FEHLENDER Inhalt, kein zu
kleiner, und mit `display: none` entkaeme er dieser Messung ohnehin
genauso.

3. UND DIE AUSNAHME PRUEFT SICH IN BEIDE RICHTUNGEN

Eine Ausnahme ohne Gegenprobe ist der Anfang einer Liste, die niemand
pflegt. Deshalb zwei neue Gegenproben, direkt neben den fuenf
vorhandenen:

    ein Absatz mit 6 px  -> MUSS gemeldet werden
    ein Punkt mit  0 px  -> darf NICHT gemeldet werden

Ohne die erste waere die neue Regel auch dann gruen, wenn sie gar
nichts mehr findet.

AM PRODUKT IST NICHTS GEAENDERT -- eine einzige Pruefdatei. Kein
Stempel, kein Neustart noetig.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 04:56:52 +02:00
DogFatherGitandClaude Opus 5 87a3a14978 pruef-gifs war nicht kaputt, sondern nachts rot -- und ein Weg war ungeprüft
DIE ZWEI FEHLER AUS DEM LETZTEN LAUF WAREN KEINE FEHLER AM PRODUKT.

    FEHL das GIF steht danach wirklich im Verlauf
    FEHL und die Tafel geht zu -- man will sehen, wie es ankommt

Gemessen statt geraten: eine Sonde, die jede Anfrage mitschreibt. Die
Antwort stand sofort da, um 04:30 Uhr:

    POST /workspace/api/chat/raeume/1/gif
    403 {"fehler":"Das Rudel schläft. Ab 06:00 Uhr geht es weiter …",
         "nachtruhe":{"zu":true,"ab":0,"bis":6,"minuten":90}}

Die Pruefung klickte „das erste Gespraech in der Liste". Das erste ist
der TREFF, den der Server beim Start selbst anlegt -- und im Treff gilt
die Nachtruhe von 0 bis 6 Uhr. Also: tagsueber gruen, nachts rot, seit
es diese Pruefung gibt. Es ist derselbe Fehler wie am 06.09. im Shop
(„ein Test, der die Wanduhr als Annahme benutzt, misst irgendwann das
Gegenteil") -- dort ein Oeffnungstermin, hier ein Raum mit Nachtruhe.

Warum es nie jemandem auffiel: Fuer Dogfather Universe gibt es keinen
naechtlichen Pruefdienst (nachgesehen: `systemctl list-timers` kennt nur
`vandiy-pruefung` und `runone-pruefung`). Die Pruefung lief immer nur
dann, wenn jemand sie von Hand startete -- und das war bisher nie
nachts.

WAS GEAENDERT IST

1. pruef-gifs legt ein eigenes Gespraech mit Miss an und oeffnet GENAU
   DAS. Fuer ein normales Gespraech gibt es keine Nachtruhe; die Messung
   gilt jetzt rund um die Uhr. Findet es den Knopf nicht, bricht es laut
   ab statt still auf nichts zu klicken.

   Gemessen, 04:40 Uhr:
     verschicken: {"vorher":0,"nachher":1,"imVerlauf":true,
                   "adressen":["/workspace/api/chat/anhang/1"],
                   "tafelZu":true}
   17 Pruefungen, 0 Fehler. Und nebenbei belegt die Adresse, was der
   Quelltext behauptet: Das GIF wird KOPIERT und haengt danach als
   ganz normaler Anhang an der Nachricht.

2. DIE NACHTRUHE IST NICHT UNTER DEN TISCH GEFALLEN -- sie steht jetzt
   dort, wo sie hingehoert: in pruef-treffchat (110 -> 114). Dort wird
   das Fenster ueber die EINSTELLUNG verschoben, nicht ueber die
   Systemuhr, und beide Zustaende kommen in einem Lauf vor.

   DENN DER GIF-WEG WAR DORT ALS EINZIGER DER DREI UEBERHAUPT NICHT
   GEPRUEFT. Im Quelltext steht neben der Regel woertlich: „Sie nur
   beim Text und beim Anhang zu pruefen hiesse, dass man nachts zwar
   nicht schreiben, aber ein GIF schicken kann -- der Weg, den jeder
   findet, der es einmal versucht." Genau dieser Weg hatte keine
   Pruefung. Der Kommentar hat den Fehler beschrieben und nicht
   verhindert -- dieselbe Luecke wie beim Spaltenverlust vom 11.09.

   Gemessen, beide Zweige in einem Lauf:
     Fenster 7–9 Uhr, jetzt 4 -> 404 „Dieses GIF gibt es nicht mehr."
     Fenster 4–6 Uhr, jetzt 4 -> 403 „Das Rudel schläft. Ab 06:00 …"

   ZWEI ENTSCHEIDUNGEN DABEI, beide mit Grund:
   · Gefragt wird als DogFather, nicht als Gast. Die GIF-Kiste gehoert
     dem Rudel; ein Gast bekaeme seine 403 von der falschen Schranke
     (`nurRudel`) -- gruen, ohne die Nachtruhe je beruehrt zu haben.
   · Mit einer Nummer, die es NICHT gibt. Kommt trotzdem die
     Nachtruhe-Absage, steht die Schranke VOR dem Nachschlagen.
     Stuende sie dahinter, verriete der Server nachts an der Nummer,
     welche GIFs es gibt.

AM PRODUKT IST NICHTS GEAENDERT. Nur zwei Pruefdateien -- kein Stempel,
kein Neustart noetig.

GEPRUEFT: pruef-gifs 17 ok (vorher 15 ok / 2 FEHL) ·
pruef-treffchat 114 ok (vorher 110).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 04:36:14 +02:00
DogFatherGitandClaude Opus 5 34a227605c Der Ausliefer-Helfer haengt nicht mehr an Express -- und ist einzeln prüfbar
GEFUNDEN BEIM MESSEN, NICHT BEIM LESEN.

Nach dem Ausliefern wollte ich auf dem Server nachweisen, dass die DORT
liegende `helfer-ausliefern.mjs` wirklich Teilanfragen beantwortet. Dafuer
habe ich ihr einen winzigen Server vorgesetzt -- `node:http`, eine
Wegwerfdatei in /tmp, eigener Port. Die volle Datei kam sauber
(`accept-ranges: bytes`, `content-length: 1000`). Beim ersten Abschnitt:

    TypeError: res.status is not a function
        at liefereDatei (.../helfer-ausliefern.mjs:134:9)

`res.status()` gibt es nur an einer EXPRESS-Antwort. Alle zehn Aufrufer
SIND Express-Handler, im Betrieb lief also alles richtig -- 146 Pruefungen
in pruef-chat-anhaenge und 33 in pruef-wissen-neu haben es bestaetigt, und
sie hatten recht. Trotzdem ist es ein Mangel: Der Helfer hing an Express,
ohne dass irgendwo stand warum, und liess sich nur noch INNERHALB der
ganzen Anwendung pruefen.

GEAENDERT: Die drei Stellen setzen jetzt `res.statusCode = n` und rufen
`res.end()`. Das kennen beide Antwortarten, und Express aendert daran
nichts -- an der ausgelieferten Antwort ist kein Unterschied messbar.

DAZU EINE PRUEFUNG, DIE OHNE SERVER AUSKOMMT (pruef-struktur, +14):
`bereichLesen()` steht ausdruecklich als eigene, ausgefuehrte Funktion da.
Jetzt wird sie auch einzeln befragt -- ohne Browser, ohne Server, ohne
Datenbank:

    kein Kopf / leerer Kopf          -> volle Datei
    bytes=0-9 · bytes=5- · bytes=-8  -> der richtige Abschnitt
    bytes=0-5000                     -> endet am Dateiende (erlaubt)
    bytes=1000- · 9-5 · -0 · leere Datei -> 416
    mehrere Bereiche · fremde Einheit · Unsinn -> volle Datei

Die letzte Zeile ist die wichtigste: NICHT VERSTANDEN ist etwas anderes als
UNERFUELLBAR. Auf einen Kopf, den der Server nicht liest, gehoert die ganze
Datei -- nie eine falsche Teilmenge und nie eine Absage.

DIE LEHRE, die ich mir aufschreibe: Durch zehn Express-Handler hindurch
waere das nie aufgefallen. Was sich einzeln pruefen laesst, wird einzeln
geprueft -- und ein Helfer, den man nur mit der ganzen Anwendung messen
kann, ist schwerer zu beweisen als einer, dem eine Antwort genuegt.

GEPRUEFT: pruef-struktur 85 -> 99 ok · pruef-chat-anhaenge 146 ok ·
pruef-wissen-neu 22 ok. Danach dieselbe Messung auf dem Server noch einmal,
gegen die ausgelieferte Datei.

BERICHTIGUNG ZUM COMMIT DAVOR: Dort steht „pruef-wissen-neu 33 ok". Das
war keine Messung, sondern geschaetzt -- nachgezaehlt sind es 22 (16 vorher
plus meine 6). Die Zahl stimmte nicht, der Befund schon. Eine Zahl, die man
nicht gezaehlt hat, gehoert nicht in eine Zusammenfassung.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 03:46:32 +02:00
DogFatherGitandClaude Opus 5 4324547eb3 Teilanfragen: Sprachnachrichten kommen jetzt auch auf dem iPhone an
Filipe: „zeurst schaust du mal ob es im system liegt dass miss, die modi,
keine sprachnachrichten hoeren kann oder ob es an ihr liegt weil bei allen
anderen klappt nur bei ihr nicht"

ES LAG AM SYSTEM.

WAS GEMESSEN WURDE (nicht vermutet)

1. An ihrer Rolle liegt es nicht. Der Weg `/workspace/api/chat/anhang/:id`
   fragt drei Dinge: gibt es die Nachricht, ist die Person im Raum, hat sie
   das Gespraech weggeraeumt. Keine Rollenpruefung. Gegen eine Wegwerf-
   Datenbank gemessen: `anmelden admin=200 modi=200`, Anhang als modi
   HTTP 200, 40018 Bytes -- genau wie als admin.

2. Sie ist in allen drei Raeumen mit Sprachnachrichten, geloescht_bis = 0,
   alle sechs Tondateien liegen auf der Platte. (Live-Datenbank, nur
   gelesen, auf einer Kopie, Kopie danach geloescht.)

3. Sie ist die EINZIGE im Haus mit Safari. Aus dem Caddy-Protokoll, ueber
   IP und Minute mit ihren Protokolleintraegen abgeglichen: iPhone,
   iOS 18.7, Safari 26.6.1. Alle anderen Geraete der letzten zwei Wochen:
   Android-Chrome 3900 Anfragen, Windows-Chrome/Edge/Firefox 2646.
   Neun von zehn iPhone-IP-Praefixen sind ihre.

4. DER FEHLER: Der Anhang-Weg beantwortete eine Teilanfrage
   (`Range: bytes=0-1`) mit einer vollen HTTP 200 -- ohne `Accept-Ranges`,
   ohne `Content-Length`, als `chunked`. Zum Vergleich dieselbe Anfrage an
   `express.static`: HTTP 206, `accept-ranges: bytes`,
   `content-range: bytes 0-1/2480`.

   Safari verlangt fuer <audio> und <video> zwingend Teilanfragen und
   verweigert die Wiedergabe bei einer 200. Chrome und Firefox nehmen die
   ganze Datei klaglos. Bilder brauchen das nicht -- deshalb sah sie Fotos
   und hoerte nichts, und deshalb fiel es sieben Tage lang nur ihr auf.

WAS GEAENDERT IST

A) EIN GEMEINSAMER AUSLIEFERWEG (server/helfer-ausliefern.mjs)

   Im Haus gaben ZEHN Stellen eine Datei mit `createReadStream(pfad)
   .pipe(res)` hinaus: Chat-Anhang, Chat-GIF, Dateiablage (ansehen und
   laden), Material (ansehen und laden), Steckbriefbild, Buehnenbild,
   Supportbild, Wissens-PDF. Nur eine davon zu reparieren hiesse, eine
   Liste zu fuehren, welche Stelle schon richtig ist -- und die naechste
   neue macht es wieder falsch. Alle zehn gehen jetzt ueber
   `liefereDatei(req, res, pfad)`: `Accept-Ranges`, `Content-Length`,
   206 mit `Content-Range`, 416 mit `bytes */groesse`. Mehrere Bereiche in
   einer Anfrage werden absichtlich nicht bedient (das darf ein Server);
   die Antwort ist dann die GANZE Datei, nie eine falsche Teilmenge.

   WAS ES AUSSER SAFARI BRINGT, gemessen: Eine MP4-Sprachnachricht meldete
   in Chromium ohne Teilanfragen 0,23 s statt 1,96 s Laenge -- der Kopf
   einer MP4 steht am Ende der Datei. Eine Ogg-Datei meldete „Infinity"
   statt 2,02 s. Und ein PDF-Betrachter springt jetzt zu einer Seite, ohne
   die ganze Datei zu holen.

B) AUFGENOMMEN WIRD AAC IN MP4 (workspace/assets/js/chat.js)

   Die Reihenfolge der Behaelter beantwortete bisher die Frage „was kann
   DIESES Geraet am liebsten". Richtig ist „was koennen die ANDEREN
   abspielen" -- die hoeren es.

   Gemessen mit echten Aufnahmen aus echten Browsern, danach in beiden
   Engines abgespielt:
     Chromium nimmt auf: webm/opus, mp4(AAC), mp4(Opus)
     Firefox  nimmt auf: webm/opus, ogg/opus -- MP4 gar nicht
     Beide spielen alle vier Behaelter vollstaendig ab (2 s rein, 2 s raus)

   ZWEI FALLEN, die die Messung gezeigt hat:
   - Ein blankes `audio/mp4` ist nicht AAC: Chromium meldet darauf
     `audio/mp4;codecs=opus` zurueck -- MP4 aussen, Opus innen, fuer Safari
     genauso unbrauchbar wie WebM. Deshalb steht `audio/mp4;codecs=mp4a.40.2`
     VOR dem blanken `audio/mp4`.
   - Firefox kann kein MP4 aufnehmen und faellt sauber auf WebM/Opus
     zurueck. Kein Rueckschritt -- das ist der heutige Stand.

   Die Pruefung nimmt jetzt im echten Browser ueber den echten Knopf auf,
   und der Server erkennt: audio/mp4, 45583 Bytes, 2734 ms.

   BERICHTIGT: In zwei Kommentaren stand „Safari und das iPhone koennen
   nur MP4". Das stimmt nicht. An Miss' eigener Aufnahme nachgemessen:
   Behaelter WebM, Mux-Programm „WebKit", Tonspur A_OPUS. Safari NIMMT
   WebM auf -- ob es WebM abspielt, ist eine andere Frage.

C) EIN AUSWEG STATT EINER VERTROESTUNG (chat.js, chat.css)

   Vorher stand im Fehlerfall „Sprachnachricht laesst sich gerade nicht
   laden". Das war fuer Miss die ganze Auskunft, und es stimmte nicht
   einmal: Die Datei kam an, ihr Browser konnte den Behaelter nicht.
   „Gerade" heisst „gleich nochmal versuchen" -- bei einem fremden
   Behaelter hilft kein Versuch mehr.

   Jetzt wird unterschieden (Fehlercode 4 = Format, alles andere = Laden)
   und daneben steht ein Weg, der wirklich zum Ton fuehrt: Herunterladen,
   44 px hoch, in der Farbe der Blase, mit eigenem Vorlesewort. Nur im
   Fehlerfall -- ein Knopf an jeder Sprachnachricht waere Unordnung fuer
   alle, damit einer Person geholfen ist.

WAS JETZT NACHGEZAEHLT WIRD

- pruef-chat-anhaenge: 119 -> 146 Pruefungen. Dreizehn davon messen
  Teilanfragen am Foto (0-9, -8, 5-, ueber das Ende hinaus, 416, mehrere
  Bereiche, unverstandener Kopf) und vergleichen jeden Abschnitt BYTEWEISE
  mit der vollen Datei -- eine 206 mit den falschen Bytes waere schlimmer
  als keine. Drei Gegenproben legen dieselbe Messlatte an erfundene
  Antworten (die alte volle 200, falsche Gesamtgroesse, falsche Bytes) und
  muessen durchfallen. Neun weitere pruefen die Sprachnachricht selbst und
  den Ausweg.
- pruef-wissen-neu: +6. Der Weg zur PDF war der EINZIGE der zehn, den nie
  eine Pruefung abgerufen hat -- genau der, bei dem eine Umstellung
  unbemerkt danebengeht. Jetzt beide Spielarten (ansehen und laden).
- pruef-struktur: +6. Wer kuenftig wieder `createReadStream(...).pipe(res)`
  schreibt, bekommt einen Befund. Mit Gegenproben in beide Richtungen; die
  Probetexte sind zusammengesetzt, sonst meldet die Wache ihre eigene
  Begruendung als Fund. Pruefdateien sind ausgenommen, weil sie an niemanden
  ausliefern -- dort ist ein Weg ohne Teilanfragen die Gegenprobe.
  (Beim ersten Lauf hat die Wache sofort meine eigene Messdatei gefunden.)

WAS NICHT NACHGESEHEN WERDEN KONNTE

Ob iOS-Safari WebM/Opus ueberhaupt abspielt. Playwrights WebKit startet auf
diesem Rechner nicht (`icuuc77.dll`, auch nach Neuinstallation), und ein
iPhone habe ich nicht. Der dritte Ausgang: konnte nicht nachsehen. Deshalb
sind A, B und C drei Sicherungen hintereinander statt einer Wette auf eine.

GEPRUEFT (alles einzeln, kein Gesamtlauf)

  pruef-chat-anhaenge   146 ok   pruef-material     159 ok
  pruef-wissen-neu       33 ok   pruef-spenden      172 ok
  pruef-struktur         85 ok   pruef-support       63 ok
  pruef-video            74 ok   pruef-steckbrief    65 ok
  pruef-galerie          26 ok   pruef-eintrag-bild  24 ok
  pruef-chat             63 ok   pruef-chat-optik    62 ok
  pruef-haus-trennung   100 ok

Die beiden Haeuser bleiben getrennt (pruef-haus-trennung, 100 ok). Der
Ausliefer-Weg gehoert beiden gleichermassen und traegt nichts Haus-
spezifisches; die Aufnahme betrifft faktisch nur Team Dogi, weil nur dort
der Mikrofonknopf steht („also nur die modis rechte linke hand und
dogfather").

NICHT VON MIR, SCHON VORHER ROT: pruef-gifs meldet zwei Fehler („das GIF
steht danach wirklich im Verlauf", „die Tafel geht zu"). Gegen den
unveraenderten Stand von HEAD nachgemessen -- dieselben zwei Fehler, mit
denselben Zahlen. Ein eigener Befund, kein Nebenschaden dieser Arbeit.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 03:41:18 +02:00
DogFatherGitandClaude Opus 5 365e789cce Tagesgrenze: jetzt auch die Vergleiche, nicht nur das Schreiben
Von den sechzehn Stellen vom 01.10. SCHREIBEN zehn einen Tag in die
Datenbank — die decken die zwei Abschnitte von vorhin ab. Sechs
VERGLEICHEN gegen „heute": ist diese Frist vorbei, faellt dieser
Lead in den Zeitraum, ist dieser Bericht aktuell.

Davon findet ein Schreibtest keinen einzigen. Die Spalte sieht
richtig aus; falsch ist die Zahl, die jemand auf dem Bildschirm
liest.

ZWEI AUFGABEN GENUEGEN. Die Regel im Haus ist `frist < heute`:

    Frist = gestern (Ortszeit)  ->  muss ueberfaellig sein
    Frist = heute   (Ortszeit)  ->  darf es nicht sein

Mit dem alten UTC-Tag geht das in BEIDEN Zweigen der verschobenen
Uhr schief:

    Etc/GMT-14 (Ortstag = UTC+1): heute_alt waere gestern -> 0 statt 1
    Etc/GMT+11 (Ortstag = UTC-1): heute_alt waere morgen  -> 2 statt 1

GEGENPROBE AM ECHTEN CODE: In workspace-aufgaben.js den UTC-Tag
wieder eingebaut -> „genau eine ist ueberfaellig (0)". Zurueckgedreht
und wieder gruen.

UND EIN BEFUND AN MEINER EIGENEN PRUEFUNG, bei genau dieser
Gegenprobe: Die zweite Zahl (`heute`) blieb 1 — aber sie zaehlte die
FALSCHE Aufgabe. Mit dem UTC-Tag galt die von gestern als heute
faellig. Mit zwei Zahlen allein ist das nicht zu trennen; in beiden
Zweigen bleibt sie 1.

Sie steht jetzt ausdruecklich als BEGLEITPROBE da: Sie zeigt, dass
ueberhaupt gezaehlt wird, und der Unterschied kommt aus der Zeile
darueber. Eine Zahl, die aus dem falschen Grund stimmt, soll nicht
aussehen wie ein Beweis.

Dazu im Lauf eine ausgerechnete Zeile, die sagt, WARUM die Zahlen
etwas beweisen: „mit dem UTC-Tag waeren es 0 statt 1".

IM FENSTER NACHGEMESSEN (00:09 bis 00:40 Ortszeit, UTC noch der
Vortag) — die restlichen Pruefungen, die ich gestern zur falschen
Tageszeit geprueft hatte: zuteilung 75, aufgabenbrett 49,
content 45, vorlagen 24, bewerbung 91, scout-zuteilung 37,
unterstuetzung 70, aufbewahrung 45, ics 38, entwicklung 79 — alle 0
Fehler. Zusammen mit den vierzehn von vorhin sind das 24 Dateien,
die diesmal im richtigen Zeitfenster gemessen wurden.

pruef-tagesgrenze: 8 -> 12 Pruefungen, 0 Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 00:36:44 +02:00
DogFatherGitandClaude Opus 5 c5f4d237e3 Tagesgrenze: der Fehler von gestern ist jetzt rund um die Uhr pruefbar
UM 00:09 DES 02.10. WAR DAS FENSTER OFFEN — Ortszeit 2026-10-02,
UTC noch 2026-10-01. Genau die zwei Stunden, in denen der Fehler von
gestern zuschlug.

Ich habe die Reparatur am 01.10. zwischen 10 und 16 Uhr geprueft,
also zu einer Zeit, in der der Fehler GAR NICHT AUFTRETEN KONNTE.
Jetzt nachgeholt — vierzehn Dateien, 1083 Pruefungen, 0 Fehler. Die
entscheidende Zeile in pruef-kreislauf:

    ok   und er liegt HEUTE, nicht gestern (2026-10-02, heute ist 2026-10-02)

Gestern um dieselbe Uhrzeit stand dort 2026-09-30 gegen 2026-10-01.

DABEI IST MIR DAS EIGENTLICHE PROBLEM AUFGEFALLEN

Diese Zeile kann den Fehler nur ZWEI STUNDEN AM TAG ueberhaupt
sehen. Den Rest des Tages sind Ortszeit und UTC-Tag derselbe, und
sie ist wahr, ohne irgendetwas zu beweisen — ein gruener Haken ohne
Aussage, 22 Stunden lang.

pruef-tagesgrenze.mjs wartet deshalb nicht auf Mitternacht, sondern
verschiebt die Uhr. Node uebernimmt eine zur Laufzeit gesetzte TZ
(nachgemessen: Stunde 0 wird zu Stunde 12 unter Etc/GMT-14), und sie
steht VOR allem anderen — sonst haette der Server schon seine
Vorstellung vom heutigen Tag.

Welche Zone, haengt von der Uhrzeit ab: Es gibt keine, in der sich
die zwei Tage IMMER unterscheiden, dafuer braeuchte es 24 Stunden
Versatz. Ab 10 Uhr UTC also Etc/GMT-14, davor Etc/GMT+11; bei 10 Uhr
gehen beide, die Grenze ist kein scharfer Rand.

UND DAS WIRD NACHGESEHEN: Unterscheiden sich die Tage wider Erwarten
nicht, bricht sie mit dem dritten Ausgang ab (3) statt gruen zu
melden. Eine Pruefung ohne ihre Voraussetzung darf nicht bestaetigen
— daran ist am 03.09. die Gitea-Pflichtpruefung wochenlang
vorbeigelaufen.

Geprueft werden die zwei Stellen, die es wirklich getroffen hat: ein
Eintrag OHNE Datum, und die Kette Wunsch -> Termin.

GEGENPROBE: Den alten Weg in workspace-bereiche.js wieder eingebaut
(beide Stellen) -> 8 Pruefungen, 2 Fehler, beide mit dem falschen
Tag im Klartext. Die Zahl bleibt bei 8, nichts wird still
uebersprungen.

ZWEI DINGE AM DETEKTOR IN pruef-struktur

1. EINE AUSNAHME, DIE SICH SELBST PRUEFT. pruef-tagesgrenze benutzt
   den falschen Weg absichtlich und wurde deshalb zu Recht und
   trotzdem falsch gemeldet. Sie ist jetzt ausgenommen — aber nicht
   als stille Liste: Es wird nachgesehen, dass jede ausgenommene
   Datei das Muster WIRKLICH enthaelt. Raeumt es jemand weg, ist die
   Ausnahme veraltet und faellt auf.

2. EINE LUECKE, DIE MIR DABEI AUFFIEL. Der Detektor kannte nur
   `.slice(0, 10)`. Denselben UTC-Tag bekommt man mit
   `.split("T")[0]` und `.substring(0, 10)`. Gemessen schreibt das
   heute niemand so — aber „niemand schreibt es so" ist kein Schutz,
   sondern Glueck. Beide zaehlen jetzt mit, mit eigenen Gegenproben.

GEPRUEFT: pruef-struktur 75 -> 79, pruef-tagesgrenze 8, beide 0
Fehler. Ports nach der neuen Datei: bis 5417, 464 Nummern, 0
Kollisionen. pruef-arbeitsschloss 48/0, pruef-fingermass 5/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-02 00:17:10 +02:00
DogFatherGitandClaude Opus 5 e8a5d7bc7e pruef-glocke: drei Viertel der Pruefung sind nie gelaufen
8 Pruefungen standen am Ende da. Jetzt sind es 36.

SCHRITT FUER SCHRITT NACHGEMESSEN, statt der Meldung zu glauben:

  1. Drei von acht Rollen scheiterten mit „Zeitsperre nach 25 s"
     beim Warten auf start.html -- hand, linke, modi. Danach brach
     die Datei ab; alles dahinter lief nie.
  2. Nicht an der Last: allein dasselbe Bild.
  3. Was antwortet die Anmeldung im Browser? 401 ungueltig.
  4. Dieselbe Anmeldung ueber die Schnittstelle, am SELBEN laufenden
     Server: 200. Es lag also nie am Server.
  5. Der Unterschied ist die KACHEL. Es gibt zwei Anmeldeseiten:
         workspace/index.html       spicy, admin, manager, scout, creator
         workspace/crew-index.html  admin, hand, linke, modi, gast
     Auf 127.0.0.1 kommt die Agenturseite.

KEIN FEHLER AM PRODUKT. Der Server ist auf einer Pruefadresse
absichtlich grosszuegig, damit Pruefungen alles testen koennen (das
steht so im Quelltext); die zwei Seiten sind die Trennung der zwei
Haeuser.

DER FEHLER WAR EIN NOTNAGEL IN DER PRUEFUNG:

    const kachel = await seite.$(`.rolle[data-rolle="${rolle}"]`)
      || await seite.$(".rolle");

Er sollte verhindern, dass ein Klick auf eine fehlende Kachel
abbricht. Seit die Kachel am 30.09. BINDEND ist (`718b267d`, auf
Filipes Wunsch), macht er aus „diese Kachel gibt es hier nicht"
etwas Schlimmeres: Er klickt irgendeine, der Server weist zu Recht
ab, und heraus kommt eine Zeitsperre nach 25 Sekunden, die wie ein
Fehler an der Glocke aussieht.

EIN NOTNAGEL, DER STILL DAS FALSCHE GREIFT, IST SCHLIMMER ALS EIN
LAUTER ABBRUCH. Jetzt wird die richtige Seite PROBIERT (nicht aus
einer Liste von Crew-Rollen gelesen -- die waere die naechste, die
beim sechsten Eintrag nicht mitwaechst), und findet sich die Kachel
auf keiner der beiden, bricht es mit Namen ab und zeigt, welche
Kacheln dastehen.

DAS IST HEUTE DER ZWEITE FALL DERSELBEN WURZEL. Bei
pruef-crew-wand-bild war es dieselbe Folgewirkung der bindenden
Kachel, nur sichtbarer. Nach jener Aenderung bin ich die Pruefungen
zum Zugang gelaufen und nicht die, die nebenbei eine Anmeldung
brauchen.

DENSELBEN NOTNAGEL GIBT ES NOCH EINMAL, in pruef-gifs. Dort zielt er
auf `creator`, und die Kachel steht auf der Agenturseite -- er
greift heute nie. Das ist Glueck und kein Entwurf, also ist er auch
dort weg.

GEPRUEFT: pruef-glocke 8 -> 36 Pruefungen, 0 Fehler, alle acht
Rollen. pruef-gifs 17 Pruefungen, 0 Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 23:26:01 +02:00
DogFatherGitandClaude Opus 5 775aabef38 Standwache: hat sich der Stand WAEHREND des Laufs geaendert?
Die zweite Sitzung hat die Luecke benannt: Das Arbeitsschloss
schuetzt den Commit und die Stempellaeufe, nicht die Pruefläufe. Wer
misst, waehrend ein anderer speichert, misst einen Stand, den es
nicht mehr gibt.

Am 06./07.09.2026 sind so fuenf Gesamtlaeufe wertlos geworden — rund
zwei Stunden Wartezeit ohne einen einzigen Befund. Am 01.10. dieselbe
Lage, nur anders: zwei Sitzungen im Verzeichnis, eine misst, die
andere speichert. Aufgefallen ist es nur, weil die andere es von
sich aus gesagt hat.

DIE FRAGE IST EINE MESSUNG, KEINE ZUSTAENDIGKEIT

„Haelt jemand das Schloss" waere die falsche Frage, und zwar in
beide Richtungen:

  * Sie blockiert zu viel: Wer zwei Stunden am Schloss sitzt, haette
    in der Zeit keinen Prueflauf mehr. Eine Sicherung, die das eigene
    Arbeiten anhaelt, wird abgeschafft.
  * Sie blockiert zu wenig: Filipe am Editor hat kein Schloss, mein
    eigenes Werkzeug auch nicht.

Gefragt wird deshalb: Ist der Stand am Ende noch derselbe wie am
Anfang? Das trifft jede Quelle.

AN DER NOTBREMSE, NICHT IN 179 DATEIEN

Gemessen: 179 von 231 Pruef- und Messdateien rufen `notbremse`. Das
ist die eine Stelle, an der alle etwas bekommen — dieselbe
Ueberlegung wie bei der Notbremse selbst. Einzelne Dateien
nachzuruesten hilft nur bis zur naechsten ohne.

Fingerabdruck: Anzahl, Gesamtgroesse und juengste Aenderung von
workspace, assets, server, webdesign und den Seiten im
Wurzelverzeichnis — 670 Dateien in 27 ms. Kein Hash ueber den
Inhalt: Gesucht ist „hat jemand gespeichert", und das aendert immer
mindestens die Zeit.

BILDER ZAEHLEN NICHT. Die Messdateien legen selbst welche ab; eine
Wache, die bei jedem Bildschirmfoto anschlaegt, wird weggeklickt und
nimmt die echte Meldung mit.

SIE HAELT NICHTS AN. Ein Lauf, dessen Grundlage sich verschoben hat,
ist nicht „nicht in Ordnung" — er ist NICHT NACHSEHBAR. Deshalb
Rueckgabewert 3 (nicht 1, das waere eine Aussage ueber den Code; und
nicht 0, ein gruener Haken ueber einen Stand, den es nicht mehr
gibt, waere das Schlimmere) und ein ausdruecklicher Satz, dass das
kein Befund ist.

GEPRUEFT — pruef-arbeitsschloss 35 -> 48 Pruefungen, 0 Fehler:

  zwei Aufnahmen hintereinander gleich   (sonst waere jede Meldung
                                          wertlos)
  geaenderte Datei            -> faellt auf
  neue Datei                  -> faellt auf
  neues Bild                  -> faellt NICHT auf
  Lauf mit Aenderung          -> Rueckgabe 3, sagt NICHT NACHSEHBAR
  Lauf ohne Aenderung         -> Rueckgabe 0  (Gegenprobe; sonst
                                 waere „endet mit 3" auch wahr, wenn
                                 sie IMMER 3 meldet)

Alles in einem Wegwerf-Verzeichnis mit gefaelschtem Baum — moeglich,
weil die Wache ihre Wurzel aus ihrem EIGENEN Pfad ableitet. Waere
sie festgeschrieben, liesse sich die Wache nicht pruefen, ohne am
echten Haus zu wackeln.

UND AM ECHTEN LAUF NACHGEWIESEN: Mitten in pruef-arten eine Datei
gespeichert -> Rueckgabe 3, mit Groesse und Uhrzeit. Ohne Eingriff
bei neun Laeufen (treff 85, kalender 141, material 159,
erwaehnung 129, arten, dabei-optik, tagesblick, aufgabenbrett,
kopfleiste, seiteninhalt) kein einziger Fehlalarm.

EINE ERWARTUNG VON MIR WAR FALSCH, und die Wache hatte recht: Ich
hatte im gefaelschten Baum eine zaehlende Datei erwartet, es sind
zwei — die Seite UND die Kopie der Wache selbst im server-Ordner.
Der zaehlt mit, und das ist richtig: Eine geaenderte Pruefdatei
verschiebt den Stand genauso wie eine geaenderte Seite.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 23:18:13 +02:00
DogFatherGitandClaude Opus 5 ec0ee61691 Arbeitsschloss: der Haken bleibt auf LF, und ein Messfehler von mir
ZWEI NACHTRAEGE ZUM SCHLOSS.

1. DER HAKEN HAT KEINE DATEIENDUNG

Damit greift keine der Regeln in .gitattributes von sich aus — und
git kuendigt beim Committen selbst an: „LF will be replaced by CRLF
the next time Git touches it". Auf Linux ist `#!/bin/sh` mit einem CR
dahinter ein Programmname mit einem unsichtbaren Zeichen am Ende
(„bad interpreter"), und die Datei hat schon einen Kommentar genau
darueber.

Eigene Zeile dazu: `tools/git-haken/* text eol=lf`.

NACHGEMESSEN, DAMIT HIER KEINE BEHAUPTUNG STEHT: Auf Windows
blockiert auch ein CRLF-Haken richtig — Rueckgabe 1, null Commits,
richtige Meldung. Das ist also Vorsorge und keine Reparatur. Aber ein
Haken, der still nicht laeuft, ist genau die Sicherung, die aussieht,
als waere sie da.

Zwei neue Pruefungen dazu: der Haken hat reine LF-Enden (byteweise
gemessen), und die Regel steht in .gitattributes.

2. EIN MESSFEHLER VON MIR, UND ER GEHOERT AUFGESCHRIEBEN

Ich habe gemeldet, im Verlauf lägen 73 CR-Bytes. Es war keines.
Gemessen hatte ich mit einer Rohrkette aus `tr` und `od`, und `tr`
nimmt in dieser Shell die Maskierung fuer das Wagenruecklauf-Zeichen
nicht als Zeichen — gezaehlt wurden am Ende Zeilenenden, und die
Datei hat 73.

Mit Python byteweise nachgemessen: 0 im Arbeitsbaum, 0 im Index. Die
Datei war immer LF; git hat nur VORHERGESAGT, was beim naechsten
Auschecken passiert.

Das ist heute der dritte Messfehler aus Shell-Maskierung — nach zwei
`\b`, die als Steuerzeichen in regulaeren Ausdruecken landeten und
dort je eine Pruefung lahmgelegt haben. Und beim Aufschreiben dieser
Lehre ist sie mir ein viertes Mal passiert: Aus dem Kommentar
`tr -d '\r'` wurde `tr -d ''`, die Aussage hat sich selbst bewiesen
und dabei unlesbar gemacht.

DIE REGEL STEHT JETZT, und zwar im Werkzeug selbst: Alles mit einem
Rueckstrich gehoert in eine DATEI, nie in ein Hier-Dokument. Und wer
Bytes zaehlen will, zaehlt Bytes — `readFileSync` ohne Zeichensatz,
und 13 ist 13.

GEPRUEFT: pruef-arbeitsschloss 33 -> 35 Pruefungen, 0 Fehler.
Steuerzeichen im ganzen Haus: 834 Dateien, keines.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 20:07:20 +02:00
DogFatherGitandClaude Opus 5 603319a145 Arbeitsschloss: zwei Sitzungen sehen sich jetzt
HEUTE ZWEIMAL NUR GUTGEGANGEN. Zwei Claude-Sitzungen arbeiteten
gleichzeitig in diesem Verzeichnis, ohne voneinander zu wissen.
Keine hat etwas falsch gemacht — sie konnten es nicht wissen.

  * Beide haben `git add -A` benutzt. Haette die eine
    unfestgeschriebene Arbeit der anderen im Baum gehabt, waere sie
    mitcommittet worden — unter fremdem Namen, in einer fremden
    Begruendung, und niemandem waere es aufgefallen. Nachgesehen:
    diesmal war nichts dabei.
  * Beide haben den Stempellauf gestartet. Der schreibt 45 Dateien
    um. Wer dort eine offen hatte, bekam sie unter den Haenden weg
    geaendert.

Dasselbe hat in RunOne am 03.09.2026 sieben Minuten Ausfall
gekostet. Dort gibt es seitdem `arbeitsschloss.sh`; diese Fassung
uebernimmt seine Lehren.

WAS ES IST UND WAS NICHT. Es ist kein Riegel — wer wirklich muss,
kommt vorbei. Es beantwortet die eine Frage, die heute niemand
beantworten konnte: „arbeitet hier gerade sonst jemand?"

Die teuren Fehler liegen bei einem Schloss alle in derselben
Richtung: Es blockiert zu viel und wird deshalb abgeschafft. Also:

  * Es blockiert NICHT, wenn das Schloss DEINES ist. RunOnes erste
    Fassung fragte „ist abgeschlossen" statt „haelt es jemand
    anders" — damit haette, wer ordentlich abschliesst, nie mehr
    ausliefern koennen. Dafuer gibt es `fremd`.
  * Es VERFAELLT nach zwei Stunden, und dass da jemand war, steht
    beim Uebernehmen dabei.
  * Es blockiert NICHT, wenn es selbst unlesbar ist — dritter
    Ausgang, kein Stillstand.
  * Notausgang: SCHLOSS_ZWANG=ja git commit …

DAS PROBLEM, AN DEM RUNONE HAENGT, IST HIER GELOEST. Dort faellt die
Kennung im Zweifel auf den Systembenutzer zurueck, und zwei
Claudian-Sitzungen laufen BEIDE als `claudian` — die Sicherung griff
ausgerechnet zwischen den zwei Faellen nicht, fuer die sie gebaut
wurde. Deshalb ist dort `export ARBEITER=…` Pflicht, und Pflicht
heisst: man vergisst es.

Hier steht `CLAUDE_CODE_SESSION_ID` in jeder Sitzung und ist je
Sitzung verschieden (nachgesehen, 36 Zeichen UUID). Zwei Sitzungen
auf demselben Windows-Benutzer unterscheiden sich damit von selbst,
ohne dass jemand etwas tun muss. Reihenfolge: ARBEITER, dann
Sitzungskennung, dann Benutzername MIT Warnung.

NIEMAND MUSS DARAN DENKEN:
  * die beiden Stempelwerkzeuge nehmen es selbst und geben es selbst
    frei — auch nach einem Absturz und bei Strg+C (wie `bauen.sh` im
    Shop; eines, an das man denken muss, wird vergessen und ab da
    umgangen)
  * `tools/git-haken/pre-commit` bricht jeden Commit ab, solange
    jemand ANDERS das Schloss haelt. Das ist die Stelle, die heute
    gefehlt hat: `git add -A` ist der Griff, den man ohne Nachdenken
    macht, und gegen einen Reflex hilft keine Regel auf Papier.
  * `core.hooksPath` statt `.git/hooks` — letzteres ist nicht
    versioniert und waere nach einem Klon genau dann leer, wenn es
    gebraucht wird.

GEPRUEFT, server/pruef-arbeitsschloss.mjs: 33 Pruefungen, 0 Fehler —
in einem WEGWERF-Verzeichnis mit eigenem git, damit kein echtes
Schloss angefasst wird. Darunter am echten git:

    ohne Schloss committen        -> geht      (0)
    mit dem EIGENEN Schloss       -> geht      (0)
    mit einem FREMDEN Schloss     -> bricht ab (1), nennt wer und warum
    und es stehen genau ZWEI Commits da, nicht drei
    SCHLOSS_ZWANG=ja              -> kommt vorbei
    ohne das Schloss-Werkzeug     -> laesst durch

Dazu: verfallenes Schloss laesst durch, mit laengerer Frist blockt
dasselbe Schloss wieder (Gegenprobe), unlesbarer Inhalt und
unlesbarer Zeitstempel blockieren nicht.

Portnummern nach der neuen Pruefdatei nachgemessen: Pruefbereich bis
5415, 462 Nummern, 0 Kollisionen. pruef-struktur 75/0,
pruef-fingermass 5/0, pruef-ports 10/0.

In DEPLOY.md steht es jetzt an erster Stelle — eine Sicherung, von
der nur der weiss, der sie gebaut hat, ist die erste, die umgangen
wird.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 20:04:28 +02:00
DogFatherGitandClaude Opus 5 1afb38258c Anfuehrungszeichen: drei Loecher in meiner eigenen Wache
Die zweite Sitzung hat in den Praesentationen des Vaults 83 Stellen
gefunden — und damit auf Loecher in MEINER Wache gezeigt. Ich habe
sie nachgemessen, alle drei waren echt.

LOCH 1 — SIE SAH NUR `server/workspace-*.js`

Also ausgerechnet nicht `workspace.js`, die groesste Datei des
Hauses. Der weitere Filter fand dort sofort drei Stellen:

    workspace.js:3404  Kanal „Chat-Moderation"     (Protokoll)
    workspace.js:3422  „${titel}" -> ${haus}       (Protokoll)
    workspace.js:3304  „${… || "ohne Titel"}"      (siehe Loch 3)

Das ist heute der DRITTE Fall von „die Wache kennt nur die halbe
Menge" — nach pruef-struktur (sah nur die Pruefdateien, nicht die
Anwendung) und pruef-fingermass (sah keine variable Breite).

LOCH 2 — IHR AUSDRUCK GILT JE ZEILE

Ein `„`, das erst in der naechsten Zeile mit einem geraden `"`
schliesst, fiel durch. Gemessen: drei echte Faelle, zwei davon
sichtbarer Seitentext.

    workspace/leistung.html       „nicht / zugeordnet"
    workspace/leistung.html       „Backstage-Tabelle / einfuegen"
    workspace/assets/js/ampel.js  „noch ' + 'verbessern"

Beim letzten laeuft das Zitat ueber eine Zeichenketten-Verkettung.

Neue Regel ohne Fehlalarme: erst alle RICHTIG geschlossenen Paare
entfernen (auch mehrzeilig), dann die einzeilig falschen (die meldet
die alte Regel). Was danach noch ein `„` hat und binnen drei Zeilen
ein gerades `"`, ist ein Fund. Ausgenommen bleibt das Zeichen ALS
WERT — in `content: "„";` und in den Sprachtabellen ist das `„` der
Inhalt und das `"` die Begrenzung.

LOCH 3 — EINE AUSNAHME, DIE EINEN FUND VERSCHLUCKT HAT

Gefunden durch die ZAHL, nicht durch den Blick: Der weitere Filter
liess die Ausnahmen von 12 auf 13 steigen. Die dreizehnte war

    `… „${zeile[titelSpalte] || "ohne Titel"}"`

Der Ausdruck blieb am `"` von `"ohne Titel"` haengen; als Inhalt kam
`${zeile[titelSpalte] || ` heraus, das endet auf ein Leerzeichen,
und damit galt „der Satz geht in der naechsten Zeile weiter". Das
echte Schlusszeichen stand hinter dem `}` und war gerade.

Dass die Ausnahmen gezaehlt UND genannt werden, hat ihn gefunden.
Genau dafuer steht die Zeile dort.

Behoben an der Wurzel: Anfuehrungszeichen innerhalb einer Einsetzung
`${…}` werden vorher durch X ersetzt, bei gleicher Laenge und
gleichen Zeilenumbruechen. Das nimmt einer ganzen Sorte
Fehlklassifizierung die Grundlage — die Ausnahmen fielen danach von
13 auf 11.

UND EIN VIERTES, BEIM MESSEN AUFGEFALLEN

`„Van-Van”` in assets/js/data-modis.js schliesst mit U+201D, dem
ENGLISCHEN Zeichen. Zweimal, beide Male in einer DEUTSCHEN Zeile
(`de:` und `"de-CH":`) — nicht einmal eine Uebersetzung, in der es
richtig waere. Eigene Regel dafuer, die keine Ausnahme braucht: Wer
mit `„` oeffnet, schliesst deutsch; in fremdsprachigen Zeilen steht
gar kein `„` am Anfang.

DIE AUSNAHMEZAHL IST JETZT STRENG. Sie stand auf „hoechstens 12" —
damit waere der Anstieg auf 13 nicht aufgefallen. Jetzt genau 11,
wie bei den Grundlinien in pruef-fingermass.

GEPRUEFT: pruef-struktur 68 -> 75 Pruefungen, 0 Fehler. Dazu
leistung-optik 59/0, ampel 47/0, treff 85/0, modi-verborgen 87/0 —
die Seiten, deren Text ich angefasst habe. Steuerzeichen: 830
Dateien, keines. Beide Stempel gesetzt.

Sechs echte Stellen berichtigt, vier neue Gegenproben.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 19:28:38 +02:00
DogFatherGitandClaude Opus 5 2b3f140112 Wissen: ein gerades Schlusszeichen, von der Wache gefunden
workspace/assets/js/wissen.js:556

    ... legst du unter „Dateien" ab.      (gerades ")
    ... legst du unter „Dateien“ ab.

Die Zeile ist nicht von mir: Sie kam heute um 14:33 aus einer
zweiten Sitzung im selben Verzeichnis (Commit 63a56980). Die Wache,
die ich heute Vormittag gebaut habe (95c4599b), hat sie beim ersten
Lauf danach gemeldet — mit Datei und Zeile.

GENAU DAFUER WAR SIE DA. 199 Stellen aufzuraeumen ist nichts wert,
wenn am Abend desselben Tages die naechste dazukommt. Zwischen
Aufraeumen und erstem Rueckfall lagen fuenf Stunden.

NACH DEM FREMDEN ZUSAMMENLAUF DAS HAUS DURCHGESEHEN:
  pruef-struktur         68 / 0   (nach dieser Berichtigung)
  pruef-wissen-formular  30 / 0   (neu, aus der anderen Sitzung)
  pruef-dateien-liste    15 / 0   (neu, aus der anderen Sitzung)
  pruef-wissen-neu       16 / 0
  pruef-ports            10 / 0   460 Ports durchprobiert
  pruef-portnummern      41 / 0
  pruef-fingermass        5 / 0

UND EINE WACHE, DIE ICH BEWUSST NICHT GEBAUT HABE: Nach den zwei
Zeitbomben von heute (pruef-dabei-optik, pruef-chat-anhaenge — beide
gruen allein, rot unter Last) habe ich die ganze Klasse
nachgemessen. 850 feste Wartezeiten in 139 Dateien — dagegen eine
Wache zu bauen waere eine Warnung, die immer kommt.

Das engere Merkmal der beiden echten Faelle: Sie lasen einen Wert,
den eine Ueberblendung DURCHLAEUFT (`opacity`), nach einer festen
Wartezeit. Gemessen: 8 solche Stellen im ganzen Haus, 4 ohne
Absicherung — drei davon sind die heute reparierten, und die vierte
(pruef-glocke:380) ist keine: Am `.glocke__strich` haengt gar keine
Blende, nur an Rahmen, Hintergrund und Farbe.

Also null echte Funde und vier Fehlalarme. Eine solche Wache ist
schlechter als keine. Die Lehre steht stattdessen ausfuehrlich an
den zwei Stellen, an denen sie etwas gekostet hat.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 19:17:49 +02:00
DogFatherGitandClaude Opus 5 159036efc9 helfer-port: die gemessene Zahl ist ein Stand, keine Wahrheit
Im Kommentar stand „die Pruefungen reichen bis 5409, Luft fuer 245
weitere Dateien". Noch am selben Tag kamen zwei Pruefdateien aus
einer anderen Sitzung dazu, und daraus wurde 5413/243.

Das ist kein Fehler, sondern der Beweis, dass die Umstellung von
gestern richtig war: Zwei fremde Dateien haben alle Nummern
dahinter verschoben, und es musste niemand etwas nachtragen.
Nachgemessen danach: 460 Nummern, alle verschieden, 0 Kollisionen,
pruef-ports 10/0 und pruef-portnummern 41/0.

Aber eine Zahl im Kommentar, die sich am Tag ihrer Messung schon
bewegt hat, ist genau die Sorte, der jemand spaeter glaubt. Sie
steht jetzt als STAND da, mit dem Hinweis, wo die heutige zu holen
ist: pruef-portnummern sagt sie bei jedem Lauf.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 15:50:41 +02:00
DogFatherGitandClaude Opus 5 b2b016f8dd Reaktion auf 320 px: das Bild ist ganz zu sehen
NACHGEMESSEN, wie es nach dem Einklappen der Reiterleiste wirklich
aussieht — und zwar im ANFANGSZUSTAND, mit zugeklappter Leiste:

                Regie   Raum   Kino   Schiene   Pult   Transport
    412x915       45     620    232     388      128     181
    390x844       45     549    219     330      128     181
    360x640       45     345    203     143      128     181
    320x568       45      75     75       1      198     181

Die Regieleiste ist von 101 bzw. 148 auf 45 Pixel geschrumpft — auf
320 px sind das 197 gewonnene Pixel.

EIN MESSFEHLER VON MIR, hier festgehalten: Mein erster Lauf zeigte
die Leiste GROESSER als vorher (148, 195, 242). Das Werkzeug klappt
sie weiter oben selbst auf, um die Register zu messen, und ich habe
danach die Hoehen gelesen. Gemessen war also der falsche Zustand —
eine Messung, die veraendert, was sie misst.

WAS AUF 320 BLEIBT: Der Raum hat 75 Pixel, das Bild wollte 180. Das
Pult liegt mit `z-index: 60` darueber, die Knoepfe sind also
erreichbar — und genau deshalb melden pruef-breiten und pruef-handy
nichts. Zu sehen war vom Bild trotzdem nur das obere Drittel.

`max-height: 100%` an der Leinwand. Gemessen wird der Kasten damit
320x75; die Breite bleibt, das Verhaeltnis gilt nicht mehr — aber
der Spieler darin setzt das Bild mittig mit Balken links und
rechts. Es ist klein und GANZ, statt gross und zu zwei Dritteln
hinter dem Pult.

(Im Kommentar stand zuerst, die Breite folge dem Verhaeltnis. Tut
sie nicht — 320x75, nicht 133x75. Berichtigt, bevor jemand sich
darauf verlaesst.)

AUF 360, 390 UND 412 AENDERT SICH NICHTS: Dort ist der Kasten
hoeher, als 16:9 verlangt, und `max-height` greift nicht ein.
Nachgemessen: 203, 219, 232 — wie vorher.

GEPRUEFT: pruef-handy 186/0, pruef-breiten 23/0, pruef-reaktion
421/0, mess-quer „NICHTS rollt seitlich".

EHRLICH BLEIBT: 320x568 zeigt weiterhin keinen Chat (Schiene 1 px),
und das Bild ist dort 320x75. Mit 198 Pixeln Pult und 181 Pixeln
Transport von 499 geht nicht mehr. Das waere ein eigener Schritt
und eine eigene Entscheidung — kein Nebenbei.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 15:47:14 +02:00
DogFatherGitandClaude Opus 5 63a56980c0 Wissen: Eine Absage ohne Alternative ist eine halbe Antwort
Wer eine Nicht-PDF in die Ablage zieht, bekam "Das ist keine
PDF-Datei." -- richtig, aber eine Sackgasse. Filipe hat heute eine
HTML-Praesentation dort abzulegen versucht, keinen Weg genannt
bekommen und den Fehler bei sich gesucht.

Jetzt steht dabei, wohin sie gehoert: unter "Dateien". Das ist die
einzige Stelle, an der wir es ueberhaupt sagen koennen -- beim
Auswaehlen ueber den Knopf greift schon `accept`, und die Datei ist
im Fenster des Betriebssystems gar nicht erst anklickbar.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 14:33:06 +02:00
DogFatherGitandClaude Opus 5 5a9f1f467c Wissen und Dateien: Zwei Raster, die ihren Inhalt verloren haben
Filipe zum Bildschirmfoto der Wissen-Seite: "erstens sieht das richtig
scheisse aus". Zu sehen war die Kategorie-Auswahl quer ueber "STUFE",
"GERAET", "VEROEFFENTLICHT AM" und den Tag-Knoepfen. Text auf Text.

Zweimal dieselbe Ursache, zweimal ein Raster, das Kinder in eine Zelle
zwingt, die zu klein ist:

1. FORMULAR "NEUE ANLEITUNG" (aufgaben.css). Die Regel
   `grid-template-rows: 1fr 44px` gibt jeder Zelle eine feste
   Eingabezeile -- richtig und wichtig, damit alle Felder auf einer
   Linie sitzen. Die Zelle "Hauptkategorie" enthaelt aber keine
   Eingabe, sondern sechs Gruppen mit zwanzig Knoepfen. Gemessen: der
   Kasten 40 px hoch, sein Inhalt 442 -- 402 px liefen ueber alles
   darunter. Unter 560 px passierte das nicht, weil dort ohnehin
   `auto auto` gilt; deshalb sah es am Handy richtig aus.
   Es ist exakt die Falle, die eine Regel darueber schon einmal
   zugeschnappt ist ("EINE ZELLE, DIE AUFKLAPPT ..."). Dieselbe
   Antwort, diesmal fuer .katwahl.

2. DATEILISTE (dateien.css). .datei hat die Spalten `34px 1fr auto`.
   Die ersten vier Kinder sitzen richtig; alles danach wird automatisch
   platziert und landet in der ZEICHENSPALTE. Gemessen: "Fassung 2" in
   34 px Breite, 22 px herausragend; auf 390 px zusaetzlich die
   Metazeile ("1,9 MB" in zwei Zeilen) und "Sichtbar fuer" mit 49 px
   Ueberstand.

ZWEI NEUE PRUEFUNGEN, und die erste war erst selbst falsch:
pruef-wissen-formular.mjs verglich zunaechst den KASTEN der Auswahl mit
dem der Zelle und meldete gruen, waehrend das Bildschirmfoto die
Ueberlappung deutlich zeigte. Der Kasten ist ja brav 44 px hoch --
herausgelaufen ist sein INHALT. Jetzt wird scrollHeight gegen
clientHeight gemessen, und die Pruefung wird rot, bevor der Fix
dazukommt. pruef-dateien-liste.mjs legt bewusst zweimal dieselbe Datei
ab, damit "Fassung 2" und "nicht mehr aktuell" ueberhaupt entstehen.

Versionsstempel neu gesetzt (202610011426, 670 Verweise in 45 Dateien).
Ohne ihn liegt die Korrektur auf dem Server und kommt bei niemandem an:
Cache-Control steht auf immutable.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 14:27:44 +02:00
DogFatherGitandClaude Opus 5 3a07c52499 Die drei dauerhaft roten Pruefungen sind gruen
Alle drei waren vorbestehend (Gegenprobe gegen den alten Stand
derselben Datei), und keine der drei war ein Fehler am Haus.

1. pruef-browser — WINDOWS BLOCKIERT WEBKIT

   Schritt fuer Schritt nachgegangen:
     - gemeldet: „WebKit: browserType.launch: Target page, context
       or browser has been closed"
     - nicht an paralleler Last; allein dasselbe Bild
     - `npx playwright install --force webkit` nennt den Grund:
       „Full list of missing libraries: icuuc77.dll"
     - die Datei IST da, 1,8 MB, im Ordner webkit-2336
     - Playwrights eigenes Werkzeug sagt, warum:
           PrintDeps.exe icuuc77.dll
           -> Eine Anwendungssteuerungsrichtlinie hat diese Datei
              blockiert.

   Smart App Control laesst die unsignierte Bibliothek nicht laden.
   Das ist eine Einstellung des Rechners, kein Fehler im Haus — und
   sie zu aendern waere Filipes Entscheidung, keine meine. (Smart
   App Control laesst sich nur ABschalten; wieder einschalten geht
   ohne Windows-Neuinstallation nicht. Fuer einen Testbrowser ist
   das der falsche Preis.)

   Der Kommentar im Code sagte es schon richtig — „eine Maschine,
   die nicht startet, ist nicht ,in Ordnung', sie ist nicht
   nachgesehen" —, umgesetzt war es als FEHLER. Jetzt drei
   Ausgaenge wie in pruef-ports: „BESTANDEN — 0 Fehler, 2 nicht
   nachsehbar". Damit daraus kein stiller Freispruch wird, haengen
   zwei Dinge daran: mindestens ZWEI Maschinen muessen wirklich
   gemessen haben, und die Zahl der Seitenaufrufe wird aus den
   gelaufenen Maschinen abgeleitet statt gegen eine feste 3
   geprueft.

2. pruef-crew-wand-bild — MEINE EIGENE FOLGEWIRKUNG VOM 30.09.

       anlegen("Marina", "modi", "CODE-MODI-0001");
       { name: "Modi", rolle: "creator", code: "CODE-MODI-0001" }

   Marina ist ein `modi`, angemeldet wurde sie mit der Kachel
   `creator`. Bis zum 30.09. war das egal; seit `718b267d` („die
   gewaehlte Kachel ist bindend", auf Filipes ausdruecklichen
   Wunsch) wird es zu Recht abgelehnt. Drei Befunde aus einer
   Wurzel, und mir ist es damals entgangen, weil ich nach der
   Aenderung die Pruefungen zum Zugang gelaufen bin und nicht die
   zum Wandbild.

   Die Ursache war aber nicht die falsche Zeile, sondern dass es
   ZWEI gab. `anlegen` gibt jetzt zurueck, was es angelegt hat, und
   die Anmeldung nimmt genau das. Nebenbei beweist die Pruefung
   damit zum ersten Mal, was sie beweisen sollte: Der Modi bekommt
   „Aufgaben · Team Dogi" und seine eigenen Zeichen.

3. pruef-chat-anhaenge — EINE BLENDE, DIE UNTER LAST STILLSTEHT

   Gemeldet: „0 Figuren" und „[]" statt der zwei Schriftzuege —
   aber nur mit vier parallelen Pruefungen. Allein zweimal gruen.

   Gemessen, was wirklich dasteht: lage „hoch", Figuren da, Bilder
   geladen (447x450), Deckung exakt „0". Nicht 0,3 oder 0,7 — die
   Ueberblendung hatte nicht ANGEFANGEN. Unter Last wird
   `requestAnimationFrame` gedrosselt, und eine Blende, die auf
   Bildern laeuft, steht still.

   Mein erster Versuch — „warten, bis sich nichts mehr aendert" —
   war genauso falsch wie die feste Wartezeit davor: Stillstand
   heisst auch „noch nicht angefangen", und er kam sofort zurueck.
   Auf eine Bewegung zu warten, die nicht laeuft, geht nicht.

   Also wird sie abgeschaltet. Das Haus hat die Regel schon:
   `@media (prefers-reduced-motion: reduce)` nimmt genau diesen
   beiden Dingen die Blende. Der Endwert steht damit sofort da, die
   Messung haengt nicht mehr am Rechner, und der Weg wird nebenbei
   zum ersten Mal wirklich begangen.

   Nicht tautologisch: Die Gegenprobe „und OHNE die zwei Figuren —
   die gehoeren ins Hochformat (0)" steht weiter und bleibt gruen.

GEPRUEFT, und zwar unter DERSELBEN vierfachen Last, die sie vorher
rot gemacht hat:

  pruef-chat-anhaenge  123 / 0     pruef-material      159 / 0
  pruef-crew-wand-bild  45 / 0     pruef-kalender      141 / 0
  pruef-browser       11+2 offen   pruef-start-ansicht 160 / 0
  pruef-dabei-optik     23 / 0     pruef-neue-seiten   109 / 0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 13:54:45 +02:00
DogFatherGitandClaude Opus 5 2f3b8630c7 Messungen am Telefon: 37 bekommen ihren Finger
Gestern Mittag gemessen: 39 `newContext`-Aufrufe nehmen ihre Breite
aus einer Variablen und setzen kein `hasTouch`. Ohne das meldet der
Browser `pointer: fine`, und KEINE Regel aus `@media (pointer:
coarse)` greift — dort stehen im ganzen Haus die 44-Pixel-
Beruehrziele, die ausgeblendeten Tastenkuerzel und die
eingeklappte Reiterleiste.

Was das anrichtet, war an pruef-breiten zu sehen: drei Befunde auf
320, 390 und 430 Pixeln, die mit dem Finger allesamt verschwanden —
Messfehler, keine Fehler.

37 DAVON HABEN IHN JETZT. Nur `hasTouch`, nicht `isMobile`: Gefragt
ist genau die eine Sache, um die es geht. `isMobile` waere eine
zweite Aenderung in derselben Zeile, und wenn danach etwas anders
aussieht, wuesste niemand, welche von beiden es war.

ZWEI BLEIBEN STEHEN, beide in pruef-grosscheck.mjs. Die Aenderung
dort waere ein Zweizeiler; sie zu pruefen hiesse, 206 Seiten ueber
vier Rollen laufen zu lassen, und das braucht Filipes Zusage. Eine
Aenderung, die ich nicht pruefen darf, liefere ich nicht aus.
Grundlinie in pruef-fingermass steht deshalb auf 2.

JEDE EINZELN NACHGELAUFEN — 37 Laeufe:

  34 gruen, darunter pruef-handy 186, pruef-material 159,
  pruef-start-ansicht 160, pruef-kalender 141, pruef-erwaehnung 129,
  pruef-bewerbung-aufgaben 163, pruef-neue-seiten 109

  3 mit Befunden, ALLE DREI VORBESTEHEND (Gegenprobe: alter Stand
  derselben Datei, gleicher Lauf, gleiche Zahl):
    pruef-browser        3  (WebKit startet auf diesem Rechner nicht)
    pruef-chat-anhaenge  2
    pruef-crew-wand-bild 3

EINE ZEITBOMBE GEFUNDEN UND ENTSCHAERFT

pruef-dabei-optik meldete „Haekchen: 0 -> 0" — aber nur, wenn vier
andere Pruefungen gleichzeitig liefen. Allein: „0 -> 1", gruen.

Dort stand `waitForTimeout(250)` mit der Begruendung „250 ms sind
reichlich ueber den 160" (der Dauer der Blende). Auf einem Rechner,
auf dem nebenher vier Browser messen, sind sie es nicht. Die
Pruefung war damit gruen, solange nichts anderes lief, und rot im
Gesamtlauf — also genau dann, wenn niemand sie einzeln nachstellen
kann.

Eine Wartezeit ist eine Annahme ueber den Rechner. Gewartet wird
jetzt auf das, worauf es ankommt: dass das Haekchen da ist. Laeuft
die Frist ab, faellt die Pruefung mit dem ECHTEN Wert um und nicht
mit einem Messfehler. Gegenprobe: unter derselben vierfachen Last,
die sie vorher rot gemacht hat, jetzt gruen.

UND DIE GRUNDLINIE WIEDER STRENG. Ich hatte sie kurz auf
„hoechstens" gestellt — damit haette ein Rueckgang stillschweigend
Platz fuer die naechste Suende gedeckt. Genau davor warnt der Kopf
derselben Datei bei der anderen Grundlinie, und ich habe es eine
Stunde spaeter selbst falsch gemacht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 13:37:05 +02:00
DogFatherGitandClaude Opus 5 dc5e6a0c24 Reaktion: das Chatfeld bekommt einen Namen
pruef-handy-teamdogi meldete auf beiden Geraeten und fuer Modi und
Community dasselbe:

    reaktion.html: Bedienelement ohne Namen — input#chat-feld

Sein einziger Name war der PLATZHALTER. Der ist keiner: Er
verschwindet in dem Moment, in dem jemand anfaengt zu tippen, und
danach hat das Feld fuer ein Vorleseprogramm gar keinen Namen mehr.
Der Knopf daneben macht es seit jeher richtig
(`aria-label="Senden"`).

UND DER NAME WANDERT MIT. Das Feld sagt im Platzhalter, warum
gerade nicht geschrieben werden kann — „Der Chat ist gerade zu",
„Du bist gerade stumm geschaltet", „Gerade schreibt nur das Team".
Ein fester `aria-label` haette genau diese Auskunft fuer das Ohr
verschluckt. Er kommt deshalb aus derselben Zeile wie der
Platzhalter: eine Angabe, zwei Ausgaben. Zwei getrennte Texte
waeren die naechste Stelle, an der einer gepflegt wird und der
andere nicht.

GEPRUEFT

  pruef-handy-teamdogi  8 Befunde -> 14 Pruefungen, 0 Fehler
  pruef-reaktion        421 Pruefungen, 0 Fehler
  pruef-handy           186 Pruefungen, 0 Fehler

Damit ist die Liste der alten offenen Punkte abgearbeitet:
  - pruef-fingermass (Grundwert 1)       unveraendert 1, dazu eine
                                         zweite Zahl fuer die
                                         Faelle, die sie bisher gar
                                         nicht sehen konnte
  - Regie/Transport auf 320x568          die Ueberlappung ist weg
  - report.html 27x18 px                 gibt es nicht mehr; beide
                                         Messungen melden die Seite
                                         sauber (Notiz war veraltet)
  - Ueberstand pruef-handy-teamdogi      0 Befunde

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 12:24:46 +02:00
DogFatherGitandClaude Opus 5 48470961c7 Reaktion am Handy: nichts liegt mehr auf einem Knopf
AUSGANGSLAGE, gemessen: pruef-breiten meldete auf sechs von neun
Breiten einen verdeckten Knopf, pruef-handy auf allen drei
Telefonen. Immer dieselbe Stelle: „Offen", „Team" und „Zu" aus dem
Chatkopf lagen auf dem Pult. Wer sie antippte, traf „Starten" oder
„Beenden".

ENDSTAND: pruef-breiten 23 Pruefungen / 0 Befunde, pruef-handy 186 / 0,
mess-quer „NICHTS rollt seitlich", pruef-reaktion 421 / 0.

Davon waren DREI VON VIER Befunden Messfehler. Gefunden, weil ich
ihnen nachgegangen bin statt ihnen zu glauben.

1. pruef-breiten MASS OHNE FINGER

   newContext({ viewport: { width: breite, height: hoehe } })

   Ohne `hasTouch` meldet der Browser `pointer: fine`, und KEINE
   Regel aus `@media (pointer: coarse)` greift — dort stehen die
   44-Pixel-Beruehrziele, die ausgeblendeten Tastenkuerzel und seit
   heute die eingeklappte Reiterleiste. Auf 320, 390 und 430 Pixeln
   wurde also eine Seite vermessen, die es auf keinem Telefon gibt.
   Aufgefallen, weil mess-quer dieselbe Seite auf 390 MIT Finger
   misst und dort nichts findet. -> 390 und 430 sofort gruen.

2. DER VERDECKUNGS-FINDER KANNTE KEINE ROLLKAESTEN

   Gemeldet war auf 1024, 1920 und 2560 immer ein Feld AUS DEM PULT
   „unter" der Transportleiste — und auf 1280 und 1440 nichts. Das
   Pult rollt in sich; was unten herausgerollt ist, liegt
   rechnerisch dort, wo die Leiste steht, und `elementFromPoint`
   liefert die Leiste. Verdeckt ist da nichts — es ist weggerollt.
   Das Fenster kannte der Finder schon (`r.bottom < 0`), den
   Rollkasten nicht. -> drei Breiten gruen, die Gegenproben
   („ein echtes Hindernis wird gefunden") schlagen weiter an.

3. UND EIN ECHTER BEFUND, ZWEIMAL

   a) Reiterleiste: acht Register brauchen am Handy zwei Zeilen
      (100 px auf 360, 148 auf 320). Sie klappen jetzt hinter ihren
      eigenen Wert — dasselbe Muster wie die Tempo-Gruppe, und der
      Knopf zeigt, wo man steht. NICHT einzeilig zum Wischen:
      Filipes Ansage vom 28.09. galt dem Wischen nach links und
      rechts, und mess-quer misst genau das.

   b) Bei OFFENER Regie nimmt das Pult auf 412x915 vierhundert-
      vierundachtzig der 846 Pixel. Nebeneinander stehen Regie und
      Bild erst ab 1100 px. Am Fingergeraet tritt die Chatschiene
      deshalb beiseite, solange die Regie offen ist — wer etwas
      einstellt, muss das Bild im Auge behalten, den Chat nicht, und
      der ist einen Fingertipp entfernt.

4. MEINE EIGENE WACHE WAR BLIND — ZWEIMAL

   pruef-fingermass sucht `width: <Zahl>`. In pruef-breiten stand
   `width: breite`, eine Variable: kein Treffer, also „in Ordnung".
   Sie meldete dabei brav „1 blindes Fenster, unveraendert zur
   Grundlinie" — und war selbst blind. Jetzt gibt es einen dritten
   Ausgang: Breite vorhanden, aber keine Zahl, und kein hasTouch
   daneben -> „konnte nicht nachsehen", mit eigener Grundlinie.

   Beim ersten Anlauf meldete der 45 Faelle, darunter jedes
   `newContext({ permissions: [...] })`. Zu grob: Ein Fenster ganz
   OHNE Breite ist das Standardfenster, kein Telefon. Enger gefasst.

   UND DANN WAR DIE ZAHL 0 — WEIL DER AUSDRUCK TOT WAR. Das `\b` in
   `/\bwidth\s*:/` war ein echtes Rueckschritt-Zeichen (0x08),
   unsichtbar im Quelltext. Heute Nacht hat mich dasselbe schon
   einmal eine halbe Stunde gekostet. Mit heilem Ausdruck sind es
   39 echte Faelle — etwa mess-chat-liste bei 390 px ohne Finger.
   Als Grundlinie festgehalten: Sie darf nur sinken, jede neue
   faellt auf, und abgearbeitet wird Datei fuer Datei mit je einem
   Lauf danach.

   Ein Werkzeug sucht jetzt alle Steuerzeichen im ganzen Haus
   (tools, gitignoriert). Es fand zwei: meins von heute und ein
   aelteres in pruef-reaktion.mjs — `!/^none\b/.test(wert)` hat
   dort nie gegriffen. Beide bytewise ersetzt, 830 Dateien sauber.

5. mess-quer MUSS TUN, WAS EIN MENSCH TUT

   Es wartete auf eine SICHTBARE Reiterleiste und lief in die
   Zeitsperre, seit sie zugeklappt startet. Jetzt wartet es auf die
   Leiste und klappt auf — vor jedem Register, denn ein Klick
   schliesst sie wieder.

WAS NICHT GEMACHT WURDE, UND WARUM: Die Messwerte im Pult („Sehen
zu", „Mit Bild", „Gaeste", „Upload") standen in meiner eigenen
Auswahl als Sparposten. Beim Nachsehen steht beim Upload die
Begruendung im Quelltext: „der Unterschied zwischen ,es ruckelt bei
euch?' und ,ich sehe, dass es zu viel wird'". 26 Pixel gegen echte
Information waehrend der Sendung — falscher Tausch.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 12:10:29 +02:00
DogFatherGitandClaude Opus 5 d7f3e747b8 Reaktion: 26 Pixel zurueck fuer den Chat am Handy
Die rechte Gruppe der Transportreihe war auf 360x640 gemessen
122 Pixel hoch statt 44: In der dreispaltigen Reihe bekommt sie nur
89 Pixel Breite und bricht dreimal um. Das Wort „Weiter" davor ist
dabei eine Beschriftung fuer zwei Knoepfe, die ihre Aufgabe selbst
draufstehen haben — „Naechstes" und „Wechseln zu <Titel>".

Dieselbe Ueberlegung wie beim Wort „Tempo", das aus genau diesem
Grund schon weg ist. Am Rechner bleibt es: Dort ist Platz, und dort
ordnet es die Leiste.

GEMESSEN (mess-quer, mit Finger, Regie zugeklappt):

    Transportleiste   207 -> 181 px   auf 320, 360, 390 und 412
    Chatschiene       +26 px          auf jedem Handy
    Rechner/Tablet    unveraendert    (158 / 185)

WAS DAS NICHT LOEST, UND DAS SAGE ICH LIEBER GLEICH: Die verdeckten
Chatstufen auf 320 und 360 sind weiterhin da. pruef-breiten und
pruef-handy melden unveraendert 6 bzw. 3 Befunde. Der Grund steht
jetzt mit Zahlen im Quelltext — es ist eine Platzfrage, keine
Regelfrage, und sie braucht eine Entscheidung.

EIN VERSUCH, DER ZURUECKGENOMMEN WURDE: `minmax(0, auto)` statt
`auto` an der Kinozeile des Raums. Gemessen null Pixel Unterschied
(Kino vorher wie nachher 203 px). Der Raum ragt naemlich nicht aus
eigener Kraft ueber seine Zeile — die Zeile hat auf 360 px noch
161 Pixel, und ein 16:9-Video auf 360 px Breite will 203. Keine
Angabe an DIESEN Zeilen aendert daran etwas. Die Begruendung steht
jetzt dort, damit es niemand ein zweites Mal probiert.

Eine Regel, die nur aussieht, als taete sie etwas, ist schlimmer
als keine.

GEPRUEFT: pruef-handy 186 Pruefungen (3 Befunde, unveraendert),
pruef-breiten 23 (6 Befunde, unveraendert) — also keine neue
Beanstandung und keine verschwundene Pruefung. Stempel gesetzt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 10:46:22 +02:00
DogFatherGitandClaude Opus 5 95c4599baa Anfuehrungszeichen: 199 falsche Schlusszeichen im sichtbaren Text
Deutsch oeffnet mit „ und schliesst mit “. An 199 Stellen, die ein
Mensch liest, stand als Schlusszeichen ein GERADES " -- „Nächstes"
statt „Nächstes“. Auf sechzehn oeffentlichen Seiten, in vierzig
Dateien des Workspace und in zwoelf Servermodulen, die Texte
verschicken.

Auf dem Bildschirm sieht man den Unterschied sofort. Beim Schreiben
nicht: Das gerade " liegt auf der Tastatur, die anderen nicht.

WARUM EIN ERSTER ANLAUF ZURUECKGENOMMEN WURDE

Ein gerades " ist an vielen Stellen SYNTAX und kein Schriftzeichen --
Grenze einer Zeichenkette, Grenze eines HTML-Attributs, Zeichen in
einem regulaeren Ausdruck. Wer stumpf ersetzt, macht aus

    „<a href="https://…                  ein kaputtes Attribut
    /^["'„»\s]+|["'“«.\s]+$/              einen kaputten Ausdruck
    "… nichts „mal " + "eben …"          eine kaputte Zeichenkette

DIE UNTERSCHEIDUNG LAEUFT AN MERKMALEN, NICHT AN EINER LISTE

  < > = dazwischen        -> HTML-Marke oder Attribut
  endet auf Leerzeichen   -> die Zeichenkette hoert hier auf, der
                             Satz geht in der naechsten Zeile weiter.
                             Ein deutsches Schlusszeichen steht NIE
                             hinter einem Leerzeichen.
  Rueckstrich mittendrin  -> regulaerer Ausdruck
  ${ ohne }               -> mitten in einem Ausdruck

Eine Liste erlaubter Ausnahmen waere die naechste, die niemand
pflegt. Zwoelf Stellen bleiben dadurch stehen, alle zwoelf einzeln
angesehen und alle zwoelf zu Recht -- dort steht das richtige
Schlusszeichen ohnehin weiter unten im Satz.

Fuenf davon waren allerdings ECHTE Fehler HINTER dem Link
(`…>HasiDog</a>".`) -- die erste Regel hatte nur das Attribut
gesehen, nicht den Satz danach. Gezielt nachgezogen.

Ein maskiertes `\"` in workspace-vorlagen.js (28 Hooks) wird zu “ --
ohne Rueckstrich, denn “ begrenzt nichts.

KOMMENTARE BLEIBEN, WIE SIE SIND. Dort liest es niemand ausser mir;
eine Wache, die auch Kosmetik anmahnt, wird weggeklickt. Beim ersten
Messen fielen ausserdem acht Stellen aus buehne.html faelschlich an,
weil `/* */` in HTML (in <style> und <script>) nicht ausgeblendet
war -- jetzt schon.

DIE WACHE DAZU

pruef-struktur prueft es ab sofort mit derselben Regel: 322 Dateien
mit sichtbarem Text, 0 Funde, und die zwoelf bewussten Ausnahmen
werden GEZAEHLT und genannt (erlaubt: 12). Eine Ausnahme, die niemand
sieht, waechst -- und irgendwann steht der echte Fall darin.

GEPRUEFT

  pruef-struktur   59 -> 68 Pruefungen, 0 Fehler
  node --check auf allen geaenderten JS-Dateien
  nachgemessen: 199 geaendert, 12 mit Grund stehen geblieben

  gruen geblieben: bewerbung-aufgaben 163, nachwuchs 262,
  reaktion 421, support 63, content 45, terminregel 35, treff 85

  Und nachgesehen, ob eine Pruefung noch die alte Schreibweise
  ERWARTET: 13 Fundstellen, alle dreizehn nur Text in ihrer eigenen
  Ausgabe, keine einzige ein Vergleich mit dem Seitentext.

GEGENPROBE: In reaktion.html ein Schlusszeichen zurueckgedreht ->
„workspace/reaktion.html:546 „Nächstes"", mit Datei und Zeile. Und
die Erkennung einzeln gegen HTML-Attribut, fortgesetzte
Zeichenkette, regulaeren Ausdruck und eingesetzten Wert geprueft.

Stempel gesetzt: workspace 670 Verweise in 45 Dateien, oeffentlich
554 in 48 Seiten.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 01:56:15 +02:00
DogFatherGitandClaude Opus 5 7dc5356c80 Datum: der Tag kommt aus der Ortszeit, nicht aus UTC
GEFUNDEN UM 01:22, von pruef-kreislauf -- und nur, weil nachts
gearbeitet wurde.

Die Pruefung legt einen Wunsch mit dem HEUTIGEN Datum an und macht
daraus einen Termin. Gemessen:

    geschickt:   datum = 2026-10-01   (heuteLokal auf dem Server)
    gespeichert: datum = 2026-09-30

Der Termin lag also in der Vergangenheit. Auf „Was ansteht" sortiert
er sich damit in den Abschnitt „Vorbei" ein -- und der ist mit
Absicht zugeklappt. Beim Wunsch stand „Daraus wurde ein Termin", auf
dem Brett war er nicht zu sehen. Zwei Stunden jede Nacht (im Winter
eine), genau in den Stunden, in denen hier gearbeitet wird.

URSACHE

    const jetzt = () => new Date().toISOString();   // UTC
    ... jetzt().slice(0, 10) ...                     // UTC-Tag

ES WAR NICHT EINE STELLE. Nachgemessen: SECHZEHN in vierzehn Modulen,
davon ZEHN, die den falschen Tag in die Datenbank schreiben --
Termine, Wuensche, Highlights, Talente, Leads, Videos, Vorlagen --
und sechs, die „heute" vergleichen (ueberfaellige Aufgaben, Berichte,
die Frist einer Entwicklungsaufgabe).

NICHT ANGEFASST, WEIL RICHTIG: Rechnungen auf einem Datumstext mit
fester Uhrzeit (`Date.parse(tag + "T12:00:00Z") + n * 86400000`). Die
bleiben in jeder Zeitzone am selben Kalendertag -- kalender, teamlage
und serien machen es so, und das bleibt.

WARUM ES NIEMAND GEMERKT HAT

pruef-struktur sucht dieses Muster seit dem 06.09.2026. Aber:
  - sie sah NUR in die `pruef-*.mjs`, nie in die Anwendung
  - sie kannte die Schreibweise ueber eine FUNKTION nicht
    (`const jetzt = () => ...` statt `const jetzt = ...`)

Die Wache stand vor den Pruefungen, nicht vor dem Haus -- derselbe
Fehler wie heute Nacht bei den Messports: eine Sicherung, die nur die
halbe Menge kennt, faellt in der anderen Haelfte aus, und zwar
lautlos, denn sie meldet ja „nichts gefunden".

Jetzt sieht sie in beides und kennt beide Schreibweisen. Beim ersten
scharfen Lauf fand sie sofort 23 weitere Stellen in den Pruefdateien
selbst -- dieselben Zeitbomben, gegen die sie gebaut worden war.

EINE ZWEITE WACHE, WEIL ICH SELBST HINEINGELAUFEN BIN

Mein Umbauwerkzeug hat in elf Modulen `heuteLokal()` eingesetzt und
die Einfuhr weggelassen: Es hat erst ersetzt und DANN gefragt, ob der
Name schon in der Datei steht -- da stand er, mein eigener Aufruf.
`node --check` sagt dazu nichts, „Laedt jedes Server-Modul?" auch
nicht: Die Datei ist syntaktisch tadellos. Erst der Aufruf faellt um
mit `ReferenceError: heuteLokal is not defined`. Gefunden hat es
pruef-video, zufaellig. Die anderen zehn waeren durchgerutscht.

Deshalb neu: „Ruft ein Modul etwas, das es nie eingefuehrt hat?" --
die Namen des Hauses aus den export-Zeilen gelesen, nicht
aufgezaehlt. 460 Aufrufe in 350 Dateien, alle mit Einfuhr.

pruef-kreislauf STELLT JETZT DIE RICHTIGE FRAGE

Sie war rot und hat den Fehler dabei nur gestreift: „`.kette` wird
nicht sichtbar", Zeitsperre nach 15 s. Das klingt nach der Anzeige
und schickt einen zur falschen Stelle. Neu:
  - eine Zeile fragt das DATUM (ohne Browser, nennt den Fehler beim
    Namen)
  - der Browserteil klappt zu, was zu ist, und misst dann die Kette;
    „gar nicht da" wird von „da und unsichtbar" unterschieden

NEBENBEFUND IN pruef-ics

Die Probe „fast richtig" war `echt.slice(0, -1) + "A"`. Der
Schluessel ist base64url; sein letztes Zeichen ist eines von
sechzehn. Endet er auf „A", IST die Probe der echte Schluessel, der
Server antwortet zu Recht mit 200, und die Pruefung meldet ein Loch,
das es nicht gibt -- einmal je sechzehn Laeufe. Heute Nacht zweimal
hintereinander, und die Suche ging eine halbe Stunde in eine
Aenderung, die damit nichts zu tun hatte.

GEPRUEFT

  pruef-struktur   44 -> 59 Pruefungen, 0 Fehler
  pruef-ics        37 -> 38, 0 Fehler
  pruef-kreislauf  Absturz bei Nr. 17 -> 25 Pruefungen, 0 Fehler

  und gruen geblieben: treff 85, arten 28, video 74, uebernahme 39,
  entwicklung 79, content 45, vorlagen 24, zuteilung 75,
  scout-zuteilung 37, unterstuetzung 70, aufbewahrung 45,
  bewerbung 91, treff-start 42, uebergang 65, nachwuchs 262,
  auskunft 46, modi-ideen 30, neue-seiten 109, spicy 85,
  wege-nach-draussen 67, aufgabenbrett 49, agentur 62,
  bereiche-lesend 37 -- beide Haeuser

GEGENPROBEN, DIE WIRKLICH ROT WERDEN

  - den UTC-Tag im `daraus`-Weg wieder eingebaut: pruef-kreislauf
    meldet „er liegt HEUTE, nicht gestern (2026-09-30, heute ist
    2026-10-01)", 25 Pruefungen, 1 Fehler -- und der Browserteil
    bleibt gruen, weil er jetzt aufklappt. Jede Frage bei ihrer
    eigenen Pruefung.
  - eine Einfuhr aus workspace-video.js entfernt: die neue Wache
    meldet „workspace-video.js: heuteLokal() (aus helfer-tag.mjs)"
  - beide Erkennungen je gegen einen gebauten Rueckschritt geprueft
    (Funktion, Variable, zwei Schritte, Date.now-Rechnung) und gegen
    das, was NICHT anschlagen darf (UTC-Mittag, voller Zeitstempel,
    fremdes Date, Name im Kommentar, Eigenschaft am Objekt)

EIN FEHLER BEIM UMBAU, HIER FESTGEHALTEN: Mein erster Lauf ueber die
Pruefdateien hat stumpf ersetzt und dabei KOMMENTARE umgeschrieben --
in sieben Dateien stand die alte Schreibweise als Beleg in der
Begruendung, und daraus wurde das Gegenteil. Bemerkt hat es der
Vergleich der Zahlen (34 Stellen statt der gemessenen 24), nicht die
Absicht. Zurueckgenommen und mit Schutz fuer Kommentare und
Zeichenketten wiederholt.

Datenbank vorher gesichert. Keine Schemaaenderung.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 01:45:16 +02:00
DogFatherGitandClaude Opus 5 f6225d7341 Ports: auch die Messwerkzeuge leiten ihre Nummer ab
GEMESSEN, BEVOR ICH ETWAS ANGEFASST HABE:

  204 pruef-Dateien, abgeleitete Ports 5000-5409 (dicht belegt)
  24 mess-Dateien, Nummern von Hand: 4471 bis 5493
  davon IM Pruefbereich: 5387, 5397, 5397, 5399, 5399, 5401, 5403, 5405
  untereinander doppelt: 5397, 5399, 5461, 5483, 5491

Aufgefallen ist es, weil mess-buehne und mess-reaktion beide auf 5483
lagen und ein haengengebliebener Lauf gestern einen ganzen Messlauf
gekostet hat.

Beim Umbau kam das Groessere heraus: EINUNDZWANZIG der 24 Messdateien
hatten nicht nur eine Nummer von Hand, sondern ueberhaupt keinen
Waechter -- schlicht `const PORT = 5397;`. Liegt dort schon ein
Server, startet der eigene still nicht, und gemessen wird ab da ein
fremder Stand. Genau der Fehler, gegen den helfer-port.mjs gebaut
wurde; die Messdateien standen die ganze Zeit ausserhalb.

WAS JETZT GILT

Zwei Sorten, zwei Bereiche, beide abgeleitet aus der Stelle im
Alphabet -- jede Sorte unter ihresgleichen, sonst verschoebe eine
neue Pruefung die Nummern aller Messungen. Pruefungen ab 5000,
Messungen ab MESS_BASIS = 5900.

5900 und nicht 5500: dazwischen bleibt Platz fuer 245 weitere
Pruefdateien (bei 5500 waeren es 45). Nach oben 5948 + AUSWEICHEN
4000 = 9948, also unter 10080, der naechsten gesperrten Nummer.
Nachgerechnet, nicht geschaetzt -- eine geschaetzte 4500 hatte bei
BASIS schon einmal danebengelegen.

Eine Wache dazu: Waechst der Pruefbereich bis an MESS_BASIS heran,
bricht die Ableitung ab und sagt, was zu tun ist. Eine stille
Ueberschneidung waere genau der Fehler, den das hier beseitigt.

Die zweite Nummer kommt ueber nr=1, nie ueber `PORT + 1`:
portNummer ueberspringt gesperrte Nummern, deshalb kann die naechste
Zahl die Nummer der naechsten DATEI sein, sobald einmal eine Sperre
dazwischenliegt. Heute liegt dort keine -- das ist Glueck, kein
Entwurf.

NEBENBEI GEFUNDEN UND MIT REPARIERT

Sechs bild-*.mjs riefen den Waechter und warfen seine Antwort weg:

    await portMussFreiSein(4315, "das Bildwerkzeug");
    process.env.PORT = "4315";
    const BASIS = "http://127.0.0.1:4315";

Er lief, meldete nichts und wirkte nicht. Gibt das System den Port
dauerhaft nicht her, weicht er auf Port + 4000 aus und GIBT DIE NEUE
NUMMER ZURUECK -- diese Werkzeuge hoerten danach trotzdem auf der
alten und stuerzten mit `listen EACCES` ab, also mit genau dem
Fehler, gegen den er gebaut wurde. Dazu stand die Zahl dreimal je
Datei. Jetzt einmal, und die Antwort wird benutzt.

tiktok-videos.mjs hatte den Waechter ABGESCHRIEBEN -- eine kurze
eigene Fassung ohne den dritten Ausgang: Bei EACCES meldete sie
"belegt" und brach ab, statt auszuweichen. Auf diesem Rechner ist
genau das am 23.09. eingetreten (Port 5040, Windows-Dienst).
mess-fokus und mess-notizblock hatten dieselbe Abschrift. Eine
abgeschriebene Sicherung ist dieselbe Falle wie eine abgeschriebene
Liste.

GEPRUEFT

  pruef-portnummern  15 -> 41 Pruefungen, 0 Fehler
  pruef-ports         8 -> 10 Pruefungen, 456 statt 408 Ports geprobt
  node --check auf allen 33 geaenderten Dateien

Gegenproben, die wirklich rot werden:
  - eine Messdatei auf eine feste Nummer zurueckgesetzt -> 2 FEHL,
    danach wieder 41/0
  - die Wache: in einem Wegwerf-Ordner mit 452 pruef-Dateien bricht
    eigenerPort ab statt still zu ueberlappen; eine Datei knapp
    darunter bekommt weiter ihre Nummer (5846)
  - die Erkennungen fuer feste Nummern, PORT + 1 und weggeworfene
    Waechterantworten je gegen einen gebauten Rueckschritt

Am echten Verhalten gemessen:
  - mess-chat-liste und mess-alle-einzelsicht (beide vorher 5397)
    GLEICHZEITIG gestartet: 5906 und 5900, beide exit=0. Vorher war
    das unmoeglich.
  - die 48 neuen Nummern 5900-5947 auf diesem Rechner durchprobiert:
    keine belegt, keine vom System gesperrt
  - bild-chat.mjs durchgelaufen, drei Bilder, exit=0

Kein Eingriff am laufenden Dienst: helfer-port.mjs wird von index.js
und workspace.js nicht geladen (nachgesehen), nur von Pruef- und
Messwerkzeugen. Beide Haeuser unberuehrt -- es wird keine Zeile
angefasst, die eine Seite ausliefert.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 01:19:41 +02:00
DogFatherGitandClaude Opus 5 8e18c7bcf0 Aufgaben: eine Bewerbung auf eine erledigte Aufgabe ist keine mehr
Beim Durchsehen der echten Daten am 30.09. gefunden, Filipe am
01.10.: „mach alles los."

GEMESSEN: Zwei Bewerbungen von Miss standen auf „beworben" -- an
Aufgaben, die laengst `erledigt` bzw. `review` waren. Bei ihr stand
weiter „wartet auf Antwort", und in der Liste der Leitung stand eine
Entscheidung an, die es nicht mehr gibt.

DAS MUSTER GIBT ES IM HAUS SCHON. `uebernahmeAbschliessen` raeumt
genau so die offenen Bewerbungen weg, wenn jemand anderes eine
Pool-Aufgabe bekommt -- samt dem Kommentar daneben: „Ohne diese Zeile
blieb eine Bewerbung auf ,beworben' stehen, nachdem jemand anders die
Aufgabe bekommen hat." Derselbe Fall, ein anderer Ausloeser, dieselbe
Behandlung.

ZWEI WEGE FUEHREN IN DEN ENDZUSTAND -- erledigen und abbrechen. Beide
rufen jetzt dieselbe Funktion; nur einen zu bedienen waere die
Haelfte, die man spaeter sucht. Der SATZ ist verschieden:
„abgebrochen" ist nicht „erledigt", und wer gewartet hat, soll den
Unterschied lesen koennen.

KEIN `entschieden_von`. Niemand hat entschieden, die Frage hat sich
erledigt. Dadurch faellt die Zeile auch aus der Absagen-Uebersicht
von gestern heraus (die fragt `entschieden_von IS NOT NULL`) --
richtig, es ist keine Absage an diesen Menschen.

KEINE BENACHRICHTIGUNG. „Deine Bewerbung: diesmal nicht" waere
falsch -- es hat niemand nein gesagt. Der Satz steht an der Zeile.
Wenn Filipe hier doch eine Meldung will, ist es eine eigene Art mit
eigenem Wortlaut, kein Anhaengsel an die bestehende.

GEPRUEFT -- pruef-bewerbung-aufgaben 163/0 (9 neue):

  bewirbt sich          -> „beworben"
  Aufgabe erledigt      -> faellt weg, mit Satz, ohne Entscheider
  Aufgabe abgebrochen   -> ebenso, mit anderem Satz
  Aufgabe noch offen    -> Bewerbung bleibt   <- die Gegenprobe

Ohne die letzte Zeile hiesse „faellt weg" womoeglich nur, dass jede
Bewerbung wegfaellt.

Ein eigener Messfehler unterwegs: Mein Lesehelfer fragte
`/api/aufgaben/:id` und bekam `undefined` -- die Antwort dort hat eine
andere Form. Vier Pruefungen waren rot, waehrend der Mechanismus im
Protokoll nachweislich lief. Jetzt ueber die Liste, die in dieser
Datei erprobt ist.

Die eine vorhandene Zeile wird nachgetragen; auf einer Kopie der
echten Datenbank durchgespielt (danach 0 offene Bewerbungen auf
durchgelaufenen Aufgaben, integrity_check ok).

pruef-zuteilung, pruef-aufgabenbrett, pruef-zwischenspeicher.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 00:59:27 +02:00
DogFatherGitandClaude Opus 5 09375047a7 Entwicklung: die Karte geht auf dem Zugetragenen auf
Filipe, 01.10.2026: „mach alles los." Damit auch der offene Punkt von
gestern: „Zugetragen" ist beim Aufmachen einer Karte die Vorgabe.

DER ALTE EINWAND BLEIBT GUELTIG -- er steht jetzt in der Bedingung
statt im Weg. Er lautete: „Ein Filter, der beim Öffnen schon etwas
versteckt, lässt einen Punkte suchen, die gestern noch da waren."
Richtig, und er trifft genau EINEN Fall: den, in dem gar nichts
zugetragen ist. Dann zeigte „Zugetragen" eine LEERE Karte, und eine
leere Karte sieht aus wie ein Fehler.

Also: Hat dieser Mensch zugetragene Punkte, steht der Filter darauf.
Hat er keine, steht er auf „Alle". Beides ist eine Auskunft, keines
ist eine Suche.

UND ER WIRD JE MENSCH NEU ENTSCHIEDEN. Bisher blieb der Filter ueber
den Personenwechsel hinweg stehen -- richtig, solange er eine
Erwartungsstufe meinte („wer Fortgeschritten gewaehlt hat, will das
weiter sehen"). „Zugetragen" ist eine Aussage UEBER DIESE PERSON;
sie mitzunehmen waere die falsche Frage.

GEMESSEN, beide Faelle:

  Diene (2 zugetragen)   -> Filter „Zugetragen", 2 Punkte
  VanVan (nichts)        -> Filter „Alle", 68 Punkte
  ein Klick auf „Alle"   -> wieder 68

Die Messung fragt jetzt, WAS DASTEHT, bevor jemand etwas anfasst.
Vorher klickte sie auf den Filter und zaehlte nach -- seit er die
Vorgabe ist, haette derselbe Klick ihn AUSgeschaltet. Sie haette das
Gegenteil gemessen und trotzdem eine Zahl gemeldet.

ZWEI NACHZUEGLER AUS DEM SICHT-WEG VON GESTERN

`pruef-werdegang` wurde rot: „403 Forbidden" im Browser, ohne Adresse.
Die Meldung sagte nicht, WORAN sie scheitert -- also sagt sie es
jetzt (`403 /workspace/api/chat/sicht`).

Die Ursache lag in der Messumgebung, nicht im Programm: Der
HTTPS-Vorbau der Pruefung reicht den Host OHNE Port weiter, waehrend
der Browser seine Herkunft MIT Port schickt. `gleicheHerkunft`
vergleicht beides und antwortet folgerichtig 403. mess-reaktion macht
es seit Langem richtig; zwei Dateien nicht.

Aufgefallen ist es erst jetzt, weil der Sicht-Weg der erste
zustandsaendernde POST ist, der auf JEDER Seite laeuft. Live stimmen
Herkunft und Host ueberein (beide ohne Port, Caddy reicht den Host
durch) -- nachgemessen.

GEPRUEFT
pruef-werdegang 103/0 (war 103/1), pruef-entwicklung 79/0,
pruef-entwicklung-kacheln 34/0, mess-vanvan-karte ohne ein einziges
ACHTUNG, pruef-zwischenspeicher 34/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 00:52:07 +02:00
DogFatherGitandClaude Opus 5 718b267de0 Zugang: die gewaehlte Kachel ist bindend
Filipe, 01.10.2026: „mach das. es soll fest sein."

VanVan hatte gemeldet: „Man kann sich mit seinem Zugangscode immer
noch über jeden Button der Startseite anmelden, egal welche Rolle man
hat."

ICH HATTE ZUERST ABGERATEN -- und lag falsch, weil ich eine alte Lage
beschrieben habe.

Am 09.09.2026 hatte Filipe entschieden, dass die Modis KEINE eigene
Eingangskachel bekommen: „damit die von der workspace auch nicht mal
sehen dass die modis von mir einen eigenen zugang haben." Wer keine
Kachel hat, muss irgendeine nehmen koennen -- daher der stille Zugang.

SEIT DER HAUSTRENNUNG AM 24.09.2026 STIMMT DAS NICHT MEHR. Auf
`crew.` steht laengst ein eigener Kachelsatz mit ALLEN fuenf Rollen:
DogFather, rechte Hand, linke Hand, Modi, Community (CREW_KACHEL, und
crew-index.html zeigt sie). Das Verbergen leistet seither die ADRESSE
-- wer sie nicht kennt, findet die Wand nicht; wer sie kennt, liest
die Rollennamen ohnehin offen darauf.

Der stille Zugang war damit ein Rest. Er hat niemanden mehr
geschuetzt und nur dafuer gesorgt, dass die Kachelwahl folgenlos
blieb. Nachgesehen habe ich das erst, NACHDEM Filipe widersprochen
hat; die Kachelsaetze standen die ganze Zeit im Quelltext.

WAS SICH NICHT AENDERT: Auf der Agenturwand war der stille Zugang nie
aktiv. Ein Team-Dogi-Code verhaelt sich dort weiterhin wie ein
erfundener -- gleiche Antwort, gleicher Weg, gleiche Dauer. Das ist
jetzt ausdruecklich gemessen.

EINE PRUEFADRESSE IST KEINE WAND. `127.0.0.1` ist weder crew. noch
Agentur. Ohne den stillen Zugang gaelte dort der Agentursatz -- und
kein Modi kaeme mehr herein. Fuenfzig Pruefdateien melden Team-Rollen
ueber diese Adresse an. Auf einer Adresse ohne Wand gibt es deshalb
ALLE Kacheln; welche auf welcher ECHTEN Wand steht, misst
pruef-modi-verborgen mit ausdruecklichem Host-Kopf.

GEPRUEFT -- pruef-modi-verborgen 87/0 (war 85; die fuenf Zeilen „jede
Kachel geht" sind durch sieben ersetzt, die die neue Regel und ihre
Gegenproben messen). Die Anzahl ist Zeile fuer Zeile verglichen.

  Modi-Kachel + Modi-Code      -> herein
  admin/hand/linke/gast        -> abgewiesen
  rechte Hand auf ihrer Kachel -> herein
  Agenturwand + Modi-Code      -> wie ein erfundener

pruef-crew-adresse 169/0 (unveraenderte Anzahl, zwei Zeilen
umgedreht).

SECHZEHN PRUEFDATEIEN MELDETEN SICH UEBER FREMDE KACHELN AN -- ein
Rest derselben Zeit. Systematisch gesucht statt einzeln entdeckt:
Waere ich dem roten Lauf hinterhergelaufen, haette ich beim zwoelften
aufgehoert.

UND DABEI EIN EIGENER FEHLER: Mein erster Durchlauf las die Rolle am
CODENAMEN ab (CODE-MODI- -> modi). Das ging gut, bis „Nane" kam: ein
Modi mit dem Code CODE-NANE-0001. Zwei Pruefungen wurden rot, und
zwar an einer Stelle („die Stimmen stimmen"), die mit Anmeldung
nichts zu tun hat. Ein Codename ist eine Beschriftung, keine
Tatsache -- die Rolle steht in `anlegen()`. Danach abgeleitet blieben
genau zwei Abweichungen uebrig, und beide sind absichtliche
Gegenproben.

Drei Browserpruefungen tippten die Creator-Kachel mit einem
Modi-Code. Die Modi-Kachel gibt es nur auf der Crew-Wand, und ein
Browser auf 127.0.0.1 bekommt die Agenturwand; sie melden sich jetzt
ueber die Schnittstelle an und bekommen den Keks. Gemessen werden
soll dort, was ein Modi SIEHT -- nicht, wie er hereinkommt.

Grün: pruef-modi-verborgen, pruef-crew-adresse, pruef-treff 85/0,
pruef-galerie, pruef-kanaele, pruef-modi-katalog 150/0,
pruef-modi-ideen, pruef-modi-kategorien, pruef-modi-checkliste 75/0,
pruef-modi-livecheck, pruef-kachelraster, pruef-team-ampel 32/0,
pruef-team-stufen 47/0, pruef-wunschliste, pruef-bremse,
pruef-gespraech, pruef-personen-formular 43/0, pruef-start-ansicht,
pruef-community-sicht, pruef-reaktion 421/0, pruef-abzeichen,
pruef-chat, pruef-chat-kanaele 81/0, pruef-entwicklung 79/0,
pruef-bewerbung-aufgaben 154/0, pruef-struktur,
pruef-zwischenspeicher 34/0.

`code_kennung` wird weiter geschrieben, aber nicht mehr gelesen --
sie war der Suchschluessel des stillen Weges. Stehen gelassen: Eine
Spalte zu entfernen ist eine Schemaaenderung mit Sicherung, und sie
kostet nichts.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-01 00:22:55 +02:00
DogFatherGitandClaude Opus 5 4503b1a475 Benachrichtigungen: nicht "Verbindung offen", sondern "sieht jemand hin"
Diene im Support (vor 5 Tagen): „Die Benachrichtigungen werden nicht
angezeigt, wenn neue Nachrichten reinkommen. Erst, wenn man die App
öffnet."

ERST GEMESSEN, WAS NICHT DAS PROBLEM IST. Am echten Bestand
nachgesehen: Diene HAT ein angemeldetes Geraet (Android, Chrome, seit
dem 29.09.), und alle zehn Geraete im Haus melden `fehler = 0`. An
der Zustellung liegt es nicht.

DANN NACHGESTELLT (pruef-abzeichen, Abschnitt 8):

    Verbindung offen  ->  KEINE Benachrichtigung
    Verbindung zu     ->  sie kommt

Genau sein Befund.

DER GEDANKE WAR RICHTIG, DIE FRAGE FALSCH. Im Quelltext stand:

    if ((zuschauer.get(personId) || new Set()).size) continue;

und daneben die Begruendung -- „wer die Seite offen hat, sieht die
Nachricht ohnehin; ihm auch noch eine Meldung aufs Handy zu schicken
ist der schnellste Weg, dass er Benachrichtigungen abschaltet." Das
stimmt. Nur beantwortet `zuschauer` eine ANDERE Frage: ob eine
VERBINDUNG offen ist. Ein Handy mit der App im Hintergrund haelt sie
weiter -- und der Server hielt Diene fuer anwesend, waehrend sein
Bildschirm schwarz war.

DIE SEITE WEISS ES, DER SERVER NICHT. `document.visibilityState` ist
die einzige Stelle, die den Unterschied kennt. Also sagt sie es --
ueber einen winzigen Weg (`/api/chat/sicht`), beim Aufbau, bei jedem
Wechsel und mit `keepalive` beim Weggehen.

MIT VERFALL, und das ist der wichtige Teil: Ein Geraet, das
abstuerzt, im Funkloch steht oder eingefroren wird, sagt gar nichts
mehr. Ohne Verfall bliebe es fuer immer „sichtbar" und fuer immer
still. Wer nicht widerspricht, gilt nach zweieinhalb Minuten als weg
-- eine Meldung zu viel ist laestig, eine zu wenig ist genau der
Fehler, den Diene gemeldet hat. Dazu alle Minute ein Lebenszeichen,
solange die App vorn liegt.

EINE STELLE FUER DIE FRAGE. Sie wurde an zwei Orten gestellt:
`siehtZu()` und eine Abschrift mitten in `chatEreignis`. Die
Abschrift war die kaputte. Jetzt fragen beide dieselbe Funktion.

GEPRUEFT -- vier Lagen, und die zweite ist die wichtigere
Gegenprobe:

  App liegt hinten        -> Meldung kommt      (war: nichts)
  sieht wirklich hin      -> KEINE Meldung      (Absicht bleibt)
  App weggelegt           -> Meldung kommt wieder
  gar keine Verbindung    -> Meldung kommt

Ohne die zweite Zeile hiesse die Reparatur nur „jetzt kommt immer
eine", und das waere der schnellste Weg, dass jemand
Benachrichtigungen abschaltet.

UND EINE PRUEFUNG HAT DEN FEHLER MITGETRAGEN. pruef-anruf-klingelt
hielt den WORTLAUT der kaputten Zeile fest -- genau das, wovor ihr
eigener Kommentar drei Zeilen darueber warnt („Die Pruefung hat den
alten Wortlaut bestaetigt statt sein Verhalten"). Sie prueft jetzt
beides: dass gefragt wird, und dass die Frage die richtige ist.

pruef-abzeichen 26/0, pruef-chat, pruef-anruf 132/0,
pruef-chat-kanaele 81/0, pruef-anruf-klingelt 25/0, pruef-push-ziel
38/0, pruef-arten 28/0, pruef-reaktion 421/0, pruef-struktur,
pruef-zwischenspeicher 34/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 23:48:49 +02:00
DogFatherGitandClaude Opus 5 d4a3e54a72 Aufgaben: dauerhafte Aufgaben, die nicht abgehakt werden
VanVan im Support: „Man kann bei den Aufgaben, wenn man sie verteilt,
ob selbst erstellt oder über die Vorlage noch nicht festlegen, dass
die Aufgabe dauerhaft sein soll und somit nicht vom Modi in den Status
erledigt gesetzt werden kann."

Nachgesehen: Das Wort kam im Aufgabenmodul kein einziges Mal vor. Es
war keine vergessene Zeile, es fehlte ganz.

WAS EINE DAUERHAFTE AUFGABE IST: keine, die man abarbeitet, sondern
eine, die man TUT. „Neue begruessen" ist nicht fertig, wenn man es
einmal gemacht hat.

ZWEI FOLGEN, und die zweite faellt leicht durchs Raster

1. Der Zugeteilte kann sie nicht auf „erledigt" setzen. Die Sperre
   steht im SERVER -- ein fehlender Knopf ist eine Bitte, abgelehnt
   wird an der Route. „Ich fange an" bleibt erlaubt: Auch eine
   stehende Aufgabe hat einen Anfang.

2. SIE HAT KEINE FRIST. Eine dauerhafte Aufgabe mit Frist waere ab
   dem naechsten Tag fuer immer ueberfaellig -- und eine Warnung, die
   immer kommt, ist keine mehr. Die Frist wird GELOESCHT, nicht
   ignoriert: Ein Datum, das dasteht und nicht gilt, ist schlimmer
   als keins.

WER DARF DAS SETZEN: nur, wer verteilt. Koennte der Zugeteilte seine
eigene Aufgabe dauerhaft machen, waere das eine Ausrede; koennte er
es zuruecknehmen, waere die Sperre ein Knopf weiter offen. Beides
nachgemessen.

UND SIE LAESST SICH BEENDEN. Eine Pflicht, die niemand mehr beenden
kann, waere eine Falle statt einer Regel.

DREI STELLEN, KEINE VIERTE: das Anlegeformular auf „Aufgaben", das
auf „Eure Aufgaben" (dort wird verteilt) und das Bearbeiten-Feld.
Ueber das letzte laeuft VanVans „oder ueber die Vorlage" -- eine
Vorlagen-Aufgabe entsteht ohne Formular, ein Schalter im
Vorlagenbrett waere eine vierte Stelle fuer dieselbe Frage.

An der Karte steht die Marke fuer ALLE, nicht nur fuer den
Zugeteilten: Wer sie ansieht, soll wissen, warum dort kein „Fertig"
steht. Ein fehlender Knopf ohne Erklaerung liest sich wie ein Fehler.

GEPRUEFT
pruef-bewerbung-aufgaben 154/0 (10 neue) mit vier Gegenproben: eine
GEWOEHNLICHE Aufgabe laesst sich sehr wohl abhaken (sonst hiesse 409
nur, dass niemand je etwas abhaken kann), „Ich fange an" geht
weiterhin, der Zugeteilte setzt und nimmt „dauerhaft" nicht, und nach
dem Beenden durch die Leitung geht das Abhaken wieder.

ZWEI EIGENE FEHLER, beide von Pruefungen gefunden

* Ein BACKTICK in einem Kommentar -- mitten in einem Template-String
  (`SPALTEN`). Er hat ihn beendet, die Datei war syntaktisch kaputt.
  Dieselbe Familie wie die deutsche Anfuehrung in einem
  Anfuehrungsstring: ein Zeichen, das in der Umgebung etwas bedeutet.
* `toISOString().slice(0,10)` fuer „morgen" -- pruef-struktur hat es
  noch am selben Abend gefunden. Zwischen 00:00 und 02:00 liegt der
  UTC-Tag noch auf gestern; die Pruefung haette nachts falsch
  angeschlagen. Jetzt ueber `tagLokal()`.

Und einer, den nur die Messung zeigen konnte: `holen()` in
workspace-zuteilung liest die Aufgabe mit einer eigenen, kurzen
Spaltenliste. Ohne `dauerhaft` darin fragte die Sperre `a.dauerhaft`
und bekam `undefined` -- sie war still wirkungslos, und im Quelltext
daneben sah alles richtig aus.

pruef-aufgabenbrett, pruef-zuteilung, pruef-aufgaben-vorlagen,
pruef-entwicklung 79/0, pruef-css-klassen, pruef-deutsche-texte,
pruef-struktur, pruef-zwischenspeicher 34/0.

Schemaaenderung: ADD COLUMN dauerhaft. Datenbank vorher gesichert und
geprueft (integrity_check ok, 12 Aufgaben).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 18:52:37 +02:00
DogFatherGitandClaude Opus 5 5e26df788b Bewerbungen: die Absage bleibt lesbar, und ihr seht, was ihr absagt
VanVan im Support: „Wenn sich ein Modi auf eine Aufgabe bewirbt und
man diese ablehnt, dann bekommt der Modi keine Benachrichtigung
darüber, dass die Aufgabe abgelehnt wurde und sieht somit auch eine
eventuelle Begründung nicht. Außerdem haben auch wir nirgendwo eine
Übersicht, bei wem wir welche Aufgaben schon abgelehnt haben."

GEMESSEN, BEVOR GEBAUT WURDE -- die Pruefungen standen zuerst da und
waren rot:

    Frida sieht ihre beantwortete Bewerbung     0
    Die Leitung sieht die Absagen               0

DIE URSACHE. `vorlagenBewerbungenFuer` fragt `WHERE zustand =
'beworben'`. Sobald jemand antwortet, faellt die Zeile aus JEDER
Ansicht heraus -- mitsamt der Begruendung, die Filipe am 23.09.
ausdruecklich verlangt hat („mit einem text als notiz"). Der Satz
wird also verlangt, geschrieben und weggesperrt.

Bei einer ZUSAGE fiel das nicht auf: Dort entsteht eine Aufgabe, und
an ihrer Karte steht die Antwort. Bei einer ABSAGE entsteht nichts.

Die Benachrichtigung selbst gab es (`bewerbung_antwort`, vorgabe an,
fuer ja und nein). Sie war nur das EINZIGE -- wer sie wegwischt oder
kein Geraet angemeldet hat, erfuhr nie, warum.

WAS JETZT DASTEHT

* BEIM BEWERBER: „Antwort auf deine Bewerbung" mit dem Ergebnis, dem
  Satz und dem Namen dessen, der geantwortet hat. Beide Ausgaenge --
  eine Liste, die nur Absagen sammelt, waere eine andere Sache. Nach
  14 Tagen verschwindet sie von selbst.

  SIE STEHT VOR DEM ZUKLAPPEN. Beim ersten Anlauf lag sie im Koerper
  des Vorlagenbretts, und der wird nur gebaut, wenn das Brett
  aufgeklappt ist -- zugeklappt ist die Vorgabe. Eine Antwort, die
  man erst aufklappen muss, ist wieder keine.

* BEI DER LEITUNG: „Schon abgesagt", 90 Tage, mit der Zahl JE MENSCH
  vorn. Das ist VanVans eigentliche Frage („falls sich jemand immer
  wieder bewirbt und immer wieder abgelehnt wird"), und die
  beantwortet eine Liste von zwanzig Zeilen nicht.

  AUS BEIDEN WEGEN -- Vorlage und Aufgabe. Eine Uebersicht, die nur
  die Haelfte zeigt, ist schlimmer als keine: „Frida wurde nie
  abgelehnt" waere dann eine Auskunft, die stimmt und taeuscht.

  ZUGEKLAPPT. Eine Liste von Absagen, die immer offen steht, ist eine
  Sammlung von Nein-Sagen ueber Menschen, mit denen man morgen wieder
  arbeitet.

  KEIN ROT. Eine Absage ist kein Fehler; „diesmal nicht" ist keine
  Aussage ueber den Menschen. Gedeckter Bernstein, und ab zwei Malen
  faellt die ZAHL auf -- nicht nur die Farbe.

ZWEI EIGENE FELDER UND NICHT `bewerbungen` ERWEITERT. Dort heisst
eine Zeile im Browser „wartet auf Antwort", samt Zurueckziehen-Knopf.
Beantwortete Zeilen hineinzumischen haette bei einer Absage genau das
gezeigt. Ein Feld, dessen Bedeutung sich aendert, bricht seine Leser
lautlos.

`entschieden_von IS NOT NULL` TRENNT DREI DINGE, die alle `abgelehnt`
heissen: die Leitung hat eine Bewerbung abgelehnt (das hier), die
Person hat eine Zuteilung abgelehnt (ihre Entscheidung), und „von
jemand anderem uebernommen" (gar keine Absage).

Haustrennung gilt: `darfSchreibenMit` je Zeile.

GEPRUEFT
pruef-bewerbung-aufgaben 144/0 (weitere 10 Pruefungen plus zwei
Bilder). Die Gegenprobe steht in der Vorgeschichte: Dieselben
Pruefungen waren vor dem Bau rot.

Zwei eigene Messfehler, beide im Text festgehalten: Ich habe zuerst
auf dem AUFGABENbrett gemessen -- der Vorlagenkatalog steht aber auf
„Eure Aufgaben" (`zweig: 'team'`). Und `innerText` liefert den Text
so, wie er DASTEHT: Die Zeile suchte „Diesmal nicht" und fand
„DIESMAL NICHT", weil das Schild `text-transform: uppercase` traegt.

pruef-vorlagen 24/0, pruef-aufgaben-vorlagen, pruef-zuteilung,
pruef-aufgabenbrett, pruef-entwicklung 79/0, pruef-css-klassen,
pruef-zwischenspeicher 34/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 18:34:24 +02:00
DogFatherGitandClaude Opus 5 c933bcd2e0 Aufgaben: wer verantwortlich ist, hat auch eine Zuteilung
VanVan im Support: „Wenn ein Modi sich auf eine Aufgabe beworben hat
und die von uns angenommen wurde, dann steht beim Modi unter der
Aufgabe immer noch ich bewerbe mich."

GEMESSEN AN DEN ECHTEN DATEN (lesend, auf einer Kopie):

    Aufgaben mit Verantwortlichem:     11
    davon OHNE Zuteilungszeile:         8

Darunter Marinas zwei offene Vorlagen-Aufgaben -- genau die zwei
Karten aus ihrem Bildschirmfoto.

DIE URSACHE. `katalogAufgabeAnlegen()` schrieb eine Zeile in
`aufgaben` mit `verantwortlich_id` und KEINE in
`aufgaben_zuteilung`. Das Brett liest aber die Zuteilung, nicht den
Verantwortlichen: Es fand nichts, lieferte `meine_zuteilung: null`,
und die Bedingung im Browser beginnt mit `!mein` -- also bot sie an,
sich auf die eigene Aufgabe zu bewerben.

ES WAR NICHT NUR EIN FALSCHER KNOPF. „Ich fange an" und „Fertig"
haengen an derselben Zeile. Der Mensch bekam eine Karte, auf der er
das Falsche tun konnte und das Richtige nicht.

WARUM DIE VORHANDENE PRUEFUNG ES NICHT FAND: Sie geht den Weg ueber
das AUFGABENbrett -- dort war alles in Ordnung, nachgemessen steht
nach dem Annehmen richtig „Ich fange an | Fertig". VanVans Weg ist
der ueber das VORLAGENbrett, und der endet in einer neu angelegten
Aufgabe. Dieser Weg war nie geprueft.

DREI TEILE

1. `katalogAufgabeAnlegen` legt die Zuteilungszeile mit an. Mit
   Zustand: `angenommen`, wenn die Person darum gebeten hat und die
   Bitte angenommen wurde; `offen`, wenn die Leitung zutraegt -- dann
   steht bei ihr Annehmen/Ablehnen, und das ist richtig, sie hat noch
   nicht ja gesagt.

2. Eine Umstellung traegt nach, was schon dasteht. Wiederholbar
   (`NOT EXISTS` + `INSERT OR IGNORE`), deshalb bei den Umstellungen
   und nicht in einem Skript, das jemand vergisst. Auf einer KOPIE
   der echten Datenbank durchgespielt: 8 Zeilen angelegt, danach 0
   ohne Zuteilung, `integrity_check ok`. Marinas Karten stehen
   danach auf `angenommen`.

3. Ein Riegel im Browser: Auf eine Aufgabe, die mir schon gehoert,
   bewirbt man sich nicht. Er faengt jeden weiteren Weg ab, der eine
   Aufgabe ohne Zuteilungszeile anlegt -- nicht alle acht kamen aus
   der Vorlage.

GEPRUEFT
pruef-bewerbung-aufgaben 126/0 (15 neue: der ganze Vorlagenweg von
der Bewerbung bis zum Knopf auf ihrem Brett). NACHGESTELLT: Ohne die
Zuteilungszeile wird sie rot („und sie hat eine Zuteilungszeile
(undefined)"). pruef-zuteilung, pruef-aufgabenbrett, pruef-vorlagen
24/0, pruef-aufgaben-vorlagen, pruef-struktur, pruef-zwischenspeicher
34/0.

Ein Messfehler unterwegs, im Text festgehalten: Mein neuer Block
bewarb sich auf dieselbe Vorlage wie ein spaeterer Abschnitt und
nahm ihm damit seine -- zehn Pruefungen wurden rot, ohne dass am
Programm etwas falsch war.

Datenbank vor der Umstellung gesichert und geprueft
(integrity_check ok, 12 Aufgaben, 3 Zuteilungen).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 18:08:36 +02:00
DogFatherGitandClaude Opus 5 721ad262df Entwicklung: „Deine Karte" laesst sich einklappen
VanVan im Support: „Deine Karte im Bereich eure Aufgaben kann man
noch nicht einklappen, was die Seite unnötig lang zieht und
unübersichtlich macht."

GEMESSEN (mess-vanvan-karte, Abschnitt 5). Es ist IHRE eigene Karte,
nicht die eines Modi -- im Bildschirmfoto steht an jedem Punkt „1 ×
Läuft", also eine einzige Antwort. Ueber die rechte Hand urteilt nur
DogFather; bei ihr ist deshalb alles durch und die Karte entsprechend
lang, waehrend ein Modi zwei Stimmen braucht.

                       vorher     nachher
  Seite gesamt         7245 px    2945 px
  davon „Deine Karte"  6186 px    1886 px   (zugeklappt 636 px)
  Schalter                   0    6 + „Alle"-Knopf

6186 von 7245 px waren eine einzige Karte -- 85 Prozent der Seite,
68 Zeilen am Stueck, kein einziger Schalter.

DERSELBE MECHANISMUS WIE NEBENAN, NICHT EIN ZWEITER. Die Karte der
Leitung klappt seit Langem auf und zu. Die Klassen, der Pfeil, die
Zahl im Kopf und der Knopf „Alle auf-/zuklappen" sind dieselben --
ein zweiter Mechanismus daneben waere der, der beim naechsten Umbau
vergessen wird, und er saehe anders aus, obwohl er dasselbe tut.
Herausgeloest als `klappAbschnitt()`.

WELCHER STEHT OFFEN: Was ich TUN soll („Deine Aufgaben"), und von den
Beobachtungen die erste Kategorie. Alle zu hiesse „jedes Mal erst
suchen", alle auf waere der Zustand von vorher.

DIE ZAHL STEHT IM KOPF (14, 12, 12, 11, 10, 9). Eine zugeklappte
Kategorie, die nicht sagt, wie viel in ihr steckt, klappt man einmal
auf und danach nie wieder zu.

GEPRUEFT
Die Messung ist jetzt selbst die Wache: Sie schlaegt an, wenn es
keine Schalter gibt (so ist der Befund entstanden), wenn Zuklappen
weniger als die Haelfte spart, und wenn es Schalter ohne
„Alle"-Knopf gibt. Alle drei nachgestellt. Ein ANTEIL und keine feste
Pixelzahl -- 68 Punkte heute, vielleicht 90 naechstes Jahr.

pruef-entwicklung 79/0, pruef-werdegang 103/0,
pruef-entwicklung-kacheln 34/0, pruef-css-klassen,
pruef-zwischenspeicher 34/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 17:33:37 +02:00
DogFatherGitandClaude Opus 5 51c47e1c07 Entwicklung: der Mensch sieht, was seine Aufgabe ist
VanVan im Support: „wenn ich … Aufgaben an einen Modi zutrage und
auch bewerte, dann sieht der Modi zwar die Auswertung im Bereich
Entwicklung, aber bei ihm taucht nichts im Bereich eure Aufgaben
unten in der Karte auf."

IHR FALL NACHGESTELLT (server/mess-vanvan-karte.mjs): VanVan traegt
einem Modi zwei von 68 Punkten zu und bewertet sie, Filipe bewertet
nichts -- genau wie bei ihr.

  vorher   seine Karte: fertig=0 von 68, alles „offen",
           Punktzeilen sichtbar: 0
           Kennt sie das Wort „zugetragen"?  NEIN
  nachher  Abschnitt „Deine Aufgaben (2)" mit beiden Titeln

ZWEI DINGE WAREN EINS, DIE GETRENNT GEHOEREN

  Was er TUN soll   die Zuteilung. Die gibt es, bevor jemand etwas
                    bewertet, und sie gehoert ihm.
  Was man SIEHT     die Bewertung. Die erscheint erst, wenn alle
                    hingesehen haben.

`meine-karte` kannte nur das Zweite. War die Bewertung noch nicht
vollstaendig, stieg die Anzeige mit `return` aus -- und damit sah er
gar nichts, obwohl ihm zwei Aufgaben zugetragen waren. Das ist die
falsche Reihenfolge: Wer seine Aufgabe erst sieht, wenn sich zwei
Leute ueber ihre Ausfuehrung einig sind, kann sie nicht angehen.

Die Regel fuer die Bewertung bleibt unveraendert. Eine einzelne
Meinung soll bei einem Menschen nicht als Urteil des Teams ankommen.

UND DIE ANDERE HAELFTE: NIEMAND SAGTE ES IHR

VanVan hatte gesetzt, es kam nicht an, und nichts auf ihrem
Bildschirm erklaerte das. Ein Mensch, der das zweimal erlebt, hoert
auf zu setzen. An einem Punkt, den sie bewertet hat, steht jetzt
leise: „Er sieht das noch nicht -- es fehlt noch eine Einschaetzung."
Ohne Namen: Wer fehlt, waere eine Aufforderung, jemanden
anzutreiben.

IHRE ZWEITE BEOBACHTUNG, EBENFALLS GEMESSEN

„bei jedem Punkt läuft obwohl auch wenn die Aufgaben darüber gar
nicht zugetragen wurde." Stimmt: Die vier Bewertungsknoepfe („✓
Läuft ↗ Wächst ! Da hakt es – Kann ich nicht sagen") stehen an allen
68 Punkten, auch an den nicht zugetragenen. Beim Durchscrollen liest
man deshalb ueberall „Läuft".

DIE 68 BLEIBEN. Filipe am 25.09.2026 ausdruecklich: „dogfather und
die rechte hand sollen immer noch die 68 sachen sehen wie vorher …
unsere sicht soll sich nicht aendern." Also kein Ausblenden und
keine neue Vorgabe, sondern ein Knopf mehr in der Leiste, die es
schon gibt: „Zugetragen · 2". „Alle" bleibt, was beim Aufmachen
gilt. Gemessen grenzt er auf 2 Punkte ein, Kopf „2 / 2".

NEBENBEI ZUSAMMENGEFUEHRT
* `beurteilerZahl()` an einer Stelle -- beide Enden stellen dieselbe
  Frage, zwei Abschriften saegten irgendwann Verschiedenes ueber
  denselben Punkt.
* `antwortReihe()` und `punkteGefiltert()` ebenso.
* Die Abfrage stand zuerst je Punkt in der Schleife: 68
  Datenbankfragen fuer eine Zahl, die sich nicht aendert.

GEPRUEFT
pruef-entwicklung 79/0 (9 neue, mit Gegenproben in beide Richtungen:
ein nicht zugetragener Punkt traegt die Marke nicht, und sobald der
zweite Beurteiler setzt, geht es durch). mess-vanvan-karte ohne
ACHTUNG. pruef-werdegang 103/0, pruef-entwicklung-kacheln 34/0,
pruef-deutsche-texte, pruef-css-klassen, pruef-zwischenspeicher 34/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 16:48:24 +02:00
DogFatherGitandClaude Opus 5 a3ec558127 Reaction: der Gleichlauf rechnet ohne Uhrenvergleich
Filipe: „die videos muessen perfekt laufen wenn ich die reaktions
mache."

GEMESSEN, NICHT VERMUTET. mess-reaktion hat einen neuen Abschnitt:
Er liest den Spielstand am ECHTEN <video>-Element in beiden Browsern,
rechnet beide auf denselben Augenblick um und sagt, wie weit Host und
Zuschauerin auseinanderliegen. Die vorhandene Pruefung fragte nur, ob
Start und Stopp ANKOMMEN -- zwei Videos koennen beide laufen und
trotzdem zwanzig Sekunden auseinander sein.

                        vorher      nachher
  Im Lauf                0,12 s     -0,04 s
  Wer dazukommt          6,91 s      0,26 s
  Uhr des Geraets 30 s vor  -29,97 s      0,26 s

DER SCHLIMMSTE FUND: DIE UHR DES TELEFONS

Der Zuschauer rechnete `Date.now() - stand.gesendet`. `gesendet` kam
vom SERVER, `Date.now()` vom Geraet -- zwei Uhren, die nie jemand
verglichen hat. Wessen Telefon dreissig Sekunden vorgeht, schaute
29,97 s weiter als alle anderen. Kein langsames Netz, kein schwaches
Handy. Oertlich faellt das nie auf: Auf einem Rechner sind beide
Uhren dieselbe.

Jetzt geht ein ALTER hinaus statt einer Uhrzeit -- die Differenz
zweier SERVERzeiten. Der Empfaenger braucht dafuer gar keine Uhr,
nur eine Stoppuhr (`performance.now()`), und die haelt Zeitumstellung
und Aufwachen aus dem Ruhezustand aus.

WEITER

* WER DAZUKOMMT, STEIGT RICHTIG EIN. Der gespeicherte Stand war so
  alt wie der letzte Takt des Hosts; neue Spalte `sekunde_am` sagt,
  wann er galt.
* DAS TEMPO GEHT IN DIE HOCHRECHNUNG EIN. Bei 2x laeuft die Videouhr
  doppelt so schnell -- das fehlte ganz.
* JEDER RECHNET ALLE ZWEI SEKUNDEN SELBST NACH statt nur auf Zuruf.
  Wer stockte, hing bis zu fuenf Sekunden hinterher.
* DER VORLAUF NACH EINEM SPRUNG WIRD GEREGELT, nicht geschaetzt --
  gemessen wird der Rest, nicht die Ladezeit (siehe unten).
* PUFFERN IST AUCH IN DER TRANSPORTLEISTE KEINE PAUSE. Der
  Start-Stopp-Knopf rief beim Puffern `playVideo()` -- wer Pause
  drueckte, bekam „weiter". Lampe und Knopfbild flackerten bei jedem
  Stocken. Die Lektion vom 29.09. war nur an einer Stelle eingeloest.
* DAS TEMPO MELDET UEBER `hostMelden()` statt ein zweites Mal von
  Hand -- es hielt Puffern fuer Stillstand und hielt damit beim
  Umschalten alle an.
* EIN VIDEO-RUNDRUF STATT DREI ABSCHRIFTEN. Beim Einbau hatte ich
  zuerst nur eine nachgezogen; das Tauschen der beiden Videos haette
  still die alte Rechnung weiterverschickt.

DREI EIGENE FEHLER UNTERWEGS, alle im Text festgehalten

1. ZWEI FUNKTIONEN HIESSEN `springen`. Meine „spring AUF die Stelle"
   wurde von der vorhandenen „spring UM so viele Sekunden"
   ueberschrieben -- lautlos, rueckwirkend fuer die ganze Datei. Ein
   Zuschauer bei Sekunde 100, dem „geh auf 101" gesagt wird, waere
   bei 201 gelandet. DREI BROWSERLAEUFE HABEN ES NICHT GEFUNDEN:
   oertlich blieb der Abstand unter der Sprungschwelle, die Zeile
   lief kein einziges Mal. Gefunden hat es erst eine Frage an die
   ganze Datei -- die steht jetzt als Pruefung drin und wurde
   nachgestellt (rot).
2. DER VORLAUF LERNTE NUR NACH OBEN. Gemessen wurde die Ladezeit
   nach einem Sprung; ein Sprung in geladenes Material dauert aber
   gar nicht, meldet nichts und lehrt nichts. Ergebnis: -0,95 s
   stabil. Jetzt wird das ERGEBNIS geregelt statt der Ursache.
3. DER AUSREISSER VON 39,84 s WAR MEINE EIGENE MESSUNG -- der Block
   davor schickt eine erfundene Position. Jetzt wird abgeklungen und
   in Messreihenfolge ausgegeben.

GEPRUEFT
pruef-reaktion 421/0 (14 neue, darunter der Riegel gegen die
Rueckkehr der Uhrenrechnung und die Wache gegen doppelte
Funktionsnamen -- beide nachgestellt), mess-reaktion ohne ein
einziges ACHTUNG, pruef-buehne 38/0, pruef-struktur, pruef-
zwischenspeicher 34/0.

Schemaaenderung: ADD COLUMN sekunde_am. Datenbank vorher gesichert
und geprueft (integrity_check ok, 20 Personen).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 15:45:48 +02:00
DogFatherGitandClaude Opus 5 d5c84c7608 Abzeichen am App-Symbol - und die Zahl gehoert zu einem Haus
Die kleine Zahl auf dem Symbol des Startbildschirms. Sie fehlte ganz;
setAppBadge kam im Haus kein einziges Mal vor.

ZWEI ENTSCHEIDUNGEN

Sie zaehlt ungelesene Nachrichten und nichts sonst. Ein Abzeichen
muss weggehen koennen: Nachrichten verschwinden, sobald man sie
liest; eine ueberfaellige Aufgabe verschwindet nicht dadurch, dass
man die App oeffnet. Eine Zahl, die dauerhaft dasteht, ist nach drei
Tagen kein Hinweis mehr, sondern ein Fleck.

Und sie hat EINE Quelle. Im Browser haengt sie an chatZahlZeigen() -
der einen Stelle, an der die Zahl ohnehin gesetzt wird (beim Laden,
aus dem Ereignisstrom, beim Lesen). Fuer die geschlossene App - wo
das Abzeichen ueberhaupt erst etwas wert ist - reist dieselbe Zahl in
der Benachrichtigung mit. Der Service Worker setzt sie nur, wenn eine
dabei ist: Eine Aufgabenerinnerung mit "0" haette dem Chat sein
Abzeichen weggenommen.

DER FUND NEBENBEI

Beim Herausloesen der Abfrage fiel auf, dass sie nie nach dem Haus
gefragt hat - die Raumliste zwanzig Zeilen darueber tut es laengst.
Gemessen: Eine Managerin schreibt DogFather an der Agenturwand an,
sein Zaehler auf crew. springt von 0 auf 1. Seit dem 24.09. soll das
nicht mehr sein. Aufgefallen ist es erst jetzt, weil dieselbe Zahl ab
heute auf dem Startbildschirm steht - und eine Zahl, die etwas
Falsches zeigt, ist schlimmer als keine.

Behoben ueber hausWo(); die Meldung nimmt das Haus des Raums, aus dem
sie stammt.

GEPRUEFT

server/pruef-abzeichen.mjs, 19 Messungen am echten Weg: ein
nachgebauter Browser macht die Benachrichtigung mit seinem privaten
Schluessel auf und liest die Zahl heraus. Mit Gegenproben - ohne Zahl
kommt keine mit, NaN rutscht nicht durch, eine echte Sieben schon.
Und Abschnitt 7 wird rot, sobald man die Hausregel wieder herausnimmt
(nachgestellt).

Zwei eigene Messfehler unterwegs, beide im Text festgehalten: eine
Suche, die im Kommentar landete statt im Code (jetzt ueber
jsOhneKommentar), und Aufrufe ohne Host-Feld - ueber 127.0.0.1 gibt
es kein Haus, die Pruefung mass also eine Regel an einer Verbindung,
die sie gar nicht kennt.

helfer-push-aufmachen.mjs: das Entschluesseln stand als lokale
Funktion in pruef-push-weg; zwei Abschriften waeren die, die
auseinanderlaufen.

Nachbarlaeufe gruen: push, push-ziel, push-weg (17 unveraendert),
arten, portnummern, struktur, chat, chat-kanaele, chatkachel, anruf,
haus-trennung, zwischenspeicher.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 13:39:55 +02:00
DogFatherGitandClaude Opus 5 2c12b8706e Highlights des Teams sind sofort zu sehen -- ohne zweiten Klick
Filipe, 30.09.2026: „wenn wir bei highlights videos rein setzen will
ich nicht mehr dass wir sie freigeben muessen, sobald die reingesetzt
wurden sollen die sofort zu sehen sein."

=====================================================================
WAS ICH NICHT GETAN HABE, UND WARUM NICHT
=====================================================================
Die naheliegende Loesung waere gewesen, `highlight` aus
`TREFF_FREIGABE_BRETTER` zu streichen. Das waere falsch: Auf diesem
Brett laedt auch die COMMUNITY hoch -- Clips, Bilder, Fanart. Im
Quelltext steht woertlich daneben:

    „Zwei Schloesser, weil hier fremde Inhalte hochgeladen werden --
     Urheberrecht und Anstand sind nichts, was man nachtraeglich
     klaert."

Filipe meint nicht das. Er meint: „wenn WIR videos rein setzen".

=====================================================================
DIE UNTERSCHEIDUNG STAND SCHON IM HAUS -- nur nicht im Code
=====================================================================
Derselbe Quelltext sagt ueber die zwei Freigabe-Bretter
Verschiedenes:

    ansteht    -> der SCHALTER „Im Treff zeigen". Das Team entscheidet
                  JE TERMIN, ob die Community ihn sieht.
    highlight  -> der Urheberrechts- und Anstandsfilter.

Ein Filter fragt „hat das jemand angesehen?". Wenn der, der ihn
bedienen darf, den Eintrag SELBST anlegt, ist die Antwort ja. Genau
diese Begruendung steht seit dem Uebernehmen aus dem Katalog im
Haus: „Eine zweite daneben waere keine Sicherheit, sondern ein
Klick."

Ein Schalter dagegen ist eine Entscheidung je Fall. Termine bleiben
deshalb unberuehrt -- sonst stuende jeder interne Termin sofort im
Treff, und danach hat niemand gefragt.

Neu: `FREIGABE_IST_FILTER` und `sofortFreigeben()` in
workspace-treff.js. DIE BEDINGUNG FRAGT DIE ROLLE, NICHT DEN WEG --
waere der Weg gefragt, waere aus dem Filter ein Loch geworden, sobald
jemand einen zweiten Weg baut. Ein Community-Mitglied ab „Stamm"
darf weiterhin einstellen; sein Eintrag wartet auf das Team.

Gerufen an ZWEI Stellen: beim Videoweg und beim Anlegen von Hand.
Beide hatten es bisher nicht.

=====================================================================
DIE VORHANDENE FREIGABEPRUEFUNG BEWEIST DAS NICHT
=====================================================================
Sie blieb nach der Aenderung gruen -- und das zu Recht: Sie legt ihre
Eintraege unmittelbar in der Datenbank an und prueft damit den
Mechanismus, nicht den Weg. Haette ich mich darauf verlassen, waere
eine Aenderung ausgeliefert worden, fuer die keine Zeile spricht.

pruef-treff (+5): DogFather legt ueber den echten Weg an -> die
Community sieht es SOFORT. Ein TERMIN bleibt verborgen. Die Regel
gibt fuer eine Rolle von aussen NICHT frei und fuer Termine
ueberhaupt nicht.

pruef-video (+3): Der Videoweg hat seinen eigenen Aufruf -- genau
dort wird einer vergessen. Geprueft wird die Freigabezeile selbst,
samt Gegenprobe „freigegeben ist nur, was auch angelegt wurde".

Meinen Abschnitt hatte ich erst HINTER das Abschalten des
nachgebauten TikTok-Dienstes gehaengt -- der Kopf der Datei warnt
woertlich davor („das Abschalten steht ganz hinten"). Gelesen habe
ich ihn, als es rot wurde.

UND `pruef-struktur` HAT MEINE EIGENE NEUE ZEILE GEFANGEN: Sie bildete
das Datum aus UTC statt Ortszeit -- zwischen Mitternacht und zwei Uhr
waere es der falsche Tag gewesen. Behoben mit `tagLokal()`, Minuten
nach dem Schreiben.

Gemessen: pruef-treff 85/0 (war 80), pruef-video 74/0 (war 71),
pruef-highlights 31/0, pruef-bereiche-lesend 37/0,
pruef-treff-werkzeuge 73/0, pruef-alle-sehen-es 43/0,
pruef-community-sicht 10/0, pruef-wege-nach-draussen 67/0,
pruef-struktur 44/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 12:55:12 +02:00
DogFatherGitandClaude Opus 5 f53791cefd Dritte Schicht: auch die Webdesign-Seiten trugen Stempel vom August
Nach den 35 oeffentlichen Seiten und den zwei Zahlen des Service
Workers lag dieselbe Faeulnis noch eine Ebene tiefer:

    webdesign/*.html   49x ?v=20260823wd20   (23. August)
                        1x ?v=20260825wd51   (25. August)

Zwei VERSCHIEDENE Stempel in 13 Seiten, und beide aus dem August. Sie
verweisen auf dieselben Dateien wie die Startseite -- darunter
`main.css` --, und der Server schickt dazu ein Jahr `immutable`. Wer
den Bereich seit August besucht hatte, hatte sie eingefroren, ganz
unabhaengig vom Service Worker.

Dritte Schicht desselben Fehlers an einem Vormittag. Alle drei hatten
dieselbe Ursache: eine Zahl, die ein Mensch pflegen sollte.

Der Stempler nimmt die 13 Seiten jetzt mit -- 554 Verweise in 48
Seiten, EIN Stempel. `workspace/` bleibt ausgenommen: Dort arbeitet
`workspace-stempel.mjs`, und zwei Werkzeuge auf demselben Ordner
waeren zwei Antworten auf dieselbe Frage.

Und die Wache liest sie mit. Haette sie nur die Wurzel gelesen, waere
sie gruen gewesen und haette die Haelfte geprueft -- genau die Sorte
gruener Haken, die nichts bedeutet.

Viermal heute ist mir beim Schreiben ein Backslash durch die Shell
verlorengegangen (`\1` wurde zum Steuerzeichen, `\\` zu nichts).
Die Hausnotiz sagt das seit Langem; ich habe es viermal trotzdem
gemacht. Ab jetzt: alles mit Backslash geht durch das Werkzeug, nicht
durch die Befehlszeile.

Gemessen: pruef-zwischenspeicher 34/0, pruef-bewegung 9/0,
pruef-css-klassen 37/0, pruef-struktur 44/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 12:14:23 +02:00
DogFatherGitandClaude Opus 5 12fa0e45ba Der Webdesign-Bereich lieferte seit dem 27.08. ein veraltetes main.css aus
Der Stempel-Fund von eben hatte eine Fortsetzung: DEPLOY.md verlangte
seit dem 26.08. „ZWEI Zahlen hochzaehlen", mit Begruendung und
Messwerten daneben.

    webdesign/sw.js       const CACHE_NAME = "dogfather-webdesign-v64"
    assets/js/wd-core.js  .register("/webdesign/sw.js?v=64", …)

Gemessen am 30.09.2026 standen beide seit dem 27.08. auf v64 --
waehrend SIEBEN Commits die Dateien geaendert hatten, die der Service
Worker vorhaelt. Er haelt sechs vor, und `/assets/css/main.css` ist
eine davon.

Wer den Webdesign-Bereich einmal geoeffnet hatte, bekam sie seither
aus seinem Zwischenspeicher. Auch die Behebung von heute Vormittag
waere dort nicht angekommen.

EIN KOMMENTAR, DER VOR EINEM FEHLER WARNT, VERHINDERT IHN NICHT. Die
Anleitung war richtig, ausfuehrlich und begruendet. Getan hat es
trotzdem niemand -- fuenf Wochen lang. Das ist dieselbe Lehre wie am
11.09., als ein Warnhinweis neben einer abgeschriebenen Spaltenliste
stand und drei Spalten mit Inhalt trotzdem verlorengingen.

DESHALB MACHT ES JETZT DAS WERKZEUG. `tools/seiten-stempel.mjs`
setzt beide Zahlen auf denselben Stempel wie die Seiten. Passt eines
der zwei Muster nicht mehr, bricht es ab, statt stillschweigend
weiterzulaufen -- sonst waere die Zahl ab da wieder von Hand
gepflegt, und das merkt niemand.

Dass der Vorrat bei jedem Stempeln neu aufgebaut wird, ist Absicht:
sechs kleine Dateien kosten nichts, ein unbemerkt alter Stand fuenf
Wochen.

UND EINE WACHE DAZU. `pruef-zwischenspeicher` prueft jetzt:
  · beide Zahlen stehen da
  · sie sind GLEICH -- sonst wird der Vorrat geleert, aber der
    Service Worker gar nicht erst neu geladen (Cloudflare ersetzt
    sein `no-cache` durch vier Stunden)
  · die Zahl ist nicht aelter als die vorgehaltenen Dateien

Die Liste der vorgehaltenen Dateien wird AUS DEM SERVICE WORKER
gelesen, nicht abgeschrieben -- eine zweite hier waere die, die beim
naechsten Eintrag auseinanderlaeuft.

Gegenprobe gemacht: die zwei Zahlen um eine Minute auseinander ->
rot, zurueck -> gruen.

DEPLOY.md sagt jetzt, dass es automatisch geht, und nennt den Befund
im Wortlaut daneben.

Gemessen: pruef-zwischenspeicher 34/0 (war 30/0), pruef-bewegung 9/0,
pruef-css-klassen 37/0, pruef-struktur 44/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 12:12:32 +02:00
DogFatherGitandClaude Opus 5 d087d02a63 Seit fuenf Wochen kam keine Aenderung der Website bei einem wiederkehrenden Besucher an
Gefunden beim Nachgehen des letzten roten Pruefstand-Eintrags. Eine
Kette aus drei Funden, und der dritte wiegt am schwersten.

=====================================================================
1. EINE ENDLOSE BEWEGUNG AUF ETWAS UNSICHTBAREM
=====================================================================
`pruef-browser` scheiterte in WebKit daran, dass der Anmeldeknopf nie
ruhig wurde. Eine der zwei laufenden Bewegungen war:

    .knopf__laden { opacity: 0; animation: dreh .8s linear infinite; }

Dieselbe Suche, ueber ALLE 42 Stilvorlagen beider Haeuser und der
Website, fand einen zweiten: An jedem Navigationspunkt der
oeffentlichen Seite lief eine elf Sekunden lange Aurora -- unsichtbar
bis zum Ueberfahren, auf jeder Seite, fuer immer.

Beides faellt niemandem auf: Nichts stuerzt ab, nichts sieht falsch
aus. Es kostet nur Rechenzeit und Akku.

NEU: `server/pruef-bewegung.mjs` mit sechs Gegenproben -- darunter
die wichtigste, dass ein Beispiel IM KOMMENTAR nicht zaehlt (genau
diese Falle hat am 29.09. eine andere Pruefung dreimal getroffen).
Der Gesamtlauf findet sie von selbst, sie laeuft ab heute Nacht mit.

=====================================================================
2. DIE WEBSITE HATTE KEINEN STEMPLER
=====================================================================
Fuer den Workspace gibt es `workspace-stempel.mjs` seit Langem. Die
oeffentliche Website hatte nichts -- dort stand ein VON HAND
gepflegter Stempel, und der ist gealtert wie jede von Hand gepflegte
Liste.

NEU: `tools/seiten-stempel.mjs`, 447 Verweise in 35 Seiten. Er kennt
beide Schreibweisen (mit und ohne fuehrenden Schraegstrich) UND die,
die in einem `style="…url(…)"` stehen -- zwei Hintergrundbilder auf
streamplan.html waeren sonst ein Jahr lang die alten geblieben.
Dieselbe Luecke gab es im Workspace-Stempler schon einmal, dort bei
den App-Symbolen.

=====================================================================
3. UND DESHALB KAM SEIT DEM 27.08. NICHTS MEHR AN
=====================================================================
    Stempel in allen 35 Seiten:     ?v=20260828e  (zuletzt 27.08.)
    Aenderungen an assets/ seither: 6 Commits
    Der Server dazu:  Cache-Control: max-age=31536000, immutable

`immutable` heisst: Der Browser fragt nicht einmal nach. Wer die
Seite einmal geladen hatte, behielt Stilvorlagen und Skripte bis zu
EINEM JAHR.

Darunter der Partnercode DOGI10 auf der gepraegten Muenze und der
komplette Sprachumbau der Oberflaeche. Sie lagen auf dem Server, sie
waren ausgeliefert, und niemand sah sie.

Dieselbe Sorte Fehler wie am 09.09. im Workspace („eine Aenderung ist
nicht gemacht" -- sie war es, nur unsichtbar) und dieselbe wie bei
VanVans Shop: Eine Aenderung ist erst fertig, wenn sie auf der
Adresse ankommt, die der Nutzer benutzt.

`pruef-zwischenspeicher` fragt jetzt nicht mehr nur, OB ein Stempel
dasteht, sondern ob er NEUER ist als die Dateien, auf die er zeigt.
Gegenprobe gemacht: eine Datei zwei Stunden in die Zukunft gesetzt ->
rot, Zeit zurueck -> gruen. Eine Stunde Nachsicht, damit die Wache
nicht bei zwei Minuten anschlaegt und weggeklickt wird.

DEPLOY.md hat jetzt einen Schritt 0 mit beiden Stemplern und dem
Grund dafuer -- der Befund steht im Wortlaut daneben.

Gemessen: pruef-bewegung 9/0, pruef-zwischenspeicher 30/0,
pruef-browser 17/0, pruef-css-klassen 37/0, pruef-struktur 44/0,
pruef-workspace-umzug 3/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 11:38:38 +02:00
DogFatherGitandClaude Opus 5 8e4e525861 Auf der Zugangswand drehte sich ein unsichtbarer Kreisel -- fuer immer
`pruef-browser` stand seit dem 28.09. rot, und zwar NUR in WebKit
(Safari): „element is not stable" beim Klick auf den Anmeldeknopf, 53
Versuche ueber 30 Sekunden. Chromium und Firefox waren gruen.

Nachgemessen wanderte sein Kasten pro Bild um ein Fuenftel Pixel:

    746.12,575.12  ->  745.10,575.60   (sechs Bilder)

Zwei Bewegungen liefen dabei -- `.buehne__bild` und `.knopf__laden`.
Beide sind echte Befunde.

=====================================================================
1. DER KREISEL DREHT SICH FUER IMMER, UNSICHTBAR
=====================================================================
    .knopf__laden { opacity: 0; animation: dreh .8s linear infinite; }
    .knopf[disabled] .knopf__laden { opacity: 1; }

Nur die Deckkraft schaltete um. Die Drehung lief ab dem Laden der
Seite, auf JEDEM Knopf, fuer immer -- nicht zu sehen und trotzdem
jedes Bild neu gerechnet. Auf einer Seite, auf der man einen Code
eintippt, ist das reine Verschwendung.

Und sie kannte die Hausregel nicht: Wer weniger Bewegung eingestellt
hat, bekam sie trotzdem. Jetzt dreht sie nur, wenn der Knopf
wirklich arbeitet -- und bei `prefers-reduced-motion` steht der Ring
still, statt zu verschwinden: Ein unsichtbarer Kreisel sagt gar
nichts, ein stehender sagt „ich arbeite noch".

=====================================================================
2. DIE KARTE BEWEGTE SICH, WENN MAN NACH IHR GRIFF
=====================================================================
Die Parallaxe folgte dem Zeiger AUCH ueber der Anmeldekarte. Wer die
Maus zum Codefeld fuehrt, bewegte damit das Feld. Bei zehn Pixeln
keine Katastrophe -- aber genau verkehrt herum: Was man bedienen
will, soll stillstehen.

Und es war der Grund fuer den Wettlauf: Der Zeiger bewegte das Ziel,
das er treffen wollte. Ein Wettlauf zwischen Maus und Karte ist auch
fuer einen Menschen keiner, den er gewinnen soll.

Ueber der Karte wird das Ziel nicht mehr nachgefuehrt. Die
Annaeherung laeuft aus und haelt an; verlaesst man die Karte, geht es
weiter. Das Bild lebt, die Bedienung steht.

=====================================================================
WARUM ES NUR WEBKIT GEZEIGT HAT
=====================================================================
Chromium liefert fuer eine zusammengesetzte Verwandlung oft den
Layout-Kasten OHNE die laufende Bewegung -- dort sah der Knopf ruhig
aus, obwohl er es nicht war. WebKit sagt die Wahrheit. Eine Maschine,
die frueher „gruen" meldet, hat nicht recht; sie sieht nur weniger.

Nachher: pruef-browser 17/0 (war 14/1), alle vier Maschinen.
Dazu gruen: crew-adresse 169/0, crew-wand-bild 45/0, kachelfarben
31/0, css-klassen 37/0, struktur 44/0, tippziele 13/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 11:27:57 +02:00
DogFatherGitandClaude Opus 5 69517e090b Wer im Chat hochscrollt, wird nicht mehr ans Ende gerissen
`pruef-chat-ausbau` stand seit dem 28.09. rot:

    FEHL die Stelle bleibt stehen (0 -> 3574)
    FEHL der Knopf sagt, wie viel wartet ("Zum neuesten")
    FEHL er zaehlt mit ("Zum neuesten")
    FEHL pruef-chat-ausbau: unbehandelter Fehler   (der Knopf blieb verborgen)

WAS WIRKLICH PASSIERTE: Man liest weiter oben im Verlauf, jemand
schreibt -- und man wird ans Ende gerissen. Der Zaehler „1 neue
Nachricht" wurde dabei zurueckgesetzt, der Knopf blieb verborgen.

DIE URSACHE STAND AN DER FALSCHEN STELLE. Die Zuhoerer, die „der
Mensch hat selbst gescrollt" feststellen (Rad, Finger, Taste,
Zeiger), hingen INNERHALB des Sprung-Blocks zur Neu-Linie -- wurden
also erst angehaengt, NACHDEM einmal gesprungen worden war.

In einem ruhigen Gespraech passiert das nie: Wer alles gelesen hat,
bekommt keine Neu-Linie, der Block laeuft nicht, die Zuhoerer gibt es
nicht. Scrollt er hoch und es kommt eine Nachricht, entsteht die
Linie ZUM ERSTEN MAL -- der Block laeuft, haengt die Zuhoerer an und
springt im selben Atemzug. Das Hochscrollen von vorhin hat nie jemand
bemerkt.

Das ist der haeufigste Fall ueberhaupt: ein stiller Chat, man liest
etwas weiter oben nach, jemand schreibt.

Die Wache steht jetzt beim Aufbau, bei den uebrigen Zuhoerern des
Verlaufs. Ausdruecklich NICHT am `scroll`-Ereignis: Der Sprung
scrollt selbst, und `scroll` unterscheidet nicht, wer gescrollt hat.
Rad, Finger, Taste und Zeiger tut nur ein Mensch.

UND DIE PRUEFUNG HAT SELBST GEMOGELT. Sie schrieb `e.scrollTop = 0`
-- das setzt die Bildlaufposition zu, ohne dass ein Rad gedreht
wurde. Damit haette sie den Fehler auch nach der Behebung noch
gemeldet. Sie dreht jetzt das Rad (`mouse.wheel`) und prueft, dass
sie oben angekommen ist. Dieselbe Lehre wie bei den Fingergeraeten:
`setViewportSize` macht aus einer Maus keinen Finger, und
`scrollTop = 0` macht aus einem Programm keinen Leser.

Nachher: 70 Pruefungen, 0 Fehler (vorher 24/4).
    die Stelle bleibt stehen (0 -> 0)
    der Knopf sagt, wie viel wartet ("1 neue Nachricht")
    er zaehlt mit ("2 neue Nachrichten")
    wer unten steht, wird weiterhin mitgenommen -- ohne Knopf

Alle sieben Chatpruefungen gruen: anhaenge 123/0, aufloesen 126/0,
ausbau 70/0, kanaele 81/0, neu-stelle 63/0, neu 36/0, optik 62/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 11:22:14 +02:00
DogFatherGitandClaude Opus 5 75ede0a8e9 Die Rueckfragen sagten nicht, was passiert -- und eine lief gar nicht ueber den Hausdialog
`pruef-nachfrage` und `pruef-call-kategorien` standen seit dem 28.09.
rot und waren als „nicht angesehen" vermerkt. Nachgemessen sind es
drei echte Befunde und eine Zeitbombe.

=====================================================================
1. FALSCHE FELDNAMEN -- die Erklaerung erschien NIE
=====================================================================
Der Hausdialog kennt `was:` und `ja:`. An vier Stellen in
`reaktion.js` stand `text:` und `knopf:`. Beides wird stillschweigend
ignoriert.

Wer „Sendung beenden?" las, bekam den Titel und zwei Knoepfe -- genau
die Frage, die `confirm()` stellt und derentwegen `nachfrage.js`
ueberhaupt gebaut wurde. Es stuerzt nichts ab, es fehlt nur; so etwas
findet keine Syntaxpruefung und kein Blick auf den Bildschirm, wenn
man den Satz nicht vermisst.

Alle vier tragen jetzt `was` UND `bleibt`. Beim Beenden steht dabei
das, was seit heute frueh dazugekommen ist: dass Titel, Video,
Vorschaubild, Beginn und das zweite Video geleert werden -- wer das
nicht weiss, traegt danach alles noch einmal ein und haelt es fuer
einen Fehler.

=====================================================================
2. `window.frageNachText` GIBT ES NICHT
=====================================================================
Nur EINE Zeile im ganzen Haus nennt es; gesetzt hat es niemand. Die
Abfrage „Wie viele Dogen waren es?" lief damit IMMER ueber den
nackten `prompt()` -- ausgerechnet die, die am haeufigsten vorkommt.

Der Hausdialog kann das laengst besser: `zahl:` ist ein Zahlenfeld
mit Obergrenze und eigener Fehlerzeile.

=====================================================================
3. DER DOPPELTE NOTNAGEL WAR TOTER CODE
=====================================================================
`window.frageNach ? await frageNach(...) : confirm(...)` -- der
Notnagel fuer Browser ohne <dialog> steckt schon IN `nachfrage.js`,
und zwar mit DEMSELBEN Text. Meiner daneben zeigte im Ernstfall
WENIGER und im Normalfall nie etwas.

Im Notizblock stand sogar der nackte `window.confirm()`, ganz ohne
Hausdialog. Er fragt „bist du sicher"; der Hausdialog sagt, was
passiert und was bleibt. Beim endgueltigen Loeschen ist das `bleibt`
der halbe Grund fuer die Rueckfrage: Der Papierkorb ist der Ort, an
dem man etwas wiederfindet.

=====================================================================
4. EINE ZEITBOMBE IN pruef-call-kategorien
=====================================================================
Sie legte eine Wiederholung „in vier Tagen" an -- im Quelltext stand
woertlich „also mit grosser Wahrscheinlichkeit dieser Monat". Heute
ist der 30.; vier Tage spaeter ist Oktober. Der Server verlangt
kuenftig UND im laufenden Monat, und am Monatsende gibt es beides
zusammen nicht.

DIE ANWENDUNG HATTE RECHT. Dieselbe Art wie bei `pruef-kalender` am
29.09. Die nahe Auspraegung wird jetzt GERECHNET (letzter Tag des
Monats, 23:59) statt gehofft -- plus ein benannter dritter Ausgang
fuer die eine Minute im Monat, in der es keinen kuenftigen Termin
mehr in diesem Monat gibt. Die drei anderen Aussagen werden auch dann
geprueft; ein Ausstieg, der gar nichts mehr misst, waere ein stiller
Aussetzer.

Gemessen: pruef-nachfrage 53/0 (war 51/2), pruef-call-kategorien 22/0
(war 21/1), pruef-notizen 79/0, pruef-reaktion 407/0, mess-reaktion
0/0, pruef-css-klassen 37/0, pruef-struktur 44/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 11:10:49 +02:00
DogFatherGitandClaude Opus 5 9125583120 Die geschlossene Reaction-Kachel sah aus wie die Aufgaben-Kachel
`pruef-kachelfarben` stand seit dem 28.09. rot und war als „nicht
angesehen" vermerkt. Nachgemessen ist sie ein echter Befund:

    engstes Paar 0.0191 (Aufgaben <-> Reaction), Grenze 0,02

Beide sind entsaettigtes Blaugrau -- die Aufgaben tragen Silber, die
Reaction im Zustand „zu" ein blaues Grau. Genau darueber ging Filipes
Klage vom 22.09.: „ich seh immer wieder sehr viele die einfach
komplett die gleiche farbe haben."

GESUCHT, NICHT GERATEN. Was auf dem Schirm ankommt, ist der Ton UNTER
Sternenfeld, Vignette und Wolke -- aus den 32 gewoehnlichen Kacheln
laesst sich die Abbildung schaetzen. Sie traf auf einen Punkt genau:

    #8b93a4 -> geschaetzt rgb(64,67,84), gemessen rgb(65,68,83)

Damit vorgesiebt, danach wirklich gerendert und nachgemessen -- eine
Schaetzung allein waere eine Rechnung, die plausibel aussieht.

UND NICHT „AM WEITESTEN WEG". Der groesste Abstand ist ein
Rechenergebnis, keine Gestaltung; er fuehrte zu dunklen Lilatoenen.
Gesucht wurde unter denen, die gleich hell bleiben wie bisher UND
warm sind: Die geschlossene Kachel ist die erste Stufe einer Folge
(zu -> gleich -> live, grau -> bernstein -> rot). Ein warmes Grau
fuehrt dorthin, ein blaues steht quer dazu.

    #b8a8a0   Abstand 0,0481 statt 0,0191, Kontrast 8,7:1

Nachher am echten Bildschirm: 31 Pruefungen, 0 Fehler, engstes Paar
jetzt 0,0277 (Willkommen <-> Notizen). Die Rohfarbe kommt zu 56,5 %
an (vorher 38,9 %).

NEBENBEI: `pruef-zentrale-ring` war ebenfalls als rot vermerkt und ist
inzwischen gruen (14/0) -- der Eintrag im Pruefstand war veraltet.
Eine Bestandsliste altert, auch die eigene.

Gemessen: pruef-kachelfarben 31/0, pruef-zentrale-ring 14/0,
pruef-crew-wand-bild 45/0, pruef-css-klassen 37/0, pruef-struktur
44/0, pruef-haus-seiten 38/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 10:52:46 +02:00
DogFatherGitandClaude Opus 5 0031091bdd Die Eckenwahl zeigt, wo die Kameras stehen -- der letzte offene Punkt der Werbung
Offener Punkt vom 29.09.2026:

  „Die Eckenbilder koennen auf den Kamerakacheln landen. 'Unten
   rechts' liegt im Layout 'Kino' genau dort, wo die Kameras stehen.
   ... aber die Regie warnt dich (noch) nicht vorher."

GEZEIGT, NICHT VERBOTEN. Ein Platz, den die Regie ablehnt, waere
falsch: Vielleicht soll das Logo genau dorthin, weil die Kameras
gleich umziehen oder weil auf „nur Video" geschaltet wird. Wer
entscheidet, braucht die Auskunft -- nicht die Entmuendigung.
Dasselbe Verhaeltnis wie beim Tempo-Knopf, der grau wird statt zu
verschwinden.

NUR IM LAYOUT „KINO". `kamera_ecke` steuert den Stapel nur dort; bei
„gleich" und „Kamera gross" stehen die Kameras woanders, bei „nur
Video" gar nicht. Ein Hinweis, der auch dann erschiene, warnte vor
etwas, das nicht passieren kann -- und so etwas gewoehnt man sich ab.

AM KNOPF UND IM VORLESETEXT. Ein gestrichelter Rahmen in Bernstein
(40 %, gedaempft -- was gewaehlt ist, muss lauter sein als was zu
bedenken ist) UND der Satz „hier stehen gerade die Kameras" in
`title` und `aria-label`. Eine Markierung, die nur eine Farbe ist,
gibt es fuer den nicht, der Farben schlecht unterscheidet oder die
Seite vorlesen laesst.

Gemessen in mess-reaktion, mit Gegenprobe -- eine Markierung, die
immer da ist, ist keine:
    Eckenwahl im Kino (Kameras unten rechts): ur:benannt
    Gegenprobe bei „nur Video": 0 Hinweis(e)
„benannt" prueft ausdruecklich, dass der Satz dransteht und nicht nur
die Farbe.

Gemessen: mess-reaktion 0/0, pruef-reaktion 407/0, pruef-css-klassen
37/0, pruef-struktur 44/0, pruef-tippziele 13/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 10:43:42 +02:00
DogFatherGitandClaude Opus 5 6a42ce3432 Der Vorhang geht von selbst wieder auf -- ein offener Punkt weniger
Offener Punkt vom 29.09.2026, woertlich aus der Projektnotiz:

  „Nimmst du jemanden aus der Sendung und machst es gleich wieder
   rueckgaengig, steht bei ihm weiter 'Du bist aus dieser Sendung'.
   ... Das sauber zu loesen hiesse, ihm waehrend der Sperre eine
   langsame Nachfrage zu lassen -- das ist ein eigener Umbau."

Der Umbau ist seit gestern da: Der geschlossene Saal fragt alle 15
Sekunden nach. Dasselbe Muster passt hier -- nur die FRAGE muss eine
andere sein.

NUR DIE EINE FRAGE, NICHT DER GANZE STAND. `rausgenommen()` schliesst
den Ereignisstrom mit Absicht: Wer draussen ist, soll die Sendung
nicht weiterverfolgen. `/api/reaktion` braechte Video, Titel und
Stand mit -- genau das, was ihr genommen werden soll. `POST /dabei`
beantwortet dagegen nur „bin ich wieder dabei?" und verraet nichts:

    403 aus_der_sendung / treff_massnahme  -> weiter warten
    409 saal_zu                            -> weiter warten
    200                                    -> neu laden

NEU GELADEN WIRD NUR BEI 200, und das ist der Unterschied zwischen
einer Loesung und einer Schleife. Schliesst der Saal, waehrend jemand
draussen ist, kaeme 409; wuerde darauf neu geladen, stuende die
Massnahme danach immer noch, der Vorhang kaeme wieder, und die Seite
laedt sich im Kreis.

ZWANZIG SEKUNDEN. Eine Massnahme ist kein Anruf -- wer
zurueckgeholt wird, ist eine halbe Minute spaeter wieder da.

UND WARUM NEU LADEN STATT WEITERZEICHNEN: `rausgenommen()` hat die
Verbindungen abgebaut, den Strom geschlossen und den Vorhang
angehaengt. Das im Betrieb wieder aufzubauen waere viel Zustand --
und genau das tut ein Neuladen in einem Schritt. Bisher haben wir
den Menschen darum GEBETEN.

DIE PRUEFUNG FEHLTE, und das ist der eigentliche Punkt: Der Mangel
stand seit dem 29.09. in der Notiz und hatte keine. So bleibt ein
bekannter Mangel fuer immer bekannt -- niemand merkt, wenn er behoben
ist, und niemand merkt, wenn er zurueckkommt. Jetzt wartet
mess-reaktion nach der zurueckgenommenen Massnahme darauf, dass der
Vorhang von selbst verschwindet. Gegenprobe gemacht: Nachfrage
abgeschaltet -> „Der Vorhang hebt sich von selbst: NEIN", Rueckgabe 1.

Gemessen: mess-reaktion 0/0, pruef-reaktion 407/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 10:37:05 +02:00
DogFatherGitandClaude Opus 5 0fbd3f45b3 Die Chatkiste steht immer, Beenden raeumt auf -- und eine verspaetete Antwort ueberschreibt nichts Neueres mehr
Filipe, 30.09.2026: „wenn eine sendung beendet wurde soll alles
automatisch verschwinden. also von daten die da stehen von dem video."
Und: „mach dass ich die chat kiste immer sehe bitte und nicht erst
wenn das video läuft."

=====================================================================
1. BEENDET HEISST LEER
=====================================================================
Beim Beenden verschwinden Titel, YouTube-Adresse, Videotitel,
Vorschaubild, Beginn und das zweite Video samt seiner Stelle. Vorher
blieb alles stehen; beim naechsten Aufmachen stand dort der Titel der
letzten Sendung und ein Beginn, der in der Vergangenheit liegt.

ERST DER VERLAUF, DANN DAS LEEREN -- weg vom Schreibtisch heisst
nicht weg aus der Welt. Geprueft: Nach dem Beenden steht die Sendung
weiter in `reaktion_verlauf`, samt Video.

EINE FELDLISTE, NICHT ZWEI. Die Aufzaehlung stand in der
Zuruecksetzen-Route; jetzt brauchen sie zwei Wege. `SENDUNGS_FELDER`
und `PULT_EINSTELLUNGEN` stehen einmal oben. Zwei Abschriften waeren
die, die beim naechsten Spaltenzuwachs auseinanderlaufen -- genau so
sind am 11.09. drei Spalten mit Inhalt verlorengegangen.

Einstellungen (Bildaufteilung, Kameragroesse, Chatmodus) und die
Warteschlange bleiben -- die raeumt weiter nur „Alles zuruecksetzen"
ab. Wer nur vorbereitet und dann zumacht, behaelt seine Eingaben; das
ist eine Entscheidung und steht als Pruefung fest.

DAS FELD „BEGINN" WURDE NIE GELEERT, nur gefuellt:
`if (lage.beginnt_am && document.activeElement !== …)` -- zwei Fragen
in einer Bedingung, und die zweite beantwortete die erste
stillschweigend mit nein. Das betraf auch den vorhandenen
Zuruecksetzen-Knopf.

=====================================================================
2. DIE CHATKISTE STEHT IMMER
=====================================================================
Sie lag in `#teil-live` und ging mit ihm weg. Im Wartebereich stand
dabei woertlich „Der Chat ist schon offen" -- der Satz stimmte sogar,
der Server laesst dort schreiben (201, geprueft); zu sehen war der
Chat trotzdem nicht.

Die drei Haeute und die Schiene liegen jetzt in einem gemeinsamen
`.raum`: links wechseln die Haeute, rechts steht der Chat. Das Raster
wandert mit nach oben statt sich zu verdoppeln -- zwei
`grid-template-columns` fuer dieselbe Frage waren am 28.09. der
Grund, warum die Regieleiste null Pixel bekam.

Wer nicht schreiben darf, liest den Grund im Feld („Der Saal ist zu").

DER UMBAU HAT DREI DINGE VERSCHOBEN, und die Messung hat sie sofort
gefunden: Kino 0 px hoch, Spendenkarte bei x=1458 ausserhalb des
Bildes, „Kamera aus"-Schild kam nicht an. Eine Ursache: Zwei Regeln
(`grid-row: 2` und `grid-area: kino`) zielten auf die drei Haeute,
weil die frueher unmittelbar im Saal lagen. Gefunden hat das nicht
das Nachdenken, sondern eine Messung der ganzen Kette --
`teil-live 0x0 @1440,742` lag NEBEN dem Raum.

=====================================================================
3. „DER SAAL IST ZU" ERREICHTE NIEMANDEN, DER DARIN SASS
=====================================================================
`stand: "zu"` loescht `reaktion_dabei`, und `melden()` suchte seine
Empfaenger erst danach -- in genau dieser geleerten Liste. Die Seiten
der Zuschauer blieben auf „live" stehen.

`melden(art, daten, wer)` nimmt jetzt eine Empfaengerliste; die
Stand-Route bestimmt sie VOR jeder Aenderung.

UND EINE ZUGESPERRTE SEITE VERSTUMMTE FUER IMMER. War der Saal zu,
hielt `anschliessen()` jeden Takt an -- und Rundrufe bekam sie auch
keine, weil sie in keiner Liste mehr stand. Machte der Host wieder
auf, passierte bei allen mit offenem Reiter NICHTS. Nicht in dreissig
Sekunden: nie, bis jemand von Hand neu lud. Gemessen: Server sagt
„vorbereitung", die Seite zeigt „zu", auch nach 40 Sekunden.
Jetzt fragt eine geschlossene Seite alle 15 Sekunden nach -- der
ruhigste Zustand des Hauses, dort kostet das nichts.

=====================================================================
4. WER ZULETZT ANTWORTET, HAT NICHT RECHT
=====================================================================
Eine Abfrage ist Sekundenbruchteile unterwegs. Kommt in dieser Zeit
ein Rundruf an, ist SEIN Stand der neuere -- und trotzdem hat die
verspaetete Antwort ihn ueberschrieben.

Gemessen: Die Regie schaltet die Werbung auf Wechsel, der Rundruf
zeichnet ihn, und einen Augenblick spaeter steht wieder Laufband.
Eine feste Wartezeit in der Messung hatte das zugedeckt; es fiel
erst auf, als ich sie durch eine echte Bedingung ersetzte.

Drei Runden Raten lagen daneben. Gefunden hat es eine Mitschrift der
Aufrufkette:

    wechsel:2  @ EventSource
    laufband:2 @ zeichnen < standHolen < signalEmpfangen

Eine Folgenummer zaehlt jeden angekommenen Rundruf. Jede Abfrage, die
die Seite VON SICH AUS macht -- nach dem Verbindungsaufbau, im
geschlossenen Saal, bei jedem Verbindungssignal, nach einer
abgelehnten Anwesenheitsmeldung, und der Anwesenheitstakt selbst --
verwirft ihr Ergebnis, wenn inzwischen etwas Neueres da war.

Abfragen nach einer EIGENEN Handlung bleiben hart: Sie bringen Dinge
mit, die kein Rundruf traegt (die Verwaltungslisten der Regie). Die
Unterscheidung steht am Aufruf, nicht in einer Bedingung im Inneren.

=====================================================================
5. UND DIE MESSUNGEN WARTEN NICHT MEHR AUF DIE UHR
=====================================================================
Feste Wartezeiten sind dieselbe Falle wie feste Schwellen: Sie
stimmen, bis daneben etwas langsamer wird, und melden dann einen
Fehler, den es nicht gibt. Zweimal ist mir das in einer Stunde
passiert -- einmal beim Band, einmal bei den Ecken. Der Werbeblock
wartet jetzt fuenfmal auf das Ergebnis, der Gleichlauf viermal; laeuft
eine Frist ab, ist es ein echter Befund.

Die erste Fassung der Gleichlauf-Gegenprobe war selbst falsch -- sie
hielt das Selbstheilen des Systems fuer einen Fehler.

Neu in mess-reaktion: „Die Chatkiste in jedem Zustand" (alle drei,
mit Breite und Sperrgrund) und „Beendet heisst leer (im Pult)" -- dort
gemessen, wo Filipe hinsieht, nicht in der Datenbank.
Neu in pruef-reaktion (+14): das Leeren, die Gegenprobe „vorher war
etwas drin", der Verlauf bleibt, und die Entscheidung „wer nur
vorbereitet hat, behaelt seine Eingaben".

Gemessen: mess-reaktion dreimal hintereinander 0/0, pruef-reaktion
407/0, pruef-css-klassen 37/0, pruef-struktur 44/0, pruef-tippziele
13/0, pruef-haus-seiten 38/0, pruef-haus-trennung 100/0, pruef-buehne
38/0, pruef-push-ziel 38/0, mess-buehne 0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 02:36:13 +02:00
DogFatherGitandClaude Opus 5 2c3b90d75c Benachrichtigungen: die Reaction laedt ein, jedes Haus bekommt sein Gesicht -- und die Videos haengen nicht mehr
Filipe, 29.09.2026: „ich will dass du die benarichtigungen
perfektionierst. dogfather und alle anderen sollen die
benachrichtigungen perfekt von dieser seite hier bekommen."
Und dazu, mit einer Bildschirmaufnahme: „wieso haengen die videos
immer."

=====================================================================
1. WARUM DIE VIDEOS HAENGEN -- zwei Zeilen, eine Rueckkopplung
=====================================================================

Die Aufnahme zeigt den YouTube-Zaehler bei 0:13 von 31:34, vier
Bilder lang unbewegt, in der Mitte der Ladering.

  a) `hostMelden()` rechnete `laeuft = getPlayerState() === 1`.
     Zustand 3 heisst PUFFERN -- „ich will spielen, mir fehlen
     gerade Daten". Der Host meldete in diesem Moment „laeuft
     nicht", und zwar sofort, weil `onStateChange` bei jedem
     Zustandswechsel meldet.

  b) `empfaenger()` fuegt den Host ausdruecklich hinzu, und
     `folgen(d)` lief im Ereignisstrom fuer alle -- auch fuer ihn.
     Seine eigene Meldung kam zurueck und traf dort auf
         if (!stand.laeuft && getPlayerState() === 1) pauseVideo();

  Der Host puffert eine halbe Sekunde, laeuft weiter -- und wird vom
  Echo seines eigenen Pufferers angehalten. Bei einem 31-Minuten-Video
  passiert das in den ersten Sekunden zuverlaessig.

  Und alle Zuschauer bekamen bei JEDEM Pufferer des Hosts ein
  Pause-Play-Paar. Das ist das Ruckeln, das man fuer die eigene
  Leitung haelt.

GEMESSEN, NICHT HERGELEITET (mess-reaktion):
    vorher   Host=laeuft -> Pufferer gemeldet -> Host=pause
    nachher  Host=laeuft -> Pufferer gemeldet -> Host=laeuft

Drei neue Messungen, jede mit Gegenprobe:
  · ein gemeldeter Pufferer haelt den Host nicht an
  · ein ECHTES Anhalten (Knopf gedrueckt) haelt alle an -- sonst
    waere das Erste mit kaputtem Gleichlauf bezahlt
  · beim Puffern meldet der Server `laeuft=true`; ist der Pufferer
    nicht herzustellen, sagt die Messung das (dritter Ausgang)
Beide Behebungen einzeln zurueckgenommen: beide Male rot.

Die erste Fassung der Gegenprobe war selbst falsch -- sie hielt das
Selbstheilen des Systems (der Host meldet alle fuenf Sekunden die
Wahrheit) fuer einen Fehler. Deshalb drueckt sie jetzt den Knopf,
statt eine Meldung zu faelschen.

=====================================================================
2. DIE REACTION LAEDT EIN
=====================================================================

Nachgemessen war `workspace-reaktion.js` STUMM: kein einziges
`benachrichtige`. Beim Einschalten lief `melden("reaktion", ...)`
ueber den Ereignisstrom -- also nur an Leute, die die Seite ohnehin
offen haben. Das Kino machte auf, und die Einladung verliess das Haus
nie. Dasselbe Muster wie bei den Bewerbungen am 23.09.

Neue Art `reaktion_live`, eigene neben `dogfather_live`: Das eine ist
sein Stream auf TikTok, das andere das Kino hier im Haus.

Eingeladen wird, wer ein Geraet hat und NICHT der Agentur gehoert
(`AGENTUR_ROLLEN` -- keine neue Liste). Nicht der, der eingeschaltet
hat. Und nicht zweimal: Eine Bremse von zwei Stunden faengt den
Neustart ab, denn das Merkmal haengt an `gestartet_am` und das wird
bei jedem Wechsel nach live neu gesetzt.

Geprueft Ende zu Ende in pruef-reaktion (+10): Sendung geht auf
Sendung, danach stehen genau fuenf Einladungen in `push_verschickt` --
rechte Hand, linke Hand, Modi, zweimal Community. Nicht der Host,
nicht die Creatorin. Einladung abgeschaltet: sechs Fehlschlaege.

=====================================================================
3. DARF DAS NACHTS KOMMEN? -- drei Antworten statt zwei
=====================================================================

Hier stand `art === "test" || art === "anruf"`, 230 Zeilen von der
Artenliste entfernt. Am 18.09. hat das eine Nacht lang alle Anrufe
verschluckt; behoben wurde damals dieser eine Fall.

GEMESSEN AM LIVE-BESTAND: `dogfather_live` ging an allen sieben
Abenden vom 22. bis 28.09. zwischen 20:28 und 21:06 raus -- jedes Mal
knapp vor der Sperre um 22 Uhr. Geht Filipe einmal um 22:05 live,
bekommt niemand etwas, und niemand erfaehrt warum.

`ruhe` steht jetzt an der ART:
  "immer" (Vorgabe)  22-7 gesperrt   -- Erinnerungen
  "spaet"            nur 1-7         -- etwas laeuft GERADE
  "nie"              nie             -- ein Mensch wartet am Hoerer

=====================================================================
4. JEDES HAUS BEKOMMT SEIN GESICHT
=====================================================================

Im Service Worker stand fest `workspace-192.png`. Von acht Menschen
mit angemeldetem Geraet gehoeren fuenf ins Crew-Haus -- die sahen auf
jeder Benachrichtigung das Symbol des Hauses, in dem sie nicht
arbeiten.

Entschieden wird es auf dem SERVER: Im Browser stuende sonst die
verborgene Crew-Adresse in einer Datei ohne Anmeldung (der Befund vom
21.09. bei crew-haus.css) -- und es waere eine zweite Fassung der
Hausteilung. Zweistufig, beide Stufen gibt es schon: die Zielseite,
wenn sie in genau ein Haus gehoert (GEHOERT_ZU_ADRESSE), sonst
`AGENTUR_ROLLEN`.

=====================================================================
5. DAS ABZEICHEN WAR EIN KLOTZ
=====================================================================

`badge` ist das winzige Zeichen in der Statusleiste; Android benutzt
davon NUR den Alphakanal. Dort stand dasselbe `workspace-192.png` --
ein vollflaechiges Quadrat ohne Transparenz, also ein ausgefuellter
Klotz. Es stuerzt nichts ab, deshalb faellt es niemandem auf.

`assets/img/abzeichen-96.png`: der gefuellte Umriss des Huskys, weiss
auf durchsichtig, 3,5 KB. Drei Fassungen gebaut und bei ECHTER Groesse
(24 px) verglichen -- Strichbild zerfaellt, Flaeche traegt.

`server/helfer-png-alpha.mjs` liest den Alphakanal wirklich (PNG
auspacken, Zeilenfilter zuruecknehmen). Eine Pruefung auf „die Datei
gibt es" haette den Klotz nie gefunden -- die Datei gab es ja. Die
Gegenprobe ist der alte Zustand selbst: dieselbe Rechnung meldet auf
`workspace-192.png` „kein Alphakanal, Deckung 100 %".

Das Abzeichen liegt NICHT bei den App-Symbolen -- `pruef-struktur`
verlangt dort zu jedem Namen den vollen Satz und hielt es fuer eine
neue App. Der Waechter hat recht: Ein Abzeichen ist kein App-Symbol.

=====================================================================
Gemessen: mess-reaktion 0, pruef-reaktion 393/0 (+10),
pruef-push-ziel 38/0 (+27), pruef-push 24/0, pruef-push-weg 20/0,
pruef-glocke 36/0, pruef-struktur 44/0, pruef-haus-trennung 100/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-29 23:48:46 +02:00
DogFatherGitandClaude Opus 5 a43bc565ec Werbeeinblendung fuer die Reaction: Laufband, Wechsel und zwei Bilder in sechs Ecken
Filipe: „ich will dass du auch perfektionierst dass ich einen banner
durchlaufen kann, oder erscheinen lassen kann mit werbung drauf ...
und ich will auch das dogfather logo oben rechts links unten rechts
links genau wie oben unten mittig, so dass ich es wegmachen und
hinzufuegen kann."

DAS BAND
Zwei Arten: „Laufband" zieht die Botschaften von rechts nach links,
„Wechsel" blendet sie nacheinander ein. Ein Rabattcode gehoert in den
Wechsel -- wer „DOGI10" lesen will, waehrend es wandert, hat es
gesehen und nicht behalten. Die Dauer ist einstellbar (8-40 s).

Das Band ist Glas, kein Balken: ein Verlauf, unten dicht genug, dass
jede Schrift traegt, oben offen. Man sieht das Video weiter.

Das Laufband traegt die Folge ZWEIMAL. Wandert es um 50 % seiner
Breite, steht die zweite dort, wo die erste war, und der Sprung
zurueck ist unsichtbar. Ohne sie entstuende am Ende jedes Durchlaufs
eine leere Flaeche -- das sieht aus, als sei die Einblendung
abgestuerzt.

Wer weniger Bewegung eingestellt hat, bekommt den Wechsel statt des
Laufbands -- nicht „aus". Die Werbung soll auch dann wirken.

DER RABATTCODE
Ein Wort in Grossbuchstaben mit einer Ziffer darin bekommt eine
eigene Flaeche in Bernstein: „DOGI10" ja, „VANVAN" nicht. Er ist der
einzige Teil der Botschaft, den jemand ABSCHREIBEN soll.

Der Text wird NIE als HTML eingesetzt -- die Kennzeichnung baut echte
Elemente. Sonst waere ein Eingabefeld im Regiepult ein Weg, fremdes
Markup in den Stream zu bringen.

DIE ZWEI BILDER
Der Husky und der Haekelhase aus der Zusammenarbeit mit VanVan,
jeweils an einem von sechs Plaetzen: oben und unten, je links,
mittig, rechts -- oder aus. Links und rechts mittig gibt es mit
Absicht nicht: dort liegen bei jedem Videodienst die Bedienelemente.

Zwei Bilder auf denselben Platz werden abgelehnt (400 ecke_belegt) --
sie laegen uebereinander, und man saehe von beiden nichts.

Wer unten steht, weicht dem Band aus, und die Spendentafel rueckt
hoch. Beides im Stilblatt ueber `:has`, nicht im Programm: Das Band
kennt die Tafel nicht und die Tafel kennt das Band nicht.

Der Husky ist schwarz und laege auf dunklem Videobild als Silhouette
in der Nacht. Zwei weiche helle Schatten legen eine Kontur darum --
dieselbe Loesung, die jeder Sender fuer sein Wasserzeichen nimmt.

IM STREAM, NICHT NUR IM SAAL
Beides laeuft in der Buehnenquelle mit, die OBS abfilmt, mit
groesserer Schrift (24 statt 18 px) -- ein Stream wird auf einem
Handy gesehen, oft in einem Viertel des Bildes. Gemessen: die OFFENE
Quelle zieht eine Umschaltung nach, ohne dass die Szene neu geladen
werden muss.

EINE QUELLE, NICHT DREI
`werbungStand()` steht in `reaktion-tabellen.js` und wird von Saal,
Regie und Buehne aufgerufen. Erst standen dort drei Abschriften
derselben Abfrage; beim Entfernen der Datenbank-Kennung habe ich eine
davon geaendert, und die anderen lieferten sie weiter.

WAS DIE PRUEFUNGEN DABEI GEFUNDEN HABEN
- pruef-buehne: Die Botschaften trugen ihre Datenbank-Kennung in die
  OBS-Auskunft, die nur mit einem Schluessel geschuetzt ist. Die
  Feldliste geht jetzt zwei Ebenen tief -- eine abschliessende Liste,
  die nur die oberste kennt, laesst sich umgehen, indem man ein Feld
  in ein vorhandenes Objekt legt.
- pruef-reaktion: Acht Fehlerwoerter ohne deutschen Satz. Nachgetragen
  im Hausstil: was nicht geht UND was stattdessen.
- pruef-struktur: Die Suche nach totem CSS las `buehne.html` und
  `tafel.html` nicht -- eine Ausnahme, die fuer eine ganz andere
  Frage gemacht war (Startbildschirm-Symbol). Sie haette verlangt,
  `.obs-buehne` zu loeschen, also die Regel, die den Stream traegt.
- pruef-tippziele: Erkannte als Anhebung nur `min-height`/`min-width`.
  Ein `height: 44px` im Fingerblock hebt genauso -- Fehlalarm, und
  ein Fehlalarm an einer Pruefung, die nach jeder Aenderung laeuft,
  wird weggeklickt. Zwei Gegenproben dazu.
- mess-reaktion: Die Regieleiste am Handy wurde gegen die feste Zahl
  SIEBEN geprueft und meldete „zeigt nur 8 von 7". Sie zaehlt jetzt
  selbst.
- mess-buehne: Die Konsolenmeldung zeigte dauerhaft vier
  Fehlschlaege, alle von den Pruefungen selbst bestellt. Jetzt eng
  gefiltert, benannt, mit Gegenprobe -- und ein UNERWARTETER
  Fehlschlag in der Quelle, die in den Stream geht, faellt ab sofort
  durch.

Gemessen: mess-reaktion 0, mess-buehne 0, pruef-reaktion 383/0,
pruef-buehne 38/0, pruef-tippziele 13/0, pruef-struktur 44/0,
pruef-css-klassen 0, pruef-haus-trennung 100/0, pruef-haus-seiten 38/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-29 17:16:26 +02:00
DogFatherGit 077925ab25 Dreizehn rote Pruefungen, eine Ursache: openssl steht nicht im PATH
DER BEFUND

Im naechtlichen Lauf standen dreizehn Pruefungen mit derselben Zeile
rot:

    [uncaughtException] Error: spawnSync openssl ENOENT

Kein Programmfehler. Die Pruefungen brauchen einen https-Vorbau (der
Sitzungskeks des Hauses ist `secure` und kommt ueber http nicht an),
und dafuer erzeugen sie ein Wegwerf-Zertifikat mit openssl.

GEMESSEN, NICHT VERMUTET

  openssl liegt hier:   C:\Program Files\Git\mingw64\bin\openssl.exe
                        C:\Program Files\Git\usr\bin\openssl.exe
  im System-PATH steht: C:\Program Files\Git\cmd   (nur git.exe)
  im Benutzer-PATH:     nichts mit Git

Wer aus Git Bash startet, erbt die mingw-Pfade und merkt nie etwas.
Die Aufgabenplanung startet `node.exe` DIREKT, ohne Shell -- und
bekommt sie nicht. Bei mir gruen, nachts rot, und der Grund steht
nicht im Code.

Das Schlimmste daran ist nicht der Ausfall: Dreizehn dauerhaft rote
Zeilen in einer Notiz, die Filipe morgens liest, gewoehnen einem das
Hinsehen ab -- und decken dabei die echten Befunde zu.

DIE REPARATUR

`server/helfer-openssl.mjs` sucht openssl erst im PATH (ohne `where`
oder `which` -- beides sind selbst Programme und koennen genauso
fehlen), danach an den Orten, an denen es auf einem Windows-Rechner
mit Git wirklich liegt.

Dazu `zertifikatBauen(schluessel, zertifikat, host)`. Die acht
Aufrufformen im Haus waren identisch bis auf die Variablennamen
(schl/zert, schluesselDatei/zertDatei, zKey/zCrt, sk/zt, key/crt) --
eine Stelle traegt alle neunundzwanzig. Zwei Tage zuvor war eine
davon um ein `-addext` aermer als die anderen; gemerkt hat es
niemand, weil der Browser den fehlenden Alternativnamen erst bei
einer Weiterleitung anmahnt. Eine Stelle kann nicht von sich selbst
abweichen.

KEIN EINTRAG IN DEN SYSTEM-PATH. `mingw64\bin` enthaelt rund hundert
Programme mit Unix-Namen (`find`, `sort`, `link`), die gleichnamige
Windows-Befehle verdecken. Das fuer eine Pruefung zu aendern haette
an ganz anderen Stellen Fehler verursacht, die niemand hierher
zurueckverfolgt.

GEGENPROBE IN BEIDE RICHTUNGEN, mit dem PATH des Nachtlaufs:

  vorher (direkter Aufruf):  ABSTURZ: spawnSync openssl ENOENT
  nachher (ueber den Helfer): Zertifikat gebaut, 1236 Bytes

Und eine echte Pruefung unter denselben Bedingungen:

  PATH ohne mingw64 -> pruef-chat-neu-stelle
  63 Pruefungen, 0 Fehler, 0 Abstuerze

Genau diese Datei stand im Nachtlauf mit ENOENT rot.

EINE WACHE DAGEGEN

pruef-struktur prueft ab jetzt, dass niemand openssl wieder direkt
ruft -- der naechste merkt es dort und nicht erst in einem
Nachtlauf, den niemand liest. Drei Gegenproben.

Beim ersten Anlauf schlug sie auf ihre EIGENEN Probetexte an: Sie
liest alle Serverdateien, und dazu gehoert sie selbst. Die Texte
werden jetzt zusammengesetzt. Derselbe Selbsttreffer ist mir heute
schon zweimal passiert.

DER DRITTE AUSGANG BLEIBT, WO ER HINGEHOERT

`helfer-kachel-echtfarbe.mjs` faengt den Fehler weiterhin ab und
meldet `moeglich: false` mit Grund, statt abzubrechen. Eine
Sicherung abzuschaffen, weil ihr Anlass gerade behoben ist, ist der
Anfang des naechsten stillen Fehlschlags.

NEBENBEI: pruef-community-sicht

Sie war rot mit "ZU VIEL: reaktion.html" -- mein eigener Rueckstand
vom 28.09. Die Reaction steht als Kachel im Community-Bereich; die
Liste war nicht nachgezogen. Jetzt 10 / 0.

Die Liste bleibt bewusst von Hand gepflegt: Sie ist eine ABSICHT,
keine Ableitung. Aus rechte.js gelesen verglichen sich zwei Kopien
derselben Quelle -- immer gruen, nie ein Beweis.

GEPRUEFT
  pruef-struktur         ALLES IN ORDNUNG (mit der neuen Wache)
  pruef-community-sicht  10 / 0
  pruef-chat-neu-stelle  63 / 0  (mit dem PATH des Nachtlaufs)
  pruef-notizen, -teamlage-karten, -werdegang: EXIT 0, keine Abstuerze
  mess-quer              EXIT 0
  29 Dateien: node --check auf allen, kein direkter Aufruf mehr
2026-09-29 16:14:13 +02:00
DogFatherGit b846693de5 Die letzten fuenf blinden Messungen bekommen einen Finger
Die Grundlinie der Fingerwache sinkt von 6 auf 1.

DIE SCHWEREN FAELLE

pruef-notizen, pruef-teamlage-karten, pruef-terminregel,
pruef-werdegang, pruef-befinden.

Bei diesen fuenf stand mitten im Ablauf ein
`setViewportSize({ width: 390 })`. Das aendert nur die Groesse --
`hasTouch` gehoert zum KONTEXT und ist beim Anlegen entschieden.
Nachtragen geht nicht; es braucht ein zweites Fenster.

DAS MUSTER, DAS FUER ALLE FUENF GETRAGEN HAT

  const handyKontext = await browser.newContext({
    viewport: { width: 390, height: 844 }, hasTouch: true, isMobile: true });
  await handyKontext.addCookies(await kontext.cookies());
  const handy = await handyKontext.newPage();
  await handy.goto(seite.url(), { waitUntil: "networkidle" });

Drei Entscheidungen darin:

  - Die Anmeldung wandert als Keks mit, statt sie zu wiederholen.
    Eine zweite Anmeldung waere eine zweite Stelle, die veralten
    kann.
  - Die Adresse kommt von `seite.url()`. Sie ein zweites Mal
    hinzuschreiben waere eine zweite Wahrheit darueber, welche
    Seite gemessen wird.
  - Das fruehere Zuruecksetzen auf 1280 px faellt weg. Die breite
    Seite war nie schmal -- es gibt nichts zurueckzustellen.

Bei pruef-terminregel liessen sich die vier Schritte, die den
schwebenden Hinweis erzeugen, nicht uebernehmen: Sie werden im
neuen Kontext nachgefahren (oeffnen, "Neu", Datum eintragen).

ALLE FUENF DANACH GRUEN

  pruef-notizen         EXIT 0
  pruef-teamlage-karten EXIT 0  (39 geprueft)
  pruef-terminregel     EXIT 0  (35 Pruefungen)
  pruef-werdegang       EXIT 0
  pruef-befinden        EXIT 0

Diese Seiten halten die Fingerregeln also schon ein. Es hatte nur
nie jemand nachgesehen.

EINES BLEIBT: pruef-grosscheck

Die Datei zu aendern waere ein Zweizeiler. Sie zu PRUEFEN hiesse,
206 Seiten ueber vier Rollen und zwei Bildschirmgroessen laufen zu
lassen -- das braucht Filipes Zusage. Eine Aenderung, die ich nicht
pruefen darf, liefere ich nicht aus. Die Grundlinie steht deshalb
auf 1 und nicht auf 0.

GEPRUEFT
  pruef-fingermass  3 / 0, neun Gegenproben, Grundlinie 1
2026-09-29 16:00:57 +02:00
DogFatherGit d5e873d597 Zehn Messungen bekommen einen Finger -- und eine Zeitbombe faellt auf
Die Grundlinie der Fingerwache sinkt von 17 auf 6.

WAS UMGESTELLT WURDE

pruef-alter, pruef-countdown, pruef-gespraech, pruef-treffchat,
pruef-modi-verborgen, pruef-nachwuchs, pruef-personen-liste,
pruef-serien, pruef-team, pruef-kalender.

Alle zehn legen ein eigenes Handyfenster an; dort fehlte nur
`hasTouch`. Ohne ihn meldet der Browser einen feinen Zeiger, und
keine Regel aus `@media (pointer: coarse)` greift -- dort stehen die
44-Pixel-Beruehrziele.

JEDE EINZELN GELAUFEN, ALLE GRUEN

Diese Seiten halten die Fingerregeln also schon ein. Es hatte nur
nie jemand nachgesehen.

Vorher geprueft, wie gross jede ist: 1 bis 7 Seitenaufrufe, 1 bis 5
Fenster -- echte Einzelpruefungen. (Zum Vergleich: die Pruefung von
gestern Nacht hatte 244 Seitenaufrufe, und genau das hatte ich
vorher nicht nachgesehen.)

DIE ZEITBOMBE IN pruef-kalender

Beim Umstellen fiel sie rot aus -- zweimal, an einer Stelle, die mit
dem Finger nichts zu tun hat:

  FEHL im naechsten Monat ist kein Tag mehr "heute"

Gegen den ausgelieferten Stand gemessen: identisch rot. Nicht
meine Aenderung, sondern der Kalender.

Heute ist der 29. September. Das Oktober-Raster zeigt in seiner
ersten Zeile die letzten Septembertage mit, und einer davon IST
heute. Die Anwendung macht dabei alles richtig: `kalender.js` setzt
die Marke an `tag === daten.heute`, also am DATUM und nicht an der
Rasterposition. Genau das sollte die Pruefung beweisen -- und schlug
an, weil die Anwendung es tat.

Geschrieben wurde sie an einem Tag in der Monatsmitte. Von da an war
sie richtig, bis der Kalender sie einholte. Dasselbe Muster wie
`gate-oeffnung.mjs` am 06.09.2026 im Shop: Ein Test, der die
Wanduhr als Annahme benutzt, misst irgendwann das Gegenteil.

Gefragt wird jetzt, was gemeint war: Ein EIGENER Tag des
Folgemonats darf nie „heute" sein; ein mitgezeigter Randtag
(`data-fremd="ja"`) dagegen sehr wohl, und zwar genau dann, wenn er
es ist. Das gilt an jedem Tag des Jahres. Die Meldung nennt jetzt
beide Zahlen:

  ok  im naechsten Monat ist kein EIGENER Tag mehr "heute"
      (0 eigene, 1 mitgezeigte Randtage)

WAS UEBRIG BLEIBT: SECHS SCHWERE FAELLE

pruef-befinden, pruef-notizen, pruef-teamlage-karten,
pruef-terminregel, pruef-werdegang, pruef-grosscheck.

Dort schaltet `setViewportSize` mitten im Ablauf auf Handyformat um
-- und der Finger laesst sich nachtraeglich nicht setzen, er gehoert
zum Kontext. Jeder Fall braucht einen eigenen Kontext samt
Anmeldung: Umbau, nicht Einzeiler.

`pruef-grosscheck` bleibt unangetastet, bis Filipe einen Lauf
freigibt. Eine Aenderung, die ich nicht pruefen darf, liefere ich
nicht aus.

GEPRUEFT
  alle zehn einzeln: EXIT 0, keine FEHL-Zeile
  pruef-kalender     EXIT 0 (vorher 2 Fehlschlaege, auch auf HEAD)
  pruef-fingermass   3 / 0, Grundlinie 6
2026-09-29 14:51:52 +02:00
DogFatherGit 59b2a6d0e5 Was nur fuer Vorleseprogramme dasteht, ist kein zerquetschter Text
DER BEFUND WAR EIN FEHLALARM

pruef-handy-teamdogi meldete auf notizen.html, nur bei 412 px:

  Text auf fast nichts gedrueckt -- a.zurueck „Team Dogi…" 0 statt 82px

Nachgemessen ist das Absicht. start.css setzt auf schmalen Schirmen
`.kopfleiste .marke__text` auf 1x1 Pixel mit `clip-path: inset(50%)`
-- das uebliche Muster fuer "bleibt fuer Vorleseprogramme,
verschwindet fuer das Auge". Der Grund steht daneben: Der Text
steht auf jeder Seite zwei Zeilen tiefer noch einmal als
Ueberschrift.

WARUM DIE ERKENNUNG DANEBENGRIFF

`nurVorlesen()` gab es laengst -- sie sah aber nur das Element
SELBST an. Der Link darin ist 0 Pixel breit, aber eine Zeile hoch,
und traegt selbst kein `clip-path`. Er fiel damit durch beide
Bedingungen. Die Funktion steigt jetzt die Kette der Vorfahren hoch.

DAS MACHT DIE REGEL SCHAERFER, NICHT LAXER

Ausgenommen wird nur, was in einem nachweislich abgeklemmten Kasten
sitzt. Der echte Fund vom 20.09.2026 -- ein Gespraechsname, der in
einer normalen Kopfzeile auf null gequetscht wurde -- hat keinen
solchen Vorfahren und wird weiter gemeldet.

Und das ist nicht behauptet, sondern gemessen: Die Gegenprobe
bekommt ein PAAR statt eines Falls. Derselbe zerquetschte Text
einmal in einem abgeklemmten Kasten (darf nicht gemeldet werden)
und einmal ohne (muss gemeldet werden). Eine Regel, die enger
misst, kann zu eng sein; dann faellt echter Schaden durch und der
Lauf bleibt gruen. Sechs Gegenproben statt vier.

GEMESSEN

  244 Seitenaufrufe, 123409 Elemente, 5393 Bedienelemente
  0 Befunde   (vorher: 4-5, darunter die 40-Pixel-Knoepfe)
  alle sechs Gegenproben greifen, zweimal hintereinander gleich

  span#gp-laut  „Dieser Name ist wirklich…" 0 statt 320px  -> gemeldet
  span#gp-leise                                            -> nicht

OFFEN GEBLIEBEN

Die Ueberstandsmessung derselben Datei nimmt abgeklemmte Elemente
NICHT aus -- mein Gegenprobe-Element taucht dort als 523 px auf.
Auf echten Seiten hat das keine Folgen (0 Befunde), aber es ist
dieselbe Inkonsistenz an einer zweiten Stelle. Nicht angefasst,
weil der Nachweis dafuer wieder den ganzen Lauf braucht.
2026-09-29 14:35:29 +02:00
DogFatherGit af61f77e92 Die Transportknoepfe sind am Daumen wieder 44 Pixel hoch
DER BEFUND

pruef-handy-teamdogi meldete auf iPhone UND Android, bei zwei
Rollen, denselben Mangel:

  reaktion.html: zu kleine Tippziele --
  button#v-zurueck 48x40, button#v-vor 48x40, button#v-naechstes 83x40

Die Grundregel von `.spur__knopf` steht auf `min-height: 40px`. Am
Rechner ist das richtig; am Finger sind es vier Pixel zu wenig, und
eine Ausnahme dafuer gab es nicht.

WARUM DAS ERST HEUTE AUFFAELLT

Die Transportleiste war am Handy bis gestern gar nicht erreichbar --
sie lag 162 Pixel unter dem Fensterrand, und der Koerper hat
`overflow: hidden`. Was nicht sichtbar ist, wird nicht gemessen. Die
Reparatur von gestern hat den Mangel also nicht verursacht, sondern
aufgedeckt.

Gemessen nach der Aenderung: Transportleiste 207 statt 203 Pixel,
Saal 775 = Leiste 101 + Kino 467 + Regie 336. Kein Knopf liegt ueber
einem anderen, die Leiste verdeckt kein Bedienelement der Regie.

DIE FINGERWACHE ZAEHLT JETZT FENSTER, NICHT DATEIEN

Die erste Fassung fragte: "Steht `hasTouch` irgendwo in der Datei?"
pruef-kalender allein hat sieben Fenster, davon drei schmale -- ein
einziges `hasTouch` haette alle drei freigesprochen. Genau diese
Mischung ist im Haus die Regel.

Die geschaerfte Fassung fand prompt zwei Dateien, welche die grobe
freigesprochen hatte. Beim Nachmessen:

  - pruef-chat-optik: FEHLALARM. Ihr `setViewportSize` sitzt auf
    einer Seite, deren Kontext `hasTouch: breite < 900` traegt --
    wer danach nur die Groesse aendert, behaelt den Finger. Die
    Wache zaehlt solche Stellen jetzt nur noch, wenn in der ganzen
    Datei kein einziges `hasTouch` steht. Wo ich raten muesste,
    zaehle ich nicht: Eine Wache, die im Zweifel meldet, wird
    weggeklickt.
  - pruef-handy-teamdogi: ECHTER FUND. Ihr zweiter Kontext hatte
    keinen Finger, der erste schon. Repariert.

Grundlinie damit von 23 auf 17. Neun Gegenproben statt sechs,
darunter beide neuen Faelle.

Drei Anlaeufe, drei Zahlen: grep 18, Wache je Datei 16, Wache je
Fenster 17 (nach Abzug des Fehlalarms). Die erste Zahl, die eine
Wache liefert, ist selten die richtige.

NOCH OFFEN AUS DEMSELBEN LAUF

notizen.html, nur auf 412 px: `a.zurueck` „Team Dogi…" ist 0 Pixel
breit statt 82. Noch nicht angesehen.

GEPRUEFT
  pruef-reaktion, -tippziele, -css-klassen: alle EXIT 0
  pruef-fingermass    3 / 0
  mess-reaktion       EXIT 0, kein ACHTUNG, kein offener Punkt
2026-09-29 14:23:57 +02:00
DogFatherGit 315eb08cc4 Eine Wache dafuer, dass am Telefon mit dem Finger gemessen wird
DER FUND VON HEUTE WAR GROESSER ALS DIE EINE FUSSZEILE

`page.setViewportSize({ width: 412 })` aendert nur die Groesse.
`hasTouch` gehoert zum KONTEXT und laesst sich danach nicht mehr
setzen -- ohne ihn meldet der Browser `pointer: fine`, und KEINE
einzige Regel aus `@media (pointer: coarse)` greift. Dort stehen im
ganzen Haus die 44-Pixel-Beruehrziele.

Eine Messung mit Mauszeiger auf 412 Pixeln vermisst also eine Seite,
die es auf keinem Telefon gibt -- und meldet dabei "in Ordnung".
Das ist die dritte Sorte falscher Haken: nicht uebersprungen, nicht
rot, sondern gruen und wertlos.

GEZAEHLT: 30 Dateien oeffnen ein Telefonformat. 16 davon messen
darin Groessen, ohne einen Finger zu haben.

pruef-ueberlappung IST UMGESTELLT

Sie sucht Bedienelemente, die uebereinander liegen -- also genau die
Groessen, die erst unter `pointer: coarse` entstehen. Sie hat bis
heute mit dem Zeiger gemessen. Mit Finger: 20 Seiten-Breiten-Paare,
0 Befunde. Das ist zum ersten Mal wirklich geprueft und nicht nur
behauptet. Oberhalb von 860 px bleibt es beim Zeiger; ein Laptop
hat keinen Finger.

DIE UEBRIGEN 16 WERDEN NICHT HEUTE NACHT UMGESTELLT

Sechzehn Pruefungen anzufassen und jede einzeln neu laufen zu lassen
waere ein Gesamtlauf durch die Hintertuer -- und genau die Ausrede,
die in CLAUDE.md steht. Stattdessen haelt `pruef-fingermass.mjs`
eine Grundlinie: Sie meldet nicht 16 Fehler auf einmal (eine
Warnung, die immer kommt, wird weggeklickt und nimmt den echten Fund
mit), sondern schlaegt an, sobald eine SIEBZEHNTE dazukommt.

Sie schlaegt auch an, wenn die Zahl SINKT. Wer eine Messung
repariert und die Grundlinie stehen laesst, deckt Platz fuer die
naechste Suende. Das kostet eine Zeile und haelt die Wache scharf.

DIE ERSTE ZAHL EINER WACHE IST SELTEN DIE RICHTIGE

Mein grep hatte 18 gezaehlt. Zwei davon waren Zahlen in Kommentaren
("gemessen bei 412 px"), keine Fenster. Die Pruefung liest deshalb
nur die Stelle, die ein Fenster AUFMACHT, und blendet Kommentare
vorher aus.

DREI AUSGAENGE, SECHS GEGENPROBEN

Findet sie weniger als 50 Pruefdateien, ist das kein "alles in
Ordnung", sondern "konnte nicht nachsehen" (Rueckgabewert 2). Die
Gegenproben decken beide Richtungen ab, darunter der Fall
`setViewportSize` -- der kann `hasTouch` gar nicht nachtragen und
zaehlt deshalb immer.

`tools/alles-pruefen.mjs` liest den Ordner, keine gepflegte Liste --
die neue Wache laeuft ohne Zutun mit.

GEPRUEFT
  pruef-fingermass    3 / 0   (neu)
  pruef-ueberlappung  EXIT 0 -- 20 Paare, 0 Befunde, jetzt mit Finger
  pruef-portnummern   15 / 0
2026-09-29 14:04:06 +02:00
DogFatherGit 3dd4cef42d Die Handgriffe unter jeder Nachricht: drei Zeilen werden zwei
EINE RECHNUNG, DIE NIE GEMESSEN WURDE

In chat.css stand seit dem 25.09.2026 neben den 44-Pixel-Knoepfen
der Fusszeile:

  "Fuenf mal 44 plus vier Abstaende sind 236 px -- eine Blase hat
   auf 412 px innen 251 px. Die Reihe bleibt damit einzeilig."

Sie vergisst die Uhrzeit. Die ist 57 Pixel breit und steht in
derselben Reihe; 236 + 57 sind 293.

Auffallen konnte das nicht, weil die Regel nie lief: Alle
Handy-Messungen des Hauses liefen bis gestern mit einem MAUSZEIGER.
`setViewportSize` macht aus einem Browser kein Telefon -- `hasTouch`
gehoert zum Kontext und laesst sich danach nicht mehr setzen. Ohne
ihn meldet der Browser `pointer: fine`, und KEINE einzige Regel aus
`@media (pointer: coarse)` greift. Dort stehen im ganzen Haus die
44-Pixel-Beruehrziele. Die Rechnung wurde also gedacht und nie
gesehen.

Mit Finger gemessen, 412 px: 234 Pixel Platz fuer 277 Pixel Inhalt.
DREI Zeilen, 96 Pixel hoch -- unter jeder einzelnen Nachricht.

DIE UHRZEIT BEKOMMT IHRE EIGENE ZEILE

Sie ist das einzige Stueck der Reihe, das kein Beruehrziel ist.
Damit behalten die fuenf Knoepfe ihre 44 Pixel nebeneinander:
5 x 44 + 4 x 2 = 228 und passen in 234.

Gemessen jetzt: zwei Zeilen, 74 Pixel. Die Knopfzeile braucht 224
von 234.

EIN VERSUCH, DER ES NICHT WURDE

Zuerst hatte ich die Blase am Fingergeraet von `min(66%, 62ch)` auf
82 Prozent verbreitert -- daneben steht ja die Absicht, sie solle
"auf dem Handy trotzdem die Breite ausnutzen". Die Messung kam
SCHLECHTER zurueck (188 statt 234 Pixel Platz), und das lag an der
Messung selbst: Sie las "die erste Fusszeile". Wie breit die ist,
haengt vom Text darueber ab. Dieselbe Aenderung sah dadurch mal
besser und mal schlechter aus, ohne dass sich etwas geaendert hatte.

Der eigentliche Grund, warum 82 Prozent nicht helfen: `max-width`
ist eine Obergrenze, keine Breite. Eine kurze Nachricht hat eine
schmale Blase, und die Fusszeile bricht darin genauso um. Bei
allen vier gemessenen Nachrichten brach sie.

MESSUNG GESCHAERFT

  - Sie fragt jetzt, WIE VIELE Fusszeilen umbrechen, nicht wie die
    erste aussieht.
  - "Inhalt" ist die breiteste ZEILE, nicht die Summe aller Kinder.
    Seit die Uhrzeit absichtlich umbricht, waere die Summe die
    Breite zweier Zeilen uebereinander -- sie meldete 444 Pixel in
    einer 234 Pixel breiten Fusszeile und sah wie ein Ueberlauf aus.
  - `mess-notizblock` misst am Handy jetzt ebenfalls mit Finger
    (eigener Kontext, `hasTouch`). Vorher zeigten seine
    Handy-Bilder eine Seite, die auf keinem Handy so aussieht.

DIE KLAMMERWACHE HAT WIEDER EINEN ECHTEN FUND GEMACHT

Beim Zuruecknehmen des 82-Prozent-Versuchs blieb das schliessende
`}` der Medienabfrage stehen. Zweiter echter Fund in zwei Tagen,
beide Male an meinem eigenen Werkzeug.

GEPRUEFT
  pruef-chatkachel, -css-klassen, -tippziele, -handy: alle EXIT 0
  mess-chat-optik   EXIT 0 -- 2 Zeilen, 74 px (vorher 3 / 96)
  mess-notizblock   EXIT 0
2026-09-29 13:59:20 +02:00
DogFatherGit 7351820c55 Der Waechter gegen Namensstreit gilt jetzt fuer das ganze Haus
Er wurde gestern fuer `reaktion.css` gebaut, nachdem `.stufen` dort
zweimal stand und die Stufenleiter der Spenden dadurch das Aussehen
der Chat-Leiste bekam -- drei Stufen nebeneinander, 572 Pixel in
einer 327 Pixel schmalen Spalte, mit der waagerechten Rollleiste auf
Filipes Bildschirmfoto.

Eine Wache, die nur eine Datei ansieht, findet genau die Fehler
dieser einen Datei. Auf alle 36 Stilvorlagen angewandt fand sie
GENAU EINE weitere Stelle.

DER FUND: `.wahl2__eintrag` in gate.css

    Zeile 1584  display: block   (mit text-overflow: ellipsis)
    Zeile 2634  display: flex    (fuer Personenbilder, 08.09.2026)

Kein Streit zweier Bauteile, sondern eine spaetere Erweiterung --
und trotzdem ein echter Fehler: `text-overflow: ellipsis` wirkt bei
`display: flex` NICHT auf ein anonymes Flex-Kind. Der Knopf
„… eintragen" in jeder Auswahl des Hauses hat langen Text seither
HART abgeschnitten statt mit „…" gekuerzt.

GEMESSEN -- und nur im Bild zu sehen: `scrollWidth` ist in beiden
Faellen gleich (364 px bei 200 px Breite). Die Zahlen sagten
„kein Unterschied", das Bildschirmfoto zeigte einen. Ein Beleg mehr
dafuer, dass zwei gleiche Zahlen nicht dasselbe Ergebnis bedeuten.

REPARIERT
  - Der eigene Eintrag bekommt einen `.wahl2__name`-Span, wie jeder
    andere Eintrag auch. Damit kuerzt er wieder mit „…".
  - Die zwei Grundregeln sind eine. Wer die erste las, glaubte an
    `display: block` -- 1050 Zeilen weiter stand das Gegenteil.

DIE WACHE
  923 Grundregeln in 36 Stilvorlagen, keine Klasse zweimal
  verschieden gebaut. Gezaehlt wird nur, was sich widersprechen
  kann: nicht dieselbe Klasse in einem Zusammenhang (`.saal .pult`),
  nicht eine Variante in einer Medienabfrage, nicht
  „erst versteckt, dann gezeigt". Sechs Gegenproben, darunter der
  echte Fall vom 28.09. und eine Klasse im Kommentar.

GEPRUEFT: css-klassen, freie-namen, suchfeld, tippziele alle EXIT 0.
2026-09-29 13:45:02 +02:00
DogFatherGit 0c696f286d Der Kopf der Regie bleibt stehen, waehrend ihr Inhalt rollt
Drei kleine Dinge an der Schublade von vorhin, und eine ehrliche
Notiz zu dem, was nicht ging.

  - `overflow-y: auto` statt `overflow: hidden`. Reicht der Platz
    nicht, rollt die Schublade senkrecht -- statt ihren Inhalt
    unter der Transportleiste verschwinden zu lassen. Senkrechtes
    Rollen war nie das Problem; Filipes Ansage vom 28.09. galt dem
    Wischen nach links und rechts.

  - `flex: none` am Kopf. Ohne das ist er ein Flex-Kind mit
    `shrink: 1` -- was nichts hilft, weil sein `min-height: auto`
    ihn nicht unter die Hoehe seines Inhalts laesst. Er ragte dann
    einfach hinaus.

  - Der Kopf klebt beim Rollen (`position: sticky`). Sonst scrollt
    man „Auf Sendung" weg -- den Knopf, um den es geht.

AUF 320 PIXELN BLEIBT ES BEIM BEKANNTEN MANGEL

Dort bleiben zwischen Registern und Transportleiste rund 190 Pixel,
und der Kopf der Regie allein braucht 210. Sechs Versuche haben nur
bestimmt, WER verdeckt wird: „Vorbereiten" unter der Leiste, die
Schublade ueber „Gaeste" und „Bild", oder beim rollenden Container
22 Pixel Ueberlappung. Keiner hat es geloest.

Das steht jetzt mit Zahlen und Versuchen im Stilblatt -- samt dem
Hinweis, dass es ein eigenes Nachdenken braucht (die Regie wird dort
ein eigener Bildschirm statt einer Schublade) und nicht den siebten
Versuch mit derselben Werkzeugkiste.

NEBENBEI: Die Klammerwache hat ihren zweiten Fund in zwei Tagen
gemacht -- beim Umbauen blieb erneut eine schliessende Klammer ohne
ihren Anfang stehen. `pruef-handy` und `mess-reaktion` waren dabei
gruen; ohne die Wache waere es unbemerkt mitgegangen.

GEPRUEFT: css-klassen, handy, tippziele, reaktion alle EXIT 0;
mess-reaktion EXIT 0 (133 px sichtbares Bild, kein Knopf ueber
einem anderen), mess-quer EXIT 0.
2026-09-29 13:41:04 +02:00
DogFatherGit a6b37909ca Die Transportleiste steht am Handy in einer Reihe
Auf dem Bildschirmfoto nach dem Umbau lagen der runde Play-Knopf und
seine Nachbarn uebereinander. `pruef-handy` meldete das nicht: Sie
fragt, ob die MITTE eines Knopfes frei ist -- zwei Knoepfe koennen
sich an den Raendern ueberlagern und beide „erreichbar" sein. Wer
danebentippt, trifft trotzdem den falschen.

GEMESSEN (neue Stelle in mess-reaktion, die jedes Knopfpaar der
Leiste auf Ueberschneidung prueft):

    tempo-auf / v-spiel   21 x 44 px
    v-spiel / v-tauschen  21 x 38 px

URSACHE: `grid-template-columns: auto 1fr auto`. Tempo links und
„Wechseln zu <Videotitel>" rechts nahmen so viel, dass die mittlere
Spalte schmaler wurde als der 58 Pixel breite Play-Knopf -- und ein
zentrierter Inhalt, der breiter ist als seine Spalte, ragt ueber
BEIDE Raender.

Jetzt `minmax(0, auto) max-content minmax(0, auto)`: Die Mitte ist
so breit wie ihre drei Knoepfe zusammen und schrumpft nie, die
Seiten geben nach. `min-content` war dabei die falsche Zwischenstufe
-- damit war die Spalte so breit wie ihr BREITESTER Knopf, und
„−10" und „+10" brachen darunter um.

GEPRUEFT: pruef-handy, -tippziele, -css-klassen, -reaktion und
mess-quer alle EXIT 0; mess-reaktion meldet „Kein Knopf der
Transportleiste liegt ueber einem anderen" und 133 Pixel sichtbares
Bild.
2026-09-29 13:18:42 +02:00
DogFatherGit e272dd4673 Am Handy ist die Transportleiste wieder erreichbar
Der offene Punkt von gestern Nacht, jetzt geloest -- und dabei stellte
sich heraus, dass er schlimmer war als gemeldet.

WAS WIRKLICH LOS WAR

Gemeldet war: "Am Handy bleibt bei offener Regie vom Bild nichts."
Gemessen auf 390x844 ergab sich mehr:

    Saal 69..844 (775 px)
    Zeilen  101 + 0 + 511 + 325 = 937
    transport 681..1006  -- 162 Pixel UNTER dem Fensterrand

Der Koerper hat `overflow: hidden`; die Leiste war also nicht
abgeschnitten, sondern weg. Play, "Naechstes" und die Sprungknoepfe:
bei offener Regie nicht erreichbar. Das Bild hatte dabei null Pixel.

DIE RECHNUNG, DIE ES ERKLAERT

    Regieleiste   101  (zwei Zeilen Register)
    Regie-Kopf    207  (fuenf Zeilen zu je rund 44 px -- der
                        Klapp-Knopf stand allein in einer)
    Regie-Inhalt  305
    Transport     325  (Schiene 48 + drei Gruppen untereinander)
                 ----
                  938  von 775.

Video, Regie und Transport passen auf einem Handy nicht nebeneinander.
Das ist keine Frage der Gestaltung, sondern des Platzes.

VIER SCHNITTE UND EINE ENTSCHEIDUNG

  1. Die Tempo-Gruppe klappt hinter ihren eigenen Wert -- dasselbe
     Muster wie "Aa" im Chat, das dort 73 Pixel gespart hat. Der
     Knopf zeigt "1x" oder "1,5x", man muss zum Nachsehen also nicht
     aufklappen. Am Rechner gibt es ihn nicht.
  2. Der Klapp-Knopf rutscht neben die Lampe statt in eine eigene
     Zeile.
  3. Die drei Gruppen der Transportreihe stehen nebeneinander (158
     statt 240 Pixel) -- moeglich, seit die Tempo-Gruppe klappt.
  4. Die Messwerte stehen in einer Zeile, die grossen Knoepfe
     bekommen weniger Polsterung.

Das reichte nicht. Also die Entscheidung: AM HANDY LEGT SICH DIE
REGIE UEBER DAS BILD, statt ihm Platz wegzunehmen -- als Rasterfeld
ueber die Zeilen 2 und 3, unten angedockt, hoechstens 72 Prozent
hoch. Oben bleibt ein Streifen Bild stehen (gemessen 135 px): Wer
mitten in der Sendung etwas einstellt, muss sehen, worueber er redet.

Gemessen jetzt: Saal 775 = Leiste 101 + Bild 481 + Regie 346, und
der Transport steht bei 601..844 -- erreichbar.

DREI VERSUCHE, DIE ES NICHT WURDEN (und warum)

  - `position: absolute` mit gemessener Transporthoehe: lief, lag
    aber 17 Pixel ueber den Registern. Der Bezugsrahmen eines
    absolut gesetzten RASTERFELDES ist sein Rasterbereich, nicht der
    Container -- mit `grid-row: 3` (0 Pixel hoch) wurde aus
    `max-height: 100%` eine Hoehe von einem Pixel.
  - `top` UND `bottom` UND `height: fit-content`: Der Browser
    verwirft dann das `bottom`; die Regie ragte 101 Pixel in die
    Leiste.
  - `grid-row: 2 / 4` mit `align-self: end` statt absolut: ragte 146
    Pixel nach oben und schob die Seite 198 Pixel breiter.

AUF 320 PIXELN BLEIBT ES BEIM ALTEN

Dort passen Register (104), Regie-Kopf (210) und Transportleiste
(158) zusammen nicht in die 499 Pixel Saal -- es fehlten 17. Fuenf
Verteilungen haben nur bestimmt, WER verdeckt wird: erst
"Vorbereiten" und "Beenden" unter der Leiste, dann die Schublade
ueber "Gaeste" und "Bild". Die Schublade greift deshalb erst ab 360
Pixeln; darunter bleibt der Stand von vorher -- ein bekannter Mangel,
aber kein neuer. Der Grund steht im Stilblatt.

NEBENBEI GEFUNDEN

  - `.muenzsatz` brach nicht um und ragte auf 320 px 8 Pixel hinaus
    -- die Tafel rollte dort wieder waagerecht.

WACHEN GESCHAERFT

  - Die Klammerwache von gestern hat heute ihren ersten echten Fund
    gemacht: Beim Herausschneiden einer Regel blieb eine `}` stehen.
    Ohne sie waere das als drei Befunde in `mess-reaktion`
    aufgetaucht, die wie Programmfehler ausgesehen haetten.
  - Der Namensstreit-Waechter meldete `pult (grid vs. flex)` und
    `messwerte__paar (grid vs. flex)` -- beides Fehlalarm: Eine
    Regel in einem Zusammenhang (`.saal .pult`) und eine in einer
    Medienabfrage sind Varianten, kein Streit. Er nimmt beides jetzt
    aus. Dabei fiel auf, dass sein Muster die schliessende Klammer
    verbrauchte, die der naechste Treffer als Anfang braucht -- der
    echte Fall vom 28.09. (`.stufen` zweimal) wurde dadurch gar
    nicht gefunden. Die Gegenprobe deckt jetzt fuenf Faelle ab.
  - `mess-reaktion` mass die HOEHE der Kinozeile und haette 431
    Pixel gemeldet, waehrend das Bild vollstaendig verdeckt war.
    Sie misst jetzt, wieviel oberhalb der Schublade uebrig bleibt.

GEPRUEFT
  pruef-reaktion, -css-klassen, -tippziele, -handy, -struktur,
  -buehne: alle EXIT 0
  mess-reaktion  EXIT 0, kein ACHTUNG, kein offener Punkt
  mess-quer      EXIT 0 -- fuenf Groessen, nichts rollt seitlich
  mess-buehne    EXIT 0
2026-09-29 12:56:03 +02:00
DogFatherGit a9e0834cfb Nichts wird mehr nach links oder rechts geschoben
Filipe, 28.09.2026: "ich will auch nicht dass man sachen nach links
und rechts schieben muss. perfektion das untereinander. ich will
niemals irgendwas nach links oder rechts swippen muessen." Dazu ein
Bildschirmfoto der Tafel "Gestaltung" mit waagerechter Rollleiste.

GEMESSEN, NICHT GERATEN

Ein grep nach `overflow-x` findet nur die absichtlichen Roller. Er
findet nicht die Stelle, an der ein Inhalt breiter ist als sein
Kasten und der Browser von sich aus eine Rollleiste anhaengt -- und
genau das war auf dem Bild zu sehen. `server/mess-quer.mjs` geht
deshalb im echten Browser jedes Element durch, auf fuenf
Bildschirmgroessen, in allen sieben Registern, bei offener und
zugeklappter Regie und in allen fuenf Anordnungen.

Erster Lauf: 78 Stellen. Davon waren 54 KEINE -- `overflow-x: hidden`
ist abgeschnittener Text, dort laesst sich nichts schieben. Die
Messung trennt das jetzt; wer es mitzaehlt, findet die echten nicht
mehr. Uebrig blieben vier Ursachen:

  1. DIE REGISTER rollten absichtlich waagerecht. Auf 412 px standen
     von 605 px Registern 193 rechts ausserhalb -- dass es
     "Gestaltung" und "Spenden" gibt, erfuhr man nur beim Wischen auf
     Verdacht. Sie brechen jetzt um. Das kostet oben rund 45 Pixel
     und bringt Gewissheit dafuer.

  2. `.stufen` STAND ZWEIMAL IN reaktion.css -- einmal fuer die
     Stufenleiter der Spenden (`display: grid`), 600 Zeilen spaeter
     fuer die Chat-Leiste Offen/Team/Zu (`display: flex`). Die
     spaetere gewinnt: Die Stufenleiter stellte ihre drei Stufen
     NEBENEINANDER, 572 Pixel in einer 327 Pixel schmalen Spalte.
     Das ist die Rollleiste auf Filipes Bild. Die Chat-Leiste heisst
     jetzt `.chatstufen` / `.chatstufe`.
     Dritter Fall dieser Art nach `.tafel` und `.stufe-knopf`.

  3. DIE TAFELN KONNTEN NICHT SCHRUMPFEN. Ein Gitterfeld hat von
     sich aus `min-width: auto` und besteht auf seinem unteilbarsten
     Inhalt. Mit `minmax(0, 1fr)` und `min-width: 0` bricht jetzt
     alles um, statt hinauszulaufen.

  4. DIE TRANSPORTLEISTE ragte am Handy 76 Pixel ueber beide Kanten
     ("Naechstes" war nur halb zu sehen). Zwei Gruende: `.transport__teil`
     hatte kein `flex-wrap` (die mittlere Gruppe schon -- zwei Regeln
     fuer dieselbe Sache, eine vergessen), und im Umschalter steht
     ein ganzer Videotitel, der als Flex-Kind auf seiner vollen
     Breite bestand.

NEBENBEFUND: EINE FESTE ZAHL VON GESTERN

Der Saal stand auf `height: calc(100dvh - 69px)` -- 69 war einmal
die gemessene Hoehe der Kopfleiste. Sie ist 73 geworden, und der
Saal endete damit 4 Pixel unter dem Fensterrand: Der Play-Knopf war
nur mit Scrollen zu erreichen. Die Antwort ist keine neue Zahl,
sondern eine Regel, die misst -- der Koerper ist jetzt eine Spalte,
die Kopfleiste nimmt, was sie braucht, der Saal bekommt den Rest.
(Dabei noch ein Spezifitaetsunfall: `.reaktion-seite` (0,1,0)
verliert gegen `body.start` (0,1,1) aus start.css.)

NEUE WACHEN

  - `mess-quer.mjs` mit Gegenprobe (ohne die Reparaturen findet sie
    47 px, mit ihnen nichts).
  - pruef-reaktion: kein absichtliches `overflow-x: auto` mehr; und
    zwei Grundregeln derselben Klasse mit verschiedenem `display`
    sind ein Namensstreit. Der bisherige Waechter verglich nur
    ZWISCHEN Stilvorlagen -- `.stufen` stand zweimal in DERSELBEN.
  - pruef-css-klassen: jede Klammer hat ihr Gegenstueck. Beim
    Umschreiben blieb heute das Ende einer Regel ohne ihren Anfang
    stehen; der Browser wirft die Zeile weg und schliesst dafuer den
    naechsten @media-Block zu frueh. Drei Befunde sahen daraufhin wie
    Programmfehler aus.

MESSUNG NACHGEZOGEN

`mess-reaktion` stammte noch aus der Zeit vor "Regie links" und
"drei Kacheln" und meldete drei Dinge, die keine Fehler waren --
gemessen gegen den Stand von HEAD: identisch rot. Sie misst ausserdem
seit heute mit FINGER statt Mauszeiger; ohne `hasTouch` greift keine
einzige Regel aus `@media (pointer: coarse)`, und dort stehen alle
44-Pixel-Beruehrziele des Hauses.

OFFEN UND AUFGESCHRIEBEN

Am Handy bleibt bei offener Regie vom Bild nichts (0 px). Der Mangel
besteht seit dem Umbau "Regie links"; drei Versuche, ihn heute zu
loesen, haben Knoepfe verdeckt -- und ein verdeckter Knopf ist
schlimmer als ein kleines Bild. Die Versuche und der richtige Weg
(Tempo-Gruppe hinter einen Knopf, wie "Aa" im Chat) stehen in
reaktion.css. `mess-reaktion` meldet ihn als dritten Ausgang: nicht
als Fehler und nicht als bestanden.

GEPRUEFT
  pruef-reaktion     384 / 0   (vorher 379)
  pruef-spenden      172 / 0
  pruef-buehne        36 / 0
  pruef-css-klassen, -tippziele, -struktur, -handy: ohne Befund
  mess-quer          EXIT 0 -- 28 Stellen, fuenf Groessen, nichts rollt
  mess-reaktion      EXIT 0, 1 benannter offener Punkt
  mess-buehne        EXIT 0
2026-09-29 02:34:09 +02:00
DogFatherGitandClaude Opus 5 813d2e85a1 Die Kuerzel stehen jetzt an dem, was sie bedienen
Filipe, 28.09.2026: "das soll nicht ueberall sein sondern da perfekt
integriert werden."

Er hat recht: Die Legende war ein eigener Absatz am Ende der Regie --
hinter ALLEN Registern. Damit stand sie unter "Ton", unter "Spenden",
unter "Gestaltung", also an sechs Stellen, an denen keines ihrer
Kuerzel etwas tut. Eine Legende, die ueberall steht, gehoert nirgends
hin.

Und eine Legende ist ohnehin der Umweg: Sie zwingt dazu, vom Knopf zu
einer Liste zu schauen und zurueck. Steht die Taste AM Knopf, liest
man sie beim Bedienen -- und lernt sie dabei.

  Leertaste  unter dem runden Play-Knopf   (ein Wort passt nicht
             hinein, und der Knopf soll das Zeichen bleiben, das man
             blind trifft)
  Pfeile     an -10 und +10
  + und -    am Wort "Tempo"
  N          an "Naechstes"
  T          an "Wechseln"
  M          am Mikro-Knopf in der Senderleiste
  1 bis 5    bei der Anordnung im Register "Bild"

Nichts geht verloren, jedes steht dort, wo es wirkt.

UND DIE PRUEFUNG STELLT EINE ANDERE FRAGE ALS VORHER. Sie pruefte, ob
ein Kuerzel IRGENDWO in der Legende steht. Jetzt prueft sie, ob es am
RICHTIGEN Knopf steht -- ein Kuerzel an der falschen Stelle ist
schlimmer als keins. Dazu eine Gegenprobe, dass die alte Legende
wirklich weg ist: Stuende beides da, pflegte beim naechsten Kuerzel
jemand nur eine der beiden Stellen.

Der Chat bleibt unveraendert: Er liegt in `#teil-live` und erscheint
damit nur, wenn die Sendung laeuft -- so, wie Filipe es erwartet hat.

pruef-reaktion 379/0 - pruef-css-klassen ok - pruef-tippziele 11/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 20:51:30 +02:00
DogFatherGitandClaude Opus 5 a6d55d939a Die Regie steht links neben dem Video, nicht nur unten
Filipe, 28.09.2026: "anstatt alles nur unten zu haben wieso nicht
rechts und links noch ausnutzen um mehr ueberblick zu haben."

ICH HATTE IHN ZWEIMAL FALSCH VERSTANDEN. Beim ersten Mal baute ich
zwei Spalten INNERHALB der unteren Leiste, beim zweiten Mal Kacheln
darin. Gemeint war der BILDSCHIRM: Die Regie klebte als 272 Pixel
hoher Streifen unten, waehrend darueber das ganze Bild frei war. Man
sah entweder das Video oder die Bedienung.

AUFGEKLAPPT steht sie jetzt LINKS neben dem Video, ueber die volle
Hoehe. Rechts der Chat, unten die Senderleiste und der Transport --
die Anordnung jedes Sendepults: Was man bedient, liegt neben dem, was
man dabei ansieht.

ZUGEKLAPPT bleibt alles wie vorher, eine schmale Leiste unten. Wer
die Regie zumacht, will das Bild gross; eine leere Spalte daneben
waere das Gegenteil.

WAS DAS NEBENBEI LOEST: Die Kacheln hatten unten 272 Pixel fuer sich
-- drei Felder untereinander passten nicht hinein, und die
Transportleiste verdeckte den Rest. In einer Spalte stehen rund 700
Pixel zur Verfuegung. Die Enge war nie eine Frage der Gestaltung,
sondern des Platzes.

DER TRANSPORT VERLAESST DAS REGISTER. Er lag in "Sendung" und war
damit weg, sobald jemand auf "Ton" oder "Spenden" ging. Jetzt ist er
eine eigene Zeile unter dem Saal -- und damit auch bei zugeklappter
Regie da. Der Play-Knopf ist der eine, den man mitten in einer
Sendung blind treffen muss.

`:has(.pult[data-auf="ja"])` UND KEINE KLASSE AM KOERPER: Der Zustand
steht schon am Pult; ein zweiter Merker waere die zweite Antwort auf
dieselbe Frage. Erst ab 1100 px -- darunter bleibt fuer das Video
keine Breite: 26rem Regie plus 23rem Chat sind 784 Pixel. Gerechnet,
nicht geraten.

=======================================================================
DREI BEFUNDE GEGEN DIE EIGENEN PRUEFUNGEN -- UND EINER IST ERNST

1. "GENAU EINE REGEL DARF DIE ZEILEN DES SAALS SETZEN" war die
   Faustregel zum Befund vom Nachmittag, aber nicht die Frage, um
   die es geht. Eine zweite FASSUNG (Handy, aufgeklappte Regie) ist
   richtig und noetig -- sie setzt die Zeilen neu UND verteilt die
   Kinder neu. Der Fehler war eine zweite ANGABE, die die Zeilenzahl
   VERKLEINERT und die Kinder stehen laesst. Geprueft wird jetzt
   genau das: Jede Fassung, deren Gegenstand der Saal IST, muss
   gleich viele Zeilen haben.

2. DER ERNSTE: Dieselbe Pruefung hatte einen BLINDFLECK. Ihr Muster
   liess den Regelrumpf ueber eine oeffnende Klammer hinweg laufen
   (`[^}]*` statt `[^{}]*`) -- damit fiel jede Regel INNERHALB eines
   `@media` heraus. Gemessen: Sie meldete "alle 1 Fassungen",
   obwohl zwei dastanden. Ein Fehler im Medienblock -- und genau
   dort steht die ganze Handyansicht -- waere unbemerkt
   durchgegangen. Die Gegenprobe beweist jetzt, dass eine Fassung
   mit weniger Zeilen wirklich auffaellt.

3. Auch beim Regieplatz zaehlte sie Fassungen statt Wirkung und
   schlug an, sobald eine dritte dazukam. Jetzt prueft sie, ob eine
   Fassung eine KACHEL VERGISST -- dann verschwindet die in genau
   dieser Ansicht, und gemerkt haette es niemand.

pruef-reaktion 374/0 - pruef-css-klassen ok - pruef-tippziele 11/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 20:45:34 +02:00
DogFatherGitandClaude Opus 5 6033d1b6f2 Der Regieplatz sind jetzt Kacheln
Filipe, 28.09.2026, zum ersten Versuch: "ich wollte was hoch
professionelles wo rechts links und unten kacheln sind wo alles drin
ist, schoen verteilt. wieso so einen kleinen scheiss."

Er hat recht, und es steht auf seinem Bildschirmfoto:

  DIE LINKE SPALTE WAR LEER. "Was laeuft" zeigte nur einen Titel --
  und wenn nichts laeuft, steht dort nichts. Ein grosses schwarzes
  Loch neben einer vollen Spalte sieht nicht nach Aufteilung aus,
  sondern nach Fehler.

  ES WAREN KEINE KACHELN. Zwei Spalten mit einer Trennlinie sind eine
  Teilung, keine Gliederung. Ohne Rahmen, ohne Kopf, ohne eigenen
  Grund fehlt genau das, was eine Flaeche aufgeraeumt aussehen
  laesst.

  DIE LEISTE WAR EIN KASTEN MIT LUFT. `1fr auto 1fr` schiebt drei
  kleine Knopfgruppen an die Raender eines 1400 Pixel breiten
  Kastens. Leere zwischen Knoepfen liest sich als "hier fehlt noch
  etwas".

WAS JETZT DASTEHT

  LINKS   Eine Kachel "Was laeuft" mit VORSCHAUBILD -- damit ist sie
          immer gefuellt. Ohne Video steht der Satz darin, der sagt,
          was zu tun ist; ein leerer Kasten sagt nur, dass etwas
          fehlt. Sie geht ueber beide Zeilen der rechten Seite,
          sonst franste eine Seite unten aus.
  RECHTS  Zwei Kacheln: "Die Sendung" (Titel, YouTube, Beginn) und
          "Bereitlegen" (zweites Video, Vorschaubild, Zuruecksetzen).
  UNTEN   Die Transportleiste, dichter: jede Gruppe beschriftet
          ("Tempo", "Weiter"), und der Umschalter ist aus der linken
          Kachel hierher gewandert. Er ist ein Handgriff IM Live wie
          "Naechstes" -- und fuellt die rechte Seite, die vorher leer
          war.

Das Vorschaubild nimmt ein eigenes, wenn eines eingetragen ist, sonst
YouTubes. Laedt keines, tritt der Platzhaltersatz ein: Ein Bild, das
404 antwortet, steht genauso im Dokument wie eines, das laedt -- auf
dem Bildschirm ist an seiner Stelle nichts.

UND EIN FUND DER HAUSPRUEFUNG: `kachel` gibt es bereits in start.css
und module.css. Ein Namensstreit ueber Stilblaetter hinweg ist genau
die Sorte Fehler, die spaeter irgendwo ganz anders etwas verschiebt
-- und den niemand dort suchen wuerde. Heisst jetzt `regiekachel`.

pruef-reaktion 369/0 - pruef-css-klassen ok - pruef-tippziele 11/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 20:12:21 +02:00
DogFatherGitandClaude Opus 5 99e62eebbe Regieplatz, Bildschirm teilen, Zuruecksetzen und der Preis
Vier Sachen aus Filipes Ansagen vom 28.09.2026.

=======================================================================
1. DER REGIEPLATZ

"kann das nicht bissl aufgeteilt sein auf links und rechts und eine
barre unten in der mitte. kannst du das nicht hoch professionell
machen und hochwertig vom aussehen?"

Die Teilung folgt dem, was WANN gebraucht wird:
  LINKS   Was laeuft. Das liest man.
  RECHTS  Was eingetragen wird. Das tippt man VOR der Sendung.
  UNTEN   Der Transport. Den fasst man WAEHREND der Sendung an.

Vorher stand alles in einem Stapel, und wer im Live an den Play-Knopf
wollte, musste an den Eingabefeldern vorbeiscrollen. Der Play-Knopf
ist jetzt rund und 58 px -- der einzige, den man blind treffen muss,
und die Form unterscheidet ihn schon vor dem Hinsehen.

UND EIN FUND, DEN NUR DIE MESSUNG FAND: Nach dem Umbau lag die Leiste
bei y=986 in einem 900 Pixel hohen Fenster. Die Rechnung ging auf
(links, rechts, Leiste darunter) und das Ergebnis war trotzdem
falsch. Jetzt klebt sie (`position: sticky`) -- unten, wie gewollt,
und immer sichtbar. Ihr Grund musste dafuer dicht werden: eine
halbdurchsichtige Leiste, durch die Text scrollt, ist die Flaeche,
auf der man sich im Live verliest.

=======================================================================
2. DEN BILDSCHIRM TEILEN

"waere es nicht einfach eine bildschirm uebertragung zu installieren
und es zu perfektionieren?"

Ja -- der Weg war schon da: Die Kamerabilder laufen als
Direktverbindung von Mensch zu Mensch. Geteilt wird deshalb AN STELLE
der Kamera; `replaceTrack` tauscht die Bildspur in jeder bestehenden
Leitung aus, ohne dass eine einzige neu ausgehandelt werden muss.
Eine zweite Spur daneben waere eine zweite Verhandlung je Zuschauer,
und jede davon kann scheitern.

Vier Dinge, die sonst schiefgegangen waeren:
  - Wer waehrenddessen dazukommt, bekommt den Bildschirm und nicht
    das Gesicht.
  - Das eigene Fenster zeigt, was die anderen sehen -- sonst waere es
    die eine Anzeige, der man nicht trauen kann.
  - Der Stopp-Knopf des Browsers wird gehoert; sonst bliebe die Seite
    auf "teilt" stehen und sendete ein totes Bild.
  - Der Kameraknopf wird grau, solange geteilt wird. Er haette keine
    Wirkung mehr -- und ein Knopf, der still nichts tut, ist
    schlimmer als keiner.

Ein Bildschirm wird ausserdem NICHT zugeschnitten: `cover` ist fuer
ein Gesicht richtig, bei einem Schreibtisch faellt links und rechts
genau das weg, worum es geht.

UND DIE WAHRHEIT STEHT AN DER BEDIENUNG: Netflix, Disney+ und Prime
bleiben beim Teilen schwarz (Widevine schaltet den Videobereich ab --
auf Discord und Zoom ist es genauso), und einen Film weiterzusenden
waere eine oeffentliche Wiedergabe. Wer das erst erfaehrt, nachdem im
Stream zehn Minuten ein schwarzes Rechteck stand, erfaehrt es zu
spaet.

=======================================================================
3. ALLES ZURUECKSETZEN

"brauch ich auch noch einen button wo ich alles easy zuruecksetzen
kann."

"Alles" heisst: der Schreibtisch, nicht das Gedaechtnis. Geleert
werden Titel, Video, zweites Video, Vorschaubild, Beginn,
Warteschlange, Gaesteliste; Anordnung, Kameragroesse, Ecke, Tempo und
Chatmodus gehen auf Vorgabe.

NICHT ANGETASTET werden Spenden, die Dogen der Leute, der Chatverlauf
und die Massnahmen der Moderation. Eine bezahlte Spende aus den
Buechern zu nehmen waere eine Faelschung; eine stillschweigend
aufgehobene Sperre waere eine Entscheidung, die niemand getroffen
hat. Beides steht nebeneinander im Dialog, BEVOR etwas passiert -- ein
"Bist du sicher?" ohne diese Liste ist keine Frage, sondern eine
Huerde.

Im Live ist der Knopf grau und sagt warum. Und die Spalten stehen
einzeln da statt als "alles ausser": Eine Ausnahmeliste waechst still
mit jeder neuen Spalte mit, und dann loescht das Zuruecksetzen
irgendwann etwas, das es nie loeschen sollte.

=======================================================================
4. DER PREIS BEI DEN DOGEN

"da muss ich auch sehen so viel dogen sind so viel euro. damit ich
auch immer weiss was es ist. aber nur ich. die leute sollen nur sehen
was dogen kosten."

Das ist keine Ruecknahme von "nie Geld", sondern ihre Grenze. Die
Regel war richtig fuer alles, was ANZEIGE ist -- Karte, Stream, Chat,
Punktestand -- und falsch fuer die eine Stelle, an der jemand KAUFT.

GENAU ZWEI AUSNAHMEN, und die Pruefung nennt sie beim Namen statt die
Regel aufzuweichen:
  knoepfe[].cent      fuer alle -- der Preis am Kaufknopf
  kurs_cent_je_doge   nur fuer die Leitung

DIE ERLAUBNIS STECKT IN DEN DATEN UND NICHT IN EINEM `if`. Ein
Zuschauer hat den Kurs nicht und kann deshalb GAR KEINEN Preis
ausrechnen -- auch nicht, wenn eine spaetere Zeile es versuchte. Eine
Abfrage "darf der das sehen?" in der Oberflaeche waere eine Regel, die
man vergessen kann; eine fehlende Zahl ist eine, die man nicht
vergessen kann.

Eine Zahl statt dreissig Einzelumrechnungen: Wer je Zeile einen Cent
mitschickt, hat dreissig Gelegenheiten, eine zu vergessen.

=======================================================================
FUENF BEFUNDE GEGEN DIE EIGENEN PRUEFUNGEN

1. Eine Pruefung fragte "liegt die Leiste unter beiden Spalten?" --
   das tut eine klebende Leiste beim Hochscrollen absichtlich nicht.
   Sie stellte die Frage von vorher. Jetzt zaehlt die Reihenfolge im
   Dokument, die beim Scrollen wie beim Stillstand gilt.
2. Eine Messung klickte auf einen Namen und wartete 400 ms auf die
   UHR -- und verschluckte den Klickfehler still. Derselbe Lauf war
   dreimal gruen und beim vierten rot, ohne Codeaenderung. Jetzt wird
   auf das Merkmal gewartet, bis zu dreimal, und die Zahl der
   Anlaeufe steht im Protokoll.
3. Eine Pruefung loeschte erst selbst den Chat (eine Sendung zu
   beenden tut das mit Absicht) und fragte dann, ob er noch da ist.
4. "Die Dogen sind unberuehrt (0 Staende)" -- null bleibt auch dann
   null, wenn das Zuruecksetzen sie mitnaehme. Jetzt steht vorher
   eine echte Spende da, und die Zahl gehoert in die BEDINGUNG.
5. `knopf-still--haupt` stand seit Wochen im HTML und war in KEINEM
   Stilblatt definiert -- eine Klasse, die aussieht, als sei etwas
   hervorgehoben, und auf dem Bildschirm ist es das nicht. Gefunden
   beim Nachsehen, ob es sie gibt, bevor ich sie ein zweites Mal
   benutze.

Und eine neue Pruefung, die es vorher nicht gab: ALLE 118 Kennungen,
die das Programm mit `$('...')` anspricht, werden gegen das HTML
gehalten. Nach einem Umbau, der die halbe Tafel neu sortiert, waere
eine verlorene Kennung KEIN Fehler beim Laden -- `$()` gibt still
`null` zurueck, und der Fehler erscheint erst, wenn jemand mitten in
der Sendung den Knopf drueckt.

pruef-reaktion 365/0 (vorher 321) - pruef-spenden 172/0 (vorher 167) -
pruef-buehne 36/0 - pruef-css-klassen ok - pruef-tippziele 11/0 -
mess-reaktion und mess-buehne ohne Beanstandung

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 20:03:38 +02:00
DogFatherGitandClaude Opus 5 96bdd79a91 Die Dogen-Muenzen: drei Saetze zu je drei Stufen
Filipe, 28.09.2026: "ich werde die drei varianten schicken fuer
niedrige spenden. mittlere und hohe spenden. alle drei varianten will
ich drauf so dass ich sie aussuchen kann wie ich will. aber pass sie
sofort diesen 3 kategorien an."

DIE ZUORDNUNG IST GELESEN, NICHT GERATEN

In allen drei Saetzen geht es nacktes Metall -> Steinkranz ->
Vollbesatz; Filipes Dateinummern (01/02/03) und die Uhrzeiten seiner
Entwuerfe laufen genau mit. Klassik: Palladium, Gold mit Saphir,
Diamant. Amethyst: Stahl, Rosegold, Vollbesatz. Neon: Chrom auf
Schwarz, Steinkranz, Vollbesatz.

AUS 25 MB WURDEN 443 KB

Je Bild 320 px WebP statt 1254 px PNG, Faktor 58. Die Zahl ist
gemessen: Groesster Fall in der Seite 110 px (Karte, hoechste Stufe),
auf der OBS-Tafel 189 px, bei doppelter Bildschirmdichte rund 220.
Drei Megabyte fuer ein 24-Pixel-Zeichen waeren ein Ladebalken mitten
in der Sendung -- wer auf dem Handy zusieht, bekaeme die Karte, wenn
sie schon wieder weg ist. Die Originale liegen neben den
Datenbanksicherungen, nicht im Repo: 26 MB, die bei jedem Klon
mitkaemen und die niemand ausliefert.

WELCHE MUENZE WANN -- ABGELEITET STATT GEPFLEGT

"Niedrig, mittel, hoch" gibt es im Haus schon: die Stufenleiter. Zwei
eigene Grenzen daneben waeren eine zweite Antwort auf dieselbe Frage,
und spaetestens beim Verschieben einer Stufe zeigte die Muenze etwas
anderes an als der Name auf der Karte. Die Leiter wird deshalb in
DRITTEL geteilt -- bei den drei Werksstufen genau eine je Muenze, bei
sechs zwei je Muenze, bei einer einzigen ueberall die mittlere.

DIE MUENZE STEHT AUCH GROSS AUF DER KARTE

Sonst haette Filipe neun Bilder fuer ein 24-Pixel-Zeichen gezeichnet.
"dogen" ist dafuer eine neue Vorlage neben Herz, Welle und Krone --
und die drei Werksstufen bekommen sie EINMAL zugeteilt, nur wo noch
die Werksvorlage steht und kein eigenes Bild hochgeladen ist. Wer
danach ein Herz zurueckstellt, findet es morgen nicht wieder als
Muenze vor: Eine Einstellung, die sich gegen den Benutzer durchsetzt,
wird abgeschafft.

Und steht sie gross da, nimmt das Stilblatt die kleine neben der Zahl
weg -- dieselbe Muenze in zwei Groessen auf einer Karte sieht aus wie
ein Versehen.

AM BILDSCHIRMFOTO NACHGEBESSERT

Bei 0,92em blieb an den Spendenknoepfen ein 13,5-Pixel-Fleck uebrig;
bei einem flachen Symbol reicht das, bei einer Muenze mit Pfote,
Schriftzug und Steinen nicht. Jetzt 1,05em ueberall und 1,6em auf den
Knoepfen. In der Auswahl sahen "Amethyst" und "Neon" bei 40 px
praktisch gleich aus -- und genau sie auseinanderzuhalten ist der
Zweck dieser Liste. Jetzt 56/64/72 px. Und was gewaehlt ist, steht
als WORT da: Neben neun glaenzenden Muenzen geht ein ruhiger Rahmen
unter, und wer Farben schlecht unterscheidet, sieht ihn gar nicht.

EIN SATZWECHSEL ERREICHT ALLE

Die Karten trugen ihren Satz immer selbst mit und waren richtig. Die
Muenzen an den Spendenknoepfen und beim eigenen Stand aber nicht --
die holt eine Seite nur bei einer Spende neu. Eine Einstellung, die
nur dort ankommt, wo sie gemacht wurde, ist keine Einstellung des
Hauses.

ZWEI BEFUNDE GEGEN DIE PRUEFUNG SELBST

1. Sie verlangte "erste Grenze ECHT kleiner als zweite". Bei genau
   zwei Stufen fallen beide absichtlich zusammen -- sie meldete einen
   Fehler, wo das Verhalten richtig ist.
2. Sie prueft die Muenzverteilung jetzt auf einer FRISCHEN Datenbank.
   Vorher lief sie auf der, die ein frueherer Abschnitt umgebaut
   hatte: Eine Pruefung, die den eigenen Kollateralschaden misst,
   misst sich selbst. Dazu eine Gegenprobe, dass eine selbst
   gewaehlte Vorlage NICHT ueberschrieben wird.

UND DREI AN DER MESSUNG

Sie suchte noch die gezeichnete Muenze (svg), wo jetzt ein Bild
liegt. Umgestellt nicht auf "ist ein img da", sondern auf
`naturalWidth > 0` -- ob es etwas ZEIGT. Ein img, das 404 antwortet,
steht genauso im Dokument wie eines, das laedt; auf dem Bildschirm
ist an seiner Stelle nichts. Und beim Satzwechsel las sie die vorige
Karte, die noch acht Sekunden stand: Die Karten laufen in einer
Schlange, also wird auf das Merkmal gewartet, das nur die neue hat.

pruef-spenden 167/0 (vorher 136) - pruef-reaktion 321/0 -
pruef-css-klassen ok - pruef-tippziele 11/0 -
mess-reaktion und mess-buehne ohne Beanstandung

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 19:36:05 +02:00
DogFatherGitandClaude Opus 5 c00c209ac9 Dogen statt Geld -- und die Texte schreiben die Leute selbst
Filipe, 28.09.2026:
  "der text der dazu erscheint sollen die leute selber schreiben
   koennen. soll auf nicht zu viel aber auch nicht zu wenig
   schreiben koennen. aber es sollen personalisierte texte sein von
   den leuten selbst."
  "mann soll nie die summe sehen sondern die dogen auch mit dem
   symbol ... es soll auch nie geld da stehen sondern Dogen."
  "ich will dass die den leuten auch als punkte hinzugefuegt werden."

DER TEXT KOMMT VON DEM, DER GIBT

Bisher konnte ihn nur die Leitung tippen; beim Melden schickte der
Zuschauer gar nichts mit. Jetzt stehen nach dem Tippen auf einen
Betrag zwei Felder da: Name auf der Karte (mit dem eigenen Namen
vorausgefuellt) und der eigene Text, bis 140 Zeichen.

140 ist gemessen, nicht geraten: Die Karte steht je nach Stufe sechs
bis elf Sekunden. Bei 140 Zeichen sind das zwei bis drei Zeilen -- die
fasst man im Vorbeischauen. Bei 200 wird die Schrift auf einer kleinen
Karte so eng, dass niemand mehr hinsieht, und ein Gruss, den keiner
liest, ist schlechter als ein kurzer. Der Zaehler erscheint erst ab
30 uebrigen Zeichen; einer, der von Anfang an mitlaeuft, macht aus
einem Gruss eine Aufgabe.

UND EINE SCHRANKE DAVOR. Der Text kommt von einem Fremden und steht
gleich im Livestream. Er laeuft ohnehin durch die Bestaetigung -- neu
ist, dass die Leitung ihn dort AENDERN kann. Ohne das bliebe nur "ganz
ablehnen", und dann faellt wegen eines Wortes eine echte Spende unter
den Tisch.

NIE WIEDER GELD AUF DEM BILDSCHIRM

Ein Doge sind zehn Euro (Filipes Angabe "1 euro sind 0,10 dogen",
rueckgefragt und bestaetigt -- zwischen den beiden Lesarten liegt der
Faktor 100). Gerechnet wird in Tausendsteln, nie in Kommazahlen.

Das Entscheidende ist nicht die Beschriftung: DER BROWSER BEKOMMT
KEINEN EURO-BETRAG MEHR, auch nicht verborgen im JSON. Der Kurs steht
einmal auf dem Server. Was nicht gesendet wird, kann an keiner Stelle
versehentlich erscheinen, und niemand muss daran denken. Gemessen:
38 Felder im Stand, kein Geldfeld, kein Eurozeichen, auch nicht auf
der Buehnentafel. Der einzige Ort, an dem noch ein Euro entsteht, ist
die PayPal-Adresse -- weil PayPal ihn braucht.

DIE PUNKTE: EIN BUCH, KEIN ZAEHLER

Ein Feld `dogen` an der Person waere kuerzer gewesen -- und die zweite
Antwort auf dieselbe Frage. Der Stand IST die Summe der Buchungen, und
eine Summe kann sich nicht von ihren Posten entfernen. Weil Filipe
spaeter etwas daran haengen will ("spezielle sachen ... wo mit diesen
dogpunkten zu tun hat"), steht neben jeder Zeile ein Grund und ein
Datum: Ein Zaehler, der kleiner wird, laesst keine Frage mehr
beantworten.

Dass nie doppelt gutgeschrieben wird, entscheidet ein eindeutiger
Index in der Datenbank und keine Bedingung im Programm -- "nochmal
zeigen" und ein wiederholter Strom koennen es damit gar nicht
ausloesen.

Ohne Person keine Punkte: Eine von Hand eingetragene Spende hat oft
nur einen Vornamen auf dem Handy. Daraus eine Person zu RATEN waere
schlimmer als keine Gutschrift -- deshalb waehlt die Leitung sie aus,
und tut sie es nicht, laeuft die Karte trotzdem.

DAS SYMBOL IST VORBEREITET

Filipe: "die symbole schick ich dir spaeter." Es wird im Regiepult
hochgeladen, ohne Deploy -- bis dahin steht eine gezeichnete Muenze
da. Es liegt bei den Stufenbildern, weil das der einzige Weg ist, der
Bilder OHNE Anmeldung ausliefert; sonst fehlte es ausgerechnet im
Stream.

=======================================================================
UND EINE REPARATUR AN DEM, WAS HEUTE MITTAG LIVE GING

Seit 3fedeea7 war der Buehnenmodus (reaktion.html?nur=buehne) kaputt:
Leinwand null Pixel hoch, im Stream ein schwarzes Bild. Das ist die
Fensterquelle fuer den Fall, dass Gaeste im Bild sind.

Ursache: Teil A hat die Zeilen des Saals festgenagelt (#teil-live auf
Zeile 2). Im Buehnenmodus stand aber seit jeher eine eigene Regel, die
dem Saal nur EINE Zeile gibt -- das Video landete in einer impliziten
Zeile, die sich nach ihrem Inhalt bemisst, waehrend die Leinwand ihre
Hoehe aus der Zeile nimmt. Beide warten aufeinander, heraus kommt
null.

Das ist heute der VIERTE Fall von "zwei Regeln fuer dieselbe Frage"
(Tafeln, Saalzeilen, Kamerabreite, Buehnenmodus). Die Loesung ist
jedes Mal dieselbe: nicht die zweite Regel richtig stellen, sondern
sie abschaffen.

DREI DINGE, DIE DARAN LEHRREICH SIND:

1. MEINE EIGENE PRUEFUNG WAR GRUEN UND WERTLOS. Ich hatte nach Teil A
   extra geprueft: "genau eine Regel bestimmt die Zeilen des Saals".
   Sie verlangte, dass die Zeile mit `.saal` BEGINNT -- und hat
   `body[data-nur="buehne"] .saal { … }` deshalb nie gesehen. Jetzt
   zaehlt sie jede Regel, in deren Auswahl `.saal` vorkommt, mit einer
   Gegenprobe, die eine eingeschobene zweite wirklich findet.

2. EINE SEITE MIT ZWEI ANSICHTEN BRAUCHT BEIDE MESSUNGEN. Nach Teil A
   liefen `pruef-buehne` (Schnittstelle) und `mess-reaktion` (normale
   Ansicht). `mess-buehne` -- die einzige, die diese Ansicht
   ueberhaupt oeffnet -- lief nicht.

3. EIN PYTHON-SKRIPT, DAS ERST AM ENDE SCHREIBT, MELDET "ok" FUER
   AENDERUNGEN, DIE NIE ANKOMMEN. Eine fehlgeschlagene Zusicherung hat
   einen ganzen Stapel verworfen, obwohl die erste Aenderung schon
   bestaetigt war. Die Messung meldete daraufhin "Auf der Karte steht:
   undefined" -- kein Fehler im Code, sondern eine Zeile, die nie
   geschrieben wurde. Gefunden hat es die Messung, nicht das Lesen.

pruef-spenden 136/0 (vorher 95) - pruef-reaktion 321/0 -
pruef-buehne 36/0 - pruef-css-klassen ok - pruef-tippziele 11/0 -
mess-reaktion und mess-buehne ohne Beanstandung

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 18:54:02 +02:00
DogFatherGitandClaude Opus 5 3fedeea716 Kamerafenster: Groesse und Ecke lassen sich stellen
Filipe: "und danach perfektionierst du auch die verschiedenen
groessen von kamera und so, perfektionier das alles bitte."

Sechs Groessen (0,6x bis 2x) und vier Ecken, beide an der SENDUNG
und nicht am Browser: Was Filipe einstellt, sehen alle. Waere es
eine Einstellung je Geraet, redete er ueber ein Bild, das bei den
Zusehenden anders aussieht -- und im Stream stuende ein drittes.

Anordnung, Groesse und Ecke gehen jetzt EINEN Weg (/layout), weil
sie zusammen eine einzige Frage beantworten: Wie sieht das Bild aus?
Drei getrennte Aufrufe waeren drei Rundrufe, und dazwischen saehen
die Zusehenden eine Mischung -- neue Anordnung, alte Ecke. Eine
falsche Angabe laesst auch das Gute stehen, statt halb umzustellen.

Die Ecke gibt es, weil unten rechts bei TikTok die Knopfreihe liegt,
bei YouTube die Fortschrittsleiste, und Untertitel fast immer unten
stehen. Eine feste Ecke ist eine, die bei jeder zweiten Plattform
im Weg ist.

Die OBS-Videoquelle kennt jetzt die Anordnung und blendet sich bei
"Nur Kamera" aus -- sonst laege im Stream ein stehengebliebenes
YouTube-Bild unter den Kameras, und Filipe saehe es nicht, weil er
auf seine Szene schaut und nicht auf die Quelle.

VIER BEFUNDE, ALLE VON DEN PRUEFUNGEN UND KEINER VOM AUGE:

1. Die Knoepfe fuer Groesse und Ecke gab es gar nicht. HTML und
   Stilblatt waren da, das Programm nicht. Gemessen: "0 von 0
   Eckknoepfen gesperrt", und der Hinweistext stand noch wortgleich
   wie im HTML -- zwei leere Kaesten, die aussahen, als sei alles
   in Ordnung.

2. Bei "Nur Kamera" war der Stapel 493 px breit statt 1072. Der
   neue Deckel max-width: 46% -- richtig gegen ein zu grosses
   Fenster bei "Video gross" -- galt still auch dort, wo die
   Kameras die ganze Flaeche fuellen sollen.

3. Am Handy haette die Groesseneinstellung ueberhaupt nichts
   bewirkt: Dort stand weiterhin width: clamp(88px, 26vw, 140px)
   am Fenster selbst. Das ist die dritte Wiederholung derselben
   Sache an einem Tag (die Saalzeilen, die Tafeln, jetzt die
   Kamerabreite): Zwei Regeln fuer dieselbe Frage sind die
   Garantie, dass eine davon irgendwo falsch gewinnt. Breite und
   Rand gehen jetzt ueber --kam-grund/--kam-rand, --kam wird an
   genau EINER Stelle gerechnet, und eine Pruefung zaehlt das nach.

4. Die Pruefung schlug auf ihren EIGENEN Kommentar an, der die
   entfernte Zeile zitiert. Ein Werkzeug, das bei jedem Lauf
   meckert, wird nach dem zweiten Mal weggeklickt -- samt dem
   echten Befund darin. Gezaehlt werden jetzt Regeln, nicht Prosa.

Gemessen beim Zuschauer und nicht in der Datenbank: 1x -> 208 px,
2x -> 416 px, alle Fenster innerhalb der Leinwand, und jede der
vier Ecken am Abstand zu den Kanten nachgewiesen statt an ihrem
eigenen Namen. Ein Knopf, der gerade nichts bewirken kann, ist
grau, und der Satz darunter sagt warum.

pruef-reaktion 320/0 - pruef-buehne 36/0 - pruef-css-klassen ok -
pruef-tippziele 11/0 - mess-reaktion ohne Beanstandung

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 14:35:02 +02:00
DogFatherGitandClaude Opus 5 2b02d88767 Die Regieleiste steht jetzt über dem Saal
Filipe: „ich hätte das gerne oben also nicht in dieser kachel sondern
über der kachel wo die videos laufen werden und das soll extrem
perfektioniert werden."

WARUM DAS MEHR IST ALS EIN UMHÄNGEN
Die Register standen INNERHALB des einklappbaren Teils. Wer die Regie
zuklappte, um mehr Bild zu haben, hatte sie nicht mehr — und genau
dann braucht man sie. Oben ändert sich ihre Aufgabe: aus dem
Inhaltsverzeichnis einer Schublade wird eine Steuerleiste über der
Sendung. Daraus folgen vier Dinge, die vorher nicht nötig waren:

1. EIN REGISTER MACHT DIE ZUGEKLAPPTE REGIE AUF. Vorher wechselte nur
   der Reiter, die Tafel lag im zugeklappten Teil — sichtbar passierte
   nichts. Nur auf, nie zu: Zugemacht wird mit dem Griff. Ein Knopf,
   der beim zweiten Druck das Gegenteil tut, versteckt irgendwann
   etwas, das jemand gerade liest.

2. SIE BRICHT NICHT UM, SIE ROLLT. Sieben Register in zwei Zeilen
   kosten am oberen Rand rund 90 px — und zwar dem Video. Gemessen:
   eine Zeile auf 1440 px wie auf 390 px, dort mit Einrasten und
   weichen Rändern als Auskunft, dass es weitergeht.

3. SIE LÖST EIN, WAS `role="tablist"` VERSPRICHT. Pfeiltasten wandern,
   Pos1/Ende springen, genau ein Register liegt in der Tabulatorfolge.
   Steht die Rolle im Markup und tut das Programm es nicht, sagt ein
   Vorleser etwas an, was nicht stimmt — schlimmer als keine Rolle.
   Gemessen wird das gedrückt, nicht gelesen: fünf Tastendrücke, und
   Fokus, Auswahl und offene Tafel müssen jedes Mal dasselbe sagen.

4. EINE GLEITENDE MARKE zeigt, wo man steht — Glas mit Lichtkante,
   darunter ein roter Streifen zur offenen Tafel. Ist die Regie
   zugeklappt, wird er leise: Der Streifen führt dann nirgendwohin.
   Dazu ein Schild „Regie" links (am Handy weg), damit die sieben
   Wörter am oberen Rand nicht wie eine zweite Navigation aussehen.

DER FEHLER, DER MICH ZWEI ANLÄUFE GEKOSTET HAT
Die Leiste war im Browser 1 px hoch, ihre Register standen 55 px hoch
daneben und ragten über das Video. Ursache: 900 Zeilen weiter unten
stand eine ZWEITE `grid-template-rows` für `.saal` (aus der Zeit, als
der Saal zwei Zeilen hatte). Sie stand später und gewann — die Leiste
landete in der `1fr`-Zeile und bekam null Pixel.

Und fast hätte ich das Falsche repariert: Beim Durchprobieren habe ich
`style.gridTemplateRows` gesetzt — ein Stilattribut schlägt jede Regel
im Stilblatt. Damit „funktionierten" `auto` und `min-content` gleich
gut, weil beide die zweite Regel aushebelten, und es sah nach einem
Unterschied zwischen den beiden aus. Erst nach dem Entfernen der
Doppelung hat die Gegenprobe gezeigt: `auto` tut es genauso. Eine
Probe, die mehr ändert als das, wonach man sucht, beantwortet eine
andere Frage. Es gibt jetzt eine Prüfung, dass genau EINE Regel die
Zeilen des Saals bestimmt.

ZWEI WEITERE FUNDE AUS DER MESSUNG
Am Handy blieben bei offener Regie 131 px für das Bild — ein Streifen.
Mein erster Versuch (62dvh → 52dvh) machte es auf 75 px SCHLECHTER:
Die Ursache lag woanders, die Leiste des Pults bricht dort in vier
Zeilen um und ist rund 200 px hoch, wovon ein Anteil der Fensterhöhe
nichts wissen kann. Mit `min(52dvh, 19rem)` sind es 210 px.

Und die Spendenkarte wurde als „steht aus dem Bild heraus" gemeldet:
413 statt 430 px, links −1. 413 ist genau das 0,96-fache — die Messung
hatte die Karte im Ausblenden erwischt. Sie wartet jetzt auf
`data-da="ja"` und misst nur, was ganz da ist.

GEPRUEFT
pruef-reaktion 280 (vorher 260), 0 Fehler — Abschnitt 18 neu.
mess-reaktion: Rückgabewert 0, kein ACHTUNG; misst die Leiste jetzt
auf 1440 und auf 390 px, samt Tastatur und Aufklappen.
Dazu grün: handy, buehne, struktur, css-klassen, tippziele.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 14:13:07 +02:00
DogFatherGitandClaude Opus 5 d2f02ba84e Spenden: Stufen gestaltbar, Bild hochladen, Größe je Stufe
Filipes Wunsch: „mach paar fertige und so dass ich auch hochladen
kann. auch so dass ich das anders gestalten kann oder die größe
verändern kann. ... auch spezielle sachen bei speziellen spenden."

WAS ES SCHON GAB, WAS FEHLTE
Drei Stufen ab Werk, fünf gezeichnete Zeichen, Farbe und Dauer je
Stufe — und sogar schon ein Feld für ein eigenes Bild. Es fehlte der
Weg, das alles zu ÄNDERN: Um eine Stufe umzubenennen, hätte jemand in
die Datenbank greifen müssen.

DIE GRÖSSE IST DAS „SPEZIELLE BEI SPEZIELLEN SPENDEN"
Je Stufe, nicht einmal für alle: Eine Rudel-Legende darf größer
dastehen als ein Danke. Eine einzige Größe für alle wäre wieder eine
Preisliste. Umgesetzt als EINE Schriftgröße, alles darin in `em` —
nicht `transform: scale()`, denn die Karte kommt schon mit
`translateX()` herein, und zwei `transform` an derselben Stelle
schließen einander aus; außerdem wird Text beim Skalieren matschig.
Nur nach oben (1 bis 2,5), und das ist eine ehrliche Grenze: Das
kleinste Wort auf der Karte steht bei 11,52 px, die Hausgrenze ist
11,5. Ein Faktor von 0,8 machte daraus 9,2 px. Kleiner geht an der
richtigen Stelle — die OBS-Tafel hat ihren eigenen Regler in der
Adresse, dort ist es eine Videoeinblendung und kein Text zum Lesen.

AUSPROBIEREN, OHNE EINE SPENDE ANZULEGEN
Der naheliegende Weg wäre gewesen: eine Spende eintragen und danach
löschen. Das ist verboten — in ein laufendes System kommen keine
Testdaten, und „gelöscht" heißt bei Geld nicht „war nie da". Die
Probe schreibt deshalb NICHTS und geht nur an den, der drückt; eine
Probe im ganzen Saal wäre eine Spende, die es nicht gab.

DREI FEHLER, DIE DIE PRÜFUNG GEFUNDEN HAT

1. `protokolliere()` wurde an 17 Stellen falsch herum gerufen —
   `(personId, aktion, detail, ip)` statt `(aktion, {…})`. JavaScript
   beschwert sich nicht: Das zweite Argument war ein Text, und einen
   Text zu zerlegen ergibt lauter `undefined`. Auf dem echten Server
   nachgemessen: 39 Protokollzeilen mit Aktionen wie „16.0", alle
   ohne Person, ohne Detail, ohne IP. Betroffen waren Material,
   Hilfe, Bühne, Reaction und Spenden — also jede Änderung an
   Dogi-Media und jede Maßnahme im Live-Chat, ausgerechnet das,
   wofür es ein Protokoll gibt. Alle 17 berichtigt, und
   pruef-struktur wacht jetzt darüber (mit Gegenprobe).

2. Beim Speichern der Leiter bekam jede Stufe eine NEUE Kennung
   (DELETE + INSERT). Ein Bild-Hochladen gegen die eben noch gültige
   Kennung antwortete mit 404 — im Alltag trifft das jeden, der einen
   zweiten Bildschirm offen hat. Jetzt werden vorhandene Zeilen
   geändert statt ersetzt; das Bild bleibt von selbst daran hängen.

3. `ab_cent` ist eindeutig. Zwei Stufen ihre Beträge tauschen zu
   lassen scheiterte mit „UNIQUE constraint failed", obwohl das
   Ergebnis in Ordnung gewesen wäre: Beim Umschreiben stößt die
   Leiter auf sich selbst. Jetzt in drei Schritten — löschen,
   geparkte Zwischenwerte, endgültige Werte —, und das ist nach
   außen nie sichtbar.

UND DREI, DIE IN MEINER MESSUNG STECKTEN
Die Messung hat eine noch laufende Karte aus dem vorigen Abschnitt
erwischt und daraus drei Fehler gemeldet, die keine waren —
darunter „die Probe läuft im ganzen Saal". Sie zählte außerdem die
versteckten Dateifelder als zu kleine Tippziele. Jetzt räumt sie
vorher auf, wartet auf die Karte MIT DER ERWARTETEN GRÖSSE (die
Karten laufen in einer Schlange — einen Knoten zu entfernen beendet
sie nicht) und lässt die Einblendung zur Ruhe kommen, bevor sie misst.
Ein Bildschirmfoto aus der Einblendphase sah aus, als stünde die
Karte links heraus; nachgemessen: links 18 px, ganz im Bild.

GEMESSEN, NICHT ANGENOMMEN
Karte bei Größe 1: Schrift 16 px, Betrag 25,92 px. Bei Größe 2:
32 px und 51,84 px — Faktor exakt 2,00. Hätte eine einzige Regel noch
in `rem` gestanden, wäre die Karte ungleichmäßig gewachsen, und auf
einem Bild sieht beides nur „größer" aus.

AUCH DAS BILD IST GEPRÜFT
Es liegt am Bühnen-Router und nicht am Spenden-Router: Die
Spendentafel in OBS hat keine Anmeldung, und ein 401 als JSON in
einem `<img>` ergibt ein kaputtes Bild ohne jeden Hinweis. Ohne
Schlüssel, aber mit 128 Bit zufälligem Dateinamen — dieselbe
Größenordnung wie der Bühnenschlüssel, und es ist ein Zierbild, das
ohnehin im Stream steht. Kein Ausbruch aus dem Ordner (vier Wege
geprüft, gemessen wird die Wirkung und nicht der Statuscode).

NACHGETRAGEN AUS BLOCK 4
`reaktion_meldungen` fehlte im Löschkonzept — eine bestehende Prüfung
hat es gefunden. 30 Tage nach dem Erledigen; meistens sind sie
ohnehin früher weg, weil der Live-Chat beim Beenden gelöscht wird und
die Meldungen daran hängen. Wer meldet, muss sich darauf verlassen
können, dass daraus keine dauerhafte Liste wird.

GEPRUEFT
pruef-spenden: 95 Prüfungen (vorher 46), 0 Fehler.
pruef-reaktion 260, pruef-buehne 36, pruef-aufbewahrung 45,
pruef-struktur, pruef-meldungen, pruef-css-klassen, pruef-tippziele,
pruef-deutsche-texte, pruef-auskunft alle grün.
mess-reaktion und mess-buehne: Rückgabewert 0, kein ACHTUNG.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 10:14:26 +02:00
DogFatherGitandClaude Opus 5 74c74a08ab Reaction: Geschwindigkeit, zwei neue Anordnungen, zweites Video
Filipes Wunsch: „auch bei den videos sachen wie pause
geschwindigkeit. meine kamera größer machen video kleiner. nur mein
bild, nur das video, möglichkeit zwischen allem zu wechseln so wie ich
will, auch gerne so dass ich vielleicht noch ein zweites nebenbei
vorbereiten kann so dass ich hin und her switchen kann."

GESCHWINDIGKEIT
Sechs Stufen von 0,5× bis 2× (0,25× fehlt mit Absicht — bei einem
Viertel klingt Sprache wie ein defektes Band). Sie gilt für ALLE: Wer
sie nur bei sich umstellte, redete über eine Stelle, die die anderen
noch nicht gesehen haben. Die OBS-Bühne zieht sie mit nach — ohne das
liefe der Stream nach fünf Minuten auf 1,5× zweieinhalb Minuten hinter
dem Saal her.
Und der Zuschauer SIEHT sie: ein kleines Schild „1,5×
Geschwindigkeit" auf der Leinwand, nur wenn es nicht 1× ist. Ohne das
hält jeder Zweite seine Leitung für kaputt.
Zwei Fallen, die dabei zugemacht wurden: Der Fünf-Sekunden-Takt des
Hosts schreibt das Tempo NICHT mit (sonst drehte ein Takt mit altem
Wert die Einstellung zurück), und nach jedem Videowechsel wird es neu
gesetzt (YouTube stellt beim Laden auf 1 zurück). Gesetzt wird nur,
was `getAvailablePlaybackRates()` hergibt — einen unmöglichen Wert
ignoriert der Player schweigend, und dann stünde der Knopf auf 1,5
und es liefe 1,0.

ZWEI ANORDNUNGEN MEHR
„Nur Video" und „Nur Kamera" sind kein weiteres Größenverhältnis,
sondern ein Weglassen — und genau das braucht OBS: Dort liegt die
Kamera ohnehin als eigene Quelle, die Bühnenseite soll sie nicht
doppelt zeigen. `display: none` und nicht `opacity: 0`: ein
unsichtbarer YouTube-Rahmen spielt weiter und hält den Ton.
Tasten 1–5, wie vorher 1–3.

DAS ZWEITE VIDEO — und warum es nicht die Warteschlange ist
Die Schlange ist eine Reihenfolge: eins nach dem anderen, das
Gespielte ist weg. Filipe will etwas anderes — zwei Videos
NEBENEINANDER, hin und her, und jedes merkt sich seine Stelle. Mit
der Schlange nachgebaut wäre es eine Schlange, aus der man nie wieder
herauskommt. Der Umschalter steht nur da, wenn es etwas zum Umschalten
GIBT; ein Knopf, der „kein zweites Video" antwortet, ist im Live eine
Falle. Getauscht wird in EINEM Schreibvorgang (BEGIN IMMEDIATE) —
ein Abbruch dazwischen hätte dasselbe Video auf beiden Seiten und die
gemerkte Stelle des anderen verloren. Und die Stelle kommt vom Host
und nicht aus der Datenbank: dort steht der Stand vom letzten Takt,
bis zu fünf Sekunden alt.
Was daneben bereitliegt, sieht nur, wer sendet — es ist die Rückhand,
und die verrät man nicht vorher (`zweit` ist aus `oeffentlich()`
ausgenommen).

DER FEHLER, DEN DIE MESSUNG GEFUNDEN HAT
Bei „Nur Kamera" war der Kamerabehälter 2175 px breit in einer
1072 px breiten Leinwand — von zwei Gästen stand nur einer im Bild,
der zweite lag hinter `overflow: hidden`. Auf dem Bildschirmfoto sah
das aus wie eine Anordnung für einen, und niemand hätte gefragt, wo
der zweite geblieben ist.
Zwei Ursachen: Die Leinwand ist ein Raster mit einer Spalte nach
Inhaltsbreite — ein zu breites Kind im Fluss zieht die Spalte mit, und
`width: 100%` bezog sich danach auf die gewachsene Spalte. Die
Begrenzung wuchs also mit dem, was sie begrenzen sollte; `max-width:
calc(50% - 8px)` rechnete gegen denselben Wert und war wirkungslos.
Jetzt `position: absolute; inset: 0` (kann das Raster nicht mehr
aufziehen) und `flex: 1 1 0; min-width: 0` an den Fenstern — eine
Regel, die nicht rechnet, kann sich nicht verrechnen.
Die Messung prüft seitdem bei JEDER Anordnung, ob alle Kamerafenster
innerhalb der Leinwand liegen.

GEMESSEN, NICHT ANGENOMMEN
Dass in der Datenbank 1.5 steht, sagt nichts darüber, ob das Video
schneller läuft. Die Messung liest deshalb die Uhr der Regie zweimal
ab und rechnet nach: 1× → 1,00 Sekunden je Sekunde, 2× → 2,00.
Der Umschalter ebenso: hin, zurück, und die Uhr steht wieder bei 79 s
statt bei 0.

GEPRUEFT
pruef-reaktion: 260 Prüfungen (vorher 216), 0 Fehler.
pruef-buehne 36, pruef-struktur, pruef-meldungen, pruef-tippziele,
pruef-css-klassen alle grün. mess-reaktion: Rückgabewert 0, kein
einziges ACHTUNG.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 09:48:26 +02:00
DogFatherGitandClaude Opus 5 a02cf5c026 Reaction: Rollen sichtbar, Moderation im Live-Chat
Filipes Wunsch: „die modis, linke hand und rechte hand soll im chat
extra aussehen und auch sachen wie stummschaltungen, sperrungen,
meldunge und alles mögliche im chat machen können falls sich jemand
nicht benimmt."

WER SPRICHT
Jeder Beitrag aus dem Team trägt jetzt ein Abzeichen: „Dogi", „Team"
(beide Hände) und „Modi". Ein WORT und nicht nur eine Farbe — rund
acht Prozent der Männer unterscheiden Rot und Grün schlecht, und hier
hängt an der Unterscheidung etwas. Gedeckte Töne auf schwacher Fläche,
11,52 px (die Hausgrenze ist 11,5), weil daneben ein Video läuft.
Die Wörter sagen den RANG nicht: Filipe steht nie über seinem Team.
Eine Prüfung schlägt an, wenn dort „Chef", „Boss" oder „Leitung"
stünde.

WAS DIE MODERATION KANN
Am Namen öffnet sich ein Menü mit vier Wegen: Beitrag wegnehmen,
10 Minuten stumm, aus der Sendung — und der Verweis in den Treff, wo
längere Maßnahmen hingehören (mit Begründungspflicht und Frist in
Tagen). Die Reaction baut kein zweites Sperrsystem daneben: Wer im
Treff eine Pause hat, schreibt hier auch nicht. Neu ist nur, was der
Treff nicht hat — MINUTEN. Höchstens eine Stunde; wer länger etwas
braucht, nimmt den Treff.
Nicht gegen das Team: Wer einen Modi stummschalten könnte, hätte einen
Weg, die Moderation selbst auszuschalten, mitten in der Sendung.

MELDEN DARF JEDER
Die Moderation sieht nicht alles, wer mitliest schon. Zweimal melden
zählt einmal (sonst füllt einer allein die Liste). Bei der Moderation
erscheint im Kopf der Schiene „1 Meldung" — nur wenn etwas offen ist;
eine Zahl, die immer dasteht und meistens null ist, wird nach drei
Tagen nicht mehr gelesen.

VIER FEHLER, DIE DABEI AUFGEFALLEN SIND

1. `oeffentlich()` nahm `meldungen` und `massnahmen` NICHT aus dem
   Rundruf. Der Rundruf wird aus dem Stand dessen gebaut, der gerade
   etwas getan hat — bei einer Moderationshandlung wären der gemeldete
   Text, der Name des Gemeldeten und der Name des MELDERS an jeden im
   Saal gegangen. Wer meldet, muss sich darauf verlassen können, dass
   das niemand sieht.

2. `meldung.js` hatte zwei Schlüssel doppelt: `geschlossen` und
   `nur_leitung`. Der spätere gewinnt stillschweigend — in der Hilfe
   stand dadurch „Der Saal ist zu". Ein Wort, ein Satz; eine Prüfung
   hält das jetzt fest.

3. Wer stummgeschaltet war, bekam bei OFFENEM Chat „Der Chat ist
   gerade zu" — der Aufrufer reimte sich den Grund aus der Chat-Stufe
   zusammen. Jetzt gibt `schreibGrund()` den echten Grund zurück.

4. Wer rausgenommen wurde, merkte nichts: Das Video lief weiter, nur
   die Anwesenheitsmeldung schlug still fehl. Jetzt hält alles an und
   es steht ein Satz da, der sagt, dass es nur für heute gilt.

UND EINER, DEN NUR DAS BILDSCHIRMFOTO GEFUNDEN HAT
Das Menü lag messbar komplett im Fenster (x=1099..1315 von 1440,
y=652..840 von 900) und war trotzdem abgeschnitten: Die Chatliste
rollt, und ein rollender Vorfahre beschneidet sein Kind. „Im Fenster"
und „sichtbar" sind zwei verschiedene Fragen, und ich hatte die
falsche gemessen. Das Menü hängt jetzt fest am Fenster und klappt nach
oben oder links, wo kein Platz ist. Die Messung fasst seitdem mit
`elementFromPoint` an jeden Knopf an, statt Rechtecke zu vergleichen.

GEPRUEFT
pruef-reaktion: 216 Prüfungen (vorher 156), 0 Fehler — zwei neue
Abschnitte. mess-reaktion misst die Moderation jetzt im echten
Browser: Abzeichen, Überlauf der Schiene, Menü, Stummschaltung beim
Betroffenen, Meldung bis zur Moderation, Rauswurf.
Dazu grün: pruef-meldungen, pruef-struktur, pruef-css-klassen,
pruef-tippziele, pruef-deutsche-texte, pruef-hilfe.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-28 09:32:10 +02:00
DogFatherGit cb8e59bb08 Eine Arbeitsdatei war mitgewandert
tools/.messkopf.txt ist ein Zwischenstand beim Bauen der Messung --
sie gehoert nicht in die Geschichte. Die uebrigen Zwischenstaende
stehen schon in .gitignore; dieser Name fehlte.
2026-09-28 09:08:59 +02:00
DogFatherGit 079cf8c74f Drei Quellen fuer OBS und TikTok Studio -- ohne Anmeldung, mit Schluessel
Filipe: "ich will das alles auch so perfekt dass ich es ganz einfach
und easy mit obs oder mit tiktok studio verbinden kann. also so dass
man dan nur die kamera und das video sieht."

WARUM OHNE ANMELDUNG -- nachgesehen, nicht angenommen

OBS speichert die Anmeldung einer Browser-Quelle NICHT zuverlaessig;
im OBS-Forum stehen dazu Meldungen bis in die aktuelle Fassung 31.
Eine Quelle, bei der man sich nach jedem Programmstart neu anmelden
muss, ist mitten in einer Sendung unbrauchbar.

Deshalb ein SCHLUESSEL in der Adresse -- derselbe Weg, den jedes
Alert-Werkzeug im Netz geht. 32 Byte aus dem Zufall des Systems,
verglichen wird zeitgleich (`timingSafeEqual`): Ein gewoehnlicher
Vergleich bricht beim ersten falschen Zeichen ab, und aus den
Bruchteilen einer Millisekunde laesst sich ein Schluessel Zeichen
fuer Zeichen erraten.

DREI QUELLEN, WEIL DREI DINGE VERSCHIEDEN SIND

  buehne.html   Das laufende YouTube-Video, auf die Sekunde genau wie
                bei allen anderen. Stumm (der Ton kommt aus dem
                Mischpult) und ohne jede Bedienung -- was hier zu
                sehen ist, geht in den Stream.

                DIE EIGENE KAMERA IST ABSICHTLICH NICHT DRIN. Sie ist
                in OBS direkt als Geraet verfuegbar, in besserer
                Qualitaet und frei in Groesse und Lage -- genau das,
                was Filipe will ("meine kamera groesser machen video
                kleiner"). Den Umweg ueber den Browser zu nehmen
                hiesse, Qualitaet gegen nichts einzutauschen und die
                Groesse festzulegen statt sie freizugeben.

  tafel.html    Nur die Spendenkarten, auf DURCHSICHTIGEM Grund.
                Groesse und Lage stehen in der Adresse (`&g=1.6`,
                `&pos=or`): Wer in OBS eine Quelle einrichtet, hat die
                Adresse ohnehin vor sich -- ein Wert, den man
                stattdessen im Regiepult suchen muesste, waere ein
                Fensterwechsel mitten im Einrichten. Alles rechnet in
                `rem`, ein Wert nimmt Schrift, Bild und Polsterung
                gleichmaessig mit.

  Buehnenmodus  `reaktion.html?nur=buehne` -- dieselbe Seite, nur ohne
                alles Bedienbare. Fuer den Fall, dass GAESTE im Bild
                sind: Deren Kameras kommen ueber eine
                Direktverbindung an, und die braucht eine angemeldete
                Seite. Diese eine wird als Fenster aufgenommen.

                ES IST DIESELBE SEITE UND NICHT EINE ZWEITE. Eine
                eigene muesste Video, Kameras, Verbindungsaufbau und
                Nachfuehrung noch einmal enthalten -- und beim
                naechsten Umbau saehe eine von beiden anders aus.

WAS HERAUSKOMMT, IST DIE EIGENTLICHE FRAGE

Wer den Schluessel hat, sieht genau das, was ohnehin im Stream
steht: Video, Stand, Sekunde, Titel -- und die Spendenkarten. Kein
Chat, keine Namen von Zusehenden, keine Zahlen ueber das Haus. Die
Pruefung zaehlt die Felder der Auskunft EINZELN auf und weist jedes
verbotene namentlich nach; eine Auskunft, die "ungefaehr das
Richtige" enthaelt, ist bei einem Weg ohne Anmeldung keine.

Ein neuer Schluessel macht die alten Adressen sofort tot -- und
schliesst die laufenden Quellen. Sonst liefe eine mit dem alten
weiter, obwohl er zurueckgezogen ist, und man haelt sich fuer
sicher, ohne es zu sein.

SIE MUESSEN TAGE LAUFEN, OHNE DASS JEMAND HINSIEHT

Das ist der Unterschied zu einer Seite im Browser: Wer eine Seite
offen hat, merkt, wenn sie haengt. Eine Quelle in OBS laeuft im
Hintergrund, und ein Stillstand faellt erst auf, wenn die erste
Spende nicht erscheint -- mitten in der Sendung. Deshalb ein
Lebenszeichen alle 25 Sekunden, eine eigene Wache (70 Sekunden ohne
alles = neu verbinden) und ein sofortiger Neuaufbau, wenn der
Rechner aus dem Ruhezustand kommt.

Und: Ein Fehler wird angezeigt, aber nur der, der etwas bedeutet --
ein falscher Schluessel. Alles andere bleibt still, weil jede
Flaeche hier im Stream zu sehen waere.

ZWEI EIGENE FEHLER, BEIDE VON DER MESSUNG GEFUNDEN

1. Die Quellen kamen mit 401 zurueck, obwohl die Seiten laengst
   geladen waren: `aufgabenRouter` haengt eine Schranke ueber ALLE
   Pfade unter /workspace/api. Genau dafuer stehen `sicherungRouter`
   und der Weg fuers Profilbild schon davor -- die Buehne ist der
   dritte Fall derselben Art und steht jetzt dort.

2. `waitUntil: "networkidle"` auf einer Seite mit Ereignisstrom. Der
   Strom endet absichtlich nie; die Messung wartete auf einen
   Zustand, der nicht eintreten kann, und brach nach 30 Sekunden ab.
   Dieselbe Falle wie am 06.09. beim Regressionslauf.

ZWEI PRUEFUNGEN WURDEN DABEI GENAUER

  `pruef-struktur` verlangte von den zwei OBS-Quellen ein Symbol fuer
  den Startbildschirm, ein Manifest und eine Leistenfarbe. Sie
  laufen in einem Programmfenster und werden nie installiert -- sie
  fallen aus dieser Frage heraus, benannt und mit Grund.

  Die Namensstreit-Regel zaehlte jede Klasse, die irgendwo in einem
  Selektor vorkommt. Damit galt auch
  `body[data-nur="buehne"] .kopfleiste { display: none }` als eigene
  Klasse -- dabei ist das das Gegenteil: eine absichtliche
  Bezugnahme, um sie im Buehnenmodus wegzunehmen. Gezaehlt wird
  jetzt nur, was am ANFANG einer Regel steht, also als eigenes
  Bauteil gemeint ist. Mit Gegenprobe in beide Richtungen -- sonst
  haette ich eine Regel nur so lange geschaerft, bis sie schweigt.

GEMESSEN

  mess-buehne     (neu) Ein Browserfenster OHNE jeden Keks: beide
                  Quellen arbeiten, 0 Kekse, Grund durchsichtig
                  (rgba(0,0,0,0)), Karte laeuft an (25 EUR,
                  Rudel-Legende, 348x178). Falscher Schluessel: kein
                  Inhalt, Grund im Bild. Neuer Schluessel: alter 404,
                  neuer 200. Buehnenmodus: Kopf, Chat, Pult und
                  Schild weg, Leinwand da, Saal 720 von 720.
  pruef-buehne    (neu) 36 Punkte, 0 Fehler
  pruef-reaktion  156 (war 154), spenden 46, haus-trennung 100,
                  haus-seiten 38, struktur 35, css-klassen 33,
                  verborgen 25, rechtetafel 19, portnummern 15,
                  ports 8 -- alle 0 Fehler.
2026-09-28 09:08:42 +02:00
DogFatherGit dcd0298700 Spenden: vier Knoepfe, eine Karte im Bild -- und die Wahrheit ueber PayPal
Filipe: "ich will dass das richtig perfekt gemacht wird so dass die
leute so einfach wie moeglich eine spende aufs paypal machen koennen.
und wenn jemand spendet soll auch der betrag erscheinen mit einem
bild."

WAS GEHT UND WAS NICHT -- NACHGESEHEN, NICHT ANGENOMMEN

Hinterlegt ist ein PayPal.me-Link auf ein PRIVATES Konto. Daraus
folgt zweierlei, und beides bestimmt den ganzen Aufbau:

  ES GEHT: `paypal.me/<name>/5EUR` oeffnet PayPal mit schon
  eingetragenem Betrag. Ein Tipp, fertig. Belegt an PayPals eigener
  Hilfeseite zu PayPal.Me.

  ES GEHT NICHT VON SELBST: PayPal meldet eine Zahlung nur, wenn ein
  Webhook oder IPN eingerichtet ist -- beides braucht Zugangsdaten,
  die nur Filipe selbst anlegen kann. Ob ein PRIVATES Konto das
  ueberhaupt kann, sagt PayPals eigene Doku nicht eindeutig; ich habe
  es gesucht und nicht gefunden, und etwas zu behaupten, das ich
  nicht belegen kann, waere hier das Gefaehrlichste.

DESHALB DREI HERKUENFTE UND NICHT EINE

  "hand"      Filipe sieht die PayPal-Meldung auf dem Handy und tippt
              den Betrag ins Pult. Geht immer, braucht nichts, ist in
              drei Sekunden getan, und die Karte laeuft sofort.
  "gemeldet"  Der Zuschauer sagt nach dem Spenden selbst Bescheid.
              Landet als OFFEN und wird erst gezeigt, wenn die
              Leitung es bestaetigt.
  "paypal"    Kommt automatisch, sobald ein Webhook eingerichtet ist.
              Bis dahin steht dieser Weg leer da -- die Tabelle und
              die Sperre gegen doppelte Zahlungsnummern sind schon
              fertig.

WARUM EINE MELDUNG NICHT SOFORT ERSCHEINT: Sonst tippt irgendwer
"500 Euro" und steht damit gross im Bild. Eine Spende ist eine
Aussage ueber Geld; die gehoert bestaetigt, bevor sie oeffentlich
wird. Der Weg dahin ist EIN Tipp -- billig genug, dass niemand in
Versuchung kommt, ihn abzukuerzen. Beim Bestaetigen darf der Betrag
berichtigt werden: Die Leitung hat die PayPal-Meldung vor sich und
weiss es besser als die Behauptung.

FUER DIE ZUSCHAUER

Vier Betraege im Chat (2, 5, 10, 25 EUR) statt eines Links. Wer eine
Liste sieht, rechnet; wer vier Knoepfe sieht, tippt. Die Adresse wird
NICHT zweimal gepflegt -- sie steht auf der Unterstuetzen-Seite, und
von dort wird sie gelesen. Steht dort nichts oder ist der Weg auf
unsichtbar, gibt es hier auch keine Knoepfe. An einer Adresse, die
kein paypal.me ist, wird kein Betrag angehaengt: Er fuehrte sonst zu
einer Seite, auf der etwas anderes steht als auf dem Knopf.

DIE KARTE

Betrag gross, Name, Gruss, ein Bild dazu -- und eine Farbe, die von
der Stufe kommt. Drei Stufen ab Werk: Danke (ab 1), Starke Runde (ab
5), Rudel-Legende (ab 20), je mit eigener Vorlage, Farbe und Dauer.
Gilt immer die HOECHSTE, die noch passt; mit Ober- UND Untergrenze je
Stufe waere die doppelte Gelegenheit, eine Luecke zu lassen -- durch
die faellt dann ausgerechnet der grosse Betrag.

EINE NACH DER ANDEREN. Drei Spenden in zehn Sekunden sind keine
Seltenheit; uebereinander gelegt waere keine mehr lesbar, und
ausgerechnet die groesste ginge unter. Bei voller Schlange werden die
Zeiten gekuerzt, nicht die Karten weggeworfen -- wer gegeben hat,
soll es sehen.

DIE KARTE IST EIN EIGENES STUECK (spendenkarte.js/.css) und haengt an
nichts aus der Reaction. Dieselbe Karte laeuft spaeter als eigene
Seite fuer OBS und TikTok Studio; zweimal gebaut hiesse, sie sieht
nach der naechsten Aenderung an einem der beiden Orte anders aus --
und man merkt es erst im Livestream.

DER BETRAG STEHT IN CENT

Nie als Kommazahl. 0.1 + 0.2 ist in keiner Programmiersprache 0.3,
und bei Geld faellt das irgendwann jemandem auf -- meistens dem, der
zahlt. Formatiert wird erst auf dem Bildschirm.

DREI EIGENE FEHLER, VON DEN PRUEFUNGEN GEFUNDEN

1. Ein Weg aus einer Verzweigung: `/spenden/${id}/${ja ?
   "bestaetigen" : "ablehnen"}`. `pruef-struktur` hat das zu Recht
   beanstandet -- ein Tippfehler im selteneren Zweig faellt erst auf,
   wenn er mitten in einer Sendung gebraucht wird. Beide Wege stehen
   jetzt ausgeschrieben da.

2. "Genau 5 Register" -- zweimal am selben Tag dieselbe feste Zahl,
   in der Messung UND in der Pruefung. Beim sechsten Register wurden
   beide rot, obwohl nichts kaputt war. Jetzt wird gezaehlt: zu jedem
   Reiter gehoert eine Tafel, und keine steht ohne Reiter da.

3. Die Messung war zu ungeduldig: Die erste Karte laeuft elf
   Sekunden (die hoechste Stufe steht am laengsten), die zweite
   wartet in der Schlange -- richtig so. Die Messung wartete 1,6
   Sekunden und meldete "laeuft nicht". Jetzt wird auf das Merkmal
   gewartet, nicht auf die Uhr.

GEMESSEN

  mess-reaktion   4 Betragsknoepfe mit richtiger Adresse.
                  25 EUR von Hand -> Karte "Rudel-Legende" bei der
                  Zuschauerin. 500 EUR gemeldet -> steht NICHT im
                  Bild, wartet im Pult. Bestaetigt mit berichtigten
                  10 EUR -> Karte "Starke Runde". Stufe passt zum
                  Betrag, beide Male.
  pruef-spenden   46 Punkte, 0 Fehler (neu) -- darunter die
                  Gegenprobe, dass ohne Zahlungsnummer beliebig viele
                  Zeilen nebeneinander stehen duerfen (sonst liesse
                  sich nur EINE Spende von Hand eintragen).
  pruef-reaktion  154, unterstuetzung 70, aufbewahrung 45,
                  struktur 35, css-klassen 33, portnummern 15,
                  tippziele 11, ports 8, meldungen 8 -- alle 0 Fehler.

SCHEMA: zwei Tabellen (spenden, spenden_stufen) mit einem
Einmalig-Index auf die Zahlungsnummer. Auf einer Kopie der echten
Datenbank durchgespielt: 20 Personen, 227 Chatnachrichten, keine
Tabelle verliert eine Spalte.
2026-09-28 08:34:42 +02:00
DogFatherGit 28b492527e Kamera und Chat -- die zwei fehlenden Host-Steuerungen
Filipes Notiz nennt acht: "Host-Steuerung fuer Kamera, Mikrofon,
Video, Gaeste, Lautstaerke, Chat, Layout und Start/Ende."
Nachgezaehlt war sechsmal etwas da und zweimal nichts.

KAMERA

Es gab keinen Weg, das eigene Bild abzuschalten. Wer kurz aufstehen,
trinken oder etwas holen wollte, musste die Sendung verlassen oder
sich dabei filmen lassen.

Jetzt liegt eine SENDERLEISTE ueber dem Bild -- Kamera, Mikro und ein
Pegel. Sie gehoert jedem, der sendet, Host wie Gast: Ein Gast, der
sein eigenes Bild nicht abschalten kann, muesste den Host darum
bitten, und das ist keine Bedienung, sondern eine Bitte.

DAS BILD WIRD AM GERAET ABGESCHALTET (`track.enabled = false`), nicht
am Server: Die Verbindung bleibt stehen, der Ton laeuft weiter, und
beim Wiedereinschalten ist das Bild sofort da. Der Server erfaehrt es
nur, damit bei den ANDEREN "Kamera aus" im Fenster steht. Ohne diese
Beschriftung sind ein abgeschaltetes und ein kaputtes Bild dasselbe
schwarze Rechteck -- und dann fragt jemand im Chat, ob die Technik
hakt.

Erst das Geraet, dann die Ansage. Andersherum stuende bei allen
"Kamera aus", waehrend noch ein Bild fliesst; man glaubte sich
unsichtbar. Geht die Ansage nicht durch, wird das Geraet
zurueckgesetzt -- ein Knopf, der halb wirkt, ist schlimmer als einer,
der gar nicht wirkt.

Das Mikro laeuft denselben Weg. Erst wollte ich es rein oertlich
lassen; das waere dieselbe stille Falle gewesen: Wer sich selbst
stummschaltet und trotzdem redet, saehe bei allen anderen ein ganz
normales Fenster.

CHAT

Es gab Moderation -- Beitraege wegnehmen -- aber keine Steuerung des
Chats selbst. Einen Beitrag zu loeschen, nachdem er stand, ist etwas
anderes, als ihn gar nicht erst zuzulassen.

Drei Stufen: OFFEN, TEAM (wer moderiert, darf -- wer aufraeumen soll,
muss dabei reden koennen) und ZU (nur die zwei, die fuehren). Zwei
Stufen waeren zu wenig: "zu" ist in einer Sendung fast immer zu viel,
dann sitzen alle vor einem stummen Fenster. Die mittlere ist die, die
man wirklich braucht.

Die Schalter stehen im Kopf der Chatschiene, nicht im Regiepult: Man
moderiert, wo man liest. Ein Umweg ueber ein Register waere in dem
Moment, in dem es laut wird, genau ein Umweg zu viel.

EIN GESPERRTES FELD SAGT, WARUM. "Gerade schreibt nur das Team" statt
eines Feldes, das sich nicht beschreiben laesst und schweigt --
sonst schreibt jemand in den Hauschat, dass die Reaction hakt. Und
die Stufe gilt AM SERVER: Ein ausgegrautes Feld haelt niemanden auf,
der die Schnittstelle kennt. Beide Antworten kommen aus derselben
Funktion; zwei Rechnungen waeren zwei Gelegenheiten, dass ein Feld da
ist und mit 403 antwortet.

EIN FUND NEBENBEI: "MEIN MIKRO" WAR EIN PLACEBO

Gemessen: `staende.mikro` wird nirgends gelesen. Der Schieber liess
sich bewegen, die Zahl daneben aenderte sich -- und es passierte
nichts. Das ist schlimmer als ein fehlender Regler: Man glaubt, man
haette leiser gestellt.

Technisch ist das auch richtig. Die eigene Lautstaerke laesst sich
nicht am Regler aendern; man muesste den Ton umrechnen und die Spur
in jeder Verbindung austauschen. Was man beim eigenen Mikro braucht,
ist AN oder AUS -- und ein Pegel, der zeigt, dass es ankommt. Genau
das steht jetzt dort, als vierte Spalte im Pult, mit demselben
Zustand wie die Senderleiste. Die drei anderen Regler bleiben Regler:
Sie steuern, was ICH hoere, und das geht am Empfaenger.

UND EINER IN MEINER EIGENEN ARBEIT

`kasten.append(el("div","pegel")).append(el("i"))` -- `Node.append()`
gibt `undefined` zurueck, nicht das angehaengte Element. Ein
TypeError beim Aufbau des Pults, den `node --check` nicht sieht.
Beim Verkuerzen nicht nachgesehen, was die Methode zurueckgibt.

Dazu: Die Pegel-Takte liefen in `pultAufbauen()`. Das Pult hat nur,
wer die Sendung fuehrt -- ein Gast haette seinen Pegel nie gesehen,
und genau er braucht ihn am dringendsten.

GEMESSEN

  mess-reaktion   Der Host schaltet ab, und bei der Zuschauerin steht
                  "Kamera aus" bei DogFather, Bild verdeckt.
                  Stufe "Team": Feld gesperrt mit Grund, und der
                  Server lehnt denselben Versuch mit 403 ab.
  pruef-reaktion  154 Punkte, 0 Fehler (vorher 132), neuer Abschnitt
                  13 mit 22 Punkten und Gegenprobe (es geht auch
                  wieder auf -- eine Sperre, die man nicht loesen
                  kann, ist keine Stufe, sondern ein Ende)
  dazu gruen      handy 180, css-klassen 33, struktur 35,
                  tippziele 11, aufbewahrung 45, meldungen 8

Der neue Abschnitt baut sich seine Buehne selbst. Abschnitt 9 beendet
die Sendung; sich auf den Stand eines frueheren Abschnitts zu
verlassen ist die Kopplung, die spaeter jemand aus Versehen
zerreisst.

SCHEMA: drei Spalten (reaktion_dabei.kamera_aus, .mikro_aus,
reaktion.chat_modus), alle per ALTER TABLE. Auf einer Kopie der
echten Datenbank durchgespielt: 20 Personen, keine Tabelle verliert
eine Spalte.
2026-09-28 08:16:49 +02:00
DogFatherGit d79f6faa23 Die Reaction-Kachel steht hinter Dogi-Media
Filipe: "die kachel von der kategorie, reaktion, soll nach der
kachel, dogi-move, erscheinen bitte und danke."

EINE KACHEL "DOGI-MOVE" GIBT ES NICHT -- das Wort kommt im ganzen
Haus nicht vor. Die einzige, die passt, ist "Dogi-Media" (Bilder und
Videos zum Posten). Dorthin ist sie gesetzt; sollte etwas anderes
gemeint gewesen sein, ist es eine Zeile zurueck.

Die Reihenfolge der Community-Kacheln ist damit:

  Willkommen - Rudel-Chat - Highlights - Anschlagbrett -
  Was ansteht - Wunschliste - Dogi-Media - REACTION - Draussen

Geprueft: reaktion 132, kachelraster 24, kachel-universum 13 --
alle 0 Fehler.

Die angefangene Arbeit an der Host-Steuerung (Kamera- und
Chat-Spalten) bleibt bewusst im Arbeitsstand: Sie ist unfertig und
hat in dieser Lieferung nichts zu suchen.
2026-09-28 08:04:07 +02:00