Commit Graph
316 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 06f3fecaa7 Material: Bilder und Videos zum Posten, jedes nur einmal
Filipe, 22.09.2026: "ich brauch auch noch eine neue kachel im bereich
community, wo wir als team ... bilder reinschicken koennen, mit text
und wo die leute sei es community oder modis sich die bilder nehmen
koennen zum posten. die community soll keine posten koennen ... sobald
ein bild oder ein video ... runtergeladen wurde, soll direkt blockiert
werden ... damit nie ein bild zwei mal gepostet wird ... und die rechte
hand und dogfather, nur die beiden sollen auch immer sehen koennen wer
das bild oder video runtergeladen hat."

DER KERN IST DIE EINMALIGKEIT, und deshalb sind Nehmen und Laden ZWEI
Schritte. "nehmen" schreibt in EINER Abfrage fest, wer es hat -- mit
`WHERE genommen_von IS NULL` in der Bedingung. Wer zu spaet kommt,
aendert null Zeilen und bekommt 409. Ein einziger Schritt ("laden und
dabei markieren") haette dieselbe Luecke wie ein Pool ohne Sperre:
zwei Anfragen, beide sehen "frei", beide laden.

UND DIE SPERRE GILT AUCH FUER DIE VORSCHAU. Waere sie offen
geblieben, waere sie der Weg, ein vergebenes Bild doch noch zu
bekommen (Rechtsklick, speichern) -- und die ganze Einmaligkeit eine
Behauptung. Ausnahme: wer es selbst genommen hat, sieht es weiter.

WER WEN SIEHT, entscheidet der Server, nicht die Seite. Fuer alle
ausser DogFather und der rechten Hand fehlt das Feld `genommen_von`
ganz -- nicht `null`: Ein Feld, das da ist und leer bleibt, laedt
dazu ein, es spaeter "zu fuellen".

pruef-material.mjs (70 Pruefungen, 0 Fehler) misst den ganzen Weg,
mit Gegenprobe zu jeder Grenze. Die Zahl der vergebenen Stuecke steht
in der BEDINGUNG -- ohne sie waere "keine Namen dabei" trivial wahr.

DREI DINGE HAT ERST DER BLICK MIT ECHTEN AUGEN GEFUNDEN
(tools/material-blick.mjs, drei Rollen, vier Bildschirmbreiten):

  * "hat es genommen am 22.09.." -- eine deutsche Datumsangabe endet
    selbst auf einen Punkt. Kein Pruefprogramm haette danach gefragt.
  * Die Knoepfe standen auf drei verschiedenen Hoehen (1127, 1155,
    1176), weil der eine Text zwei Zeilen hatte und der naechste
    keine. `margin-top: auto` am Fuss statt einer geratenen
    Mindesthoehe.
  * "Schon benutzt" nahm 273 px Hoehe je Stueck fuer ein einziges
    Zeichen -- das Bild ist dort ohnehin nicht mehr abrufbar. Jetzt
    eine Zeile mit 96 px.

Am Handy (412 px) blieb es bei EINER Spalte: 3062 px Seitenhoehe fuer
fuenf Stuecke. Filipe: "es ist alles so lang gezogen, muss ewig
scrollen". Statt einer festen Umbruchschwelle -- die am 06.09. schon
zweimal teuer war -- waechst die Spaltenbreite jetzt mit:
`max(160px, 22%)`. Gemessen 360/412/768/1500 px: 2/2/3/3 Spalten,
nirgends ein Ueberlauf, 412 px jetzt 2014 statt 3062 px.

Dazu neun Saetze in meldung.js. Der wichtigste ist "schon_genommen",
und er ist bewusst kein Fehler: Wer ihn liest, hat nichts falsch
gemacht. pruef-meldungen fand dabei einen Rest aus dem Aufgaben-Block
-- `nur_leitung_legt_an` hatte keinen Satz, ein Modi mit altem Tab
haette rohen Maschinentext gelesen.

pruef-material 70/0 · pruef-meldungen 8/0 · pruef-treff 80/0
pruef-rechtetafel 19/0 · pruef-sackgassen 13/0 · pruef-css-klassen ok
pruef-zwischenspeicher 27/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 02:27:21 +02:00
DogFatherGit e4c6d69ce8 "Wie geht's dir?" -- lesbar und um ein Drittel kuerzer
Filipe: "auf der seite von der kategorie wie gehts die, sind die
kacheln viel zu hell, man bekommt fast nichts gelesen, die sollen viel
kraeftiger und dunkler sein. ich will dass auch alles viel
uebersichtlicher ist, es ist alles so lang gezogen, muss ewig scrollen
um alles zu sehen."

BEIDES GEMESSEN, BEVOR ICH ETWAS ANGEFASST HABE:

  Kachelgrund   rgba(0, 0, 0, .2) -- also 80 % durchsichtig. Die Seite
                traegt ein helles Buehnenbild (Husky, Hase, viel
                Licht), und das schien mitten durch den Text.
  Laenge        2487 px am Rechner, 3431 px am Handy. 3,4 Bildschirme
                fuer neun Fragen.

DIE LESBARKEIT: Die Kacheln sind jetzt deckend -- und nicht schwarz,
sondern einen Hauch heller als die Seite, damit sich eine Frage von
der naechsten abhebt. Gemessen mit pruef-buehne: schlechtester
Kontrast 4.95:1 an 39 gemessenen Stellen (noetig 4.5).

DIE LAENGE -- gespart wurde an Weissraum und Wiederholung, NICHT an
Text. Die Erklaerung unter jeder Frage ist der Grund, warum man sie
ehrlich beantwortet.

  Vier Knoepfe, eine Reihe. Gemessen waren sie 94 von 214 Pixeln je
  Frage -- zwei Reihen, also 450 Pixel Scrollweg allein aus Umbruch.
  Gerechnet: 390 minus 28 Innenabstand minus drei Luecken, geteilt
  durch vier = 86 px je Knopf. "Kann ich nicht sagen" braucht mehr,
  "Unklar" nicht. Der LANGE Name bleibt im `aria-label` -- wer hoert
  statt sieht, bekommt weiterhin den ganzen Satz.

  Die Marke "jede Runde" steht neben der Frage statt darunter. Sie ist
  eine Eigenschaft der Frage, keine eigene Zeile.

  Zwei Spalten am Rechner. Bei 880 px Inhaltsbreite und Fragen, die
  keine 400 brauchen, halbiert das den Weg, ohne eine Frage zu
  verstecken. `break-inside: avoid` ist dabei der Kern -- sonst steht
  die Antwortreihe in der anderen Spalte.

ERGEBNIS: Rechner 2487 -> 1770 px, Handy 3431 -> 2781 px. Eine
Fragekachel am Handy 228 -> 139 px.

Und ein Fehler, den nur das Bildschirmfoto gezeigt hat: Mein erster
Anlauf sparte die Kurzform, wenn sie dem Namen gleicht -- bei "Laeuft"
ist das so. Am Handy ist die lange Fassung ausgeblendet, und der Knopf
zeigte dann nur noch das Haekchen.

Geprueft: pruef-befinden 113/0, pruef-resuemee 35/0,
pruef-entwicklung 48/0, pruef-buehne fuer diese Seite 10/0.
2026-09-22 02:02:46 +02:00
DogFatherGit bc9a902ffb Die Knoepfe stehen nicht mehr vor dem Text -- und verteilt wird bei "Eure Aufgaben"
ZWEI WUENSCHE, EINE URSACHE: beide gehen auf den Block "Noch jemanden
dazunehmen" zurueck, der am 21.09. ins Aufgabenformular kam.

1. "DIE ZWEI BUTTONS SOLLEN NICHT VOR DEM TEXT STEHEN"

Gemessen bei 1280 px: "Anlegen" und "Abbrechen" lagen ueber zwei
Hinweisen, mit 363x27 und 363x10 Pixeln Ueberlappung.

Die Ursache ist eine Regel vom 17.09., und sie ist richtig: Der
Hinweis haengt ABSOLUT unter seinem Feld, damit die Eingaben auf einer
Linie bleiben. Was aus dem Fluss genommen wird, belegt aber keinen
Platz -- solange darunter nur der Rasterabstand kam, fiel das nicht
auf. Mit dem neuen Knopf wurde die Zelle hoeher, und der Hinweis
wanderte mit, direkt auf die Knoepfe.

Jetzt bekommt das Raster unter sich 44 px, wenn es einen haengenden
Hinweis gibt (`:has()`, nicht pauschal -- ein Formular ohne Hinweis
bekaeme sonst Leere geschenkt). Die Hoehe ist gemessen: ein Hinweis
ist zweizeilig 35 px hoch plus 4 px Abstand.

UND EIN ZWEITER FUND AN DERSELBEN STELLE: Der Block sass IN der Zelle
"Wer macht es?". Dadurch stand deren Eingabe bei 780..824, die
Nachbarin "Fuer welchen Kanal?" bei 833..877 -- 53 Pixel Versatz, und
genau das sieht man als "verzogen". Er steht jetzt als eigene
Rasterzeile hinter beiden; danach sind sie wieder buendig. Als eigene
Zeile ist er ausserdem ehrlicher: "Noch jemanden dazunehmen" ist ein
zweiter Schritt, kein Teil des ersten.

Gefunden hat beides pruef-formulare, die seit dem 07.09. auf buendige
Unterkanten prueft und seit dem 21.09. rot war.

2. "BEI EURE AUFGABEN DIE AUFGABEN VERTEILEN"

Filipe, zum wiederholten Mal -- und so stand es auch im Auftrag vom
21.09. (Abschnitt 2). Auf "Eure Aufgaben" steht jetzt ein Band
"Aufgabe verteilen". Es nimmt die gerade gewaehlte Person mit:
"Aufgabe fuer Kessi" fuehrt auf das Aufgabenbrett, oeffnet das
Formular und traegt sie ein.

EIN WEG, KEIN ZWEITES FORMULAR. Zwei Formulare fuer dieselbe Sache
waeren zwei Gelegenheiten, eines zu vergessen -- und man wuesste nie,
welches das richtige ist.

Beim Bauen gemessen: Das Band blieb unsichtbar, bis man eine Person
anklickte -- `window.__ich` kommt ueber das Netz und steht beim ersten
Aufruf noch nicht. Jetzt wird darauf gewartet, laengstens drei
Sekunden, statt eine Zahl aus dem Kopf zu setzen.

Zwei Pruefungen waren selbst kaputt: pruef-formulare zaehlte ein
Eingabefeld mit, das in einem zugeklappten Block liegt und Hoehe 0 hat
-- ein Feld, das man nicht sieht, kann nicht schief stehen.
pruef-entwicklung verlangte, dass ein Modi "Eure Aufgaben" NICHT
bekommt; das hat Filipe heute umgedreht.

Geprueft: pruef-formulare 19/0 (war 18 ok / 1 FEHL), pruef-entwicklung
48/0 (war 45/1), pruef-aufgabenbrett 49/0, pruef-css-klassen 30/0.
Der ganze Weg am Bildschirm gemessen: Band sichtbar, Person mitgenommen,
Formular offen, richtige Person gewaehlt, keine Skriptfehler.
2026-09-22 01:57:08 +02:00
DogFatherGit 4b87f27451 Niemand erfaehrt, was er nicht hat -- und die Kacheln tragen ihre Farbe
ZWEI WUENSCHE, DIE ZUSAMMENGEHOEREN: die Willkommensseite.

1. "KEINER SOLL WISSEN WAS ER NICHT SIEHT"

Filipe: "das geht keinen was an. sie sehen die sachen ja nicht weil es
sie nichts angeht und das muss auch nicht erwaehnt werden.
kontrollier das ueberall bitte."

Durchgesehen: Das Haus macht es ueberall sonst schon richtig -- der
Server antwortet mit 404 statt 403, damit ein "das darfst du nicht"
gar nicht erst verraet, dass es etwas gibt. GENAU ZWEI Stellen taten
das Gegenteil, beide auf der Willkommensseite:

  der Hinweis "Was du nicht siehst" (linke Hand),
  und in ihrer Einleitung "Was du NICHT hast: Personen anlegen,
  Rollen aendern und den vertraulichen Meldeweg".

Beide entfernt, der Hinweis mit einem Kommentar an seiner Stelle --
damit ihn niemand spaeter "nachtraegt", weil er ihn fuer vergessen
haelt. Im Kopf derselben Datei stand die Ueberlegung uebrigens schon:
"Eine Liste von Dingen, die man nicht darf, ist keine Orientierung,
sondern eine Kraenkung."

Die Pruefung verlangte bis heute das GEGENTEIL ("ihr wird gesagt, was
sie nicht hat"). Sie misst jetzt alle fuenf Rollen gegen acht Muster,
mit Gegenprobe -- das "ueberall" aus dem Auftrag.

2. DIE FARBEN DER STARTSEITE

Der Server reicht `ton` durch, die Kachel traegt `data-ton="N"`, und
start.css macht daraus `--ton`. Keine eigene Farbtabelle: Die waere
die, die beim naechsten Farbwechsel stehen bleibt -- genau das ist am
19.09. elf Seiten passiert.

Drei Stellen tragen die Farbe, keine davon eine Flaeche: das Zeichen,
eine schmale Kante links und ein leiser Schimmer in der oberen Ecke.
Eine eingefaerbte Kachelflaeche waere bunt und schlecht lesbar.

UND EIN FEHLER, DEN NUR DAS MESSEN GEZEIGT HAT: Mein erster Anlauf
setzte `--ton: var(--akzent)` als Vorgabe auf `.w-kachel`. Gleiche
Spezifitaet wie `[data-ton="N"]` in start.css -- und willkommen.css
laedt SPAETER. Ergebnis: 0 von 14 Kacheln trugen die richtige Farbe,
alle waren blau. Der Rueckfall gehoert an die Verwendung
(`var(--ton, …)`), nicht an die Deklaration. Danach: 14 von 14.

Geprueft: pruef-willkommen 67/0, pruef-css-klassen 30/0.
2026-09-22 01:43:31 +02:00
DogFatherGit 82335c783d Die rechte Hand legt selbst Personen an -- und sieht die Codes
Filipe: "dan will ich dass die rechte hand auch neue personen
hinzufuegen kann. also neue erstellen kann und die codes genau so
sieht wie dogfather, damit sie das auch machen kann wenn er live ist."

WAS SIE DARF: Modis und Community anlegen, und deren Codes neu setzen.
Die Liste ist ABGELEITET aus ROLLEN_ZUM_AENDERN -- dieselben zwei
Rollen, die sie ohnehin vergeben darf. Zwei Listen waeren zwei
Gelegenheiten, eine davon zu aendern und die andere zu vergessen.

WAS SIE NICHT DARF: eine zweite rechte Hand, eine linke Hand oder
einen zweiten DogFather anlegen -- und an einer linken Hand auch
nichts aendern. Ohne die zweite Schranke haette sie den Code einer
linken Hand neu setzen koennen und damit einen Zugang in der Hand, der
fast so viel darf wie sie selbst. Die alte Schranke kannte nur "admin"
und "manager".

NUR DIE RECHTE, NICHT DIE LINKE. `istHand()` haette beide getroffen;
fuer die linke Hand ist "legt niemanden an" eine ausdrueckliche
Entscheidung vom 21.09.

VIER STELLEN IN DER OBERFLAECHE, die alle an Rollennamen hingen:

  `nurLesen = ich.rolle === 'hand'` -- sie bekam die Liste und kein
  Formular. Jetzt abgeleitet aus `darf_anlegen`.

  Die Wache darueber warf sie auf die Startseite, sobald `nurLesen`
  falsch wurde. Die Seite ging fuer sie einfach nicht auf, ohne
  Meldung.

  Der Sendeweg hing an `ich.rolle === 'admin'`. Fuer sie gab es damit
  GAR KEINEN: Die Seite antwortete "Fuer die Rolle modi gibt es hier
  keinen Weg" -- ein Satz, der wie ein Formularfehler klingt und eine
  fehlende Zeile war.

  UND EIN ECHTER FUND: `rollenwahlErgaenzen()` hing jede Zusatzrolle an
  das Formular, die mit der Personenliste kam -- ohne zu fragen, ob man
  sie anlegen darf. Solange nur DogFather das Formular sah, fiel es
  nicht auf: Er darf sie alle. Der rechten Hand bot es "rechte Hand"
  und "linke Hand" an. Der Server haette es abgelehnt -- aber der Knopf
  verriet eine Rolle, die sie nicht vergeben soll.

Zwei Pruefungen waren dabei selbst kaputt: pruef-personen-formular
erwartete sieben Rollen (seit "linke" am 21.09. sind es acht) und
suchte den Namen im sichtbaren Text -- die Abschnitte sind zugeklappt
und zeigen nur Anfangsbuchstaben. Beides abgeleitet statt gezaehlt.

Geprueft: pruef-personen-formular 43/0 (war 34 ok / 2 FEHL), davon
neun am echten Bildschirm auf der Crew-Adresse -- anmelden, Formular
oeffnen, anlegen, Code lesen, Person in der Liste wiederfinden.
pruef-haus-trennung 81/0 (war 72 ok / 2 FEHL), pruef-rollen-anlegen
11/0.
2026-09-22 01:39:12 +02:00
DogFatherGit 39c0b4dc1f Ein Modi sieht nur SEINE Aufgaben -- und gibt sich selbst keine
Filipe, unmissverstaendlich und mehrfach: "die modis sollen immer nur
ihre aufgaben auch sehen und nicht die von anderen, so wie bei den
daten ... damit wir endlich den modis aufgaben anstaendig verteilen
koennen und sie sich nicht selber aufgaben geben."

DAS DREHT DIE ENTSCHEIDUNG VOM 09.09. AUSDRUECKLICH UM. Damals: "ja,
sie sind untereinander ein team", damit ein Schichttausch ohne Umweg
geht. Beides steht jetzt im Code nebeneinander, damit niemand spaeter
die aeltere findet und fuer die gueltige haelt.

VIER AENDERUNGEN:

  Die Sicht. Ein Modi sieht nur `a.verantwortlich_id = ich`. Was ihm
  ueber aufgaben_zuteilung gegeben wurde, haengt mitZugeteilten() an --
  ein Pool, in dem er steht, bleibt also sichtbar, bis ihn jemand
  uebernimmt. Die rechte und die linke Hand behalten die Uebersicht.

  Das Anlegen. Im Team Dogi legt nur an, wer auch verteilen darf. In
  der AGENTUR bleibt es, wie es war -- dort ist eine Aufgabe eine
  Notiz an sich selbst, kein Auftrag von jemandem. Eine Regel, die
  beide Haeuser ueber einen Kamm schert, waere falsch.

  Der Knopf. "Neue Aufgabe" steht fuer einen Modi gar nicht mehr da.
  Ein Knopf, der mit 403 antwortet, ist schlimmer als keiner: Die
  Meldung erscheint ganz oben, und wer weiter unten steht, sieht nur,
  dass nichts passiert.

  Die Kacheln. Ein Modi sieht jetzt den Bereich "Entwicklung &
  Nachwuchs" mit denselben zwei Kacheln wie die Leitung -- nicht mehr
  zwei eigene mit anderem Namen. Zwei Namen fuer dieselbe Sache ist
  genau der Fehler, der am 19.09. zwei Kacheln "Chat" ergeben hat.
  "Talente" bleibt draussen: Dort stehen Notizen ueber Zuschauer, die
  nichts davon wissen.

UND DIE LINKE HAND SIEHT "DEIN TEAM" NICHT MEHR (Filipes Wunsch).
Abgeleitet, nicht nachgebaut: Ihre Liste ist die der rechten Hand
MINUS dieser einen Kachel, erkannt am ZIEL statt am Namen -- der Name
ist am 17.09. schon einmal gewandert.

Gemessen: admin 30 Kacheln, hand 30, linke 29 (ohne "Dein Team"),
modi 25 (mit dem Bereich, ohne Talente).

Zwei Pruefungen hielten die alte Regel fest und wurden dadurch rot --
genau ihre Aufgabe. Beide umgedreht, mit der alten Entscheidung im
Kommentar. pruef-zuteilung 65/0, pruef-verteilen 19/0 (war 15),
pruef-aufgabenbrett 49/0.
2026-09-22 01:17:11 +02:00
DogFatherGit ea32d6790b Das Auge ist am Finger ein volles Ziel -- und die Leiste bleibt eine Reihe
Filipe zur offenen Entscheidung "36-px-Auge oder 44-px-Fingerziel":
"mach was du am besten haelst es soll nur immer alles einfach zu
bedienen sein und geil aussehen fertig."

DIE ENTSCHEIDUNG WAR EINE SCHEINALTERNATIVE. Gemessen am echten
Aufbau, statt der Notiz zu glauben:

    Breite    Auge      uebrige Knoepfe   Leiste
    360 px    42 x 44   alle 44 x 44      zwei Reihen
    390 px    42 x 44   alle 44 x 44      zwei Reihen
    412 px    34 x 44   alle 44 x 44      eine Reihe
    1280 px  116 x 32   mit Beschriftung

Die HOEHE stimmte laengst. Es fehlten zwei Pixel Breite -- bei 412 px
zehn. Der Umschalter war als einziger Knopf der Leiste kein volles
Ziel, und ausgerechnet er sitzt zwischen zwei anderen.

ZWEIMAL DIE ALTE FALLE AUF DEM WEG:

  Erster Anlauf vergroesserte nur den Knopf. Gemessen bei 412 px:
  Knopf 44, Behaelter 36 -- der Knopf ragte 3 px ueber den Nachbarn.
  Genau so lag am 11.09. der Umschalter ueber dem Chat-Knopf, und wer
  "Meine Sicht" antippte, landete im Chat. Die Lehre von damals steht
  in start.css ("wer nur den Rahmen begrenzt, begrenzt nichts") und
  gilt andersherum genauso.

  Danach brach die Leiste bei 412 um -- "Abmelden" in einer zweiten
  Zeile, genau Filipes Beanstandung vom 09.09. Gerechnet: 386 px
  noetig, 380 verfuegbar. Sechs Pixel. Sie kommen jetzt aus dem
  Weissraum (4->2 zwischen den Zeichenknoepfen, 10->6 zur linken
  Gruppe), nicht aus den Tippzielen -- am Ziel zu sparen ist genau der
  Fehler, der sie ueberhaupt erst auf 34 und 36 gebracht hat.

NEBENGEWINN, nicht geplant: Bei 390 px -- der haeufigsten Breite --
geht die Leiste dadurch von zwei Reihen auf eine, 117 px auf 69. Bei
360 px bleibt sie zweireihig, und das ist richtig: Dort fehlen auch
so noch zwoelf Pixel, und Umbrechen ist die ehrliche Antwort auf zu
wenig Platz.

Am Rechner unveraendert: 116 x 32 mit Beschriftung, weil dort eine
Maus zielt und kein Daumen. Die Regel haengt an `pointer: coarse`.

Gemessen nachher: alle vier Breiten 44 x 44, keine Ueberlappung,
nichts breiter als der Schirm. pruef-tippziele 11/0,
pruef-css-klassen 30/0.
2026-09-22 00:58:42 +02:00
DogFatherGit 2b6c2be1ad Die Stelle bleibt -- auch wenn die Seite dazwischen neu laedt
Filipe, zum vierten Mal: "wenn ich in eine kategorie rein gehe und dan
zurueck geh die hauptseite immer wieder ganz hoch ... ohne dass die
seite hoch scrollt ODER NEU LAEDT."

DAS "ODER NEU LAEDT" WAR DER HINWEIS, und ich habe ihn zweimal
ueberlesen. kopf.js laedt die Seite selbst neu, sobald der Browser sie
aus seinem Rueckwaerts-Speicher holt -- damit keine veralteten Zahlen
dastehen. Nach einem Neuladen heisst die Navigationsart aber "reload",
nicht "back_forward".

UND DIE EIGENTLICHE BOSHEIT stand in einer Zeile, die ich selbst
geschrieben habe: Wurde eine Ankunft nicht als Zurueck erkannt, wurde
die gemerkte Stelle GELOESCHT. Ein einziges Neuladen reichte -- danach
half auch das naechste Zurueckgehen nicht mehr. Deshalb "geht es immer
noch nicht", obwohl ich es dreimal fuer behoben hielt.

WARUM ES IN JEDER MESSUNG FUNKTIONIERT HAT: kopf.js haelt einen
Ereignisstrom offen, und der sperrt den Rueckwaerts-Speicher aus.
`persisted` bleibt hier immer false, die Neulade-Zeile lief nie. Auf
einem echten Handy greift er sehr wohl. Man muss den Weg gehen, den der
Mensch geht -- und wenn man ihn nicht nachstellen kann, baut man gegen
ALLE Wege robust statt gegen einen.

FUENF AENDERUNGEN:

  Die Stelle wird LAUFEND gemerkt (gedrosselt auf 250 ms), nicht nur
  beim Klicken und Verlassen. Deckt auch die Glocke, eine
  Benachrichtigung und einen Absturz des Reiters ab.

  Nichts wird mehr geloescht. Die Stelle verfaellt von selbst nach
  einer Stunde.

  Wiederhergestellt wird jetzt auch bei "reload" und bei "navigate mit
  Herkunft aus diesem Haus" -- nicht nur bei "back_forward".

  Vor dem Neuladen aus dem Rueckwaerts-Speicher wird die Stelle samt
  Merker festgehalten.

  Der Pfeil in der Kopfleiste setzt den Merker jetzt fuer BEIDE seiner
  Wege. Er nimmt history.back() nur, wenn `document.referrer` da ist --
  sonst location.assign(), und das ist fuer den Browser ein Hingehen.
  Hier stand "der braucht nichts"; fuer den zweiten Weg stimmte das nie.

Ein Neuanfang faengt weiterhin oben an: keine Herkunft, kein Merker --
also vom Startbildschirm, aus einer Benachrichtigung, ueber die
Adresszeile.

Beim Bauen fast hineingelaufen: `START` steht in einem anderen Block
derselben Datei und waere an der neuen Stelle ein Absturz gewesen --
dieselbe Falle wie bei `$` am 21.09. Jetzt gibt der erste Block ihn
einmal bekannt, statt ihn abzuschreiben.

Geprueft: pruef-stelle 15/0 (war 9) -- Brotkrume (navigate),
Browser-Zurueck (back_forward), NEULADEN (reload), Neuanfang oben, und
dass eine fremde Ankunft die Stelle nicht wegwirft. Dazu pruef-sprung
43/0, pruef-start-ansicht 153/0, pruef-css-klassen 30/0.
2026-09-22 00:54:28 +02:00
DogFatherGit 66789aabcd Willkommen: eine Seite, die erklaert, was es hier gibt
Auftrag vom 21.09.2026, Abschnitte 7 und 8. Aus der Kachel "Der Treff"
wird die Willkommensseite.

WARUM DAS NICHTS VERLIERT, gemessen am echten Bestand: Das Brett
"treff" hatte NULL Eintraege, der Treff-Chat daneben 29 Nachrichten.
Geredet wird im Chat; das Brett war eine Kachel ohne Inhalt.

DIE SEITE ERKLAERT NICHT "DIE WEBSITE", SONDERN DEINE. Sie baut sich
aus derselben Kachelliste wie die Startseite, durch denselben Filter
(darfSeite). Wer morgen eine Kachel bekommt, bekommt automatisch auch
ihre Erklaerung -- und wer eine nicht hat, liest nicht davon. Eine
Liste von Dingen, die man nicht darf, ist keine Orientierung.

Gemessen: DogFather 30 Kacheln, Modi 25, Community 11 -- und keine
einzige davon ist fuer den Betreffenden gesperrt.

DREI FEHLER, DIE ERST DAS BILDSCHIRMFOTO GEZEIGT HAT:

  body class="gate" ist die ANMELDEWAND (display:flex, zentriert).
  Kopfleiste und Inhalt standen dadurch NEBENEINANDER -- am Handy
  blieben dem Text 260 von 390 Pixeln.

  .huelle gibt es im Haus gar nicht. Der Inhalt stand linksbuendig
  statt mittig, ohne Sicherheitsrand an randlosen Geraeten. Jetzt
  .inhalt wie jede andere Seite.

  Der Text stand direkt auf dem Buehnenbild: Kontrast 1.68:1 am
  Rechner, 2.23:1 am Handy (noetig 4.5). Die Hausregel stand daneben
  in start.css -- "der Text steht auf eigenen Flaechen" -- und diese
  Seite hielt sich als einzige nicht daran. Jetzt 5.19 und 7.73.

UND EIN LECK, ZUM DRITTEN MAL DIESELBE URSACHE:

Die Kachel umzuleiten nahm dem Brett "treff" die Zugehoerigkeit --
TREFF_BRETTER wird aus Kachelzielen abgeleitet. Die Schranke laesst
eine AGENTURROLLE unbesehen durch, wenn ein Brett in keiner Liste
steht: Eine Creatorin konnte das Brett des Treffs lesen.

Behoben, und diesmal dauerhaft laut gemacht: Nachgemessen ist die
Trennung exakt und in beide Richtungen deckungsgleich -- die Bretter
mit `fuerAlle` sind genau die des Treffs plus die Agenturablage. Das
ist eine Eigenschaft des BRETTS und wandert nicht, wenn jemand eine
Kachel umleitet. pruef-treff prueft das jetzt.

Mein erster Entwurf der Regel war zu breit und meldete `content` und
`schutz` -- beides Agenturbretter, die eine Agenturrolle zu Recht
liest. Eine Pruefung, die zu viel meldet, wird abgeschaltet.

AUSSERDEM: 16 Kennungen aus workspace-zuteilung.js hatten keinen
deutschen Satz -- auf dem Bildschirm haette woertlich "nicht_zugeteilt"
gestanden. Gefunden von pruef-meldungen am selben Tag.

Und zwei Erwartungen in pruef-treff abgeleitet statt gezaehlt: die
Zahl der Rollenkacheln auf der Wand (die Anmeldung sucht WHERE rolle=?,
eine Rolle ohne Kachel ist unerreichbar) und "die breite Kachel steht
vorne" ueber die Eigenschaft statt ueber den Namen.

Geprueft: pruef-willkommen 66/0 (neu), pruef-treff 80/0 (war 59 ok /
13 FEHL), pruef-buehne fuer die neue Seite 10/0, pruef-meldungen 8/0,
pruef-css-klassen 30/0, pruef-rechtetafel 19/0.
2026-09-22 00:00:14 +02:00
DogFatherGit b506c7f533 Die Oberflaeche dazu: Resuemee, Annehmen, Ablehnen, Bewerten
Auftrag vom 21.09.2026, Abschnitte 1 bis 5 -- der sichtbare Teil.

UEBER DEM BRETT STEHT JETZT EIN BAND, und es ist rollenabhaengig:

  Modi           "Deine Aufgaben" -- sein persoenliches Resuemee mit
                 offen / in Arbeit / erledigt / ueberfaellig, und
                 darueber EIN Satz, der die Zahlen einordnet. Fuenf
                 nackte Zahlen sind eine Tabelle, ein Satz ist eine
                 Auskunft.
  DogFather,     "Wer hat gerade was" -- eine Zeile je Person mit
  beide Haende   ihren Marken. Antippen filtert das Brett auf sie,
                 noch einmal antippen zeigt wieder alles. Ohne das
                 zweite waere der Filter eine Falle: hinein ja,
                 heraus nein.

WELCHES BAND JEMAND BEKOMMT, entscheidet `darf_verteilen` vom Server
-- aufgaben.js muss die Rollen dafuer nicht kennen.

AN JEDER KARTE steht jetzt, wer sie hat und wie es bei jedem steht:
Name, Zustand, bei einer Ablehnung der Grund daneben (wer "abgelehnt"
liest, will als Naechstes wissen, warum), bei einer Rueckmeldung der
Text dazu.

Und genau die Knoepfe, die fuer DIESEN Menschen gerade gehen:
Annehmen / Ablehnen, bei einem Pool "Ich uebernehme das", danach
"Ich fange an" und "Fertig". Ein "Annehmen" an einer fremden Aufgabe
waere ein Knopf, der mit 403 antwortet -- und die Meldung erscheint
ganz oben, wo man sie bei einer Karte weiter unten gar nicht sieht.
Diese Lektion stand in aufgaben.js schon einmal.

DIE BEWERTUNG SIND DREI BENANNTE KNOEPFE, keine Auswahl im Dialog.
Abschnitt 5 nennt drei Moeglichkeiten -- als Auswahl hiesse das: erst
klicken, dann lesen, dann waehlen. Als drei Knoepfe sieht man sofort,
was es gibt. Bei "Verbesserungsmoeglichkeiten" ist der Text Pflicht
("soll ein Eingabebereich erscheinen"), bei den anderen freiwillig.

AN MEHRERE VERTEILEN ist ZUSAETZLICH und nicht statt dessen: Eine
Person ist der haeufigste Fall und bleibt ein Klick. Wer mehr will,
klappt "Noch jemanden dazunehmen" auf. Die Namen darin werden aus der
Auswahl darueber ABGELEITET -- zwei Namenslisten in einer Datei, die
jeder herunterlaedt, waeren eine zu viel. Die Frage "wie soll das
laufen" erscheint erst ab zwei Leuten; vorher waere sie eine
Entscheidung ohne Gegenstand.

EIN EIGENES MODUL (zuteilung.js), weil aufgaben.js schon 1900 Zeilen
hat. Die Zustandswoerter kommen vom SERVER, nicht aus einer zweiten
Liste im Browser -- sonst heisst derselbe Zustand an zwei Stellen
anders.

ZWEI DINGE, DIE ERST DAS MESSEN GEZEIGT HAT:

(1) `window.nachfragen` gibt es nicht -- der Dialog heisst `frageNach`
    und kennt `grund`/`grundPflicht`, aber keine Auswahl. Ich hatte
    eine Schnittstelle benutzt, die ich mir gemerkt statt nachgesehen
    hatte. Aus der Not wurde die bessere Loesung: drei Knoepfe.
(2) Auf dieser Seite gibt es KEIN Suchfeld -- `#wer` in der
    Kopfleiste ist die Anzeige, wer angemeldet ist. Der Personenfilter
    wirkt deshalb unmittelbar am Brett.

pruef-zuteilung: 66/0 (war 48/0) -- 18 davon am echten Bildschirm.

Der Browserteil scheiterte zuerst mit `chrome-error://chromewebdata/`:
crew.dogfather-universe.com steht in Chromiums eingebauter HSTS-Liste,
der Browser schaltet von sich aus auf https, und der Testserver
spricht http. Abschalten geht nicht (die Liste ist einkompiliert).
Jetzt derselbe https-Vorbau wie in pruef-handy-teamdogi -- eine
Nachbildung waere die zweite Fassung, die anders altert.

Nachbarn gruen: pruef-aufgabenbrett 49/0, pruef-verteilen 16/0,
pruef-css-klassen 30/0, pruef-tippziele 11/0.
2026-09-21 18:01:30 +02:00
DogFatherGit 21793b6c36 Neue Rolle: die linke Hand
Aus dem Auftrag vom 21.09.2026, Abschnitt 6: "Die linke Hand erhaelt
grundsaetzlich dieselben Rechte wie die rechte Hand in allen Bereichen,
die die Modis, Aufgaben, Aufgabenzuweisungen, Uebersichten,
Kommunikation und Auswertungen betreffen. Die linke Hand darf keine
neuen Personen oder Accounts hinzufuegen. Die linke Hand darf keine
privaten bzw. persoenlichen Bereiche oder Informationen von Dogfather
sehen."

GEMESSEN VOR DEM BAUEN: Die Rolle "hand" steht an 35 Stellen im
Servercode und 17-mal in der Rechtetafel. Haette ich ueberall ein
"linke" danebengeschrieben, waere die naechste Stelle, die jemand
hinzufuegt, die erste, die es vergisst -- und eine vergessene Stelle
heisst hier: Die linke Hand sieht etwas nicht, ohne dass jemand merkt,
warum.

DESHALB EINE REGEL STATT DREISSIG ABSCHRIFTEN:

  WIE_RECHTE_HAND = new Set(["hand", "linke"])   in workspace.js
  istHand(person)                                fuer die Faehigkeiten
  eine Schleife ueber SEITEN                     fuer die Rechtetafel

Die Schleife gibt der linken Hand jede Seite der rechten -- ausser
fuenf, und jede davon steht mit Grund da:

  personen.html      legt Personen an
  bewerbungen.html   fuehrt zu neuen Personen
  talente.html       fuehrt zu neuen Personen
  hilfe.html         vertraulicher Meldeweg
  rechte.html        Rechteverwaltung

Gemessen: 25 Seiten fuer die rechte Hand, 20 fuer die linke. Als
Kacheln: 30 gegen 26 -- die vier verbotenen erscheinen gar nicht erst,
statt beim Antippen abgelehnt zu werden.

ZWEI DINGE, DIE ERST DAS MESSEN GEZEIGT HAT:

(1) OHNE KACHEL AUF DER ANMELDEWAND GIBT ES DIE ROLLE NICHT. Die
    Anmeldung sucht `WHERE rolle = ?` auf die angetippte Kachel -- es
    gibt keinen rollenuebergreifenden Sonderweg, auch nicht auf der
    Crew-Wand. Eine linke Hand haette sich mit dem richtigen Code
    NIEMALS anmelden koennen, und der Fehler haette ausgesehen wie ein
    falscher Code.

(2) DIE REIHENFOLGE DER DATENBANK-UMSTELLUNG ZAEHLT.
    `checkListeErweitern` baut die CHECK-Regel NEU aus der Liste, die
    man ihm gibt. Mein Schritt stand zuerst bei der rechten Hand --
    der Schritt fuer "gast" darunter nahm die Rolle damit wieder
    heraus, denn seine Liste kennt sie nicht. Die Kette ist kumulativ;
    neue Schritte gehoeren ans ENDE. Das steht jetzt auch dort.

Dazu zwei kleinere Funde beim Bauen:

  - Meine erste Ableitung aenderte die Rollenliste AN ORT UND STELLE.
    Mehrere Seiten teilen sich dieselbe Liste (`ALLE`) -- das haette
    die Rolle allen Seiten gegeben, die sie benutzen, auch einer
    Ausnahme. Faellt nicht auf, solange keine Ausnahme `ALLE` benutzt.
    Jetzt eine Kopie je Seite.
  - ROLLEN_NAME fehlte der Eintrag: Die linke Hand haette ueberall
    "linke" geheissen statt "Linke Hand". Gefunden hat das
    pruef-rechtetafel, weil sie diese Tabelle gegen ROLLEN haelt.
    Ihre Meldung nennt jetzt, WELCHE Liste was vermisst -- vorher
    zeigte sie beim Fehlschlag nur eine der beiden.

NICHT BEKOMMEN -- und jedes einzeln begruendet im Code:
Personen anlegen (ANLEGBAR.linke = []), Rollen aendern
(darfRollenWechseln), Bewerbungen, der vertrauliche Meldeweg. Beim
Meldeweg ist es bewusst das kleinere Recht: Ein Wort von Filipe
oeffnet ihn, eine versehentlich gelesene Meldung laesst sich nicht
zurueckholen.

UNBERUEHRT GEBLIEBEN, obwohl dort "hand" steht:
workspace-leistung.js:406 -- dort heisst "hand" nicht die Rolle,
sondern "von Hand eingetragen".

Am laufenden System gemessen: Datenbank nimmt die Rolle, Anmeldung
HTTP 200, 26 Kacheln, darf_verteilen = true, personen/hilfe/rechte
antworten mit 302, aufgaben und teamlage mit 200.

pruef-rechtetafel 19/0 (war 18/1), pruef-schranke 39/0,
pruef-umstellung 18/0.
2026-09-21 17:44:48 +02:00
DogFatherGit 432e533c86 Am Handy wird aus einer Kalenderpille ein Punkt
GEMESSEN, was dort wirklich stand:

    Fenster   Zelle   Pille   Platz fuer Text
     360 px   42 px   32 px   16 px  ->  1-2 Buchstaben
     390 px   46 px   36 px   20 px  ->  2-3 Buchstaben
     412 px   49 px   39 px   23 px  ->  3 Buchstaben
     768 px   95 px   85 px   69 px  ->  lesbar

"Content-Ideen sammeln" wurde zu "C…" -- eine Zeile, die Hoehe kostet
und nichts sagt. Drei Termine an einem Tag waren drei solche Zeilen.

JETZT: ein Punkt je Termin, nebeneinander. Man sieht, DASS an dem Tag
etwas ist und wie viel, und tippt den Tag an, um zu lesen, was. Der
Tagesdialog dafuer steht seit jeher, ist lesbar und hat 44-px-Zeilen;
er war nur schwer zu finden, solange das Raster so tat, als koenne man
dort lesen.

  - Zeitraum: bleibt ein durchgehender Balken. Ihn auch zu Punkten zu
    machen naehme genau das weg, wofuer er am 21.09. gebaut wurde.
  - Anlass (Feiertag u. a.): ein ECKIGES Zeichen, damit man es vom
    runden Termin unterscheidet. "DE…" fuer "Tag der Deutschen
    Einheit" sagt genauso wenig.
  - Erledigtes: hohl statt voll -- sonst saehe ein abgehakter Termin
    aus wie ein offener, und der Kalender loege.
  - Die Punkte sind NICHT einzeln antippbar (pointer-events: none).
    Ein 8-px-Link waere ein Nadeloehr; so faellt jeder Tipp auf die
    Zelle. Am Rechner bleibt die Pille ein Link.

DREI DINGE, DIE ERST DAS BILDSCHIRMFOTO GEZEIGT HAT:

(1) Die Zahlen sagten 8 x 8 -- und der Titel lief trotzdem quer ueber
    die Nachbarzellen. Ursache: start.css traegt eine Sammelregel
    `body.start .k-pille { font-size: .75rem }`, um ein Element
    spezifischer als `.k-tag .k-pille` (0,2,1 gegen 0,2,0). Sie
    gewinnt, egal welche Datei spaeter laedt. Aufgeklaert hat es die
    Frage an den Browser, WELCHE Regeln auf das Element passen.

(2) `.k-tag` traegt `container-type: inline-size` und ist damit der
    Behaelter fuer ihre KINDER. Eine Regel fuer `.k-tag` SELBST in
    `@container` wird gegen den naechsten Behaelter darueber geprueft
    und greift nie. Die Zelle blieb eine Flex-Spalte, jeder Punkt bekam
    eine eigene Zeile. Jetzt fragt die Zelle das Raster -- ein
    benannter Behaelter, Schwelle gerechnet: 46 + 8 + 7 x 60 = 474.

(3) Die Kinder der Pille (Uhrzeit, Wiederholzeichen) haben eine eigene
    Schriftgroesse und hielten den Punkt auf 26 px Hoehe. Ein 8 x 26
    grosser "Punkt" ist ein Strich.

pruef-kalender: 141/0 -- vorher 135 ok und 6 FEHL.

Die sechs waren KEIN Fehler am Kalender, und nur einer davon war neu:

  - Vier kamen von Screen 11 (Termin von-bis): Ein Eintrag ueber fuenf
    Tage setzt fuenf Marken, und die Pruefung zaehlte Marken statt
    Eintraege. Sie hatte am 17.09. schon gelernt, ihre Erwartung
    abzuleiten -- veraltet war diesmal nicht die Erwartung, sondern
    das, was gemessen wurde. Gezaehlt wird jetzt ueber den VERWEIS
    (`zeigen=eintrag-N`), der an jedem Tag derselbe ist. Der `title`
    ginge nicht: Er endet mit "(Tag 3 von 5)".
  - Zwei waren meine: Die Pruefung las die Farbe aus der linken Kante
    -- die faellt beim Punkt weg, also meldete sie "1 Farbe" statt 5.
    Gelesen wird jetzt `--pfarbe`, die Quelle selbst.

Neun neue Zusicherungen, darunter die, die beim Bauen gefehlt hat:
"nichts ragt ueber den Rand seiner Zelle hinaus". Groesse allein
genuegt nicht -- die Pille war bereits 8 x 8 und trug trotzdem Text.
Gegenprobe: Raster auf 1200 px aufziehen, Titel muss zurueckkommen.

Nachbarn gruen: pruef-tippziele 11/0 (sieht die 11 neuen Regeln, zaehlt
den Punkt richtig nicht als Tippziel), pruef-css-klassen 30/0,
pruef-zeitraum 16/0, pruef-terminregel 35/0.
2026-09-21 17:01:54 +02:00
DogFatherGit bfbe6feafe Fett, kursiv, unterstrichen, durchgestrichen -- ueberall
Filipe, 21.09.2026: "dan will ich dass die leute auch immer die art
von text aussuchen können, fettgedrückt, unterstrichen und so alles.
das überall sei es im chat jeder für sich oder sei es wenn die modis
oder rechte hand oder dogfather eine aufgabe oder sachen posten."

VORHER GEMESSEN: Es gab genau EINE Auszeichnung im ganzen Haus --
fett, und nur auf den Brettern (`mitFett` in bereich.js). Im Chat
konnte niemand etwas hervorheben.

EINE QUELLE FUER DAS GANZE HAUS: workspace/assets/js/textform.js.
Chat, Bretter und Aufgaben zeichnen ihren Text jetzt durch denselben
Zerleger. Drei Fassungen derselben Regel waeren drei Fassungen, die
verschieden altern.

  **fett**   _kursiv_   __unterstrichen__   ~~durchgestrichen~~

Dazu eine Leiste ueber jedem Schreibfeld: F K U S, 44 px am Finger,
Strg+B/I/U, und ein zweiter Druck nimmt die Zeichen wieder weg.

DIE WORTGRENZEN SIND DER EIGENTLICHE BAU. Ein Zerleger, der alles
auszeichnet, ist schlimmer als keiner: `datei_name_hier` hiesse
plotzlich anders, als es heisst, und `@max_muster` ebenso. Deshalb
stehen bei den Unterstrichen Wortgrenzen -- bei Sternchen und Tilden
nicht, die kommen in Text nicht versehentlich paarweise vor.

GEBAUT MIT createTextNode, NIE innerHTML. Wer Text zu Auszeichnung
macht, ist einen Tippfehler von einer Luecke entfernt. Das ist heute
sicher; pruef-textform misst es, damit es das morgen auch ist.

EIN ECHTER FEHLER DABEI GEFUNDEN -- in meinem eigenen Einbau von
vorhin: Auf dem Aufgabenbrett stand `$('f-text')` in einem Block, der
`$` gar nicht kennt (die Datei hat drei getrennte Bloecke).
`ReferenceError: $ is not defined`, die Leiste kam dort nie an, und
die Seite sah dabei vollkommen normal aus. Derselbe Block beginnt
ausserdem mit `if (!feld) return;` auf ein Aufwand-Feld, das mit
Textgestaltung nichts zu tun hat -- die Leiste haette an einer
voellig fremden Bedingung gehangen. Jetzt ein eigener Block, ohne
fremden Helfer und ohne fremde Bedingung.

Gefunden hat es die Pruefung, weil sie die Leiste AM FELD sucht,
statt den Aufruf im Quelltext zu zaehlen. Sie sammelt seitdem auch
Skriptfehler ein -- ein ReferenceError ist immer ein Befund, auch
wenn man noch nicht weiss, was er anrichtet.

pruef-textform.mjs, 50 Aussagen:
  - welche Seite das Modul braucht, wird ABGELEITET (beide
    Richtungen: keine ohne, keine umsonst) -- 3 brauchen, 32 nicht
  - 13 Regelfaelle im echten Browser an der echten Datei, davon
    sechs, die NICHT gestaltet werden duerfen
  - eine echte Nachricht wird zu <strong>/<em>/<u>/<s>
  - Sicherheitsprobe: <b> und <img onerror> bleiben Text, nichts
    wird ausgefuehrt -- und die echte Auszeichnung daneben wirkt
    trotzdem (sonst waere nur bewiesen, dass gar nichts passiert)
  - die Leiste legt Zeichen wirklich um und wieder ab
  - Gegenproben fuer beide Richtungen

Nachbarn unveraendert gruen: pruef-chat-optik 45/0 (war 39 -- die
Antwortleiste kam dazu), pruef-aufgabenbrett 49/0, pruef-nachfrage
49/0, pruef-css-klassen 30/0, pruef-tippziele 11/0, pruef-meldungen
8/0.
2026-09-21 16:42:43 +02:00
DogFatherGitandClaude Opus 5 7305f694d5 Die Stelle bleibt -- auch wenn man ueber die Kopfzeile zurueckgeht
Filipe, zum vierten Mal: "muss ich jedes mal wenn ich von einer seite
zurück scrolle immer wieder runter scrollen um weiter zu schauen und
das nervt."

DIE WIEDERHERSTELLUNG GAB ES SEIT DEM 20.09. -- sorgfaeltig gebaut,
mit Warten auf die nachgeladene Hoehe, mit Aufgeben nach drei
Sekunden, mit "wer selbst scrollt, gewinnt".

SIE LIEF NUR FAST NIE. Denn sie lief ausschliesslich bei
`navigation.type === "back_forward"`, also beim Zurueck-Knopf des
Browsers. Im Haus geht man anders zurueck: ueber die Kopfzeile ("TEAM
DOGI › HIGHLIGHTS"), und dort steht ein ganz gewoehnliches
`<a href="start.html">`. Fuer den Browser ist das eine Fahrt
VORWAERTS. Die Bedingung war also falsch -- und der else-Zweig
loeschte die eben gemerkte Stelle noch dazu.

IM KOPF DERSELBEN DATEI STAND DIE LOESUNG ALS ABSICHT: "Ein eigener
Merker faengt den Fall ab, dass der Zurueck-Knopf der Kopfleiste
benutzt wurde." Gebaut wurde er nie.

UND DESHALB HAT ES IN JEDEM TEST FUNKTIONIERT: Wer mit `goBack()`
prueft, prueft den einen Weg, den niemand geht. Gemessen am 21.09.:
ueber goBack sauber wiederhergestellt, ueber den Link in der
Kopfzeile oben gelandet. Gefunden hat es Filipes Bildschirmvideo --
17 Sekunden, drei Bilder, und der Ablauf war eindeutig.

Der Merker gibt es jetzt wirklich: Beim Klick auf einen EIGENEN
Zurueck-Weg (`.zurueck`, `.zurueck-knopf`) wird das Ziel notiert; wer
dort binnen 30 Sekunden ankommt, bekommt seine Stelle zurueck. Er
gilt fuer genau eine Ankunft -- wer die Seite eine Minute spaeter
normal oeffnet, faengt wieder oben an. Und NUR fuer diese zwei
Klassen, nicht fuer jeden Link: Sonst landete man beim Oeffnen eines
Brettes mitten darin.

Dazu der Rueckwaerts-Speicher des Browsers: Holt er eine Seite aus dem
Speicher, laeuft keine Zeile mehr, und unser `manual` verbietet ihm
gleichzeitig, die Stelle selbst wiederherzustellen. Ein `pageshow`
faengt das ab. Dieser Fall ist NICHT gemessen -- in Playwright greift
der Speicher nicht -- sondern aus der Spezifikation begruendet. Das
steht auch so im Kommentar, damit niemand spaeter glaubt, er sei
nachgewiesen.

NEU: pruef-stelle.mjs, 9 Pruefungen. Sie geht beide Wege zurueck --
Kopfzeile UND Browser -- und haelt ausdruecklich fest, dass der erste
KEIN "back_forward" ist. Dazu die Gegenprobe, dass eine frisch
geoeffnete Seite oben anfaengt: Ohne sie waere alles auch dann gruen,
wenn die Seite IMMER zur alten Stelle springt, und das waere
schlimmer als das Problem.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 14:24:19 +02:00
DogFatherGitandClaude Opus 5 9a30f9e304 Beim Antworten war das Schreibfeld einen Buchstaben breit
Filipes Bildschirmfoto: Die Antwortleiste nimmt die ganze Breite, und
daneben steht ein Schreibfeld, in dem der Text senkrecht laeuft --
"defi / niti / v / hah / a".

DIE ABSICHT STAND DA, DIE REGEL NICHT. `.chat__eingabe` ist eine Reihe
OHNE Umbruch, und die Antwortleiste ist darin ein gleichberechtigtes
Element -- sie nimmt ihren Platz NEBEN dem Schreibfeld. Das
`margin-bottom: 8px` an der Leiste sagt seit jeher, dass sie darueber
gehoert; durchgesetzt wurde es nie.

Dazu stand am Schreibfeld `min-width: 0`. Das ist woertlich die
Erlaubnis, auf nichts zu schrumpfen -- und genau das hat es getan.

BEHOBEN MIT EINER REGEL, NICHT MIT EINER ZAHL: Die Zeile darf jetzt
umbrechen, die Antwortleiste nimmt sich mit `flex-basis: 100%` immer
die ganze Zeile, und das Schreibfeld hat eine Untergrenze von 8rem.
Bricht es darunter, bricht lieber die Zeile um, als dass das Feld
unbenutzbar wird.

Gemessen an der schmalsten Breite, die das Haus kennt:
  320 px: Schreibfeld 166 px, Antwortleiste 670 px (eigene Zeile)
  430 px: Schreibfeld 216 px
Vorher: rund 30 px.

pruef-chat-optik prueft das jetzt mit -- und nicht nur die Breite des
Feldes, sondern auch, dass die Leiste wirklich eine eigene Zeile
nimmt. Ohne die zweite Zeile waere die erste nur zufaellig gruen,
solange der zitierte Text kurz genug ist.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 14:11:04 +02:00
DogFatherGitandClaude Opus 5 314561fb64 Aufgaben an bestimmte Leute verteilen -- jetzt auch sichtbar
Filipe: "ich sehe noch immer nicht dass dogfather oder die rechte hand
wenn sie aufgaben verteilen die spezifisch an leute verteilen können.
mach das endlich auch weil das ist seeehr wichtig damit wir arbeiten
können mit den leuten."

GEMESSEN, BEVOR GEBAUT WURDE -- und die Messung hat zwei verschiedene
Antworten gegeben:

  DogFather   Feld sichtbar, vier Menschen in der Auswahl
  Rechte Hand Feld VERSTECKT, Auswahl leer

Fuer ihn gab es die Zuteilung also, fuer sie nicht. Beides war falsch,
jedes auf seine Art.

1. DIE RECHTE HAND KAM NIE AN DIE FELDER

   Das Absenden fragte `ich.darf_verteilen` -- das sagt der Server:
   Leitung ODER rechte Hand (seit 20.09.). Das ANZEIGEN fragte eine
   andere Menge aus bereiche.js: spicy, admin, manager. Zwei
   Bedingungen fuer dieselbe Sache, und eine davon war nie nachgezogen
   worden.

   Der Server haette ihre Zuteilung angenommen; sie konnte sie nur
   nirgends eintragen. Vier Stellen betroffen, und eine davon war
   gefaehrlich: Beim BEARBEITEN wurde `verantwortlich_id` nicht
   mitgeschickt -- die rechte Hand haette durch blosses Speichern die
   Zuteilung einer Aufgabe stillschweigend geloescht. Kein Fehler,
   keine Meldung, die Aufgabe gehoert danach niemandem.

   Alle vier fragen jetzt den Server. `LEITUNG.has(ich.rolle)` bleibt
   nur noch als Rueckfall hinter `??`, fuer den Fall einer aelteren
   Serverfassung.

2. UND FUER DOGFATHER LAG ES AM WORT

   Das Feld hiess "Verantwortlich" und stand auf "—". Das liest sich
   wie eine Eigenschaft der Aufgabe, nicht wie eine Frage an einen
   selbst. Es heisst jetzt "Wer macht es?", der leere Wert "— noch
   niemand —", und darunter steht, was die Auswahl bewirkt: Die
   Aufgabe steht bei ihm unter "Nur meine", und er bekommt eine
   Meldung.

   Eine Frage beantwortet man. Ein Strich uebersieht man.

WARUM KEINE PRUEFUNG DAS GEFUNDEN HAT: Alle fragten den Server, und
der war in Ordnung -- Rechte da, Leute da, Zuteilung wird angenommen.
Eine Erlaubnis, an die niemand herankommt, sieht von dort aus wie eine
Erlaubnis. pruef-verteilen liest deshalb jetzt auch den Quelltext der
Oberflaeche: dieselbe Frage an beiden Stellen, und die Beschriftung
muss eine Frage sein. Kommentare zaehlen dabei nicht mit -- beim
ersten Lauf hat die Pruefung meine eigene Begruendung als Befund
gezaehlt.

pruef-verteilen 16/0 · pruef-aufgabenbrett in Ordnung

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 14:07:25 +02:00
DogFatherGitandClaude Opus 5 8a214ecd0e Keine Mischung mehr -- Team Dogi nur noch bei Team Dogi
Filipe: "ich will dass du im workspace alles von team dogi weg nimmst.
nur was ich im kalender eintrage soll ich im workspace sehen und im
team dogi. aber die kacheln von team dogi soll ich nur bei team dogi
sehen und die von workspace nur bei workspace bitte. ich will keine
mischung mehr von kacheln. wie gesagt nur die der kalender soll
verbunden sein von dogfather sonst nichts."

GEMESSEN, WIE SCHLIMM ES WAR: Auf der Agenturadresse bekam DogFather
0 eigene Kacheln ueber die Schnittstelle und 17 fremde -- Dein Team,
Ideen-Board, Rueckmeldung, Wer sieht was, Entwicklung, Werdegang,
Talente und den ganzen Treff samt Moderation. Zwei Betriebe auf einer
Seite.

Das Bittere daran: Dieselbe Datei hatte den Fehler fuer die ANDERE
Richtung am 10.09. schon erkannt und behoben ("Fuenfundzwanzig
Kacheln, von denen zwei Drittel Creator, Scouts und Agentur betreffen,
waeren dort Fenster in ein Haus, in dem er gerade nicht ist"). Nur
andersherum stand es weiter so.

DIE AUSNAHME BRAUCHTE NICHTS: Nachgemessen filtern die Terminabfragen
in workspace-kalender.js NICHT nach Haus. Was er eintraegt, steht
ohnehin auf beiden Adressen. Die Verbindung, die er will, existierte
schon -- sie musste nur nicht zerschnitten werden.

STATT SIEBZEHN BRETTERN STEHT DORT EINE TUER. Ohne sie waere von der
Agenturadresse aus kein Weg mehr zu Team Dogi sichtbar; er muesste die
Adresse tippen. Das ist die Sorte Sackgasse, die dieses Haus nicht
baut. Eine Tuer ist keine Mischung: Sie zeigt kein Brett, sie geht
hinueber. Und sie kommt vom Server, nur fuer `admin` -- in keiner
ausgelieferten Datei steht sie.

MEIN ERSTER ENTWURF GAB SIE AUCH DER RECHTEN HAND UND DER MODERATION.
pruef-modi-checkliste hat es sofort gemeldet: "Modi bekommt 1
Zusatzkachel(n), erwartet keine". Wer NUR zu Team Dogi gehoert, hat
auf der Agenturadresse nichts zu suchen -- die Tuer waere dort seine
einzige Kachel gewesen, also eine Seite, die aus nichts als einem
Ausgang besteht.

VIER PRUEFUNGEN VERLANGTEN DANACH DIE ALTE WELT. Keine davon war ein
Mangel; alle vier haben am falschen Ort gesucht:

  pruef-haus-trennung  verlangte woertlich, dass die Team-Kachel AUCH
     auf der Agenturadresse steht. Sie prueft jetzt die Trennung in
     beide Richtungen -- kein Brett von Team Dogi drueben, aber die
     eine Tuer -- und leitet die Namen aus der Antwort von crew. ab,
     statt sie abzuschreiben.
  pruef-start-ansicht  zaehlte acht Gruppennamen in fester
     Reihenfolge. Gemeint war eine Ordnung ("die Community steht ganz
     unten, denn dort stehen Namen und Saetze von Zuschauern"), und
     die wird jetzt als Regel geprueft -- bedingt, mit drittem Ausgang
     auf Adressen, wo es diese Gruppen gar nicht gibt.
  pruef-treff und pruef-rueckmeldung fragten ueber die Agenturadresse
     nach Brettern, die dort nicht mehr stehen. Sie fragen jetzt dort,
     wo diese Bretter zuhause sind.

EINE HALBE STUNDE WAERE DABEI FAST VERLOREN GEGANGEN: `fetch` kann den
Host-Kopf nicht setzen -- er ist ein verbotener Kopfzeilenname und
wird STILLSCHWEIGEND verworfen. Die Anmeldung ueber die Crew-Wand
genuegt nicht; jede einzelne Abfrage braucht die Adresse. Deshalb geht
die Messung jetzt ueber http.request, so wie es `anmelden()` in
derselben Datei laengst tut.

pruef-haus-trennung 74/0 · pruef-modi-checkliste 75/0 · pruef-treff
72/0 · pruef-rueckmeldung 30/0 · pruef-start-ansicht 153/0 ·
pruef-haus-seiten 34/0 · pruef-entwicklung 46/0 · pruef-befinden
113/0 · pruef-rechte-umstellen 46/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 14:00:14 +02:00
DogFatherGitandClaude Opus 5 a39d02da5a Ein Vorschlag ist ein Vorschlag -- DogFather entscheidet
Filipe: "bei diesen vorschlägen ist sehr wichtig dass immer wenn es um
was geht was ich machen soll oder so dass immer erwähnt wird dass ich
immer am ende entscheide ob ich was mache oder nicht. ich kann immer
annehmen oder ablehnen. über all auf der website soll dass bei den
vorschlägen erwähnt werden."

WARUM DAS MEHR IST ALS HOEFLICHKEIT: Auf den Karten stehen Saetze wie
"Was soll DogFather im naechsten Stream unbedingt machen?" oder
"Welches Spiel soll DogFather mal ausprobieren?". Wer so gefragt wird,
schreibt etwas hin -- und rechnet damit. Passiert es dann nicht, sieht
es aus wie ein gebrochenes Versprechen, obwohl nie eines gegeben
wurde. Der Satz verhindert genau diese Enttaeuschung vorher, statt sie
hinterher zu erklaeren.

GEMESSEN, BEVOR GEBAUT WURDE -- und die Messung hat den Auftrag
groesser gemacht: Die Vorschlagskarten sieht NUR das Team. Die
Community bekommt sie mit 404 gar nicht; sie liest nur, was daraus auf
dem Brett landet. Ein Satz allein ueber den Karten haette also genau
die Leute nicht erreicht, um die es geht.

Deshalb steht er jetzt an ZWEI Stellen, aus EINER Quelle:
  - ueber den Vorschlagskarten (das Team beim Auswaehlen)
  - auf dem Brett selbst, unter der Ueberschrift (die Community beim
    Lesen)

WELCHE BRETTER IHN TRAGEN, WIRD ABGELEITET: genau die, fuer die es
ueberhaupt Vorschlaege gibt. Eine zweite Liste "Bretter mit Hinweis"
waere die naechste, die altert -- wer ein Brett in den Katalog
aufnimmt, denkt nicht daran, es auch dort einzutragen. Auf einem Brett
fuer Termine oder Dateien steht er nicht: Ein Hinweis, der ueberall
steht, wird nirgends gelesen.

EINMAL UND NICHT AUF JEDER KARTE. Vier Karten nebeneinander mit
viermal demselben Satz liest niemand mehr. Er steht ueber dem Block,
wo man ihn liest, bevor man die erste antippt.

Der Text selbst steht an genau einer Stelle im Haus
(VORSCHLAG_HINWEIS), und pruef-vorschlaege haelt beide Anzeigeorte
dagegen -- mit Gegenprobe, dass ein Brett ohne Vorschlaege ihn NICHT
traegt.

pruef-vorschlaege: 28 Pruefungen, 0 Fehler (war 21)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:41:06 +02:00
DogFatherGitandClaude Opus 5 ea8ceaa539 Das Farbhaus von Team Dogi lag oeffentlich im Netz
Ausgeloest von pruef-modi-wortleck, die seit Tagen rot war: "24
Fundstellen -- der verborgene Zugang waere damit auffindbar." Die
erste Frage war, ob sie recht hat. Gemessen: ja, und schlimmer als
gedacht.

WER DIESE DATEIEN BEKOMMT: Nicht nur Kollegen. `curl` ohne jeden Keks
auf workspace.dogfather-universe.com liefert die Skripte und
Stilvorlagen des Arbeitsplatzes mit HTTP 200 -- fuer jeden im Netz
lesbar.

DARUNTER crew-haus.css, 27 806 Byte, das ganze Farbhaus von Team Dogi
samt seiner Kommentare. In deren Kopf stand seit dem 10.09. woertlich
"Diese Datei wird NUR auf crew.dogfather-universe.com ausgeliefert."
Das war eine Behauptung, keine Tatsache: Die Weiche biegt `haus.css`
auf diesen Namen um, wer den Namen direkt nannte, ging an ihr vorbei.
Ein Kommentar, der eine Absicht beschreibt, erfuellt sie nicht.

Zwei Stellen im Haus haben sich damit widersprochen -- die Datei sagte
"nur auf crew.", pruef-crew-adresse verlangte ausdruecklich das
Gegenteil ("sie ist kein Geheimnis"). Durchgesetzt war die offene
Fassung. Filipe hat am 21.09. entschieden: zusperren. Die alte
Begruendung dagegen war die Sorge, eine Sperre koenne die Pruefung
blind machen -- die ist jetzt beantwortet statt vermieden: Jeder
Eintrag der Tafel wird in BEIDE Richtungen gemessen, und dass die
Umbiegung von `haus.css` auf crew. weiterhin greift, ebenfalls.

DIE ADRESSE WAR DAS EIGENTLICHE GEHEIMNIS, nicht das Wort. Die
Rollennamen stehen auf der Zugangswand von Team Dogi ohnehin offen --
so gewollt. WO sie liegt, stand dagegen im Klartext in gate.css,
gate.js und crew-haus.css, alle drei oeffentlich abrufbar. Jetzt steht
sie in keiner ausgelieferten Datei mehr.

DIE PRUEFUNG SELBST HATTE DREI MAENGEL:

  1. Sie kannte die Mehrzahl nicht. `\bmodi\b` fand "ein Modi", nicht
     "die Modis" -- 23 weitere Stellen, darunter der Satz "Fuer die
     rechte Hand und die Modis gibt es dort den stillen Zugang". Also
     genau die Auskunft, die sie verhindern soll, in der Form, die sie
     nicht sah.
  2. Ihre Ausnahmeliste war abgeschrieben. Sie nannte eine Datei; die
     zweite, die der Server auf crew. begrenzt, haette sie nie
     erfahren. Ausgenommen ist jetzt genau das, was der Server auch
     durchsetzt (GEHOERT_ZU_ADRESSE) -- kein Muster, sondern die
     Durchsetzung selbst.
  3. Sie mahnte 45 Kommentare an. Filipes Entscheidung: in Kommentaren
     ja, in Code und sichtbaren Texten nein. Rot, das immer da ist,
     wird ueberlesen -- und dann faengt sie auch den echten Fall nicht.

Dafuer neu: helfer-ohne-kommentar.mjs, ein Zerleger, der Kommentare
zeichengenau durch Leerzeichen ersetzt, ohne Zeichenketten,
Vorlagen oder Suchmuster zu beschaedigen. KEIN Suchausdruck -- genau
daran ist am 20.09. die Portumstellung gescheitert, mit gueltigem
JavaScript ohne das Feld `port`. Dreizehn Proben in beide Richtungen
beweisen, dass er weder zu viel noch zu wenig wegnimmt; ein Zerleger,
der zu viel nimmt, macht die ganze Pruefung STILL gruen.

Von 45 blieben damit drei echte, alle behoben:
  - daten.modis  -> daten.leute (Feldname in der Auskunft, also Code)
  - zwei Saetze, die Menschen lesen, auf "die Moderation" umgestellt --
    fuer jemanden, der neu im Treff ist, sogar klarer

Nebenbei, beim selben Durchgang gefunden und geschlossen:
  - teamlage.js fiel auf einen Rollennamen zurueck. Nachgemessen: Die
    Stilvorlage kennt zu dieser Karte gar keine solche Regel -- der
    Rueckfall hat nie etwas bewirkt und nur das Wort ausgeliefert.
  - werdegang.js fuehrte die Saetze ueber den Rollengruppen selbst,
    mit den Rollennamen als Schluessel. Der Kommentar daneben
    behauptete sogar, sie seien "abgeleitet, nicht abgeschrieben".
    Sie kommen jetzt vom Server, und pruef-werdegang misst, dass
    jede Gruppe ihren eigenen behaelt.

pruef-modi-wortleck  8/0  (war 5, davon 1 rot)
pruef-crew-adresse 144/0  (war 135)
pruef-werdegang    98 statt 95 Pruefungen, dieselben 3 alten Fehler
pruef-team-ampel 32/0, pruef-team-stufen 28/0, pruef-hilfe 84/0

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:00:01 +02:00
DogFatherGitandClaude Opus 5 eca9aed279 Der Treff sagt jetzt, ob gerade gestreamt wird
Filipe zu dieser Seite: "mach was anderes daraus oder mach es viel
krass und geiler ... erstell was was mich von den socken schmeisst. es
soll wirklich sogar ein wow effekt fuer die community ergeben." Dazu
die eine Auflage: die Kachel bleibt.

WAS SIE WAR: zwei Karten mit zwei Adressen. Sauber gebaut, richtig
beschriftet -- und niemand kam ein zweites Mal wieder. Wer im Treff
ist, kennt die Website. Den Rabattcode merkt man sich beim ersten Mal.

DIE FRAGE, DIE WIRKLICH JEMAND HAT, IST EINE ANDERE: Laeuft er
gerade? Und wenn nicht -- wie lange noch? Die Antwort kennt das Haus
seit dem 20.08.: postfach.dogfather-universe.com/live-status, derselbe
Dienst, von dem der oeffentliche Streamplan lebt. Im Treff gab es sie
bisher nicht.

Jetzt steht oben ein Puls: ein Ring, der sich ueber den Tag bis zur
naechsten Sendezeit fuellt, darin der Countdown auf die Sekunde. Sendet
er, wird die Karte rot, atmet im Ruhepuls und traegt den Titel des
Streams plus einen Weg hin. Darunter die drei Accounts und -- wenn die
Verwaltung eines eintraegt -- das besondere Event mit eigener Uhr.

DREI AUSGAENGE, NICHT ZWEI. Das ist der eigentliche Unterschied zur
oeffentlichen Seite: streamplan.js faengt dort jeden Fehler ab und
setzt `istLive = false`. Aus "wir konnten nicht fragen" wird "er sendet
nicht" -- und wer das liest, macht die Seite zu und verpasst den
Stream. Der Dienst liefert `autoHealthy` sogar mit; gelesen wird es
draussen nicht. Hier schon: Bei einer Stoerung steht "Konnten wir
gerade nicht nachsehen", dazu der Hinweis, dass das NICHT heisst, dass
kein Stream laeuft. Der Countdown laeuft dabei weiter -- er braucht
kein Netz.

NICHTS IST ABGESCHRIEBEN. Die drei Accounts kommen ueber
/workspace/api/draussen aus derselben KANAELE-Liste, an der die
Aufgabenverteilung haengt; die Adressen baut der Steckbrief. Die
Sendezeit steht im Server, und pruef-draussen haelt sie gegen
FIX_STUNDE in streamplan.js -- verschiebt jemand den Termin und aendert
nur einen Ort, wird die Pruefung rot.

Gemessen, bevor gebaut wurde: der Dienst antwortet und meldet sich
gesund, CORS steht auf *, und `connect-src` der Treff-Seiten fuehrt
postfach bereits. Ohne das Letzte waere der Abruf still blockiert
worden und haette ausgesehen wie ein toter Dienst.

Die Kachel heisst jetzt "Draussen" statt "Unsere Seiten" -- drei Dinge
statt zwei Adressen. Ziel und Datei bleiben gleich.
pruef-wege-nach-draussen schreibt den Namen nicht mehr ab, sondern
verlangt, dass Kachel und Seitenueberschrift uebereinstimmen. Zwei
Namen fuer denselben Ort waren schon einmal ein echter Fehler.

Nebenbefund, dort gleich behoben: Dieselbe Pruefung verlangte, dass
die Community-Kacheln restlos in Dreierreihen aufgehen -- obwohl ihr
eigener Kommentar sagt, eine freie Zelle am Ende sei erlaubt. Sie war
rot bei einwandfreiem Raster. Gemessen wird jetzt, was wirklich
schiefgeht: eine doppelt breite Kachel, die in der letzten Spalte
beginnt und die Zelle davor leer laesst. Mit Gegenprobe.

pruef-draussen: 39 Pruefungen, alle vier Lagen im echten Browser --
die Stoerung wird dafuer absichtlich hergestellt.
pruef-wege-nach-draussen: 67 statt 66, keine Fehler mehr.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 12:06:23 +02:00
DogFatherGitandClaude Opus 5 2a6008d699 Versionsstempel auf 202609211145
chat.css hat sich geaendert. Ohne den Stempel behaelt jeder Browser
seine alte Kopie, und die groesseren Farbkacheln kaemen bei niemandem
an. 505 Verweise in 37 Dateien.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:45:23 +02:00
DogFatherGitandClaude Opus 5 0082c74bd7 Versionsstempel nachgezogen
pruef-zwischenspeicher hat es gemeldet: Der Commit davor hat
Stilvorlagen und Skripte geaendert, aber keine HTML -- damit bleibt
der Verweis `?v=...` stehen, der Browser haelt seine alte Kopie fuer
aktuell (ein Jahr, unveraenderlich), und die Reparatur kaeme bei
niemandem an.

Genau der Fall, fuer den die Pruefung gebaut wurde: Ein Deploy, der
fehlerfrei durchlaeuft und trotzdem nichts ausliefert.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 23:14:14 +02:00
DogFatherGitandClaude Opus 5 b0e7542507 Der Anrufkasten zeigt, WER dran ist -- nicht dreimal "Verbunden"
Filipe, zu Screen 1: "wenn ich anrufe soll das auch viel besser geiler
und spezieller aussehen aber es soll nicht raushaengen."

Erst gemessen: Es haengt nichts raus. Der Kasten ist 374 px am Handy,
340 am Rechner, 72 Teile geprueft, kein einziges ueber dem Rand. Die
Optik war also gar nicht der Mangel -- zwei andere Dinge waren es.

1. DER NAME DES ANRUFERS GING IMMER VERLOREN.
   `wer(raumName || "Anruf")` lief VOR `kastenBauen()`. Das Element
   #anruf-wer gab es zu dem Zeitpunkt noch nicht, die Zuweisung lief
   ins Leere, und oben stand bei jedem Anruf das Wort "Anruf". Die
   Reihenfolge ist umgedreht: erst bauen, dann beschriften.

2. IN EINEM ANRUF OHNE VIDEO STAND JE PERSON DAS WORT "Verbunden".
   Bei dreien dreimal dasselbe Wort -- und man sah nicht, WER dabei
   war. In einer Gruppe ist genau das die Frage: Ist Kessi schon
   drin? Jetzt steht dort ein Kreis mit den Anfangsbuchstaben und der
   echte Name; waehrend es klingelt ein wartendes Gesicht mit dem
   Namen dessen, den man anruft. Vorher war die Flaeche in dieser
   Sekunde leer, und ein leerer Kasten mit "Es klingelt ..." sieht
   aus wie einer, der haengt -- ausgerechnet im unsichersten Moment.

Der Name kommt NICHT aus einer Abfrage. Wer anruft, bekannt beim
Start nur sich selbst; alle weiteren kommen ausschliesslich ueber das
Ereignis "dabei", und genau dort fehlte das Einsammeln. Deshalb sah
der ANRUFER unter jedem Kreis "Jemand" -- die Angerufenen nicht.

UND DIE PRUEFUNG WAR ZU NACHSICHTIG. Sie verlangte einen Namen
"laenger als ein Zeichen"; der Rueckfalltext "Jemand" ist sechs
Zeichen lang und kam damit durch. Gruen, waehrend der Hauptfall
kaputt war. Die zweite Fassung verglich gegen eine abgeschriebene
Namensliste -- die nannte "Jonas, Luna, Mara, Pat", angelegt werden
aber "Filipe, Rieke, Kessi, Tili", und der Kommentar daneben
behauptete schon da, sie sei abgeleitet. Jetzt ist sie es wirklich:
Die Namen werden beim Anlegen eingesammelt, und geprueft wird, dass
jeder GENAU DIE BEIDEN ANDEREN sieht -- nicht "irgendeinen echten
Namen", denn der eigene Name im eigenen Kasten waere auch einer.

pruef-anruf: 127 Pruefungen, 0 Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 22:25:45 +02:00
DogFatherGitandClaude Opus 5 c4e26409b9 Die Seite laesst sich als App installieren
Das Manifest war lange vollstaendig -- die App LIESS sich
installieren. Nur bot das ausschliesslich der Browser an, versteckt
in seinem Dreipunktemenue. Wer es nicht sucht, findet es nie. Und
ohne installierte App gibt es auf dem Handy keine verlaesslichen
Benachrichtigungen; genau daran hing im September das Telefonieren.

Jetzt steht der Knopf in der Kopfleiste, auf allen Seiten, mit drei
Antworten statt einer:

  schon installiert -> gar kein Knopf
  Browser bietet an -> der Knopf fragt ihn
  Safari am iPhone  -> der Knopf erklaert den Weg

Der dritte Fall ist der gefaehrliche: Dort gibt es
beforeinstallprompt nicht und wird es nicht geben. Ein Knopf, der
am iPhone nichts tut, waere schlimmer als keiner -- man drueckt ihn
und sucht den Fehler bei sich.

pruef-installieren.mjs: 14 Pruefungen, alle drei Zustaende, mit
Gegenprobe in der installierten App.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:13:36 +02:00
DogFatherGitandClaude Opus 5 586eb51504 Profilfotos im Chat, rechte Hand zuerst, Karten lesbar
---- SCREEN 9: DIE FOTOS -------------------------------------------

Filipe: "da soll man im chat auch die profilfotos von den leuten sehen
wenn die schon eins drin haben."

ZWEI Luecken, beide an Stellen, wo ein Feld weggeworfen wurde:

1. Die GESPRAECHSLISTE bekam kein Bild. `teilnehmerVon` liest es aus
   der Datenbank, die Detailansicht nimmt es mit -- die Zeile fuer die
   Liste warf es weg. Folge: im offenen Gespraech ein Gesicht, in der
   Liste daneben ein Buchstabe. Vom selben Menschen.

2. Eine FRISCH GESENDETE Nachricht trug kein Bild. Der Verlauf beim
   Laden schon. Folge: Wer gerade zusieht, bekommt einen Buchstaben;
   wer neu laedt, ein Gesicht -- der Unterschied haengt nur daran, wann
   man geschaut hat.

Der Buchstabe bleibt als Unterlage LIEGEN und wird nicht ersetzt: Laedt
das Bild nicht, steht dort weiterhin etwas Sinnvolles statt eines
kaputten Bildsymbols. Vier Stellen, ein Verhalten.

---- SCREEN 3: REIHENFOLGE UND AUSSEHEN ----------------------------

Filipe: "ich will dass hier wie ueberall die reihenfolge immer rechte
hand und dan erst die modis."

Die Abfrage sortierte nach `aktiv DESC, name` -- die ROLLE wurde nicht
einmal mitgelesen. Die Seite konnte gar nicht wissen, wer rechte Hand
ist; sie sortierte alphabetisch, und damit stand Diene vor Funny, weil
D vor F kommt. Jetzt mit ROLLEN_SORTIERUNG -- derselben Regel, die auch
Personenliste, Chat und Rechtetafel benutzen.

"die kiste von rechte hand soll auch noch vieeeeeel krasser und
spezieller aussehen ... der hintergrund von den kacheln soll auch viel
krasser und geiler sein und so dass man texte und so besser erkennt.
weil gerade ist es schwer lesbar."

ZUERST DAS LESEN: Der Grund fuer die schlechte Lesbarkeit war der
durchscheinende Untergrund -- die Karten lagen auf dem Buehnenbild, und
ein Foto wird stellenweise hell. Sie bekommen jetzt eine DECKENDE
Unterlage und erst darueber die Verlaeufe. Die Verlaeufe sieht man
weiterhin, nur nicht mehr das Bild dahinter.

DANN DAS BESONDERE: Die rechte Hand bekommt einen goldenen Ton, eine
deutlich hellere Kante und eine schmale Leiste an der linken Seite --
man sieht den Rang aus zwei Metern, ohne ein Wort zu lesen. KEIN
zweiter Bauplan: dieselbe Karte, dieselben Felder, nur ein Merkmal am
Element. Zwei Karten zu bauen hiesse, jede kuenftige Aenderung zweimal
zu machen.

---- EINE PRUEFUNG, DIE EINE POSITION FESTNAGELTE ------------------

`ok(leute[0]?.id === idMarina, "die Aktiven stehen oben")` wurde rot,
sobald die rechte Hand nach vorn sortierte. Richtig wurde sie dadurch
nicht: Die Aussage "die Aktiven stehen oben" hat mit Marinas Platz
nichts zu tun. Jetzt prueft sie die EIGENSCHAFT (keine Pause vor einer
Aktiven) -- eine Pruefung, die eine Position festnagelt, verbietet jede
Umsortierung, auch die gewollte.

GEPRUEFT: pruef-team-stufen 28/0 (zwei Aussagen mehr),
pruef-erwaehnung 69/0 (zwei mehr: das Bild kommt in der Liste an, und
wer keines hat, bekommt auch keines vorgegaukelt), pruef-css-klassen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:07:06 +02:00
DogFatherGitandClaude Opus 5 c59517cb23 Ein Anruf faengt leise an
Filipe: "uebrigens soll man auswaehlen koennen ob man lautsprecher will
oder nicht bitte. es soll ohne lautsprecher anfangen das gespraech und
nur wenn man drauf klickt soll es laut werden ... es soll nicht
raushaengen oder so, das ist nicht cool."

DER GRUND IST DER STREAM. Ein Anruf, der beim Annehmen sofort aus den
Lautsprechern kommt, ist im schlimmsten Fall fuer alle Zuschauer zu
hoeren, bevor irgendjemand reagieren kann. Das laesst sich nicht
zurueckholen.

HIER STAND `hoeren = true` mit der Begruendung: "Wer den Ton abgestellt
hat, will ihn nicht beim naechsten Gespraech wieder an." Das war richtig
gedacht und ist jetzt umgedreht -- aus demselben Grund, nur in die
andere Richtung: Der Zustand soll NICHT ueberdauern. Eine Entscheidung
von vorhin darf nicht fuer ein Gespraech gelten, von dem man noch
nichts wusste. Zurueckgesetzt wird an BEIDEN Wegen, beim Anrufen und
beim Rangehen -- einer allein waere die Haelfte, und die andere Haelfte
faellt niemandem auf, bis es einmal zu laut war.

UND MAN SIEHT ES. Leise anfangen ohne Hinweis waere die naechste
Sackgasse: "ich hoere nichts" ohne Grund und ohne Weg. Ein Balken sagt
es, solange es gilt, und verschwindet in dem Moment, in dem man den Ton
anmacht. Er ist SELBST der Knopf -- wer liest "tippen, um den Ton
anzumachen", will genau das tun. Gedaempftes Bernstein statt Alarmrot:
Es ist kein Fehler, sondern ein Zustand.

DABEI EINEN EIGENEN FEHLER GEFANGEN: Der Balken fragte `!anruf` -- und
diese Variable wird erst gesetzt, NACHDEM der Kasten aufgeht. Beim
Aufbauen blieb er deshalb versteckt, und man sass in einem stummen
Gespraech ohne einen Satz dazu. Genau der Zustand, den er verhindern
soll. Jetzt haengt er am sichtbaren Kasten.

DIE PRUEFUNG WURDE ROT und hat damit ihre Arbeit getan -- sie hielt das
alte Verhalten fest. Umgedreht, nicht gestrichen: Die wichtigste Falle
(ueberlebt der Schalter das Neuzeichnen, wenn jemand auflegt?) bleibt,
nur der erwartete Zustand hat sich gedreht.

GEPRUEFT: pruef-anruf 117/0 (war 114) -- drei Aussagen mehr, darunter
dass der Hinweis da ist, 44 px hoch und im richtigen Moment
verschwindet.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:01:28 +02:00
DogFatherGitandClaude Opus 5 01151574ae Die rechte Hand verteilt Aufgaben und wechselt Rollen
Filipe: "jeder soll sich selber aufgabe vergeben koennen aber nur die
rechte hand und dogfather aufgaben an andere verteilen." Und: "ich will
dass ich da auch die rollen der leute wechseln kann ohne dass ich denen
einen neuen account machen muss ... perfektionier das fuer die rolle
dogfather und rechte hand."

---- AUFGABEN VERTEILEN ---------------------------------------------

Die Regel gab es schon -- sie fragte `istLeitung`, und darin steht die
rechte Hand NICHT. Sie konnte also keine Aufgabe weitergeben.

`hand` DORT EINZUTRAGEN WAERE FAHRLAESSIG GEWESEN: `istLeitung` wird an
57 Stellen in 19 Dateien gefragt -- unter anderem im vertraulichen
Meldeweg, in der Personenverwaltung und in den Auswertungen ueber
Menschen. Das haette in einem Zug ueber Einsicht in fremde Meldungen
entschieden, und das hat niemand gewollt.

Stattdessen `darfAufgabenVerteilen` -- eine eigene Regel mit eigenem
Namen. Man sieht an der Aufrufstelle, worum es geht, und wer sie
spaeter aendert, aendert genau diese eine Sache.

Wer nicht verteilen darf, bekommt KEINE Absage: Die Aufgabe landet bei
ihm selbst. Das ist genau, was Filipe wollte ("jeder soll sich selber
aufgabe vergeben koennen") und freundlicher als ein Fehler.

---- ROLLEN WECHSELN ------------------------------------------------

Auch das gab es schon, samt dem wichtigen Satz in der Rueckfrage: "Der
Zugangscode bleibt derselbe." Es konnte nur DogFather (und Spicy
Media).

DREI GRENZEN, JEDE MIT GRUND:
  * Niemand wird zu "admin" -- unveraendert seit dem 11.09.2026.
  * Die rechte Hand ernennt keine zweite rechte Hand. Wer jemanden auf
    die eigene Ebene hebt, vergibt Vertrauen, das ihm nicht gehoert.
    Und wer eine Rolle UEBER sich aendern koennte, koennte sich selbst
    befoerdern, indem er zuerst den anderen herabstuft.
  * Niemand aendert die eigene Rolle -- sonst waere jede Grenze nur ein
    Umweg.

SPICY MEDIA BEHAELT, WAS SIE HATTE. Beim ersten Anlauf waere sie durch
die neue Regel ausgesperrt gewesen -- ein Rueckschritt, den ich selbst
verursacht haette. Sie steht jetzt ausdruecklich in der Tabelle.

---- UND DIE OBERFLAECHE RECHNET NICHT MEHR SELBST ------------------

Die Rollenwahl nahm die Knoepfe des ANLEGE-Formulars. Fuer die rechte
Hand ist das leer -- sie legt niemanden an. Die Wahl waere leer
geblieben, das Recht unbenutzbar.

Der Server schickt jetzt zwei Listen mit: wozu ich machen darf
(`rollen_zum_aendern`) und wessen Rolle ich anfassen darf
(`rollen_anfassbar`). Beide aus denselben Funktionen wie die Schranke.
Damit kann die Seite weder zu streng sein (ein Recht, das niemand
findet) noch zu grosszuegig (ein Knopf, der eine Absage bringt) -- der
Fehler vom 10.09.2026, als zwei Listen drei Zeilen auseinander
einander widersprachen.

Dabei fast hineingelaufen: `ROLLEN_REIHE` ist die SORTIERUNG, und
darin fehlt "gast" mit Absicht. Wer sie fuer eine Aufzaehlung nimmt,
verliert die Community still -- genau diese Verwechslung hat am
17.09.2026 schon einmal verhindert, dass sich jemand zu "Community"
machen liess.

---- AUSSERDEM ------------------------------------------------------

Screen 2: "Unsere Seiten" und "Regeln & Hilfe" haben die Plaetze
getauscht -- nur diese zwei.

GEPRUEFT: pruef-verteilen 11/0 (neu, inkl. der Abgrenzung "darf
verteilen, ist aber NICHT Leitung"), pruef-rollen-anlegen 11/0,
pruef-personen-formular 36/0, pruef-personen-liste 33/0,
pruef-personen-loeschen 40/0, pruef-rechtetafel 19/0, pruef-treff 72/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 18:56:03 +02:00
DogFatherGitandClaude Opus 5 e378514bb4 Einmal anmelden reicht -- und beim Zurueckgehen bleibt die Seite stehen
Filipe: "kannst du bitte machen dass die leute sich nur einmal anmelden
muessen und dan nur noch abgemeldet werden wenn sie sich selbst
abmelden. damit sie auch die benarichtigungen sofort kriegen ... und
auch sofort die anrufe annehmen koennen."

---- 1. DIE ANMELDUNG BLEIBT ----------------------------------------

VORHER: zwoelf Stunden, feste Frist ab dem Anmelden. Wer morgens um
acht anfing, flog abends um acht raus -- mitten im Betrieb. Und wer
abgemeldet ist, hat die Seite nicht offen; ein Anruf erreicht ihn dann
nur noch ueber die Benachrichtigung, und bis er sich wieder angemeldet
hat, ist das Klingeln vorbei. Genau das beschreibt Filipe.

JETZT: ein gleitendes Fenster von 180 Tagen, das sich bei jeder Nutzung
verlaengert. Wer die Seite benutzt, bleibt angemeldet -- ohne Ende.

NICHT UNENDLICH, und das ist Absicht: In diesem Haus liegen
vertrauliche Meldungen ueber Menschen. Ein Zugang, der nie ablaeuft,
ist auf einem verlorenen Handy fuer immer offen. Ein halbes Jahr ohne
Besuch schliesst das Geraet und ist niemandem zu viel zugemutet.

An EINER Stelle gebaut: `sitzungLesen` -- durch die gehen alle 26
Fachmodule. Ein Parameter mehr haette 26 Aufrufe geaendert und beim 27.
Modul vergessen werden koennen; `req.res` haengt ohnehin an der
Anfrage. Verlaengert wird erst, wenn weniger als die Haelfte des
Fensters uebrig ist -- sonst waere das ein Schreibzugriff bei jedem
Bild und jedem Herzschlag des Ereignisstroms.

Drei Texte, die noch "zwoelf Stunden" behaupteten, sagen es jetzt
richtig -- inklusive der Abmelde-Nachfrage, die jetzt dazusagt, dass
man angemeldet bleiben SOLLTE, um Anrufe zu bekommen.

---- 2. BEIM ZURUECKGEHEN BLEIBT DIE STELLE -------------------------

Filipe, zum dritten Mal und in Grossbuchstaben. Also erst gemessen:

    gescrollt auf:  900
    gemerkt:        900
    gelandet:      1054      <- 154 px daneben, zuverlaessig

Die Wiederherstellung LIEF also -- sie traf nur nicht. Ursache ist
Chromes Scroll-Verankerung: Waechst Inhalt OBERHALB der Stelle,
verschiebt der Browser den Bildlauf mit, damit das Sichtbare stehen
bleibt. Im Alltag genau richtig; beim Wiederherstellen das Gegenteil.

Sie wird jetzt fuer die Dauer des Wiederherstellens abgeschaltet und
danach wieder eingeschaltet -- nicht dauerhaft, sonst spraenge einem im
Chat der Text unter dem Finger weg. Dazu wird die Stelle nachgesetzt,
solange die Seite noch waechst, und aufgehoert, sobald sie 400 ms lang
ruhig ist. Ergebnis: 900 -> 900, und es bleibt dort.

DAZU, und das ist der groessere Teil: Der Ereignisstrom in kopf.js
laeuft auf 32 Seiten und wird jetzt beim Weggehen geschlossen. Eine
offene EventSource sperrt den Vor-/Zurueck-Speicher des Browsers aus --
deshalb wurde bisher JEDE Rueckkehr ein vollstaendiger Neuaufbau.
Filipe hat genau das beschrieben ("OHNE DASS DIE SEITE ... NEU LAEDT").

EHRLICH DAZU: Playwright schaltet diesen Speicher fuer Tests ab, und er
liess sich hier nicht einschalten. Ich kann also NICHT messen, dass er
jetzt greift -- die Aenderung ist trotzdem richtig (eine offene
Verbindung ist die dokumentierte Sperre, und ein Strom, der beim
Weggehen offen bleibt, ist ohnehin ein Zuhoerer, den niemand mehr
liest). Gemessen und abgesichert ist der Weg OHNE diesen Speicher --
also der schlechteste Fall.

---- 3. DABEI GEFUNDEN: pruef-schranke mass seit neun Tagen nichts --

Sie suchte `const GESCHUETZT = {` per Textmuster in workspace.js. Diese
Tabelle ist am 11.09.2026 nach rechte.js umgezogen -- seitdem fand das
Muster nichts, und die Pruefung meldete "0 geschuetzte Seiten", "alle 0
Seiten leiten um", "0 Schreibweisen ausprobiert". Drei rote Zeilen, die
nach einem Zaehlfehler aussahen und in Wahrheit hiessen: hier wird
nichts mehr geprueft.

Jetzt wird die Tabelle IMPORTIERT. Ein Textmuster auf fremden
Quelltext reisst beim naechsten Umzug still; ein import reisst laut.
Ergebnis: 33 geschuetzte Seiten, 363 Schreibweisen -- alles gruen.

GEPRUEFT: pruef-rollstelle 8/0 (neu, mit Spur ueber die Zeit und zwei
Gegenproben), pruef-schranke (war rot), pruef-code 17/0,
pruef-haerte 20/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 18:48:34 +02:00
DogFatherGitandClaude Opus 5 75019ec8c3 Am Handy stand nicht da, mit wem man schreibt
Gemessen in der Kopfzeile eines Gespraechs, Name "Team-Runde":

    360 px ->  0 px sichtbar (98 noetig)
    390 px -> 12 px
    412 px -> 33 px
   1280 px -> passt

Auf JEDEM Telefon stand also kein Name da -- man oeffnet ein Gespraech
und sieht nicht, mit wem. Und weil die Zeile nicht leer aussieht
(Zurueck-Pfeil, fuenf Knoepfe), wirkt sie nicht kaputt, sondern eng.

URSACHE: `flex: 1` heisst ausgeschrieben `1 1 0%` -- Grundbreite NULL.
Damit "passt" der Name rechnerisch immer, egal wie eng es ist, und es
bricht nie etwas um. Die Knopfreihe daneben hat `flex: none` und
schrumpft nie; seit die Knoepfe am Finger 44 px breit sind, bleibt bei
sechs Knoepfen nichts uebrig.

Zwei Stellen setzten dieselbe Eigenschaft, die spezifischere gewann --
die erste Reparatur wirkte deshalb nur bei 360 px und sonst nicht.
Beide nennen jetzt dieselbe Grundbreite.

KEINE NEUE SCHWELLE: `flex-wrap` bricht genau dann um, wenn der Platz
wirklich nicht reicht. Dieses Haus ist an festen Breiten schon zweimal
gescheitert (Kopfleiste, 06.09.2026); kommt morgen ein siebter Knopf
dazu, stimmt es weiter. Ergebnis: 244 / 268 / 289 px statt 0 / 12 / 33.

---- WARUM DER HANDY-RUNDGANG DAS NICHT GEFUNDEN HAT ----------------

Zwei eigene Entscheidungen, jede fuer sich vernuenftig, zusammen ein
Loch:

  1. `sichtbar()` verlangt `width > 0`. Ein auf null gequetschtes
     Element ist unsichtbar -- und "unsichtbar" hiess "nichts zu
     pruefen". Genau falsch herum: Nichts zu sehen IST der Befund.
  2. `text-overflow: ellipsis` gilt als Absicht. Das stimmt auch --
     ein langer Name soll gekuerzt werden. Es stimmt nur nicht mehr,
     wenn nichts uebrig bleibt.

Die neue Regel ist bewusst schmal: gemeldet wird nur, was unter 40 px
sichtbar ist und mindestens das Doppelte braeuchte. "Jede Kuerzung
melden" waeren die ~350 Fehlalarme, die diese Pruefung schon einmal
zugedeckt haben.

NACHGEMESSEN: 206 Seitenaufrufe, 91 638 Elemente. Die Regel schlaegt
an genau EINER Stelle an (kalender.html, sechsmal) und sonst nirgends
-- 64 -> 70 Befunde. Die Pruefung ist genauer geworden, nicht die App
schlechter.

DER KALENDER-FUND BLEIBT OFFEN: Im Monatsraster ist ein Tag am Handy
36 px breit, ein Eintrag braucht 186 bis 317. Das ist kein Versehen im
Code, sondern die Frage, ob die Monatsansicht am Telefon ueberhaupt
die richtige Vorgabe ist -- eine Entscheidung, keine Reparatur.

GEPRUEFT: pruef-chat-optik 39/0 (drei neu, mit einer Gegenprobe, die
den gemessenen Fall HERSTELLT -- fuenf Knoepfe wie in einer Gruppe;
der erste Anlauf blieb gruen, weil in einem Zweiergespraech nur drei
stehen und der Platz auch ohne Reparatur reicht: 12 px mit der alten
Angabe, 268 mit der neuen, im selben Aufbau).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 18:14:08 +02:00
DogFatherGitandClaude Opus 5 2a26a49f91 Mit "@" jemanden im Chat ansprechen
Filipe: "ich will das man die leute mit @ markieren kann im chat."

MARKIEREN IST KEINE FARBE, SONDERN EINE ANSPRACHE. Sie funktioniert
nur, wenn drei Dinge zusammen stimmen: Der Richtige ist gemeint, er
MERKT es, und man sieht es im Satz. Fehlt eines davon, ist es eine
Attrappe -- und zwar eine, die gut aussieht.

WER GEMEINT IST, ENTSCHEIDET DER SERVER. Der Browser schickt nur Text.
Damit wirkt ein von Hand getipptes "@VanVan" genauso wie eines aus der
Auswahlliste, und niemand kann jemanden ansprechen, der gar nicht im
Raum sitzt -- auch nicht ueber die Schnittstelle.

Die Regeln stehen in server/chat-erwaehnung.js, jede mit Begruendung.
Zwei davon sind keine Feinheit, sondern der Unterschied zwischen
brauchbar und laestig:

  * Das Zeichen VOR dem "@" darf kein Buchstabe sein. Sonst piepst
    jede E-Mail-Adresse im Chat jemanden an
    ("[email protected]").
  * Das Zeichen DANACH auch nicht, und der laengste Name gewinnt.
    Sonst spricht "@Tilikum" Tili an.

MAN MERKT ES AUCH OHNE OFFENEN RAUM. Eine Zahl in der Gespraechsliste
sagt "hier ist etwas" -- nicht, ob es an dich war. Wer morgens vier
Raeume mit Zahlen sieht, macht den lautesten zuerst auf, und dort
steht selten das, was auf ihn wartet. Jetzt steht ein "@" daneben.

UND DIE MELDUNG AUFS HANDY SAGT ES: "VanVan hat dich erwaehnt" statt
"Nachricht von VanVan". Als EIGENE Art, die sich getrennt abschalten
laesst -- wer den lauten Chat stumm stellt, will trotzdem wissen, wenn
ihn jemand direkt anspricht. Ohne Ausnahme von der Ruhezeit: Ein Anruf
wartet auf eine Antwort, ein "@Anna" nicht.

DIE AUSWAHL BEIM TIPPEN loest drei Dinge, die man sonst selbst wissen
muesste: wie die Person genau heisst, wer ueberhaupt im Raum ist, und
ob man sich vertippt hat. Tastatur zuerst (Pfeile, Enter, Tab, Escape).
Sie erzwingt nichts -- wer weitertippt, schreibt einfach weiter.

ZWEI RECHNUNGEN, EINE ANTWORT: Der Browser braucht dieselbe Aufloesung,
um sofort hervorzuheben. Genau dort laufen Dinge auseinander, und dann
haette die Seite jemanden hervorgehoben, den niemand benachrichtigt
hat. pruef-erwaehnung LIEST die Browserfassung aus der Datei und fuehrt
sie aus -- ein Nachbau wuerde pruefen, ob ich zweimal dasselbe
schreiben kann.

---- DABEI GEFUNDEN: "gelesen bis 999999" ----------------------------

Der Server nahm fuer den Lesestand JEDE ganze Zahl an. Wer einmal eine
Zahl hinter allem Vorhandenen schickte, sah in diesem Gespraech nie
wieder einen Zaehler und nie wieder ein @-Zeichen: Alles Kuenftige galt
als gelesen, bevor es geschrieben war. Das faellt niemandem als
Zusammenhang auf -- man merkt nur, dass "die Benachrichtigungen nicht
gehen".

Der Browser schickt heute immer die letzte gesehene Nummer, ist also
nicht der Grund. Aber eine Grenze, die nur davon lebt, dass der
Aufrufer sich benimmt, ist keine. Jetzt wird auf die juengste
Nachricht des Raums begrenzt -- abgeleitet, nicht geraten.

Gefunden hat es meine eigene Pruefung: Sie setzte zum Aufraeumen 99999
und wunderte sich danach, warum das frische "@" nicht leuchtete.

WOHER MAN ERFAEHRT, DASS ES DAS GIBT: Im Chat gibt es keinen
Hilfeknopf. Der Hinweis steht deshalb im Leersatz einer neuen Gruppe --
dort, wo man beim ersten Oeffnen ohnehin hinsieht, und nur ab drei
Leuten. In einem Zweiergespraech waere er Ballast.

GEPRUEFT: pruef-erwaehnung 67/0 (neu) -- 13 Regelfaelle ohne Server,
der Weg durch die Schnittstelle, das Zeichen in der Liste samt
Gegenprobe bei jemandem, der dabei aber nicht gemeint war, beide
Aufloesungen nebeneinander, und der ganze Ablauf am echten Bildschirm
bis "Enter waehlt und schickt NICHT ab".
Dazu pruef-chat 48/0, pruef-chat-optik 36/0, pruef-treffchat 110/0,
pruef-chat-kanaele 79/0, pruef-glocke 31/0, pruef-push 24/0,
pruef-anruf-klingelt, pruef-css-klassen, pruef-meldungen,
pruef-nachfrage, pruef-tippziele.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 17:54:16 +02:00
DogFatherGitandClaude Opus 5 409ed551f3 "Review" heisst jetzt "Zur Freigabe" -- und Datumsfelder sind so hoch wie alle anderen
Im Code stand die Begruendung selbst: "«Review» allein sagt einem Neuen
nichts." Das Wort ist englisch, ein Hauptwort ohne Handlung, und es
verraet nicht, WER jetzt dran ist. "Zur Freigabe" sagt beides: fertig
von mir, wartet auf jemanden.

Geaendert wurde nur, was ein Mensch LIEST -- der Zustandsschluessel
bleibt `review`, der gehoert der Datenbank. Betroffen: Spalte und
Weiterknopf im Aufgabenbrett, Dateien-Filter, Startseiten-Zaehler,
Kachel-Unterzeile, Hinweis "Datei wartet auf Freigabe", Report.

NICHT geaendert: der Kalender. Dort ist `review` eine TERMINART (ein
Gespraech, in dem man zurueckschaut), kein Zustand. Ich hatte das beim
Umbenennen selbst verwechselt und wieder zurueckgenommen -- ein
Kommentar an der Stelle haelt die zwei Bedeutungen jetzt auseinander.

pruef-sprung hing an der Wortwahl (`/review/i` auf der Beschriftung)
und wurde rot, obwohl der Filter richtig stand. Sie prueft jetzt
`data-status` -- den Schluessel, der sich nicht mit der Sprache aendert.

DAZU, unabhaengig gefunden: Datumsfelder waren 48 px hoch, alle anderen
Felder 44. Gemessen auf drei Seiten bei 390 px. Alle liegen auf dem
44-px-Beruehrziel -- nur das Datumsfeld drueckte sich darueber, weil
Chromium in `::-webkit-datetime-edit` eine eigene Innenpolsterung setzt,
die sogar ein gesetztes `height: 44px` ueberstimmt.

Zwei Anteile, einzeln nachgemessen (jeder allein 48->46, erst beide
zusammen 48->44): 1 px Polsterung oben und unten im Feldkasten, und
eine Zeilenhoehe von 24 statt 22. Keine feste Hoehe gesetzt -- die
Zeilenhoehe wird aus Beruehrziel und Polsterung gerechnet, damit sie
mitwandert, wenn sich eines davon aendert.

Geprueft: pruef-formulare 19/0 (war 16 mit 3 Fehlern), pruef-sprung
43/0, pruef-start-ansicht 151/0, pruef-aufgabenbrett 49/0,
pruef-uebersicht 35/0, pruef-uebersicht-browser 20/0,
pruef-deutsche-texte, pruef-css-klassen.

Ausserdem: vorlagen.js geloescht (8,2 KB). `vorlagenBlock(` wurde in
ca104799 eingebaut und in 9267797d wieder ausgebaut -- seither laedt
die Datei auf zwei Seiten, ohne dass jemand sie aufruft.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 17:27:09 +02:00
DogFatherGit 0f5faf7ee6 Eine Seite, die nicht laedt, sagt es -- und bietet einen Weg zurueck
Fuenf Suchlaeufe parallel, ihre Funde selbst nachgemessen und behoben.

DER GROESSTE: 13 VON 21 SEITEN SCHLUCKTEN JEDEN NETZFEHLER.
Jede Seite beginnt mit `try { await hole('/api/ich') } catch { return; }`.
Faellt das Netz aus -- Aufzug, U-Bahn, Funkloch --, bricht der Block ab,
und die Seite bleibt fuer immer auf "wird geladen …" stehen. Gemessen:
0 von 32 Stellen setzten `aria-busy` im Fehlerfall zurueck, und es gab
KEINEN EINZIGEN "Nochmal versuchen" auf allen 21 Seiten.

Im Code stand der richtige Satz dazu -- an genau einer Stelle:
"Ein Platzhalter, der nie ersetzt wird, ist eine Luege mit
Fortschrittsanzeige." Er galt ueberall ausser dort.

Neu: window.ladefehler() in meldung.js. Sie ersetzt alles, was gerade
"laedt", durch drei Dinge: was los ist, was das bedeutet, und einen
Knopf, der es noch einmal versucht -- ohne die Seite neu zu laden.
21 Dateien angeschlossen. Neu: server/pruef-ladefehler.mjs, 26/0, mit
abgeklemmtem Netz im echten Browser.

UND DIE STARTSEITE WARF BEI EINEM FUNKLOCH AUF DIE ANMELDUNG.
`catch { location.assign('/workspace/') }` -- der Mensch glaubt, er sei
rausgeworfen, und tippt seinen Code neu. Dabei haelt seine Sitzung 12
Stunden; nur die Anfrage kam nicht durch. Umgeleitet wird jetzt nur
noch bei einer ANTWORT, die das sagt (401).

DER ANMELDEHINWEIS FUEHRTE MODIS IN DIE SPERRE.
Nach zwei Fehlversuchen stand: "Stimmt die Auswahl oben? Ein Code
gehoert immer zu genau einer davon." Auf der Crew-Wand ist das FALSCH
-- `stillerZugang()` sucht ueber die Codekennung, die angetippte
Kachel spielt fuer hand/modi keine Rolle. Sie probieren alle vier
durch, sammeln vier Fehlversuche, und nach acht in zehn Minuten ist
ihre Adresse gesperrt. Ein Hinweis, der die Sperre herbeifuehrt, gegen
die er helfen soll. Auf der Agenturwand stimmt der Satz weiter --
deshalb wird gefragt, auf welcher Wand man steht.
Dazu: Die Crew-Wand nannte nur der Community einen Weg ("Frag im Live
nach"). Wer zum Team gehoert und dessen Code nicht geht, fand dort
niemanden.

SACKGASSE AUF DER KERNSEITE EINES MODI.
treff-moderation sagte: "Zugaenge legst du in 'Personen & Zugaenge'
an" -- eine Seite, die ein Modi nicht oeffnen darf. Am ersten Tag, bei
leerer Community, war das der einzige Satz im Abschnitt. Jetzt fragt
die Seite ueber `window.__ich.seiten`, ob es den Weg fuer DIESEN
Menschen gibt. Und ein 404 wirft ihn nicht mehr wortlos auf die
Startseite.

TOTE KNOEPFE AN FREMDEN KARTEN.
"◀ zurueck" und "▶ In Arbeit" standen an JEDER Aufgabenkarte, auch an
fremden. Ein Modi sieht das Brett des ganzen Teams; er tippt, der
Server lehnt mit 403 ab, und die Meldung erscheint GANZ OBEN. Bei
einer Karte weiter unten sieht er nichts. Zwei Zeilen tiefer stand die
Regel im Klartext: "niemandem etwas anzubieten, das dann abgelehnt
wird." Der Server schickt jetzt `darf_aendern` mit.

13 STELLEN ROLLTEN GEGEN DEN WILLEN DES NUTZERS.
`scrollIntoView({ behavior: 'smooth' })` beachtet "Animationen
reduzieren" NICHT. Wer das eingestellt hat, hat es meist wegen
Schwindel getan. Zwei Stellen fragten vorher, dreizehn nicht.
Jetzt `window.sanft()`, einmal statt dreizehnmal.

DAS WORT UEBER DEN BRETTERN EINES MODI HIESS "BETREUUNG".
Fest im HTML, ueberschrieben nur bei Brettern mit eigenem `ober` --
sechs haben keines. Jetzt faellt es auf die GRUPPE der Kachel zurueck,
ueber die er hergekommen ist. Je Rolle richtig, ohne zweite Liste.

DER HINWEIS-ZU-KACHEL-WEG WAR DOPPELT KAPUTT.
`bereichZu` suchte nur in GRUPPEN -- der Liste der AGENTUR. Die
Kacheln von Team Dogi schickt der Server; fuer einen Modi fand die
Zeile entweder nichts oder eine fremde Kachel und uebernahm deren
Farbe. Und sie suchte ueber den NAMEN: "LIVE-Analyse" heisst auf der
Crew-Adresse "Live-Ablauf". Beim Beheben erst den Namen umgedreht --
und damit die Agenturseite kaputt gemacht (pruef-start-ansicht sofort
rot). Jetzt ueber das ZIEL, das in beiden Haeusern dasselbe ist.

UND EIN BRETT WAR SEIT GESTERN GESPERRT.
`TREFF_BRETTER` wird aus Kachelzielen abgeleitet. Als die Kachel
"Regeln & Hilfe" am 19.09. auf `treff-regeln.html` umgelenkt wurde,
fiel `regeln` heraus -- und `treff-regeln.html` verweist weiterhin
darauf ("Haeufige Fragen stehen auf dem Brett Regeln & Hilfe").
Gefunden hat es pruef-treff, die seit gestern rot war. 72/0.

NEBENBEI 7 SEITEN LEICHTER: meldung.js wird jetzt abgeleitet
eingebunden -- nur dort, wo sagWas/ladefehler/sanft wirklich
gebraucht werden. Die Anmeldewand traegt es nicht mehr.

Gruen: pruef-ladefehler 26/0, pruef-sackgassen 11/0 (582 Wege, 0 ins
Leere), pruef-start-ansicht, pruef-treff 72/0, pruef-treffchat,
pruef-community-sicht 10/0, pruef-aufgabenbrett, pruef-code 17/0,
pruef-chat-optik, pruef-nachfrage 49/0, pruef-meldungen 8/0,
pruef-css-klassen, pruef-tippziele 11/0, pruef-leerzustand 13/0,
pruef-rechtetafel.
2026-09-20 15:49:57 +02:00
DogFatherGit cc39552b4f Eine Eingabe geht nicht mehr wortlos verloren
Filipe: "Was passiert, wenn jemand eine Funktion abbricht?"

GEMESSEN: Acht Dialoge im Workspace enthalten Eingabefelder --
"Aufgabe bearbeiten" (10 Felder), der Tageseintrag in der Leistung
(8), Ziele, Netzwerk, Import, ein neuer Chat-Raum, ein Creator. Bei
allen galt: Esc, Klick daneben oder "Abbrechen" wirft ALLES weg,
wortlos. Wer zehn Felder ausgefuellt hat und mit dem Daumen den Rand
trifft, faengt von vorn an.

Neu: window.verwurfWache() in nachfrage.js.

BEIDE SCHLIESSWEGE, denn sie laufen verschieden:
  Esc / Klick daneben  loest `cancel` aus, close() wird NICHT gerufen
  "Abbrechen"-Knopf    ruft close(), loest kein `cancel` aus
Wer nur einen abfaengt, hat eine halbe Sicherung -- und die ist
schlimmer als keine, weil man ihr vertraut.

NICHT VON HAND VERTEILT: Jeder Dialog mit Feldern bekommt sie
automatisch (ausser dem Nachfrage-Dialog selbst -- er wuerde beim
Schliessen nach sich selbst fragen, in sich selbst, und haenge fuer
immer). Wer morgen einen neunten baut, hat sie, ohne daran zu denken.

UND SIE FRAGT NUR BEI WIRKLICHER AENDERUNG. Beim Oeffnen wird ein
Abbild der Felder genommen, beim Schliessen verglichen. Wer einen
Dialog aufmacht und gleich wieder zu, merkt nichts.

ZWEI SACHEN BEIM BAUEN GEMESSEN STATT VERMUTET:

  MEINE EIGENE "ROBUSTHEIT" HAT DIE WACHE STILL AUSGESCHALTET.
  Gegen den Fall "Felder werden erst nach dem Oeffnen gefuellt" hatte
  ich einen zweiten Schnappschuss beim Hineinklicken (`focusin`)
  eingebaut. Gemessen: Der entstand NACH dem Tippen -- Fokus und
  Werteingabe passieren im selben Atemzug. `beimOeffnen` war danach
  gleich dem getippten Text, und der Dialog ging wortlos zu. Die
  Sicherung sah eingebaut aus und tat nichts.
  Jetzt wird im naechsten BILD nachgetragen: Was das Skript beim
  Oeffnen nachtraegt, ist drin; getippt haben kann in derselben
  Sechzehntelsekunde niemand.
  (Nachgemessen: Alle acht Dialoge fuellen heute VOR showModal.)

  ZWEIMAL ESC HINTEREINANDER SCHLIESST TROTZDEM. Das ist Chromiums
  "close watcher": Eine Seite darf den Nutzer nicht mit Esc
  einsperren. Die Regel ist richtig; dagegen anzubauen waere falsch.
  Sie steht deshalb im Code und in der Pruefung -- festgehalten,
  nicht umgangen. Der Knopf unterliegt ihr nicht, und am Handy gibt
  es ohnehin kein Esc.

Elf Speicherwege rufen `vergessen()`, damit nach erfolgreichem
Speichern nicht gefragt wird. Eine Warnung nach dem Speichern waere
genau die, die man wegklickt -- und danach auch die echte.

pruef-nachfrage 49/0 (war 33), davon zehn am Bildschirm:
  unberuehrt geht er ohne Nachfrage zu
  nach einer Aenderung fragt Esc nach, der Dialog bleibt offen
  "Weiter bearbeiten" laesst ihn offen UND der Text steht noch da
  auch der Abbrechen-Knopf fragt -- jedes Mal
  "Verwerfen" schliesst wirklich, und der Text steht nirgends

pruef-aufgabenbrett, -leistung, -uebersicht-browser, -chat-optik,
-css-klassen gruen, pruef-tippziele 11/0.
2026-09-20 15:11:25 +02:00
DogFatherGit 285038f400 Der vertrauliche Meldeweg vergisst jetzt -- und sagt, bis wann
Zwei Entscheidungen, die offenstanden. Beide getroffen, nachdem
gemessen war, was wirklich da ist.

1. WIE LANGE BLEIBEN ABGESCHLOSSENE FAELLE?  90 Tage.

Die Entscheidung war bereits getroffen: `AUFBEWAHRUNG_TAGE = 90` steht
seit dem 19.09. in hilfe-tabellen.js, mit Begruendung ("ein Fall kommt
manchmal wieder auf"). Nur hat sie NIEMAND durchgesetzt --
`hilfeAufraeumen()` gab es, und der einzige Aufrufer war ihre eigene
Pruefung. Der Kommentar darueber behauptete "Wird beim Start
aufgerufen (siehe index.js)"; das war nie wahr.

Jetzt steht die Regel in workspace-aufbewahrung.js, dem Loeschkonzept,
das sich selbst durchsetzt -- beim Start und danach taeglich. Die
zweite Fassung in workspace-hilfe.js ist WEG, nicht doppelt: Zwei
DELETEs auf dieselben Daten waeren morgen verschieden, und der
Unterschied fiele erst auf, wenn er zaehlt.

GEMESSEN VOR DEM EINSCHALTEN:
  In der echten Datenbank steht heute KEIN einziger Fall. Der erste
    Lauf loescht nichts, und der erste Fall kann fruehestens in drei
    Monaten 90 Tage alt werden. Jetzt einschalten ist frei -- spaeter
    waere es der riskante Moment gewesen.
  PRAGMA foreign_keys steht im Dienst auf 1, und hilfe_nachrichten
    traegt ON DELETE CASCADE. An einem echten Fall mit Nachricht
    nachgemessen: vorher 1/1, nachher 0/0. Ohne diese Messung waere
    der Fall verschwunden und der eigentliche Text liegengeblieben.

2. SOLL EIN GESCHLOSSENER FALL WIEDER ZU OEFFNEN SEIN?  Nein.

Im Kopf von workspace-hilfe.js steht: "EIN GESCHLOSSENER FALL IST
GESCHLOSSEN. Auch fuer die Leitung -- sonst ist 'zugemacht' eine
Meinung und keine Tatsache." Das ist eine gute Regel, und sie bleibt.

Nachgemessen, dass sie auch traegt: Ein Melder kann seinen
geschlossenen Fall weiter LESEN, und ein geschlossener Fall zaehlt
nicht gegen das Limit von drei offenen. Wer eine Wiederholung melden
will, kann das also jederzeit -- die Bauweise ist stimmig.

NUR WUSSTE DAS NIEMAND. Dort stand ein Satz: "Dieser Fall ist
abgeschlossen (Datum)." Jetzt stehen drei -- und sie beantworten die
drei Fragen, die man in dem Moment hat:
  Kann ich noch schreiben?   Nein, und er laesst sich nicht oeffnen.
  Bleibt das hier stehen?    Bis zum TT.MM.JJJJ, dann geloescht.
  Und wenn es wieder passiert? Neu melden, der alte zaehlt nicht mit.

Das Datum kommt vom Server (`lesbar_bis`), die Frist ebenso -- sie
steht nur an EINER Stelle. Und sie steht jetzt auch im Dialog BEIM
Schliessen: Wer eine Uhr startet, soll das vorher wissen, nicht
danach.

OHNE UHRZEIT, und das ist kein Schoenheitsgrund: Ein Fall, der am
20.09. um 14:04 (Sommerzeit) geschlossen wird, verfaellt 90 Tage
spaeter um 13:04 -- die Uhr wird dazwischen zurueckgestellt. Richtig
gerechnet, sieht aus wie ein Fehler. Wer eine Stunde sucht, die es
nicht gibt, hat Zeit verloren.

UND DIE URSACHE, DAMIT ES NICHT WIEDER PASSIERT:
hilfe_faelle kam am 19.09. dazu, das Loeschkonzept ist vom 15.09., und
nichts hat die beiden je verglichen. Neue Pruefung in
pruef-aufbewahrung: Jede Tabelle mit einer Spalte, die "hier ist etwas
zu Ende" sagt, MUSS im Konzept stehen.
  Kein "jede Tabelle muss drinstehen": 46 Tabellen, 41 mit
  Personenbezug -- das gaebe 38 Meldungen, von denen fast alle falsch
  waeren (sie sind ueber personen_geloescht gedeckt). Eine Pruefung,
  die 38-mal meldet, wo einmal richtig waere, wird abgeschaltet.
  Gesucht wird das schmale Merkmal: GENAU ZWEI Tabellen im Haus tragen
  so eine Spalte. Beide jetzt im Konzept -- hilfe_faelle mit Frist,
  aufgaben ausdruecklich OHNE (erledigte Aufgaben sind
  Arbeitsdokumentation, keine Meldung ueber einen Menschen).

pruef-hilfe 84/0 (war 59) -- darunter zehn neue am Bildschirm:
"drei Saetze statt einem", "sie stehen untereinander, nicht
nebeneinander" (ein <p> in einem <p> waere ungueltig, der Container
ist jetzt ein <div>), "und WANN, mit Datum".
pruef-aufbewahrung 45/0 (war 41), mit Gegenprobe.
2026-09-20 14:10:38 +02:00
DogFatherGit 0a2363374c Eine Nachricht, die nicht ankommt, sieht man jetzt -- und schickt sie neu
DER KOMMENTAR STAND DA, DIE SACHE NICHT. Im Chat stand woertlich:
"NICHT STILL VERSCHWINDEN LASSEN. Wer etwas schreibt und es sieht,
glaubt, es sei angekommen." Gemessen: `markiereAlsGescheitert` setzte
`n.gescheitert = true` -- und gelesen hat das Merkmal NIEMAND, weder
das Skript noch das CSS. Eine gescheiterte Nachricht sah exakt aus wie
eine zugestellte. Im CSS stand an der Stelle eine leere Regel mit dem
Kommentar "Platzhalter, damit :has unterstuetzt bleibt".

Ein Kommentar, der eine Absicht beschreibt, erfuellt sie nicht.

Jetzt: sichtbare Kante an der Blase, blasse Darstellung solange sie
unterwegs ist, und ein Knopf "Nochmal senden" daneben. Der Satz in der
Meldezeile bat vorher ums Kopieren -- fuenf Handgriffe fuer etwas, das
die Seite in einem tun kann; den Text hat sie ja noch.

KEIN ZWEITER SENDEWEG: Der Knopf legt den Text zurueck ins Feld,
stellt das Antwortziel wieder her und ruft `abschicken`. Ein eigener
Weg waere morgen anders als dieser, und der Unterschied fiele erst
auf, wenn er zaehlt.

"ZUM NEUESTEN" STAND AUF EINER RECHNUNG VON GESTERN: `bottom: 96px` --
die Hoehe der Schreibleiste an dem Tag, an dem der Knopf gebaut wurde.
Das Textfeld waechst aber bis 160. Wer lange tippt und gleichzeitig
oben liest, hatte den Knopf HINTER der Leiste. Und darueber koennen
noch das Nachtruhe-Band und der Hochlade-Balken stehen.
Jetzt misst die Seite den ganzen Unterbau selbst -- ueber einen
Beobachter statt einer Liste von Ausloesern, denn das Band erscheint
um Mitternacht von selbst. Kommt morgen ein viertes Bauteil dazu,
rechnet es von allein mit.

NEUE PRUEFUNG FUER EINEN WEG, DEN NIE ETWAS GEPRUEFT HAT:
pruef-chat-optik faengt die Sendeanfrage jetzt einmal ab und geht den
ganzen Fehlerweg durch -- 10 Aussagen, darunter:
  der Unterschied ist auch zu SEHEN, nicht nur im Merkmal (Rand 1px)
  die Nachricht steht danach GENAU EINMAL da, nicht doppelt
  und sie ist beim Gegenueber angekommen
Der letzte ist der eigentliche: Alles davor koennte gut aussehen und
trotzdem nichts zugestellt haben.

pruef-treffchat war seit gestern rot -- 8 Fehler ueber "undefined".
Sie suchte die Kachel mit `ziel === "chat.html"`, seit dem 19.09.
heisst es `chat.html?raum=treff` (sie fuehrt direkt in den Raum). Kein
Befund ueber das Haus, sondern einer ueber sich selbst. Sie sucht
jetzt nach der SEITE und prueft statt des Wortlauts das, worauf es
ankommt: Man erkennt den Chat, und der Name kommt genau einmal vor.
110/0 statt 108 mit 8 Fehlern.

pruef-chat, -anhaenge, -kanaele, -optik, -ausbau gruen,
pruef-start-ansicht 151/0, pruef-tippziele 11/0, pruef-nachfrage 33/0,
pruef-leerzustand 13/0, pruef-meldungen 8/0, pruef-css-klassen gruen.
2026-09-20 12:44:31 +02:00
DogFatherGit 18148675a9 Die gepflegte Liste der Tippziele wird jetzt bewacht
In module.css steht ein Block, der ein Dutzend Klassen auf 44 Pixel
hebt. Diese Liste wurde von Hand gepflegt -- genau die Falle, vor der
die Hausregeln warnen: Wer einen Knopf mit `width: 34px` baut, traegt
ihn dort nicht nach und merkt es nicht.

GEMESSEN: FUENF Bedienelemente standen nicht drin.
  .nachricht__weg       24 breit   (das x an einer Nachricht)
  .antwort-leiste__weg  28 breit
  .chat__weg            34 breit   <- der unangenehmste
  .todo__weg            36 breit
  .sicht__weg           28 breit

`.chat__weg` ist der Knopf, der ein Gespraech wegraeumt -- und direkt
daneben sitzt der, der es FUER ALLE aufloest. Zwei 34-Pixel-Ziele
nebeneinander, eines davon unwiderruflich.

Neu: server/pruef-tippziele.mjs -- 11/0, ohne Browser, unter einer
Sekunde. Sie leitet die Bedienelemente aus dem CSS ab und verlangt
fuer jedes eine Abdeckung. Die Liste bleibt (CSS kann nicht rechnen),
aber sie kann nicht mehr still veralten.

DER ERSTE ANLAUF WAR ZU GROB und meldete 21 Treffer, davon 15 falsch:
`.chat__weg svg` ist 17 Pixel gross und soll das auch sein --
getroffen wird der Knopf darum herum. Eine Pruefung, die zu viel
meldet, wird abgeschaltet; das ist kein besseres Ergebnis als eine,
die zu wenig meldet. Jetzt unterscheidet sie Bedienelement und
Innenteil (svg, ::after, __punkt, __lupe, __pfeil).

UND DIE REPARATUR WAR ERST ZU KLUG. Fuer das 24-Pixel-x in einer
Chat-Nachricht hatte ich eine unsichtbare Trefferflaeche gebaut
(`::after { inset: -10px }`), um die Zeile nicht hoeher zu machen.
Dann gemessen: Die Zeile IST schon 44 hoch -- `start.css` hebt unter
760 px bereits JEDEN button. Es fehlte nur die BREITE. Die Flaeche
haette ein Problem geloest, das es nicht gibt, und dafuer einen Trick
eingefuehrt, den man beim naechsten Lesen erst verstehen muss.
Jetzt schlicht `min-width: 44px`.

Gemessen am Bildschirm, mit und ohne Finger:
  Maus    .nachricht__weg 24x24  .chat__weg 34x34   (unveraendert)
  Finger  .nachricht__weg 44x44  .chat__weg 44x44

`pointer: coarse` und nicht `max-width`: Ein Tablet ist 1024 breit und
wird trotzdem mit dem Finger bedient.

NACHTRAG ZUR PRUEFUNG SELBST: Sie verlangte kurz, dass es die
Trefferflaeche GIBT -- und fiel um, als sie wieder verschwand. Eine
Pruefung, die eine Bauweise erzwingt statt eines Ergebnisses, steht
dem Aufraeumen im Weg. Sie erkennt sie jetzt an, verlangt sie aber
nicht.

pruef-tippziele 11/0, pruef-chat-optik gruen, pruef-css-klassen gruen,
pruef-nachfrage 33/0, pruef-leerzustand 13/0.
2026-09-20 12:36:02 +02:00
DogFatherGit 2f3fb03ffe Eine Pruefung, die nach der ersten Aussage stirbt, prueft nichts
pruef-start-ansicht kam seit gestern Nachmittag ueber die ERSTE
Aussage nicht hinaus: 1 statt 151. Sie starb mit "Failed to execute
getComputedStyle: parameter 1 is not of type Element" -- und sagte
damit gar nichts mehr ueber die Startseite.

URSACHE WAR MEIN EIGENER HINWEIS VON GESTERN. "Bei dir klingelt
nichts" gehoert absichtlich zu keinem Bereich (die Anruf-Probe ist
ein Werkzeug, keine Kachel). Dadurch bekam die Zeile kein Zeichen --
und die Pruefung rief getComputedStyle auf null.

ZWEI FEHLER, ZWEI REPARATUREN:

  Die ZEILE sah kaputt aus. Sie stand als einzige ohne Zeichen
  zwischen allen anderen, der Text begann weiter links. Genau der
  stille Fehler, der wie Absicht aussieht. Sie bekommt jetzt immer
  ein Zeichen -- aber KEINE Farbe, denn sie soll keinen Bereich
  behaupten, zu dem sie nicht gehoert.

  Die PRUEFUNG durfte daran nicht sterben. Ein fehlendes Teil ist ein
  BEFUND, kein Absturz. Und sie nahm an, jeder Hinweis zaehle etwas.
  Seit gestern gibt es zwei Sorten: zaehlende ("2 Aufgaben sind
  ueberfaellig") und Zustaende ("Bei dir klingelt nichts"). Sie
  unterscheidet das jetzt und nennt beide Anzahlen -- faellt eine
  Sorte ganz weg, sieht man es. Das ist die GENAUERE Pruefung, nicht
  die schwaechere.

GEBAUT, GEMESSEN, WIEDER ENTFERNT: Auf dem Weg dahin hatte ich die
Kachelgruppen beim ersten Besuch einklappen lassen -- 25 Kacheln in
5 Gruppen sind fuer den ersten Tag eine Wand. Drei Messungen haben
es widerlegt:
  Die erste Gruppe ist nicht die wichtigste. Bei DogFather heisst
    sie "Rund um das Team" und hat GENAU EINE Kachel. Er haette eine
    Kachel gesehen und sieben zugeklappte Ueberschriften.
  Die Regel "nur wenn es nicht auf den Schirm passt" haette auch auf
    1280x900 gegriffen -- bei 30 Kacheln passt es nie.
  Es gibt keinen "ersten Besuch": Der Merker entsteht erst beim
    Klappen. Wer die Seite seit Wochen benutzt und nie geklappt hat,
    faende am Morgen seine Startseite umgebaut.
Die Begruendung steht jetzt im Code, damit es niemand ein zweites
Mal baut.

pruef-start-ansicht 151/0, pruef-nachfrage 33/0,
pruef-leerzustand 13/0, pruef-meldungen 8/0, pruef-css-klassen gruen.
2026-09-20 12:29:59 +02:00
DogFatherGit e5eed8506c Der gefaehrlichste Handgriff im Haus wird jetzt am Bildschirm geprueft
pruef-personen-loeschen gibt es seit Langem -- sie kennt aber nur die
Schnittstelle: kein Browser, kein Knopf, kein Dialog. Der Weg, den ein
Mensch geht, um eine Person zu loeschen, war nie geprueft. Und das ist
der eine Handgriff, den man nicht zuruecknehmen kann.

pruef-nachfrage hat jetzt einen Browserteil (33/0 statt 17/0):
  der Dialog geht auf und nennt den Namen im Titel
  er sagt, dass es endgueltig ist, was passiert und was bleibt
  ein FALSCH abgetippter Name schliesst ihn NICHT und sagt, warum
  der Abbruchknopf loescht nichts
  richtig abgetippt wird geloescht (Liste 2 -> 1)
  Abmelden fragt nach und nennt den Grund (Zugangscode)
  Esc bricht ab -- man bleibt angemeldet

BEIM BAUEN ZWEIMAL DANEBENGEGRIFFEN, beide Male gemessen statt
vermutet:
  Die Liste zeigte nur eine Person, obwohl vier in der Datenbank
    standen. Das sah nach einem Befund aus. Die Rollen-Abschnitte sind
    standardmaessig ZU -- nur der eigene ist offen, und das ist richtig
    so. Die Pruefung klappt ihn jetzt auf.
  Vorher wurde mit einer festen Wartezeit gearbeitet. Jetzt wird auf
    den Zustand gewartet, nicht auf die Uhr.

Neu: server/helfer-nachfrage.mjs (bestaetige/verwerfe/nachfrageText)
kennt beide Wege -- den <dialog> und den confirm()-Notnagel fuer
Safari vor 15.4. Ohne den zweiten liesse sich der Notnagel nie pruefen.
2026-09-19 20:24:28 +02:00
DogFatherGit 1207b79a33 Hochladen sieht man jetzt, Leerzustaende sagen was hingehoert
DREI BLOECKE AUS DEM PERFEKTIONSLAUF.

1. HOCHLADEN MIT FORTSCHRITT UND ABBRUCH
   Alle fuenf Wege (Dateien, Chat-Anhang, Wissen-PDF, Aufgaben-Anhang,
   Profilbild) benutzten `fetch`. Das kann beim SENDEN nicht sagen, wie
   weit es ist -- sichtbar war "wird hochgeladen …", von der ersten bis
   zur letzten Sekunde gleich. Bei 40 MB im Mobilfunknetz zwei Minuten.
   Wer das sieht, drueckt noch einmal und laedt dieselbe Datei doppelt.
   Neu: workspace/assets/js/hochladen.js (XMLHttpRequest, das Einzige,
   was `upload.onprogress` kann) samt gemeinsamer Anzeige.
   Drei Ausgaenge: fertig / abgebrochen / schiefgegangen -- und ein
   Abbruch ist KEIN Fehler und bekommt keine rote Meldung.

   DABEI AUFGEFALLEN: KEINE EINZIGE PRUEFUNG im Haus laedt eine Datei
   ueber die Oberflaeche hoch. Der ganze Umbau waere gruen gewesen,
   ohne dass ein Byte je den Weg der Nutzer gegangen waere.
   Neu: server/pruef-hochladen.mjs -- 18/0, mit echter Datei.
   Zwei Irrtuemer beim Bauen, beide gemessen statt vermutet:
     Ohne Drosselung gibt es auf localhost EINEN Fortschritt-Stand.
       Das sah nach Befund aus und war keiner. Jetzt 2 MBit/s ueber
       CDP -- derselbe Verlauf wie bei den Modis im Mobilfunk, 57
       gemessene Zwischenstaende.
     Gewartet wurde auf den Dateinamen "irgendwo im Dokument" -- der
       stand auch im Fortschrittsbalken. Die Bedingung war erfuellt,
       bevor etwas angekommen war.

2. LEERZUSTAENDE
   Elf von 18 Brettern fielen auf "Noch kein Eintrag in diesem
   Bereich" zurueck. Am ersten Tag ist ALLES leer -- wer da achtzehn
   Bretter oeffnet und achtzehnmal denselben Satz liest, lernt nichts
   ueber die Bretter, sondern dass das System kaputt ist. Jeder Satz
   sagt jetzt, was hier hingehoert UND was der naechste Schritt ist.
   Neu: server/pruef-leerzustand.mjs -- 13/0, leitet die Bretter aus
   BEREICHE ab; ein neunzehntes ohne Satz macht sie rot.

3. ABMELDEN UND KONTRASTMODUS
   Abmelden war am Handy ein 44-Pixel-Zeichen neben Glocke und Suche,
   sofort wirksam. Teurer als es aussieht: Zum Wiederanmelden braucht
   man den Zugangscode, und den gibt es EINMAL. Jetzt mit Rueckfrage,
   die genau das sagt -- und dazu, dass Zumachen reicht (12 Stunden).

   Kontrastmodus: 68 Regeln zeigen einen Zustand NUR ueber Farbe
   (35x aria-pressed, 33x data-an). Der Modus ersetzt alle Farben und
   entfernt box-shadow -- gedrueckt sah aus wie nicht gedrueckt.
   14 CSS-Dateien hatten gar keinen Block. Statt 14 Bloecke zu pflegen
   eine Regel in gate.css, die den ZUSTAND trifft statt die Datei.
   Gemessen mit forcedColors: active -- vorher ununterscheidbar,
   jetzt `solid 2px Highlight`.
   Was seinen Zustand als WORT traegt (.marke-status, .t-stufe,
   .spalte), braucht nichts -- nachgesehen, nicht vermutet.

PRUEFUNGEN, DIE AUF confirm() WARTETEN: Fuenf Dateien benutzten
`seite.once("dialog", d => d.accept())`. Playwright faengt confirm()
selbst ab, einen <dialog> nicht -- pruef-chat-anhaenge meldete acht
Fehler, keiner davon im Code. Neu: server/helfer-nachfrage.mjs, der
beide Wege kennt (auch den Notnagel fuer Safari vor 15.4).
pruef-chat-anhaenge, -ausbau, -optik und pruef-code wieder gruen.

hilfeAufraeumen bleibt ausgeschaltet -- das loescht echte Daten und
ist Filipes Entscheidung.
2026-09-19 20:16:23 +02:00
DogFatherGit c516aad4ed Nichts verschwindet mehr ohne eine Nachfrage, die sagt was passiert
Filipe: "Es darf vor allem keine Stellen geben, an denen ein Benutzer
etwas falsch machen kann, nur weil die Seite es nicht verstaendlich
genug erklaert."

Gemessen: 30 Stellen in 16 Dateien benutzten confirm() oder prompt().
Das Haus hatte die richtige Bauweise laengst -- einen <dialog>, in
aufgaben.html sogar ausfuehrlich begruendet -- aber sie stand IN EINER
SEITE. Wer anderswo etwas loeschen liess, hatte sie nicht.

confirm('Wirklich loeschen?') stellt die falsche Frage: Es fragt, ob
man sicher ist, und nennt nicht, WAS passiert, was BLEIBT und ob es
ZURUECK geht. Jetzt beantwortet jeder der 41 Dialoge alle drei.

Neu: workspace/assets/js/nachfrage.js -- window.frageNach() mit
Pflichtgrund, Zahlenfeld, einzeiliger Eingabe und Abtippsicherung.
Drei Ausgaenge: <dialog> / confirm()-Notnagel fuer Safari vor 15.4 /
Abbruch (Esc, Klick daneben, "Doch nicht" -- immer false).

DREIMAL DERSELBE FALLSTRICK, dreimal nachgemessen statt vermutet:
  .dialog stand in aufgaben.css und leistung.css -> auf dateien.html
    waere der Dialog ein weisser Systemkasten gewesen. 14 Regeln
    klammergenau nach module.css verschoben (Klammern gezaehlt, nicht
    per Muster geschnitten -- heute frueh hat ein nicht-gieriges
    Muster schon einmal CSS zerrissen).
  Das Formular trug .neu neu--blank -- und .neu gibt seine Abstaende
    nur in aufgaben.css. Gemessen: padding 0px, und die Felder
    verloren ihre height:44px. Jetzt steht alles unter
    .nachfrage__form in module.css; der Dialog borgt nichts mehr.
  Die erste Fassung der Pruefung zaehlte nachfrage.js SELBST als
    Nutzer -- damit war jede Seite trivialerweise "Nutzer" und die
    Pruefung gruen ohne Inhalt. Jetzt ausdruecklich ausgenommen.

ZWEI FUNDE NEBENBEI:
  hilfeAufraeumen() wird im Betrieb NIE aufgerufen. Der Kommentar
    behauptete "wird beim Start aufgerufen (siehe index.js)" -- das
    war nie wahr; einziger Aufrufer ist die eigene Pruefung. Folge:
    geschlossene vertrauliche Faelle bleiben unbegrenzt stehen. NICHT
    eingeschaltet (das loescht echte Daten und ist Filipes
    Entscheidung), sondern der Kommentar richtiggestellt.
  Einen Hilfe-Fall zu schliessen ist endgueltig -- es gibt keine
    Route, die ihn wieder oeffnet. Vorher stand darueber nur die
    Frage nach einem Schlusswort. Jetzt sagt der Dialog es.

pruef-struktur hat meine eigene Pruefung von heute Nachmittag
erwischt: Sie bildete ihr Datum aus UTC. Beim Beheben erst
heuteLokal(datum) genommen -- die Funktion nimmt gar kein Argument
und haette still "heute" statt "+3 Tage" geliefert. Jetzt tagLokal(3),
nachgerechnet: Abstand 3 Tage.

Am Bildschirm angesehen (Rechner 1280, Handy 390): passt rein, Esc
ergibt false, Fokus liegt auf dem harmlosen Knopf, Knoepfe 44px auf
Touch. Der Platzhalter im Abtippfeld zeigte den erwarteten Namen --
das sah aus wie ein schon ausgefuelltes Feld, entfernt.

Neu: server/pruef-nachfrage.mjs -- 17/0, mit sechs Gegenproben und
beiden Richtungen (wer fragt, laedt die Datei; wer nie fragt, laedt
sie nicht -- sonst truege die Anmeldewand 4,8 KB fuer nichts).

pruef-meldungen 8/0, pruef-css-klassen gruen, pruef-struktur gruen,
pruef-leistung gruen.
2026-09-19 19:57:43 +02:00
DogFatherGitandClaude Opus 5 26937dda16 Ein klingelndes Telefon haengt nicht mehr an einem einzigen Kanal
Filipe: "wenn vanvan rangeht und redet klingelt es immer noch bei mir
weiter, der anruf verbindet nicht richtig."

=== WAS DAS PROTOKOLL SAGT ===

    17:04:52  anruf_start  Person 1 (Filipe)
    17:05:25  anruf_ende   Person 4 (VanVan)  24 s
    17:05:31  anruf_ende   Person 1 (Filipe)  39 s

Sie WAR im Gespraech -- der Server hat sie 24 Sekunden als
Teilnehmerin gefuehrt. Das Ereignis "dabei" ist also verschickt
worden. Bei Filipe kam es nicht an: `tonAus()` ist das Erste im
`dabei`-Zweig, noch vor jeder Pruefung, und das Tuten lief weiter.

=== GEPRUEFT UND AUSGESCHLOSSEN ===

  Raumzugehoerigkeit   beide in Raum 1, bei keinem `raus_am` gesetzt
  Verkabelung          Server sendet mit `art: "anruf"`, chat.js reicht
                       an window.anrufEreignis weiter, anruf.js nimmt
                       entgegen -- alle drei Stellen stimmen
  Tonsteuerung         ein einziger Taktgeber, `tonAus` raeumt ihn;
                       kein zweiter Weg, der ihn neu startet
  Ereignisstrom        Keep-alive vorhanden, Kopfzeilen richtig
                       (no-transform, X-Accel-Buffering: no)
  Service Worker       hat gar keinen fetch-Handler, kann also kein
                       altes Skript ausliefern
  teilnehmerVon vs.
  teilnehmerFuerAnruf  reicht nur durch, dieselbe Abfrage

Es geht unterwegs verloren, auf einem Weg, der von hier aus nicht
messbar ist: Ereignisstrom ueber Cloudflare, ein schlafender Reiter,
ein Neustart im falschen Moment.

=== ALSO NICHT WEITERSUCHEN, SONDERN DIE ABHAENGIGKEIT BESEITIGEN ===

Ein klingelndes Telefon darf nicht an einem einzigen, zerbrechlichen
Kanal haengen. Solange es klingelt, fragt der Anrufer jetzt SELBST
nach: "ist schon jemand dran?" -- alle zwei Sekunden an
`/workspace/api/anruf/:raum`, das es laengst gibt.

Der Ereignisstrom bleibt der erste Weg, er ist schneller. Das hier ist
das Netz darunter. Kommt das Ereignis an, hat die Nachfrage nichts
mehr zu tun und haelt von selbst an (sie prueft `anruf.beginn` und die
bekannten Teilnehmer).

Sie hoert an JEDEM Ende auf: beim Auflegen, wenn die Verbindung steht,
wenn das Ereignis doch ankommt, wenn der Anruf vorbei ist. Eine
Schleife, die weiterlaeuft, fragt sonst auf jedem Geraet, das je
telefoniert hat, alle zwei Sekunden nach einem Anruf, den es nicht
mehr gibt.

Alle zwei Sekunden und nicht jede halbe: Es klingelt hoechstens zwei
Minuten, das sind sechzig Abrufe.

=== ZWEI DINGE, DIE DIESE SUCHE ERST SO MUEHSAM GEMACHT HABEN ===

DAS PROTOKOLL KANNTE ANFANG UND ENDE, ABER NICHT DEN MOMENT DAZWISCHEN.
Die wichtigste Frage -- "ist sie ueberhaupt rangegangen?" -- war nur
ueber einen Umweg zu beantworten (ein `anruf_ende` mit ihrer Nummer).
Das ist eine Schlussfolgerung, keine Auskunft. `anruf_dabei` steht
jetzt drin, mit der Zahl der Beteiligten.

UND EINE PRUEFUNG WAR GRUEN, OHNE ETWAS ZU PRUEFEN. In chatEreignis
stand `(zuschauer.get(personId) || []).length` -- `zuschauer` haelt
aber Mengen, und eine Menge hat kein `length`. Der Ausdruck war IMMER
undefined, also immer falsch, also wurde nie uebersprungen: Wer die
Seite offen hatte, bekam zusaetzlich zur Nachricht auf dem Bildschirm
noch eine Meldung aufs Handy.

Der Kommentar drei Zeilen darueber warnt woertlich davor ("der
schnellste Weg, dass er Benachrichtigungen abschaltet"), und
`siehtZu()` weiter unten macht es mit `.size` richtig. Die Absicht
stand da, die Zeile tat das Gegenteil.

Meine eigene Pruefung hat das mitgetragen: Sie bestaetigte den alten
WORTLAUT statt sein VERHALTEN und war deshalb gruen. Genau die
Hausregel vom 01.09. -- ein gruener Haken sagt nur, dass die Bedingung
erfuellt war, nicht dass sie das Richtige geprueft hat. Jetzt prueft
sie auf `.size`.

GEMESSEN: pruef-anruf-klingelt 24/0 (vorher 17), pruef-anruf 114/0,
pruef-turn-wege 15/0, pruef-meldungen 8/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 19:15:51 +02:00
DogFatherGitandClaude Opus 5 9a1287aa0e Es hat nie geklingelt -- und die Vermittlung war nie das Problem
Filipe: "irgendwas klappt mit dem telefonieren nicht."

=== WIE DER FEHLER GEFUNDEN WURDE ===

Ich habe zuerst wieder die Vermittlung verdaechtigt. Stattdessen das
Protokoll des Servers gelesen -- und dort stand es die ganze Zeit:

    24x anruf_start, jeder nach 7 bis 39 Sekunden beendet
    im Chat danach jedes Mal: "Verpasster Anruf"
    die Gegenseite schrieb: "Hab keinen Anrufeingang gehabt und
    keine Benachrichtigung"

Es ging nie um Ton oder Verbindung. Es hat bei der anderen Person
schlicht nicht geklingelt.

Dieselbe Lehre wie am 06.09. ("kommt keine Mail an" -- erst fragen, OB
gesendet wurde) und am 14.09. (zwei Tage Audiowege verfolgt, waehrend
die CPU bei 98 % stand). Eine halbe Minute in der richtigen Tabelle
haette Stunden gespart.

Nebenbefund zur Messbarkeit: Das coturn-Protokoll kann die Frage gar
nicht beantworten -- es schreibt Zuteilungen bei dieser Stufe nicht
mit. Meine eigene Zuteilung von 16:35 taucht dort ebenfalls nicht auf.
Wer daraus "null Zuteilungen, also kaputt" liest, sucht am falschen
Ende. Das ist der dritte Ausgang: nicht "in Ordnung" und nicht
"kaputt", sondern "kann ich hier nicht sehen".

=== WAS WIRKLICH DEFEKT WAR ===

Die Benachrichtigung WURDE zugestellt -- `zuletzt_ok` am Geraet stand
auf genau die Anrufminute. Sie hat nur nicht geklingelt:

1. `Urgency: "normal"` STAND FEST IM TRANSPORT, fuer jede Meldung.
   Auf Android entscheidet dieser Kopf, ob sofort zugestellt wird oder
   bis zum naechsten Aufwachen gewartet. Im Stromsparmodus werden
   daraus Minuten -- bei einem Anruf, der 120 Sekunden klingelt, ist
   das ein verpasster Anruf mit Zeitstempel.

2. `renotify: false` UND `tag: d.art`. Eine zweite Meldung mit
   derselben Kennung ersetzt die erste LAUTLOS. Wer ein zweites Mal
   anruft, WEIL nicht abgehoben wurde, loest damit gar keinen Ton mehr
   aus -- genau im wichtigsten Moment.

3. KEIN vibrate, KEIN requireInteraction. Ein stiller Kasten, der von
   selbst verschwindet. In einer Hosentasche unsichtbar.

Fuer "Aufgabe ueberfaellig" ist all das genau richtig, und der
Kommentar daneben stimmte auch ("eine Meldung, die stehen bleibt, ist
eine Zumutung"). Fuer ein klingelndes Telefon ist es das Gegenteil.

Jetzt unterscheidet das Haus beides:
  - eigene Kennung je Anruf, damit der zweite den ersten nicht
    stillschweigend ersetzt
  - renotify, vibrate (zweimal lang, wie ein Telefon),
    requireInteraction
  - Urgency: high und eine TTL von 150 Sekunden -- ist der Anruf
    vorbei, verfaellt auch die Meldung, statt eine Stunde spaeter
    nachtraeglich aufzuploppen
  - alle ANDEREN Meldungen bleiben unveraendert ruhig. Das ist kein
    Nebensatz: Wuerde alles vibrieren und stehenbleiben, schaltet es
    nach drei Tagen jemand ab -- und dann klingelt auch der Anruf nie
    wieder.

Die Dringlichkeit haengt an derselben Bedingung wie die Nachtruhe
(`art === "test" || art === "anruf"`). "Darf das nachts stoeren?" und
"darf das warten?" haben dieselbe Antwort; zwei Bedingungen waeren die,
die beim naechsten Nachschaerfen auseinanderlaufen.

=== ERREICHT ES AUCH JEMANDEN? ===

Der Service Worker ruft skipWaiting() und clients.claim() -- die neue
Fassung greift beim naechsten Oeffnen der App, ohne dass jemand etwas
tun muss.

ABER: Nachgemessen haben NEUN von fuenfzehn aktiven Zugaengen KEIN
Geraet angemeldet -- darunter eine rechte Hand und zwei Modis. Bei
ihnen kann keine Benachrichtigung ankommen, so laut sie auch waere.
Das ist kein Codefehler; das muessen die Leute einmal selbst tun.

=== GEMESSEN ===

pruef-anruf-klingelt 17/0 (neu, mit drei Gegenproben), pruef-anruf
114/0, pruef-turn-wege 15/0, pruef-meldungen 8/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 18:51:43 +02:00
DogFatherGitandClaude Opus 5 5c3bfcb47d Der Handy-Rundgang, den es fuer die Modis nie gab
Filipe: "mach einen kompletten check dass die app auf dem handy perfekt
funktioniert ... weil die modis haben schon probleme." Auf die
Rueckfrage: "einfach ALLES ABCHECKEN ALLES MOEGLICHE."

=== DER BEFUND, DER ALLES ERKLAERT ===

Es gibt seit dem 02.09. einen grossen Rundgang (pruef-grosscheck). Er
geht ueber jede Seite, zwei Bildschirmgroessen und VIER Rollen:

    admin . manager . scout . creator

Vier von acht. Es fehlen modi, hand und gast -- also genau die drei
Rollen, die auf crew.dogfather-universe.com leben, und genau die, von
denen die Beschwerden kommen. Ihre Seiten waren nie im Ganzen auf einem
Handy durchgemessen worden.

Kein Vorwurf an den Rundgang: Er wurde fuers Agenturhaus gebaut, und
Team Dogi kam spaeter dazu. Aber es erklaert, warum Fehler dort
ueberleben konnten.

pruef-handy-teamdogi.mjs schliesst die Luecke: 4 Rollen x 2 Breiten x
bis zu 32 Seiten = 206 Seitenaufrufe, 91 052 Elemente, 3 880
Bedienelemente. Gemessen wird: kommt die Seite an, stuerzt etwas ab,
laeuft etwas ueber den Rand, ist Text abgeschnitten, kann man es
treffen, liegt etwas uebereinander, weiss man was es tut.

=== WAS ES GEFUNDEN HAT ===

DIE KOPFLEISTE WAR AUF JEDER SEITE ZU KLEIN. Bei Breiten bis 400 px
schrumpften alle Knoepfe auf 34x34, bis 560 px auf 36x36. Das sind zehn
Pixel unter dem, was ein Daumen sicher trifft -- und es betraf jede
Seite, jede Rolle, jeden Aufruf. Genau das erlebt man als "der Knopf
geht nicht".

Die Verkleinerung war nie noetig. Am echten Aufbau nachgemessen:

    Breite   belegt   bei 44px noetig   verfuegbar
    360 px    237          284             328
    390 px    237          284             358
    412 px    245          284             380

Es passt ueberall, mit Luft. Jetzt 44x44 -- und dazu `flex-wrap: wrap`
als Regel statt einer dritten festen Zahl: Die Reihe bricht genau dann
um, wenn der Platz wirklich nicht reicht.

DER ZURUECK-KNOPF war 38x44 -- die Hoehe stimmte, die Breite nicht. Der
Rundgang hat ihn 192-mal gemeldet. Er ist der Knopf, den man auf jeder
Unterseite am haeufigsten trifft.

DIE KLEINEN UMSCHALTER (38 px) waren eine begruendete Ausnahme --
begruendet fuer die Maus. Auf Geraeten, die mit dem Finger bedient
werden, gilt jetzt 44. Gefragt wird `pointer: coarse` und nicht die
Breite: Ein schmales Browserfenster am Rechner braucht keine 44 px, ein
1200 px breites Tablet sehr wohl.

DIE KALENDERPILLEN waren 26 px hoch, das Rechtefeld 34 px breit, die
Kalenderpfeile 38 px. Alle auf 44.

EINE BESCHRIFTUNG HING NICHT AM FELD. In checkliste.js stand ein
<label> ohne `for` neben einem <select> ohne `id`. Optisch richtig --
fuer ein Vorleseprogramm ein namenloses Feld. Und weil wahl.js das
Systemmenue durch einen eigenen Knopf ersetzt und dessen Namen AUS DEM
LABEL holt, blieb auch der Knopf namenlos.

=== DREI FEHLER IN MEINER EIGENEN PRUEFUNG ===

Und sie sind der lehrreichere Teil.

(1) DER ERSTE LAUF MELDETE EIN 1647 px BREITES BILD auf einem 390 px
    breiten Schirm. Das sah nach dem Fund des Tages aus. Es war einer
    in MEINER Pruefung: `dogfather-universe.com` steht in der fest
    eingebauten HSTS-Liste von Chromium, der Browser schaltet
    unabaenderlich auf https um, und mein Testserver sprach http.
    Ergebnis: JEDE Stilvorlage schlug fehl. Gemessen wurde eine Seite
    ganz ohne CSS.

    Haette ich den Befund gemeldet statt nachzusehen, waere ein halber
    Tag in eine Reparatur geflossen, die nichts repariert. Die Pruefung
    spricht jetzt selbst https, mit eigenem Zertifikat und einem
    winzigen Vorbau.

(2) 350 FEHLALARME. `span.zurueck-knopf__text` wurde 192-mal als
    abgeschnitten gemeldet, `span.teilen__text` 154-mal -- beide sind
    ABSICHTLICH 1 px gross und weggeschnitten, damit ein
    Vorleseprogramm sie liest und das Auge nicht. Dazu 24-mal
    `-webkit-line-clamp` (gewolltes Kuerzen auf zwei Zeilen), 14-mal
    Textfelder MIT Beschriftung (ich fragte `labels` nur bei input und
    select, nicht bei textarea) und 26-mal Zierrat mit
    `aria-hidden="true"`.

    Eine Warnung, die immer kommt, ist keine Warnung mehr -- und diese
    haetten jeden echten Fund zugedeckt.

(3) DIE UEBERLAUF-MESSUNG WAR BLIND. Sie rechnete
    `scrollWidth - clientWidth`; `body { overflow-x: hidden }` macht
    beide Werte immer gleich. Die Pruefung fand nichts und meldete
    trotzdem gruen. Gefunden hat das die GEGENPROBE -- sie ist genau
    dafuer da. Jetzt zaehlt, ob ein sichtbares Element ueber den
    rechten Rand ragt.

=== UND EIN FEHLER BEIM AUFRAEUMEN ===

Beim Verschieben der Touch-Regeln von start.css nach module.css hat ein
NICHT-GIERIGES Suchmuster am ersten `}` am Zeilenanfang aufgehoert und
dabei mehr mitgenommen als gemeint: die Schriftgroessen-Regeln fuer
schmale Fenster. Die haetten danach nur noch auf Geraeten mit Finger
gegolten.

Gefunden hat es wieder der Rundgang, nicht das Lesen: `.k-pille` blieb
26 px hoch, obwohl die neue Regel 44 sagte -- die alte stand weiter
unten und gewann. Zurueckgeholt aus HEAD, an ihren Platz gesetzt.

Nebenbei kam dabei heraus, WARUM eine Regel nicht ankam: Jede Seite
laedt gate -> start -> seite -> module -> haus. `aufgaben.css` setzt
`.schnitt { min-height: 38px }` mit derselben Staerke, kommt aber
spaeter. Eine Regel, die man geschrieben hat und die nicht wirkt, sieht
im Editor genauso aus wie eine, die wirkt.

=== STAND ===

Befunde: 120 -> 64.

Weg sind: alle abgeschnittenen Texte (0), alle namenlosen
Bedienelemente (0), alle zu kleinen Knoepfe in Kopfleiste, Zurueck-Weg,
Filterreihen, Kalender.

Es bleiben 64, und sie sind alle von derselben Sorte: 48-mal der
Ersatzknopf eines Auswahlfeldes (34-42 px breit, aber 44 hoch), 8-mal
Kalenderpillen (36-39 breit, 44 hoch), 8 Ueberstaende. Alle sind in der
HOEHE gross genug und nur in der Breite knapp -- die komfortable
Empfehlung, nicht die Mindestanforderung. Sie stehen namentlich im
Prueflauf und sind der naechste Schritt.

GEMESSEN: pruef-css-klassen ALLES IN ORDNUNG, pruef-meldungen 8/0,
pruef-rechtetafel 19/0, pruef-turn-wege 15/0, und beide Gegenproben des
neuen Rundgangs schlagen an.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 17:16:49 +02:00
DogFatherGitandClaude Opus 5 d6df590224 Telefonieren ging nur ueber UDP -- und die Seite sprang immer hoch
=== 1. WARUM TELEFONIEREN NICHT GING ===

Filipe: "es klingelt erscheint auch alles bei jedem aber telefonieren
klappt immer noch nicht."

GEMESSEN, BEVOR ETWAS GEAENDERT WURDE -- und alles war gruen:

  coturn laeuft                 aktiv
  STUN von aussen               antwortet, nennt meine oeffentliche Adresse
  echte Zuteilung von aussen    7/7, Testpaket kam an (Port 49183)
  Dreier-Anruf im Prueflauf     verbindet, alle hoeren alle

Vier Messungen, vier Mal in Ordnung -- und das Telefon ging trotzdem
nicht. Der Grund: Der Prueflauf faehrt BEIDE Seiten auf demselben
Rechner. Dort finden sie sich ueber die direkte Adresse, und die
Vermittlung wird nie gebraucht. Draussen sitzen sie in verschiedenen
Netzen.

DER FUND: Eingetragen war eine einzige Adresse --

    turn:159.195.212.167:3478

Ein `turn:` OHNE `?transport=` heisst UDP, und nur UDP. Nachgemessen
hoert coturn aber auf beidem: 3478/UDP offen, 3478/TCP offen (5349/TLS
ist zu). Angeboten wurde nur der halbe Server.

Wer in einem Netz sitzt, das UDP nach draussen sperrt -- Mobilfunk mit
strengem Profil, Gast-WLAN, Firmennetz --, bekam damit KEINEN
Vermittlungsweg. Es klingelt (das laeuft ueber die Website, also ueber
443), und danach passiert nichts. Genau das gemeldete Bild.

Aus einem Eintrag werden jetzt drei Wege:
  stun:host:port                die eigene Adresse finden, ohne Vermittlung
  turn:host:port?transport=udp  der schnelle Weg
  turn:host:port?transport=tcp  der Weg durch fast jede Sperre

ABGELEITET, NICHT EINGETRAGEN: Drei Zeilen von Hand waeren drei
Stellen, an die beim naechsten Serverumzug jemand denken muesste --
die abgeschriebene Liste, die hier schon zweimal teuer war. Ein
Eintrag MIT `?transport=` bleibt unangetastet, ein fremder Dienst mit
eigenem Passwort sowieso.

pruef-turn-wege (neu, 15/0) sichert beides: dass jeder Weg herauskommt
UND dass jeder turn:-Weg Zugangsdaten traegt. Das Zweite ist das
wichtigere -- auffaechern ohne anmelden haette den Fehler nur
verschoben.

=== 2. DIE SEITE SPRANG BEIM ZURUECKGEHEN IMMER HOCH ===

Filipe: "das nervt man muss dan immer wieder runter scrollen bis man
da ist wo man vorher war."

Der Browser versucht es sogar -- scrollRestoration steht ab Werk auf
"auto". Nur: Jede Seite hier kommt fast leer an und holt ihren Inhalt
danach per Abruf. In dem Moment, in dem der Browser die alte Position
wiederherstellen will, ist das Dokument ein paar hundert Pixel hoch.
Er kann nicht auf Zeile 900 springen, die es noch nicht gibt -- und er
versucht es kein zweites Mal.

Jetzt macht es kopf.js selbst (gilt damit auf allen 21 Seiten): Stelle
merken beim Verlassen, beim Oeffnen zurueckholen und jeden Bildaufbau
lang versuchen, bis das Dokument hoch genug ist. Nach drei Sekunden
wird aufgegeben.

Drei Dinge sind Absicht:
  - NUR beim Zurueckgehen, nicht bei jedem Oeffnen. Wer eine Kachel
    anklickt, will oben anfangen.
  - WER SELBST SCROLLT, GEWINNT. Rad, Wisch oder Taste beenden das
    Nachspringen sofort.
  - Nach einer Stunde vergessen -- auf Zeile 900 zu landen, weil man
    gestern dort war, ist keine Hilfe.

=== 3. DIE LISTE IST NACH ROLLE GETRENNT ===

Filipe: "die rechte hand rolle immer zuerst und dan die modis. die
sollen auch schoen getrennt sein und verschieden aussehen also die
rechte hand viel spezieller."

Die Reihenfolge macht der Server ueber ROLLEN_SORTIERUNG -- dieselbe
Konstante wie ueberall sonst im Haus, nicht eine zweite. Eine
Sortierung nach ROLLE ist ausdruecklich keine Rangliste: Sie sagt
nichts darueber, wie gut jemand ist, nur welche Aufgabe er hat.
Deshalb steht ueber jeder Gruppe ein Satz und keine Zahl.

"Spezieller" heisst hier Material, nicht Groesse: eigener Farbton als
Kante und Schimmer, hellere Flaeche, kraeftigerer Name. Beide Karten
sind GLEICH GROSS und tragen dieselben Zeilen -- zwei Sorten Aufgabe,
keine Rangfolge. Im Kontrastmodus traegt eine doppelte Kante die
Unterscheidung, weil dort keine Farbe mehr wirkt.

=== 4. DER ANRUFKASTEN ===

Vorher: vier gleich aussehende Pillen nebeneinander, darunter eine
Geraeteauswahl, die das breiteste Element war. Kein Name, keine
Ordnung, und der einzige Knopf mit Folgen sah aus wie die anderen.

  - MAN SAH NICHT, MIT WEM. Der wichtigste Satz eines Telefonats fehlte.
    Der Chat kennt den Namen und gibt ihn jetzt mit; wer rangeht, sieht
    den Anrufer.
  - "MIKRO AN" WAR ZWEIDEUTIG -- "ist an" oder "schalt an"? Wer falsch
    raet, sitzt stumm da. Jetzt traegt ein durchgestrichenes Zeichen
    den Zustand, das Wort nur die Sache. aria-pressed bleibt die
    Wahrheit, auch fuer Vorleseprogramme.
  - DIE GERAETEAUSWAHL liegt hinter einem kleinen Knopf, der nur
    erscheint, wenn es ueberhaupt etwas zu waehlen gibt.
  - AUFLEGEN ist als einziger Knopf farbig und steht immer rechts.
  - Ein ruhiger Puls atmet, solange die Verbindung aufbaut, und haelt
    an, sobald sie steht. Bei prefers-reduced-motion steht er still.

=== NEBENBEFUND, DEN DIE PRUEFUNG GEFUNDEN HAT ===

pruef-anruf wurde durch die Auffaecherung an vier Stellen rot: Sie
griff `adressen[0]` und erwartete dort Zugangsdaten. Das ist jetzt der
STUN-Weg, und der hat richtigerweise keine. Gesucht wird nicht mehr
nach PLATZ, sondern nach ART -- ein Index ist eine Annahme darueber,
wie die Liste aussieht, und die hat sich gerade geaendert.

Dazu angepasst: Die Pruefung "die Uhr laeuft" verlangte, dass die Uhr
schon beim Klingeln zaehlt. Seit heute frueh beginnt sie beim
Rangehen (sonst standen im Kasten und im Chat zwei verschiedene
Zahlen). Sie prueft jetzt das Gegenteil -- statt sie zu streichen,
denn eine Zeile weniger haette den Fehler beim naechsten Umbau wieder
durchgelassen.

GEMESSEN: pruef-anruf 114/0 (vorher 111 -- drei MEHR, weil die
Auffaecherung mitgeprueft wird), pruef-turn-wege 15/0,
pruef-meldungen 8/0, pruef-css-klassen ALLES IN ORDNUNG,
pruef-rechtetafel 19/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 15:23:15 +02:00
DogFatherGitandClaude Opus 5 18a5231b70 Die Tuer ohne Klingel, der Anruf ohne Ende, die Glocke ohne Liste
Siebter Durchgang durch die Team-Dogi-Seiten aus Benutzersicht. Alles am
Code belegt, die Groessenangaben nachgerechnet.

=== DIE ANMELDUNG ===

WOHER BEKOMMT MAN EINEN CODE? Stand nirgends. Vier Kacheln, ein Feld,
ein Knopf -- wer keinen Code hatte, fand keinen einzigen Satz dazu. Fuer
die Community besonders teuer: Sie ist die einzige Rolle, die von
aussen kommt und niemanden im Haus kennt.

"BITTE KURZ WARTEN" SIND BIS ZU ZEHN MINUTEN (VERSUCHE_FENSTER_MIN).
Wer nach zwanzig Sekunden nachsieht und dieselbe Meldung liest, haelt
die Seite fuer kaputt. Jetzt steht die Zahl da.

EIN RICHTIGER CODE AN DER FALSCHEN KACHEL fiel in dieselbe Absage wie
ein erfundener -- der Server sucht nur unter der gewaehlten Rolle. Wer
aus der Community kommt und auf "Modi" tippt (das klingt ja danach),
tippt seinen richtigen Code dreimal Buchstabe fuer Buchstabe. Ab dem
zweiten Fehlversuch kommt jetzt ein Hinweis auf die Auswahl -- ohne zu
sagen, welche die richtige waere.

=== DER ANRUF: VIER FEHLER, EINE ERFAHRUNG ===

DAS FREIZEICHEN LIEF UNENDLICH. Es gab keinen Zeitgeber, der aufhoert.
Wer niemanden erreichte, sass vor einem piependen Kasten mit "02:47"
darauf, als telefoniere er laengst. Der Server schickt den Verfallszeit-
punkt sogar mit (`laeuft_bis`) -- benutzt hat ihn nie jemand.

DER KLINGELKASTEN VERSCHWAND NACH 46 SEKUNDEN, waehrend der Server 120
gibt. Wer beim Klingeln das Handy aus der Tasche holt und in Sekunde 50
hinsieht, fand nichts mehr -- kein Kasten, keine Knoepfe -- waehrend der
Anrufer noch siebzig Sekunden Freizeichen hoerte. Die 120 Sekunden sind
im Server ausdruecklich damit begruendet, dass man Zeit zum Entsperren
braucht; eine Zeile im Browser hat diese Entscheidung aufgehoben.

DAS FREIZEICHEN PIEPTE WEITER, waehrend daneben "Keine Verbindung."
stand. Ton sagte "es klingelt noch", Text sagte "vorbei".

DIE UHR ZAEHLTE AB DEM WAEHLEN. Wer 30 Sekunden klingeln liess und 12
Sekunden sprach, las im Kasten "00:42" und danach im Chat "Anruf . 12
Sekunden". Der Server rechnet es richtig; der Kasten hat es wieder
kaputtgemacht.

Dazu: Die Mikrofon-Absage verwies auf "das Schloss-Symbol neben der
Adresse" -- in der installierten App gibt es weder Adresszeile noch
Schloss. Das Haus kennt diesen Fehler und hat ihn beim Weg zur
Anruf-Probe schon behoben; hier stand er noch.

Und die Anruf-Probe: Ihr einziger Punkt ohne Handlungsanweisung war
"Antwort 503." -- auf einer Seite, die ausdruecklich fuer jemanden
gebaut ist, der nicht technisch ist. Ihr Rueckweg fuehrte ausserdem
immer in den Chat, auch wenn man von der Startseite kam.

=== DER TREFF ===

EIN EINZEILER MACHTE SECHS ERKLAERTEXTE UNSICHTBAR. bewerben.js las
`g.unter`, der Server schickt `g.text` -- also immer undefined. Damit
fehlten ALLE SECHS Gruppeneinleitungen des Fragebogens ("Kein Test mit
richtigen Antworten"), und die CSS-Regel dafuer lief ins Leere. Uebrig
blieben sechs nackte Ueberschriften ueber fuenfzehn Fragen.

DIE EINZIGE "SO LAEUFT DAS HIER"-SEITE WAR FAST UNERREICHBAR. Die
Kachel "Regeln & Hilfe" zeigte auf ein Brett, das am ersten Tag leer
ist. Die Regeln, die es wirklich gibt (Begruessung, fuenf Regeln, drei
Stufen, Mindestalter), stehen auf treff-regeln.html -- erreichbar ueber
genau einen kleinen Textlink auf einer Brettseite. Die Kachel zeigt
jetzt dorthin.

FIEL /api/treff/lage AUS, versprach die Seite einem Zuschauer
Schreibrechte, die der Server ablehnt: Die Pruefung fiel bei `lage ===
null` auf `true` durch -- von "darf auf keinem Brett" auf "darf
ueberall". Formular auf, getippt, 403.

Dazu: hilfe.js hatte eine eigene kleine Fehlertabelle fuer zwei
Kennungen und endete sonst bei "Ging nicht." -- ausgerechnet die Seite,
auf der jemand mit einem Problem sitzt, hatte die inhaltsleerste Absage
im Haus. Und der gesperrte "Neue Meldung"-Knopf erklaerte sich nur im
Maus-Tooltip; die Community kommt von TikTok, also vom Handy.

=== DIE STARTSEITE ===

DIE COMMUNITY BEKAM EIN WORT. Unter dem Titel steht bei jeder Rolle ein
Satz -- beim Community-Mitglied stand "Community". Woertlich derselbe
Mangel, den der Kommentar bei MODI_ROLLENTEXT beschreibt und fuer den
Modi behebt.

DER RING MELDETE 100 %, bevor man irgendetwas getan hat. Am ersten Tag,
ohne eine einzige Aufgabe, stand das groesste Element der Seite auf
"100 % -- HEUTE NICHTS OFFEN". Gelesen wird zuerst die Zahl, und 100 %
heisst fuer jeden "fertig", nicht "leer".

UND BEI EINER STOERUNG BLIEB "wird geladen" FUER IMMER STEHEN -- der
fruehe `return` liess den Platzhalter unberuehrt.

=== DIE ZUGANGSVERWALTUNG ===

Der Code-Kasten sagte "jetzt weitergeben" und gab die Haelfte nicht
mit, die man weitergeben muss: WO sich die Person anmeldet. DogFather
ruft den Code durchs Zimmer, der andere fragt "und wo?". Die Adresse
kommt jetzt vom Server (anmeldeAdresseFuer, abgeleitet aus derselben
Weiche), dazu ein Knopf "Code und Adresse kopieren".

Er verschwieg ausserdem den Rettungsweg: "danach nicht mehr abrufbar"
stimmt fuer DIESEN Code -- man kann jederzeit einen neuen vergeben. Wer
das nicht weiss, glaubt, er habe einen Menschen angelegt, der nie
hereinkommt. Und das Fenster liess sich wortlos schliessen, waehrend
der Code offen stand.

=== OPTIK: NACHGERECHNET, NICHT VERMUTET ===

DIE GLOCKE STAND NICHT IN DER LISTE. Sie ist ein echtes <button> und
wurde von der 44-px-Regel erfasst, waehrend ihre vier Nachbarn durch
einen staerkeren Selektor auf 36 px gehen. Zwischen 401 und 560 px --
also bei 412 px (haeufigste Android-Breite) und 430 px (iPhone Pro Max)
-- stand eine 44 px hohe runde Pille zwischen fuenf 36-px-Quadraten.
Der 400er-Block listet sie korrekt; genau dieses Band fiel durch beide
Rechnungen. Dasselbe Muster wie am 06.09.

DIE 9,6-px-REPARATUR IM KALENDER WAR SEIT WOCHEN WIRKUNGSLOS.
kalender.css wird NACH start.css geladen, beide Selektoren sind gleich
stark -- also gewann `.6rem` auf jeder Breite unter 760 px. Genau der
Wert, den start.css als behobenen Fehler protokolliert.

Und die Hebung selbst unterschritt ihre eigene Grenze: Die Regel, die
zu kleine Schrift hochziehen soll, zog `.k-pille` auf 11,2 px -- 0,3 px
unter die 11,5, die 33 Zeilen darueber aufgestellt werden.

Weitere nachgerechnete Groessen: Spaltenkopf und KW-Spalte im Kalender
(10,56 px), Kalenderwoche am Balken (9,92 px), Wecker-Knopf (30 px --
der kleinste im Haus, 14 unter der Vorgabe), Chat-Zurueck auf dem
Tablet (34x34, 40 % weniger Flaeche als noetig, und der einzige Weg
zurueck in die Liste), Emoji-Knoepfe (34 px bei 2 px Abstand -- wer
danebentippt, verschickt ein anderes Zeichen, und das ist sofort
abgeschickt).

IM WINDOWS-KONTRASTMODUS HATTE DIE STARTSEITE KEINE UEBERSCHRIFT.
`.ztitel` und der Team-Dogi-Schriftzug sind mit `background-clip: text`
gesetzt; faellt der Verlauf weg, bleibt durchsichtiger Text. Beide
haben jetzt den Rueckfall, den gate.css schon lange hat.

UND MEIN EIGENES STREIFENRASTER rechnete die Spaltenzahl aus der Breite
statt aus den Daten (`auto-fit`): Bei 390 px passten sechs, alles
darueber fiel in eine zweite, unbeschriftete Zeile. Das `overflow-x`
daneben konnte nie greifen -- ein auto-fit-Raster wird nie breiter als
sein Kasten. Der Kommentar beschrieb ein Verhalten, das es nicht gab.

GEMESSEN: pruef-meldungen 8/0, pruef-css-klassen ALLES IN ORDNUNG,
pruef-rechtetafel 19/0, alle Module laden, keine doppelten
Kachelnamen/-ziele/-farben in allen vier Rollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 15:07:31 +02:00
DogFatherGitandClaude Opus 5 273318dd9c Vier Sackgassen, zwei Kacheln namens "Chat" -- und eine Seite ohne Kopf
Durchgang durch die Team-Dogi-Seiten aus der Sicht von jemandem, der
sie zum ersten Mal sieht. Alles hier ist am Code belegt und nachgemessen.

1. "KLINGELT NICHTS?" WARF ALLE DREI TEAM-ROLLEN AUF DIE STARTSEITE.

anruf-probe.html erklaert, WARUM das Telefon stumm bleibt. Sie steht in
der Rechtetafel offen, und aus dem Chat zeigen zwei Knoepfe darauf. Nur
hatte sie nie eine Kachel -- absichtlich, sie ist kein Bereich. Seit die
Adressregel vom 15.09. eine Kachel VERLANGT, landete jeder Klick wortlos
auf start.html.

Das ist die schlimmste Sorte Sackgasse: Man ruft sie auf, WEIL schon
etwas nicht geht, und sie wirft einen hinaus.

Mit derselben Zeile geheilt: Die Hinweisleiste wirft jeden Hinweis weg,
dessen Ziel es auf dieser Adresse nicht gibt -- "Bei dir klingelt nichts"
wurde auf crew deshalb NIE angezeigt. Ausgerechnet der Hinweis, der acht
von elf Leuten betrifft.

2. UND DIESE SEITE HATTE GAR KEINE GESTALTETE KOPFLEISTE.

.kopfleiste, __zurueck, __mitte, __titel stehen in KEINER Stilvorlage --
sie leben in start.css, die diese Seite absichtlich nicht laedt. Die
Leiste war nackter Text. Auf einer Seite, die man im Stoerfall aufruft,
sieht unfertig aus wie kaputt. Jetzt im <style>-Block der Seite, aus
demselben Grund wie ihr uebriges CSS.

3. EIN MODI KAM NICHT AN SEINE EIGENE AUSWERTUNG.

entwicklung.html und werdegang.html haben BEIDE eine ausgearbeitete
Eigensicht, und die Rechtetafel laesst ihn hinein. In seiner Kachelliste
stand keine von beiden -- der Weg existierte fuer ihn nicht. Die ganze
Eigensicht war toter Code, ausgerechnet fuer den, fuer den sie ist.
Mein eigener Fehler vom Vortag.

Zwei eigene Kacheln in "Fuer dich", aus den Leitungskacheln abgeleitet.
Sie loesen zugleich eine Namenskollision: Bis heute setzten BEIDE Seiten
fuer ihn die Ueberschrift "Deine Entwicklung".

4. DER KALENDER-LINK WAR FUER DIE COMMUNITY EINE SACKGASSE.

Auf jeder Brettkarte mit Termin stand "Im Kalender am 24.09." als Link.
kalender.html steht auf ALLE -- und ALLE ist ausdruecklich ohne "gast".
Jetzt fragt der SERVER die beiden Schranken (kalender_offen) und die
Karte zeigt den Termin als Text statt als Link. Die Auskunft bleibt, nur
der Weg ins Leere faellt weg. Die Regel im Browser nachzubauen waere die
vierte Stelle fuer dieselbe Frage gewesen.

5. EIN MODI KAM AN DIE TALENTE-NOTIZEN, DIE IHM VERWEHRT SIND.

BRETTER_UEBER_SEITEN war eine feste Liste ("wer die Seite darf, muss
auch dorthin kommen") und fragte nie, WER fragt. Ueber
bereich.html?b=talente kam er an Notizen zu Zuschauern, obwohl
talente.html fuer ihn gesperrt ist -- Begruendung dort: "Hier stehen
Namen von Menschen, die nichts davon wissen."

Aus der Liste wurde eine Zuordnung Brett -> Seite, gefragt wird
darfSeite(). Nachgemessen: modi/talente 404, modi/entwicklung darf,
hand+admin unveraendert.

Dazu stand in workspace-bereiche.js ein Kommentar, der das GEGENTEIL des
Codes behauptete ("entwicklung, talente bleiben 404"). Ein falscher
Kommentar an einer Rechtestelle ist schlimmer als keiner.

6. ZWEI KACHELN "CHAT", BEIDE AUF DIESELBE SEITE.

Seit dem Treff-Chat von gestern sahen Modi und rechte Hand zweimal
"Chat" mit demselben Ziel. Jetzt "Treff-Chat" mit ?raum=treff, das den
Raum direkt oeffnet -- gesucht an denselben zwei Merkmalen, an denen ihn
der Rest der Datei erkennt.

7. VERTRAUEN: "WIE GEHT'S DIR?" VERSPRACH MEHR, ALS ES HALTEN KANN.

Dort stand: "Niemand aus dem Team sieht deine Antworten -- auch
DogFather nicht." Punkt. Fast wahr und deshalb gefaehrlich: Aus
denselben Antworten entsteht eine namenlose Ampel fuer die Leitung.

Der ehrliche Satz war laengst geschrieben und wurde vom Server sogar
mitgeliefert (block.text) -- nur hat ihn nie jemand angezeigt. Er steht
jetzt im HTML, nicht im Skript: Wer die Seite oeffnet, soll ihn lesen,
BEVOR er tippt.

8. DIE NEUE AUSWERTUNG, AUS BENUTZERSICHT NACHGEBESSERT.

- Der Streifen hatte keine Zeichenerklaerung. Im Dateikopf stand "wer
  Farben schlecht unterscheidet, liest dasselbe Zeichen" -- das stimmt
  nur, wenn irgendwo steht, was die Zeichen heissen. Jetzt eine Legende,
  aus `stufen` gebaut statt abgeschrieben.
- "nie gesetzt" war ein Mittelpunkt, "Kann ich nicht sagen" ein
  Halbgeviertstrich. Zwei kurze Striche nebeneinander fuer den
  Unterschied zwischen "niemand hat hingesehen" und "jemand hat
  hingesehen und konnte es nicht sagen". Leer ist jetzt wirklich leer,
  mit gestricheltem Rahmen.
- Die Aufschluesselung der Balken stand nur im Mausueberfahren -- am
  Handy also nie, und dort steht jemand damit im Stream. Jetzt als Text.
- Die Modi-Sicht bekam Balken ohne Erklaerung, ein "Frag danach" ohne
  Adressaten und bei fehlender Bewegung ein LEERES Element. Jetzt
  Lesehilfe, ein Leerkasten mit Satz und zwei Wege weiter.

9. NEBENBEFUNDE, DIE DIE PRUEFUNG GEFUNDEN HAT.

pruef-css-klassen war schon VOR dieser Arbeit rot (nachgemessen mit
git stash). Alle drei Befunde behoben:
  - hilfe.html und unsere-seiten.html luden ihre Seitendatei NACH
    module.css und haus.css und ueberschrieben damit das Haus.
  - Zwei Schriftgroessen unter 11,5 px aus dem gestrigen Bau
    (.71rem Monatsbeschriftung, .68rem Marke) auf .75 und .72 gehoben.
  - Die Pruefung selbst war blind fuer <style>-Bloecke in der Seite und
    meldete deshalb dauerhaft drei Fehler an einer Seite, die ihre
    Stile mit Absicht selbst traegt. Eine Warnung, die immer kommt, ist
    keine Warnung mehr -- jetzt sieht sie hin, statt die Seite
    auszunehmen.

Kleinkram nebenbei: "die Antworten sieht nur du" -> "siehst nur du" auf
der Kachel zur empfindlichsten Seite des Hauses. "Bewertet wird dort" ->
"Eingeschaetzt wird dort" in teamlage.html, zwei Zeilen unter "keine
Bewertung von Menschen". "1 Aufgabe(n) angelegt" ausgeschrieben.

GEMESSEN: pruef-css-klassen ALLES IN ORDNUNG (vorher 3 Fehler),
pruef-meldungen 8/0, pruef-rechtetafel 19/0, alle Module laden,
keine doppelten Kachelnamen/-ziele/-farben mehr in allen vier Rollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 14:57:55 +02:00
DogFatherGitandClaude Opus 5 461d41943a Keine Maschinensprache mehr auf dem Bildschirm
Filipe: "keine kryptischen oder technischen fehlermeldungen, sondern
klare aussagen darueber, was passiert ist und wie man das problem
loesen kann."

DAS PROBLEM, NACHGEMESSEN.

Der Server antwortet im Fehlerfall mit { fehler: "..." }. Darin stehen
ZWEI verschiedene Dinge, und von aussen sehen sie gleich aus:
Maschinenkennungen (nicht_verfuegbar, nicht_gefunden, ungueltig -- 43
verschiedene) und fertige deutsche Saetze.

An 84 Stellen stand `textContent = d.fehler` -- ungefiltert. Wer beim
Hochladen einer Datei Pech hatte, las woertlich "nicht_verfuegbar" auf
dem Bildschirm und wusste nicht einmal, ob er selbst schuld war.

Gezaehlt: 474 Antworten mit "nicht_verfuegbar", 392 mit
"nicht_gefunden", 125 mit "ungueltig".

DREI AUSGAENGE, NICHT ZWEI.

`sagWas()` in workspace/assets/js/meldung.js:
  bekannte Kennung   -> ihr Satz
  unbekannte Kennung -> der Ersatzsatz der Stelle, NIE die Kennung
                        (sie geht in die Konsole, wo sie jemandem
                        auffaellt, der sie beheben kann)
  fertiger Satz      -> unveraendert durch

Erkannt wird eine Kennung daran, dass sie nur aus Kleinbuchstaben,
Ziffern und Unterstrichen besteht. Ein deutscher Satz hat immer
Leerzeichen; eine Kennung nie. Die Unterscheidung ist entschieden,
nicht geraten.

UND WARUM DIE TABELLE NICHT ALTERN KANN.

Eine von Hand gepflegte Liste ist hier schon zweimal teuer geworden
(die abgeschriebene Spaltenliste, die feste Umbruchschwelle). Deshalb
rechnet pruef-meldungen.mjs die Kennungen AUS DEM SERVER aus statt sie
zu kennen -- eine neue ohne Satz macht sie rot. Man kann es nicht mehr
vergessen.

Sie prueft drei Dinge und beweist zu jedem, dass sie auch "nicht in
Ordnung" sagen kann:
  1. vollstaendig -- jede Kennung hat einen Satz
  2. angeschlossen -- keine Rohanzeige, und jede Seite, deren Skript
     sagWas benutzt, laedt auch meldung.js
  3. lesbar -- kein Satz enthaelt Kennung, Zahl oder englisches Wort

GEFUNDEN HAT SIE SOFORT EINEN ECHTEN FEHLER: leistung.html laedt seine
Skripte ohne `defer` und fiel damit durch meinen Einbau. Dort waere
sagWas nicht definiert gewesen -- aus einer Fehlermeldung waere ein
Absturz geworden, also schlimmer als vorher.

NEBENBEFUND, DER MICH FAST EINE FALSCHE MELDUNG GEKOSTET HAETTE:
"alter_offen" heisst NICHT "etwas Aelteres ist offen", sondern
"Altersbestaetigung steht noch aus" (workspace.js:4864). Geraten
haette ich es falsch uebersetzt.

GEMESSEN: pruef-meldungen 8/0, alle 46 Skripte syntaktisch in Ordnung.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 14:46:13 +02:00
DogFatherGitandClaude Opus 5 7be85c265b Der Treff bekommt einen Chat -- mit Nachtruhe, ohne Telefon
Filipe, auf die Frage ob die Community einen Chat bekommen soll:
"eine geile mischung von punkt 2 und drei. mach es perfekt so das quasi
nach mitternacht bis morgens 6 uhr keiner schreiben kann damit auch die
privatsphaere beruecksichtig wird ueber nacht ... und die sollen nicht
anrufen koennen. nur schreiben."

Zur Auswahl standen "gar kein Chat", "nur mit Oeffnungszeiten" und
"offen wie im Team". Seine Antwort ist eine vierte, die nicht auf dem
Zettel stand, und sie ist die bessere.

1. WARUM DIE NACHTRUHE MEHR IST ALS EINE EINSTELLUNG

Sein Grund war Privatsphaere -- und zwar die der Leute, die moderieren.
Die Forschung zu ehrenamtlichen Moderatoren sagt genau das: Die beiden
meistgenannten Gruende fuers Aufhoeren sind ZU WENIG ZEIT und STREIT IM
TEAM. Ein Chat, der nachts um drei weiterlaeuft, erzeugt beides.

SIE GILT FUER ALLE, AUCH FUER DIE LEITUNG. Das ist die unbequeme
Entscheidung: Der bequeme Weg waere, DogFather auszunehmen. Aber wenn er
um halb vier schreibt, liest es jemand -- und wer liest, fuehlt sich
zustaendig. Eine Nachtruhe, von der die Leitung ausgenommen ist, ist
keine, sondern eine Bitte.

MODERIEREN GEHT WEITER. Verbergen, loeschen, herausnehmen sind keine
Nachrichten. Wer nachts etwas Schlimmes sieht, kann es wegnehmen -- er
kann nur nicht darueber diskutieren. Und der vertrauliche Meldeweg
bleibt offen: Er ist ein Fall mit einer Zustaendigkeit, kein Raum mit
dreissig Leuten.

GERECHNET IN ORTSZEIT, nicht in UTC. `getHours()` auf einem UTC-Server
haette den Chat im Sommer von 2 bis 8 geschlossen -- zwei Stunden
daneben, und nur denen sichtbar, die um diese Zeit wach sind. Dieses
Haus ist mit der Rechnung schon zweimal hereingefallen.

DER RIEGEL SITZT IM SERVER, nicht im Browser. Ein ausgegrautes Feld ist
eine Hoeflichkeit; wer die Adresse kennt, spricht die Schnittstelle
direkt an. Nachrichten UND Anhaenge werden abgelehnt -- ein offener
Anhangweg waere der Umweg, den jeder findet, der es einmal versucht.

2. KEIN TELEFON -- UND WARUM DAS EINEN EIGENEN RIEGEL BRAUCHT

Ein Anruf haengt in diesem Haus an der RAUMMITGLIEDSCHAFT, nicht an der
Rolle. Solange die Community keinen Raum hatte, war die Frage muessig.
Seit sie einen hat, waere Telefonieren erlaubt -- nicht, weil es jemand
entschieden haette, sondern weil es niemand verboten hat.

Der Riegel steht ganz vorne am Anruf-Router, nicht in den neun Routen
dahinter. Alle sieben Wege sind geprueft, einzeln.

3. DER FUND, DER DIE GANZE NACHTRUHE UMGANGEN HAETTE

Ein Gast konnte ein PRIVATES ZWEIER-GESPRAECH mit DogFather aufmachen.
Die Route antwortete mit 200 und legte den Raum an.

`ohneAussen` nimmt die Community aus den Listen ANDERER heraus -- damit
kein Creator einen Zuschauer anschreibt. Die Gegenrichtung kam nie vor,
weil die Chatseite fuer 'gast' gar nicht offen war. Seit heute ist sie
offen, und damit war die Erlaubnis da.

Ein Zweier-Gespraech ist kein Kanal: keine Nachtruhe, kein Modi liest
mit, niemand koennte moderieren. Aus "die Community bekommt einen Chat"
waere ungewollt "jeder Zuschauer bekommt eine Standleitung zu
DogFather" geworden.

GEFUNDEN HAT ES DIE PRUEFUNG, NICHT DAS LESEN -- und zwar in dem Moment,
in dem ich zwei Dateien weiter selbst vor genau dieser Sorte Erlaubnis
gewarnt hatte.

4. ZWEI TOTE WEGE, EINER DAVON MEINER

pruef-community-sicht sucht nach sichtbaren Wegen, die ins Leere
fuehren. Sie fand zwei:

  a) "Bei dir klingelt nichts" -> anruf-probe.html. Der Hinweis von
     heute Vormittag, und die Seite steht einem Gast ausdruecklich NICHT
     offen. Mein Fehler, und einer, der jedem naechsten Hinweis genauso
     passiert waere.

     AN DER WURZEL BEHOBEN: Die Hinweise pruefen jetzt auch die ROLLE
     (`darfSeite`), nicht nur die Adresse. Das ist der 15.09. noch
     einmal, eine Ebene tiefer -- damals die Adresse, diesmal die Rolle,
     und dieselbe Lehre: Die Hinweise sind eine DRITTE Stelle neben
     Seiten und Schnittstellen.

  b) Der Verweis "Kalender" im Tagesblick. Steht fest im HTML, fuehrt
     fuer die Community ins Leere -- und zwar SCHON VOR den Aenderungen
     dieses Tages. Aufgefallen nur, weil (a) daneben stand. Der Weg
     wird jetzt abgeleitet: Wer die Kachel hat, hat den Weg.

5. DIE PRUEFUNG LAEUFT ZWEIMAL

Die Nachtruhe laesst sich nicht in EINEM Lauf in beiden Zustaenden
pruefen -- die Zeiten werden beim Laden gelesen, und ein zweiter Server
braeuchte denselben Port. pruef-treffchat ruft sich deshalb selbst noch
einmal auf, mit einem Fenster, das jetzt gilt. Dieselben Pruefungen,
andere Lage.

DIE UHR WIRD NICHT GEFAELSCHT. Verschoben wird die GRENZE, nicht die
Zeit -- eine Pruefung, die an der Systemzeit dreht, faelscht danach auch
anderes mit und ist nur nachts gruen.

6. WAS SICH NEBENBEI GEAENDERT HAT

- pruef-treff war SCHON VORHER ROT (8 Fehler): Sie erwartete sieben
  Kacheln fuer die Community, es waren gestern Nacht schon zehn. Feste
  Zahlen, Rechnung von gestern. Jetzt abgeleitet -- 72 Pruefungen statt
  66, alle gruen.
- Ein 404 bei jedem Seitenaufruf der Community: `anruf.js` holte die
  Verbindungsadressen, bevor es wusste, wer fragt. Der Browser
  protokolliert das, BEVOR JavaScript abfangen kann -- also darf die
  Anfrage gar nicht erst gestellt werden. `/api/ich` sagt es jetzt
  vorher. Ein Fehler, der immer kommt, macht den naechsten echten
  unsichtbar.
- Reaktionen (Daumen) bleiben nachts erlaubt. Ausdruecklich, mit
  Begruendung im Code: Ein Daumen ist keine Nachricht, er loest keine
  Meldung aus und kann keinen Streit anfangen. Eine Luecke ohne
  Begruendung wird beim naechsten Durchsehen entweder geschlossen oder
  uebersehen -- beides falsch.

GEMESSEN: pruef-treffchat 108/0 (neu, laeuft zweimal), pruef-treff 72/0
(vorher 66 mit 8 Fehlern), pruef-chat gruen, pruef-rechtetafel 19/0,
pruef-community-sicht gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 11:47:31 +02:00
DogFatherGitandClaude Opus 5 790b77a73d Bei dir klingelt nichts -- und 49 Pruefungen, die blind waren
1. SIEBEN VON ELF HATTEN KEIN GERAET ANGEMELDET.

Gemessen am echten Server, nicht geschaetzt (die Notiz von heute Nacht
sagte acht -- Tamy hat inzwischen eins). Bei ihnen kommt nichts an,
solange die Seite zu ist: keine Aufgabe, kein Termin, kein Anruf.

Die Glocke sagt das seit jeher korrekt und kennt sogar den
iPhone-Sonderfall ("erst zum Home-Bildschirm"). Nur tippt sie niemand
an -- sie ist ein stiller Schalter in einer Leiste.

Jetzt steht es dort, wo man hinsieht: als Hinweis in "Was ist dran?",
mit Weg auf anruf-probe.html. Als OFFENER PUNKT, nicht als Warnung --
eine Warnung, die bei sieben von elf Leuten dauerhaft oben steht, ist
nach einer Woche unsichtbar, und mit ihr die echten daneben. Er
verschwindet von selbst, sobald ein Geraet da ist (Gegenprobe in
pruef-glocke).

Und ohne die "1" davor: Er zaehlt nichts, er beschreibt einen Zustand.

FUENF DER SIEBEN DURFTEN DIE SEITE GAR NICHT OEFFNEN. anruf-probe.html
stand nur Leitung und Modis offen. Das war die falsche Einschraenkung:
Die Seite prueft die ganze Kette bis zur Geraete-Kennung, und die
traegt auch jede Aufgaben- und Terminerinnerung. Jetzt alle Team-Rollen,
ohne "gast" (die Community bekommt keine Erinnerungen).

2. 49 PRUEFUNGEN KONNTEN "BELEGT" NICHT VON "KAPUTT" UNTERSCHEIDEN.

Aufgefallen beim Nachsehen, warum ein Lauf rot war: Es war mein eigener,
haengengebliebener Lauf, der den Port hielt. Kein Befund.

Dabei gemessen: Von 130 Pruefungen hatten 49 keinen Portwaechter, und
SIEBEN Portnummern sind doppelt vergeben (4186, 4188, 4189, 4193, 4198,
4321, 4345). Bei belegtem Port startet der eigene Server STILL nicht --
und alles Weitere misst gegen einen fremden Stand. Das hat in diesem
Haus schon zweimal Stunden gekostet (27.08. und 05.09.).

Der Waechter existierte seit dem 05.09., er war nur nie ausgerollt.
Jetzt haben ihn alle 130. Gegenprobe gemacht: Port belegt ->
Rueckgabewert 3 mit Begruendung statt stillem Messen.

pruef-content bekommt BEIDE Ports -- sie startet zwei Server, und der
zweite gehoert zur Gegenprobe. Nur den ersten zu schuetzen hiesse,
ausgerechnet den Teil ungeschuetzt zu lassen, dem man glaubt.

Die sieben doppelten Nummern bleiben vorerst. Mit dem Waechter ist eine
Kollision jetzt laut statt still; Umnummerieren ist ein eigener Schritt.

3. pruef-rollen IST ABGESTUERZT, SEIT WANN WEISS NIEMAND.

"Target crashed" bei der fuenften Rolle, nach 234 gruenen Pruefungen.
Kein Fehlschlag -- ein toter Browser.

NACHGEMESSEN GEGEN DEN STAND VOR HEUTE (0b73fbb): dort genauso, an
derselben Stelle. Es lag also nicht an den Aenderungen dieses Tages.
Aufgefallen ist es nie, weil ein abgestuerzter Browser von aussen wie
ein Programmfehler aussieht und die 234 gruenen Zeilen davor sich wie
ein fast bestandener Lauf lesen.

Ursache ist die Menge: fuenf Rollen mal sechzehn Seiten in EINEM
Browserprozess. Die Kontexte wurden je Rolle geschlossen, der Prozess
darunter lief durch. Jetzt bekommt jede Rolle ihren eigenen Browser,
und ein Absturz meldet sich selbst statt als Zeitueberschreitung
irgendwo weiter unten aufzuschlagen.

Ergebnis: 321 Pruefungen, alles in Ordnung -- statt Absturz bei 234.

4. DAS SYMBOL FUER TIKTOK.

assets/img/app-symbole/workspace-1024.png, frisch gerendert statt
hochskaliert (das Huskygesicht lebt von harten Kanten) und als VOLLES
Quadrat ohne Rundung: Die Aufnahme hat keinen Alphakanal, die Ecken
waeren sonst weiss. App-Portale wollen ohnehin das volle Quadrat, die
Rundung macht das Betriebssystem.

Die sechs vorhandenen Groessen sind dabei bitgleich geblieben --
gepruefte Nebenwirkung, nicht gehofft.

GEMESSEN: pruef-glocke 31/0 (neu: 5 zum Hinweis), pruef-rollen 321/0
(vorher Absturz), pruef-rechtetafel 19/0, pruef-struktur 0 Fehler,
pruef-betreuung und pruef-werdegang gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 11:14:18 +02:00
DogFatherGitandClaude Opus 5 6c10ef0600 Wie geht's dir?: fester Kern, wechselnde Fragen -- und die leere Runde
Dein Auftrag von vorher, zusammen mit zwei Saetzen, die sich zu
widersprechen schienen: "viel mehr Fragen" und "kurz und knapp".

1. DER FEHLER, DEN ICH DABEI GEFUNDEN HABE, WAR GROESSER.

Eine Runde galt als vollstaendig, sobald zu jeder Frage IRGENDEIN Stand
vorlag. Nach der ersten Runde ist das immer der Fall -- die Antworten
bleiben ja stehen. Ab da liess sich jede weitere Runde abschliessen,
OHNE eine einzige Frage anzufassen: Die alten Antworten wanderten mit
neuem Datum ein zweites Mal in den Verlauf.

Der Verlauf zeigte dann eine gerade Linie, und die bedeutete nicht "es
ist gleich geblieben", sondern "niemand hat gefragt". Genau die Sorte
Zahl, die hier verboten ist: eine, die etwas Falsches behauptet, und
der man glaubt. Bei DIESEM Gegenstand -- dem Befinden eines Menschen --
waere das der schlechteste denkbare Ort dafuer.

DIE VORHANDENE PRUEFUNG HAT DEN FEHLER NICHT GEFUNDEN, SIE HAT IHN
FESTGESCHRIEBEN. Dort stand woertlich `ok(zweite.code === 201, "eine
zweite Runde geht auch sofort")` -- gruen, und ein Beleg fuer genau das
Gegenteil dessen, was sie pruefen sollte. Sie aenderte eine Antwort von
zwoelf und war zufrieden.

Ab jetzt zaehlt nur, was NACH der letzten Runde gesetzt wurde. Die alte
Antwort bleibt sichtbar -- sie ist nicht falsch, nur alt -- und traegt,
solange eine Runde faellig ist, den Hinweis "Das war deine Antwort beim
letzten Mal". Der Knopf zum Abschliessen ist weg, bis bestaetigt wurde.

2. FUENF FESTE FRAGEN, DREI WECHSELNDE.

Kern sind die, bei denen ein Ausfall teuer waere: die beiden
meistgenannten Gruende fuers Aufhoeren (zu wenig Zeit, Streit im Team),
die Erholung, die Sicherheit vor Anfeindung und der beste
Fruehindikator ("kann ich mir vorstellen, in ein paar Monaten noch
dabei zu sein"). Eine davon nur jede dritte Runde zu fragen hiesse, die
Antwort im Schnitt sechs Wochen spaeter zu bekommen.

Alle anderen rotieren, drei je Runde. Damit bleibt eine Runde bei acht
Fragen -- die Quellen sagen fuenf bis fuenfzehn, unter zwei Minuten --
und der Katalog kann WACHSEN, ohne dass eine Runde laenger wird. Das
ist der eigentliche Gewinn und die Aufloesung deines Widerspruchs.

Gerechnet, nicht gewuerfelt: aus der Zahl der bisherigen Runden. Zufall
hiesse, dass bei jedem Neuladen etwas anderes dasteht. Und weil sieben
Zusatzfragen und drei Plaetze nicht glatt aufgehen, wird der Versatz
erhoeht, falls er je einen gemeinsamen Teiler mit der Laenge haette --
sonst kaemen nur zwei feste Haelften dran, und der Rest nie.

3. WAS DARAUS FOLGTE, OHNE DASS ES IM PLAN STAND.

- `rhythmus()` zaehlte gegen ALLE Fragen. Mit der Rotation waere das nie
  wieder erfuellt gewesen: Jede Runde haette sich selbst fuer
  unvollstaendig erklaert und die Seite haette taeglich gefragt.
  Jetzt gegen den Kern, der in jeder Runde enthalten ist.
- Die Auswertung sieht ALLE zwoelf Fragen, nicht die acht dieser Runde.
  Der Verlauf hoert nicht auf, wenn eine Frage pausiert.
- Der Verlauf zeigt jede Frage MIT Geschichte (nach zwei Runden elf von
  zwoelf), nicht die der aktuellen Runde. Leere Felder heissen jetzt
  ausdruecklich "war nicht dran", nicht "keine Antwort".
- "seit 2 Runden" heisst jetzt "die letzten 2 Male". Mit der Rotation
  war die alte Formulierung eine Behauptung ueber eine Runde, in der
  gar nicht gefragt wurde.

4. ZWEI DINGE, DIE KEIN ZAHLENVERGLEICH GEFUNDEN HAT -- nur das
   Ansehen des Bildschirmfotos, und beide waren wahr und trotzdem
   irrefuehrend:

- Der Satz "diese Runde sind 8 von 12 dran" stand nur, solange etwas
  offen oder faellig war. Im Ruhezustand -- dem, den man am haeufigsten
  sieht -- fehlte er. Wer acht Fragen zaehlt, wo zwoelf im Katalog
  stehen, haelt vier fuer verschwunden.
- "Das war deine Antwort beim letzten Mal" stand an JEDER Frage,
  unmittelbar nachdem man sie beantwortet hatte.

Beide haben jetzt eine Pruefung, inklusive Gegenprobe ueber eine
zurueckdatierte Runde.

GEMESSEN: pruef-befinden 100/0 (vorher 75 -- die Zahl ist gestiegen,
nicht gefallen), pruef-entwicklung 43/0, pruef-push-ziel 10/0,
pruef-werdegang 95/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 10:33:07 +02:00