Commit Graph
100 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 24ef154a2c pruef-haus-seiten: zwei gepflegte Seitenlisten durch eine Ableitung ersetzt
GEFUNDEN BEIM NACHGEHEN DER ALTLASTEN

    FEHL  calls.html ist auf crew. noch offen (200)
    FEHL  alle 8 Agenturseiten sind auf der Team-Adresse zu

Richtig gemessen und trotzdem kein Befund: Die Seite SOLL dort offen
sein. Am 22.09. hat Team Dogi die Kachel "Calls & Protokolle"
bekommen; seither gehoert calls.html zum Team. Rot war die Liste,
nicht das Haus.

Es waren ZWEI Listen von Hand -- neun Agenturseiten in Abschnitt 2,
fuenfzehn Teamseiten in Abschnitt 3 -- und in beiden fehlte dieselbe
Aenderung. Zwei gepflegte Listen fuer dieselbe Frage sind zwei
Gelegenheiten, eine zu vergessen.

ABGELEITET STATT GEPFLEGT

Welche Seiten es auf einer Adresse gibt, entscheidet
`gehoertAufDieseAdresse`: Eine Seite gehoert hierher, wenn sie unter
den KACHELN dieser Person steht. Die Pruefung fragt jetzt dieselben
Kacheln (`bereicheFuer` + `zusatzBereicheFuer`) und misst danach ueber
HTTP.

Das beweist NICHT, dass die Regel richtig gedacht ist -- das steht in
der Regel selbst. Es beweist, dass die Schranke tut, was die Kacheln
versprechen, und dass keine Seite durchrutscht, die auf keiner Kachel
steht. Und es gibt keine Zahl mehr, die morgen falsch ist.

ZWEI SORTEN GEHOEREN WEDER DEM EINEN NOCH DEM ANDEREN HAUS

Beim ersten Anlauf zaehlte die Ableitung `crew-index.html`,
`index.html` und `start.html` als Agenturseiten -- und verlangte damit
etwa, dass crew-index.html auf der Agenturadresse steht, wo sie zu
Recht ein 404 ist.

  1. DIE EINGANGSWAENDE (OHNE_ANMELDUNG): jede gehoert zu IHRER
     Adresse, auf der anderen gibt es sie nicht.
  2. DIE SEITEN OHNE KACHEL (OHNE_KACHEL_UEBERALL): der eigene
     Steckbrief, die Regeln des Treffs -- sie gehoeren dem Menschen,
     nicht dem Haus.

Mein erster Versuch las beide Listen mit einem regulaeren Ausdruck aus
dem Quelltext. Das ging schief (leere Mengen, vier neue Fehlalarme)
und war auch der falsche Gedanke: Eine Liste, die man PARST, ist eine
Abschrift mit Zwischenschritt. `OHNE_KACHEL_UEBERALL` ist jetzt
ausgeleitet, beide werden importiert.

Gemessen: 10 Seiten gehoeren nicht zu Team Dogi (automation, content,
leistung, profil, report, scouting, startcheck, team, teilen,
uebersicht), 21 gehoeren dorthin. 38 Pruefungen, 0 Fehler.

Dazu eine Gegenprobe zur Ableitung selbst: `calls.html` darf nicht
mehr unter den Agenturseiten stehen. Stuende es dort, waere die
Ableitung kaputt -- und die Pruefung wuerde denselben Fehlalarm wie
zuvor melden, nur mit mehr Umweg.

NEBENBEI GEKLAERT: team.html schickt einen admin auf der Team-Adresse
auf start.html. Am 22.09. als "auffaellig, nicht untersucht" notiert
-- nachgesehen ist es RICHTIG: team.html ist die Teamuebersicht der
Agentur, Team Dogi hat teamlage.html. Die Umleitung ist die
Haustrennung bei der Arbeit, kein Fehler. Sie steht jetzt in der
abgeleiteten Liste der zehn.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-23 00:32:48 +02:00
DogFatherGitandClaude Opus 5 4a5c69cfc6 Die drei Altlasten: ein echter Befund, zwei Pruefungen mit Zahlen von gestern
Alle drei standen seit dem 22.09. in der Notiz und waren mit `git
stash` als vorbestehend nachgewiesen. Nachgemessen, einzeln behoben.

1. pruef-jeder-hat-eine-seite -- EIN ECHTER BEFUND
   "alle 9 Rollen sind zugeordnet -- fehlt: linke"

   Die LINKE HAND fiel im Steckbrief in den Sammelplatz "Weitere":
   Auf der Uebersicht ueber die Menschen des Hauses stand sie unter
   einer Ueberschrift ohne Bedeutung, neben niemandem. Sie gehoert
   dorthin, wo die rechte Hand steht -- beide fuehren Team Dogi mit.

   Beim Nachgehen fiel dieselbe Luecke an einer zweiten Stelle auf:
   In ROLLEN_GRUPPE (der Auswahl, mit wem man schreiben kann) fehlte
   sie ebenfalls und haette eine eigene Ueberschrift mit genau einem
   Namen darunter bekommen -- also die Rangordnung, die zwei Zeilen
   hoeher ausdruecklich vermieden werden sollte.

   WARUM DIE PRUEFUNG DAS FINDEN KONNTE und ein Mensch nicht: Sie geht
   ALLE Rollen des Hauses durch, nicht die vier, die zufaellig
   angelegt sind. Eine Zuordnung, die man an den vorhandenen Leuten
   prueft, ist eine Aussage ueber die Testdaten.

2. pruef-rollen -- DIE MESSUNG WAR FALSCH, NICHT DIE KACHEL
   "DogFather Kachel https://crew... LANDET AUF start.html"

   DogFather bekommt auf der Agenturadresse die Kachel "Zu Team Dogi".
   Ihr Ziel MUSS eine vollstaendige Adresse sein -- das andere Haus
   liegt auf einem anderen Rechnernamen. Im Server steht das
   ausdruecklich (`aussen: true` an der Kachel, samt Begruendung).

   Die Pruefung klebte jedes Ziel an `BASIS + "/workspace/"`. Bei einer
   vollstaendigen Adresse kommt dabei Unsinn heraus.

   Sie kannte ausserdem nur ZWEI Ausgaenge. Ob die andere Tuer
   aufgeht, laesst sich von hier nicht sagen -- der Browser kennt nur
   BASIS. Das ist der dritte Ausgang, und er wird jetzt als solcher
   gemeldet: 314 Pruefungen, 0 Fehler, 1 nicht nachsehbar. Geprueft
   wird stattdessen, was hier zu pruefen IST: dass die Adresse zu
   einem Haus fuehrt, das dieses Haus kennt (aus CREW_ADRESSE, nicht
   abgeschrieben).

3. pruef-kachelraster -- ZWEI ZAHLEN VON GESTERN, UND EIN MESSFEHLER
   "10 Community-Kacheln" (erwartet 8) und "die doppelt breite Kachel
   steht an erster Stelle (Platz 0)"

   `=== 8` stand in der Ueberschrift, im Text und in der Bedingung. Am
   22.09. sind Kacheln dazugekommen, und die Pruefung wurde rot, ohne
   dass am Raster etwas kaputt war.

   Schwerer wog der zweite Teil: Sie suchte "die Community-Gruppe"
   ueber deren Ueberschrift, mit der letzten Gruppe als Rueckfall. Fuer
   DogFather griff der Treffer (1 Kachel), fuer einen Modi der
   Rueckfall (10) -- und beides hiess in der Meldung
   "Community-Kacheln". Eine Pruefung, die je nach Rolle etwas anderes
   misst, kann ihr Ergebnis nicht erklaeren.

   Jetzt werden ALLE Gruppen gemessen, mit Namen in der Meldung, und
   die Frage ist ueberall dieselbe: Hat das Raster ein Loch? Die
   Kachelzahl steht in der Meldung, nicht in der Bedingung. Die Regel
   "eine doppelt breite Kachel steht vorn" bleibt -- es gibt heute
   keine solche Gruppe mehr, aber sie gilt fuer die naechste, und die
   ZAHL der geprueften Gruppen steht daneben.

   Gemessen sieht DogFather 5 Gruppen (1, 6, 11, 4, 1 Kacheln), ein
   Modi 6. Kein Loch in einer davon. 15 Pruefungen, 0 Fehler.

Mitgelaufen und gruen: pruef-steckbrief, pruef-rechtetafel (19),
pruef-chat.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-23 00:29:25 +02:00
DogFatherGitandClaude Opus 5 6be24e204f B3: Jede Seite traegt ihre Farbe -- auch ganz oben in der Leiste
"je nachdem auf welcher seite ich bin wechseln gaaanz oben in der
leiste gewissene symbole und sachen mit ... ich will das auf jeder
seite ... nicht mehr wie auf screen3 sondern genau gleich wie da."

DER BEFUND WAR EINE LADEREIHENFOLGE, KEIN FEHLENDES BAUTEIL

kopf.js setzt `data-ton` am <body> -- auf JEDER Seite, seit Langem.
Die Regel, die daraus eine Akzentfarbe macht, stand aber in
bereich.css:

    body[data-ton] { --akzent: color-mix(in srgb, var(--ton) 88%, #6f8cab); }

und bereich.css laden genau DREI von fuenfunddreissig Seiten
(bereich.html, bewerben.html, teilen.html). Auf den anderen
zweiunddreissig war die Farbe da und wurde nicht gelesen.

Das erklaert auch, warum ausgerechnet die Highlights-Seite sein
Vorbild war: Highlights IST bereich.html -- eine der drei.

Die Regel steht jetzt in start.css. Die liegt auf allen
fuenfunddreissig.

UND DIE LEISTE SELBST. "gaaanz oben in der leiste" ist woertlich zu
nehmen: Der Akzent wirkte bisher weiter unten (Knopfraender,
Fokusringe, Linien an Karten), die Leiste blieb auf jeder Seite
gleich. Sie bekommt jetzt eine Kante unten in der Farbe der Seite,
nach rechts auslaufend, und die Knoepfe rechts nehmen die Farbe beim
Beruehren auf. Dauerhaft eingefaerbt waeren es sechs bunte Knoepfe in
derselben Farbe -- dann traegt nicht mehr die SEITE die Farbe,
sondern die Leiste.

GEMESSEN, NICHT BEHAUPTET (pruef-kopfleiste-farbe.mjs, NEU, 9/0)

Im echten Browser, mit getComputedStyle -- ob eine CSS-Regel WIRKT,
steht nicht in der Datei:

    aufgaben.html   Ton 13  --akzent  #12b37e (gruen)
    chat.html       Ton  4  --akzent  #c16302 (orange)
    kalender.html   Ton  8  --akzent  #ab68ff (violett)

Welche Seiten gemessen werden, steht NICHT in der Pruefung: Sie liest
die Kacheln der Startseite und nimmt drei mit verschiedenen Toenen.
Eine Liste dort waere die, die beim naechsten Umbau eine Seite nennt,
die es nicht mehr gibt.

Zwei Gegenproben: dass die Farben VERSCHIEDEN sind (vorher war
--akzent auf 32 von 35 Seiten dieselbe -- eine Pruefung ohne diesen
Teil waere auch im alten Zustand gruen gewesen), und dass ohne
`data-ton` wieder die Hausfarbe gilt (#8ec9ff). Eine Regel, die auch
dort zuschlaegt, wuerde eine Farbe erfinden.

EIGENER FEHLER, beim ersten Lauf dieser Pruefung
------------------------------------------------
Der Kachel-Selektor war falsch (`.kachel[href]` statt `li.kachel` mit
dem Verweis darin) -- sie fand null Kacheln. Das haette auffallen
muessen, tat es aber fast nicht: DREI Zeilen waren trotzdem gruen,
weil `every()` auf einem leeren Feld `true` liefert. Genau die Falle,
vor der die Hausregel warnt, und ich bin hineingelaufen. Die Zahl
steht jetzt in jeder dieser Bedingungen.

Mitgelaufen und gruen: pruef-css-klassen (keine Stilvorlage verliert
still eine Regel), pruef-chatkachel (33), pruef-teamlage-karten (22).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:52:27 +02:00
DogFatherGitandClaude Opus 5 189d0b3363 B1: Das Anschlagbrett haelt 24 Stunden -- und sieht aus wie ein Anschlagbrett
"die sachen sollen in der seite vom anschlagbrett immer automatisch
nach 24h von da verschwinden. weil alles hat seine kategorie und was
nicht ist auch nicht um ewig auf der seite zu bleiben fertig."

SEINE BEGRUENDUNG IST DIE REGEL. Ein Anschlagbrett sagt, was GERADE
gilt. Was laenger gilt, hat seinen eigenen Bereich -- Regeln stehen bei
den Regeln, Termine bei "Was ansteht". Eine Ansage vom letzten
Dienstag, die noch haengt, ist keine Ansage mehr, sondern Papier an der
Wand.

DIE DREI ENTSCHEIDUNGEN, DIE ICH TREFFEN MUSSTE -- und woran ich sie
festgemacht habe:

1. AB WANN LAUFEN DIE 24 STUNDEN? Ab `erstellt`, nicht ab `datum`.
   `datum` ist ein vom Team gesetztes Feld und kann in der Zukunft
   liegen (es traegt die Termine). Eine Ansage, die morgen gilt, soll
   morgen verschwinden und nicht uebermorgen.

2. VERSCHWINDET SIE GANZ? Nein. Er sagt "von DA verschwinden" -- von
   der Seite. Geloescht wird nichts: Wer eine Ansage geschrieben hat,
   soll sie wiederfinden. Sie kommt als `abgehaengt` mit und steht
   zugeklappt unter einer leisen Zeile "Abgehaengt (3)". Auf dem Brett
   selbst steht sie damit nicht mehr.

3. WER ENTSCHEIDET? Der Server. Die Stunden im Browser nachzurechnen
   waere eine zweite Fassung derselben Regel, und eine davon waere
   irgendwann aelter. Die Frist geht als Zahl mit der Antwort.

DAS AUSSEHEN ("viel besser gestaltet, übersichtlicher, moderner,
hochwertiger, professioneller"): Was haengt, sieht jetzt aus wie etwas,
das haengt -- kraeftiger Rand links in der Farbe seiner ART (Ansage
babyblau, Neue Regel gold, Hinweis lila, Danke gruen), ein Schein von
links, mehr Luft. Die Art stand bisher nur im Text; jetzt sieht man
sie. Abgehaengtes ist grau statt durchsichtig -- durchsichtig hiesse,
das Buehnenbild scheint durch, also Text auf einem Foto.

pruef-anschlagbrett.mjs (NEU, 12/0) misst beide Seiten der Grenze
(23 h haengt, 25 h nicht), rechnet relativ zur jetzigen Uhrzeit statt
mit einem festen Datum, und hat den Eintrag, an dem sich alles
entscheidet: alt aufgehaengt, Datum von heute. Wer nach `datum`
filtert, laesst ihn haengen. Dazu zwei Gegenproben: auf jedem anderen
Brett gibt es das Merkmal gar nicht, und wo die Grenze WIRKLICH liegt,
wird aus den Eintraegen nachgerechnet statt aus der Zahl im Modul.

NEBENBEFUND, den erst dieser Commit ausgeloest hat
---------------------------------------------------
pruef-bereiche-lesend stuerzte ab: "listen EACCES 127.0.0.1:5040".

Die Portnummern werden aus der Stelle im Alphabet abgeleitet -- heute
sind fuenf neue Pruefdateien dazugekommen, und dadurch ist diese
Pruefung auf die 5040 gerutscht. Die haelt auf diesem Rechner ein
Windows-Dienst (svchost, PID 7136).

`portMussFreiSein` kannte nur ZWEI Antworten: EADDRINUSE oder frei.
EACCES galt als frei -- die Pruefung lief weiter, bis der echte Server
auf demselben Port startete und mit einem unbehandelten Fehler
abstuerzte. Ein Stapelauszug aus node:net, der wie ein Fehler im Code
aussieht.

Jetzt drei Antworten. Und ein belegter Port wird anders behandelt als
ein gesperrter: Belegt geht vorbei (der andere Lauf hoert auf),
gesperrt nie. Abzubrechen hiesse, die Pruefung waere auf diesem Rechner
dauerhaft nicht ausfuehrbar -- die Sorte Warnung, die immer kommt und
deshalb weggeklickt wird. Ausgewichen wird um einen festen Betrag
(+4000), damit die Nummer abgeleitet und eindeutig bleibt.

Mitgelaufen und gruen: pruef-bereiche-lesend, pruef-css-klassen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:47:52 +02:00
DogFatherGitandClaude Opus 5 7c23913347 B2: Die Regeln sind eine Flaeche statt sechs Kacheln
"lass bitte die ganzen regeln viel geiler und spezieller aussehen und
nicht sehr viele kacheln sondern eine riesige wo alles schön aussieht
und richtig geil, übersichtlich"

Vorher sechs Kaesten untereinander: jeder mit Rand, Grund und Abstand,
dazwischen jedes Mal ein Schnitt. Beim Lesen faengt man damit sechsmal
neu an -- Regeln lesen sich aber als EIN Text, nicht als sechs
Merkzettel.

JETZT EINE FLAECHE. Die Abschnitte bleiben, ihre Kaesten nicht:
innerhalb der Flaeche trennt eine Linie statt einer Luecke. Dazu ein
Schein in der Hausfarbe oben links, der nach einem Drittel ausgelaufen
ist -- Text auf einem Verlauf liest sich unruhig, und diese Flaeche ist
zum Lesen da.

UEBERSICHTLICH HEISST: EINE SPRUNGLEISTE. Eine lange Flaeche ohne
Wegweiser ist nicht uebersichtlicher als sechs Kaesten, nur laenger.
Die Leiste klebt oben, nennt alle Abschnitte und hebt den hervor, in
dem man gerade steht (IntersectionObserver -- beim Rollen zu rechnen
kostet auf einem Handy spuerbar Strom).

SIE WIRD GELESEN, NICHT GEPFLEGT: Die Eintraege kommen aus den
Ueberschriften, die ohnehin dastehen, und fehlende ids entstehen
dabei. Eine Liste von Hand waere die, die beim siebten Abschnitt
fehlt -- und niemand merkte es, weil die Seite ja funktioniert.

Die fuenf Regeln tragen ihre Zahl jetzt in einem eigenen Kreis. Die
wichtigste Liste der Seite sah aus wie jede andere Aufzaehlung.

ZWEI DINGE, DIE ERST DAS BILDSCHIRMFOTO GEZEIGT HAT

1. AUF DEM HANDY BRAUCHTE DIE LEISTE SECHS ZEILEN -- rund ein Drittel
   des Bildes, und sie klebt oben fest, also dauerhaft. Ein Wegweiser,
   der mehr Platz braucht als der Weg, ist keiner. Jetzt eine Zeile,
   die man seitlich schiebt, mit scroll-snap. Am Rechner bleibt der
   Umbruch: Dort ist Platz, und alles auf einen Blick schlaegt alles
   hinter einer Schiebebewegung.

2. DANACH WAR SIE GANZ WEG -- hinter der Kopfleiste. Ursache:
   `--kopf-hoehe` wurde nur in chat.js gemessen. Auf jeder anderen
   Seite galt der Rueckfallwert 64 px, und auf einem 390-px-Schirm ist
   die Kopfleiste rund 115 px hoch.

   Eine Zahl, die eine Seite misst und eine andere raet, ist schlimmer
   als gar keine: Auf der einen stimmt sie, auf der anderen nicht, und
   niemand sucht den Fehler bei einer Zahl. Die Messung steht jetzt in
   kopf.js -- die Datei liegt auf JEDER Seite -- und zaehlt wie vorher
   Kopfleiste plus Band mit dem fremden Namen, bei jeder Aenderung neu.
   chat.js ruft sie nur noch auf.

Mitgelaufen und gruen: pruef-treff (80/0), pruef-treff-werkzeuge
(73/0), pruef-chat-optik, pruef-css-klassen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:41:47 +02:00
DogFatherGitandClaude Opus 5 73facb7ce9 Nachtrag zu B4: die Aufraeumung lief nie -- .changes an der falschen Stelle
WAS PASSIERT IST

Der Commit 60802170 ist um 23:33 ausgeliefert worden. Im Protokoll des
Servers stand danach:

    [workspace] undefined zurueckgenommene Nachrichten endgueltig entfernt.
    [workspace] 4 blaue Herzen auf babyblau umgestellt

Die zweite Zeile stimmt. Die erste ist der Befund: `undefined` statt
einer Zahl. Nachgesehen in der Live-Datenbank -- die fuenf
zurueckgenommenen Zeilen waren noch da.

URSACHE: `d.prepare("DELETE ...").changes` statt `.run().changes` --
also die Eigenschaft der vorbereiteten ANWEISUNG, nicht die des Laufs.
Die Anweisung wurde vorbereitet und nie ausgefuehrt. Nichts stuerzte
ab, nichts war rot, kein Fehler im Protokoll.

NEBENFOLGE, die es schlimmer gemacht haette: Die Sicherung wird VOR
dem Loeschen geschrieben. Da nie geloescht wurde, blieb die Bedingung
erfuellt -- bei JEDEM Neustart waere eine weitere Sicherungsdatei
entstanden. Genau das, wovor der Kommentar zwei Zeilen darueber warnt.
Ein Kommentar, der vor einem Fehler warnt, verhindert ihn nicht.

WAS JETZT ANDERS IST

Behoben, und die Umstellung ist eine exportierte Funktion geworden:
`loeschspurenAufraeumen(d, dbPfad)`. Nicht aus Ordnungsliebe -- eine
Umstellung, die tief im Hochfahren steckt, kann keine Pruefung
aufrufen. Eine Funktion schon.

pruef-loeschen.mjs (20 -> 25): stellt den alten Zustand her (Text leer,
weg_am gesetzt), ruft die Funktion und misst
  * dass sie eine ZAHL meldet (`typeof === "number"`) -- genau hier
    stand undefined, und 0 sieht in einer Meldung fast so aus,
  * dass die Zeile wirklich verschwindet,
  * und dass beim zweiten Aufruf nichts mehr passiert und nichts
    gesichert wird.

Ohne den ersten dieser drei Haken waere der Fehler auch beim naechsten
Mal durchgegangen: Eine Meldung mit `undefined` ist gruen, solange
niemand sie liest.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:36:02 +02:00
DogFatherGitandClaude Opus 5 60802170a1 B4 + B5: Loeschen heisst Loeschen, die Schrift wechselt mit, und Blau wird Babyblau
Die beiden Auftraege gehoeren zusammen, und zwar in dieser Reihenfolge:
Eine babyblaue Kachel ist HELL. Ohne mitwechselnde Schrift waere sie
unlesbar (1,63:1 gemessen). Erst B4 macht B5 moeglich.

B4a -- LOESCHEN HEISST LOESCHEN
  "Geloeschte Nachrichten verschwinden vollstaendig - keine Spur, kein
   'wurde geloescht'-Hinweis, bei niemandem, auch nicht bei DogFather."

Bis heute blieb die Zeile stehen: Text geleert, weg_am gesetzt, und im
Chat stand "Nachricht zurueckgenommen". Das war ausdruecklich so
begruendet ("ein Loch im Verlauf wirft mehr Fragen auf"). Das Argument
beantwortet aber eine andere Frage: Ein Hinweis "hier stand etwas"
MARKIERT die Stelle. Wer etwas aus Versehen schreibt, will es weg
haben und nicht unterstrichen.

Jetzt ein echtes DELETE. Vier Raender, an denen eine Spur bleiben
koennte, alle gemessen:
  1. die Zeile selbst
  2. chat_reaktionen    (ON DELETE CASCADE - nachgesehen, nicht angenommen)
  3. chat_erwaehnungen  (ebenso)
  4. letzte_am am Raum  - wird neu gerechnet, sonst stuende er oben in
                          der Liste mit einem Zeitpunkt, zu dem es
                          nichts mehr gibt
Dazu: ein Zitat auf eine geloeschte Nachricht wird weggelassen; in der
Gespraechsliste steht kein Hinweis mehr; der Knopf heisst "loeschen".

Die 5 alten zurueckgenommenen Zeilen (Text bereits leer) raeumt eine
einmalige, wiederholbare Umstellung ab - mit Sicherung davor, und nur
wenn es wirklich etwas zu tun gibt.

B4b -- WER DARF WAS
  "jeder nur seine eigenen - ausser DogFather und rechte Hand"
`darfJedeNachrichtLoeschen` = admin oder hand. NICHT fuehrtTeamDogi
(das schloesse die linke Hand ein) und nicht istLeitung (das schloesse
Spicy Media ein, die private Chats nicht einmal sehen darf). Das Recht
kommt vom Server ins Skript, nicht aus einer Rolle im Browser: chat.js
bekommt jeder, der die Seite oeffnet.

B4c -- DIE SCHRIFT WECHSELT MIT
  "am besten schwarz auf hellen Kacheln - und weiss, wenn jemand eine
   schwarze Kachel waehlt"
`schriftFuer(farbe)` waehlt zwischen zwei Paaren, gerechnet aus der
Leuchtdichte, mit denselben Schwellen wie das Rechenwerkzeug (7:1 fuer
den Text, 4,5:1 fuer die Fusszeile). Keine dritte Spalte in
CHAT_KACHELN, die jemand pflegen muesste. Flaeche und Schrift werden
im Browser in EINEM Griff gesetzt (blaseFaerben) - zwei Stellen waeren
irgendwann eine helle Kachel mit heller Schrift.

B4d -- DIE NAMEN
Der Name ist jetzt ein eigener Streifen mit Kante darunter, .84rem,
und der Rollenpunkt wird ein 3x14-Balken. Vorher stand er als erste
ZEILE in der Blase und las sich wie der Anfang des Satzes.

B5 -- BABYBLAU
  "jedes normales blaues herz durch babyblaues herz ersetzen ... jeder
   normale blaue farbe, sei es die kachel im chat oder emojis, nur
   babyblau bitte."
* Herz: U+1F499 -> U+1FA75. Nicht geglaubt, sondern gemessen: 43,9 px
  breit wie die anderen Herzen, ein Ersatzkaestchen waere 20,7. Die
  vier vorhandenen blauen Herzen in der Datenbank wandern mit - sonst
  waeren es vier Reaktionen, die ERLAUBT nicht mehr kennt: still weg.
* Kachel: neue, HELLE Kachel "Babyblau" mit dem Wert von --akzent.
  Gemessen: Text 10,78:1, Fusszeile 4,87:1. Sie steht bewusst nicht in
  der Rechnung des Werkzeugs (das rechnet elf Toene auf EINE
  Leuchtdichte) - sie hat eine andere Leuchtdichte und dafuer ihre
  eigene Schrift. Dasselbe Versprechen, anderer Weg.

PRUEFUNGEN
  pruef-loeschen.mjs (NEU, 20/0): alle vier Raender, die vier Faelle
    der Rechtegrenze (auch: die linke Hand darf NICHT), das babyblaue
    Herz am laufenden Server, und dass der Satz "Nachricht
    zurueckgenommen" nur noch in Kommentaren steht - mit Gegenprobe,
    dass die Suche diesen Unterschied wirklich macht.
  pruef-chatkachel.mjs (33/0): misst jede Kachel mit IHRER Schrift und
    fragt dafuer dieselbe Funktion wie der Server. Neu: dass die
    Schrift ueberhaupt wechselt. Die Leuchtdichte-Regel gilt jetzt fuer
    die gerechneten Toene - das Versprechen dahinter loest die
    Kontrastzeile darueber direkt ein.
  Vier alte Pruefungen umgedreht, die den alten Zustand festgeschrieben
    hatten: pruef-chat, pruef-chat-ausbau, pruef-chat-aufloesen,
    pruef-chat-optik. Alle mit scharferer Messung als vorher (Zahl
    davor/danach statt "ein Hinweis ist da").
  Mitgelaufen und gruen: pruef-alle-sehen-es, pruef-treffchat (110/0).

Gesichert: workspace-vor-loeschumbau-20260922-233313.db
(946 KB, integrity_check ok, 111 Nachrichten, 49 Reaktionen).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:33:43 +02:00
DogFatherGitandClaude Opus 5 95da1345fc B9: In einen Kategorie-Kanal gehoert Team Dogi -- und alle davon
VanVans Befund, von Filipe weitergegeben:
  * "Patrick und BananaStift (stifti) aus der Erwaehnen-Liste
     entfernen -- sie stehen dort als SCOUT."
  * "Die Modis zum Erwaehnen hinzufuegen."
  * "Die Modis sehen den Chat Moderation auch gar nicht."

AN DER LIVE-DATENBANK NACHGEMESSEN, bevor etwas gebaut wurde:

    Raum 3  kanal  Chat-Moderation   admin, hand, SCOUT, SCOUT, linke
    Raum 7  kanal  Der Treff         admin, hand, 4x modi, linke, 3x gast
    Raum 8  gruppe Dogi und Modis    admin, hand, 4x modi, linke
    Raum 9  gruppe Abmeldungen       admin, hand, 4x modi, linke

Damit waren alle drei Punkte EIN Befund. Die Erwaehnen-Liste im
Browser zeigt genau `offen.teilnehmer`, also die Teilnehmer des Raums
(teilnehmerVon) -- eine zweite Quelle gibt es nicht. Standen dort zwei
Scouts und kein Modi, dann schlug sie Scouts vor, und die Modis sahen
den Kanal gar nicht. An der Erwaehnung selbst war nichts kaputt.

DIE REGEL

Ein Kategorie-Kanal gehoert Team Dogi: admin + TEAM_DOGI_ROLLEN
(hand, linke, modi), abgeleitet aus der einen Liste des Hauses. Der
Abgleich beim Blick in die Gespraechsliste heilt jetzt in BEIDE
Richtungen:

  hinein  jeder aktive Mensch aus Team Dogi, der im Raum NOCH NIE eine
          Zeile hatte
  hinaus  jeder aktive Teilnehmer, dessen Rolle nicht dazugehoert
          (raus_am, kein DELETE -- der Verlauf bleibt lesbar)

"NOCH NIE EINE ZEILE" ist der wichtige Teil: Wer ueber die
Mitglieder-Route bewusst herausgenommen wurde, hat eine Zeile mit
raus_am und wird NICHT zurueckgeholt. Ein Abgleich, der eine
Entscheidung von Hand beim naechsten Seitenaufruf ueberschreibt,
macht die Route wertlos -- dieselbe Ueberlegung wie bei
treffAngleichen(). Der Treff bleibt ausgenommen: Dort gehoert die
Community dazu.

Dazu dieselbe Schranke an beiden Schreibwegen (Kanal anlegen und
umbesetzen). `darfSchreibenMit` beantwortet eine ANDERE Frage -- "darf
ich diesen Menschen ueberhaupt anschreiben" -- und sagt bei einem
Scout zu Recht ja. Genau diese Luecke hat die zwei Scouts in den
Moderations-Kanal gebracht.

WARUM NICHT "NUR DIE ZUSTAENDIGEN"

Weil es die Zuordnung nicht gibt: `kategorienFuer` gibt JEDEM aus Team
Dogi ALLE Kategorien, eine Tabelle Person -> Kategorie existiert
nirgends. Eine Regel "nur die Zustaendigen" waere eine Liste, die
niemand pflegt. Wer einen engeren Kanal will, nimmt jemanden heraus --
und das haelt.

PRUEFUNGEN

  pruef-kanal-besetzung.mjs (NEU, 16/0): baut die gemeldete Lage nach
  (Scout drin, kein Modi), laesst den Abgleich darueberlaufen und
  misst beide Richtungen. Vier Gegenproben: der von Hand Entfernte
  bleibt draussen; ein Scout kommt auch ueber die Mitglieder-Route
  nicht hinein; der Gast bleibt im Treff; und ein wieder
  hereingeschmuggelter Scout fliegt beim naechsten Abgleich erneut
  hinaus -- die Regel wirkt dauerhaft, nicht einmalig.

  pruef-chat-kanaele.mjs (79 mit 3 Fehlern -> 81/0): Die Zeile "wer
  nicht drin ist, sieht ihn nicht" hat den alten Zuschnitt
  festgeschrieben -- sie prueft jetzt die schaerfere Grenze: wer
  HERAUSGENOMMEN wurde, bleibt draussen, auch nach dem naechsten
  Abgleich. Dieser Weg war bis heute ungeprueft.

Mitgelaufen und gruen: pruef-chat, pruef-treffchat (110/0).

Vor dem Ausliefern gesichert: workspace-vor-kanalregel-20260922-231409.db
(946 KB, integrity_check ok, 17 Personen, 37 Teilnehmerzeilen,
111 Nachrichten).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 23:14:38 +02:00
DogFatherGitandClaude Opus 5 803750edbc Aufgaben verteilen: der Knopf ist nie mehr tot, und die Bewerbung steht im Formular
screen1 -- „dogfather, die rechte hand und die linke hand sollen immer
noch aufgaben werden teilen können plus die option dass die modis sich
für aufgaben bewerben können. weil gerade hängt das und weiß nicht
wieso."

WAS WIRKLICH LOS WAR -- gemessen, nicht geraten

Auf entwicklung.html stand oben „Aufgabe verteilen · Wähl LINKS
jemanden aus", und der Knopf war so lange abgeschaltet. Im Browser
nachgemessen (1420 px, als DogFather):

    Band          oben 284 px, linke Kante 130 px
    Personenwahl  oben 490 px, linke Kante 130 px
    -> UNTER dem Band, 127 px darunter, gleiche linke Kante

Links war nichts. Wer der Anweisung folgte, schaute auf eine leere
Fläche und hatte einen Knopf, der nicht ging. Das Recht selbst war die
ganze Zeit richtig: `darfAufgabenVerteilen` = Leitung oder Hand, also
DogFather, rechte Hand UND linke Hand -- alle drei mit
`darf_verteilen: true` gemessen.

Kurz: Die Regel stimmte, der Weg dorthin nicht.

WAS JETZT ANDERS IST

1. DER KNOPF IST IMMER BENUTZBAR. Er öffnet das Formular, auch ohne
   vorherige Auswahl.
2. DIE FRAGE „für wen" STEHT IM FORMULAR, als erste Zeile, mit allen
   Personen zur Wahl. Wer unten eine Kachel angeklickt hat, findet sie
   angehakt wieder -- beide Wege führen zum selben Ziel.
3. EINE LISTE STATT ZWEIER. „Noch jemanden dazunehmen" ist weg. Es
   waren zwei Bedienungen für dieselbe Frage -- und die
   Bewerbungs-Option steckte ausgerechnet in der zugeklappten
   zweiten: Sie war nur zu finden, wenn man erst aufklappte UND dort
   jemanden ankreuzte. Eine Möglichkeit, die man nicht findet, gibt es
   nicht.
4. DIE BEWERBUNG STEHT DA, sobald zwei Leute angehakt sind: „Wer
   zuerst Zeit hat, übernimmt. Sie bewerben sich, du nimmst an oder
   lehnst ab."

ZWEI FEHLER, DIE DABEI AUFFIELEN

* Nach dem Anlegen wurde `fuerPerson` auf null gesetzt und DANACH
  `aufgabenZeigen(fuerPerson, …)` aufgerufen -- die Liste, die zeigen
  soll, was gerade entstanden ist, blendete sich damit aus. Die Namen
  werden jetzt festgehalten, bevor `reset()` sie abräumt.
* Die Bestätigung sagte immer „steht jetzt bei ihm" -- `fuerName` wird
  nur beim Klick auf eine Kachel gefüllt. Sie sagt jetzt, was wirklich
  passiert ist, und bei einem Pool, dass eine Bewerbung kommt.
* `e-mehr-art` heisst `e-art`: Der Name sagte „gehört zu ‚noch
  jemand'", und das gibt es nicht mehr. Dieselbe Sorte Falle wie
  `tperson__namen` heute Nachmittag.

DIE PRÜFUNG HATTE MEINEN FEHLER FESTGESCHRIEBEN

`pruef-bewerbung-aufgaben.mjs` enthielt wörtlich:

    ok(vorher.aus === true,
      "und ist aus, solange niemand gewaehlt ist");

Sie lief, sie war grün, und sie hat den toten Knopf verteidigt. Das
ist die unangenehmste Sorte: nicht übersprungen, nicht kaputt --
sondern eine Bestätigung meines Entwurfs statt der Sache. Jetzt wird
das Gegenteil verlangt.

Dazu zwei neue Abschnitte (84 -> 101 Prüfungen, 0 Fehler):
  6b  verteilen OHNE vorherige Auswahl, als Pool, samt Nachweis am
      Server (verteilart=pool, zwei Leute darin) und der Meldung, die
      nicht „bei ihm" sagen darf
  6c  alle drei Rollen am Bildschirm: DogFather, rechte Hand, linke
      Hand -- mit Gegenprobe, dass ein Modi das Band NICHT sieht

EIGENER MESSFEHLER, offen notiert: Mein erster Versuch, die Bewerbung
nachzustellen, meldete „kein Abruf, nichts passiert". Der Knopf öffnet
eine Rückfrage, und die hatte ich nicht beantwortet. Die Bewerbung war
nie kaputt -- meine Messung war es. Erst der zweite Anlauf zeigte den
ganzen Weg: POST /api/aufgaben/1/bewerben -> {"ok":true,"zustand":"beworben"}.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 20:18:35 +02:00
DogFatherGitandClaude Opus 5 ba0e326585 Team-Lage: fuenf Stufen mit eigener Farbe, Karten neu gebaut, 404 wirft nicht mehr hinaus
B7 -- "wenn ich auf diese sachen drücke werd ich auf die startseite
geschickt" und "ich will das es ein zwei kategorien mehr gibt und das
soll geiler aussehen und jede seine eigene farbe, stark erkennbar"

1. DER RAUSWURF. Ein Druck auf einen Stufen-Knopf schickte auf die
   Startseite. Ursache: `hole()` stand ACHTMAL Zeichen fuer Zeichen
   gleich in acht Dateien, und darin warf JEDER 404 hinaus -- auch der
   auf eine blosse Handlung. Jetzt eine gemeinsame `assets/js/holen.js`
   mit der engeren, abgeleiteten Regel: Ein 404 wirft nur, solange die
   Seite noch gar nichts bekommen hat.

2. ZWEI STUFEN MEHR, und keine davon erfunden: "Fortgeschritten" gibt
   es im Entwicklungs-Katalog laengst (ENTWICKLUNG_ERWARTUNG), hier
   fehlte genau diese Mitte; "Vertretung" stand bis heute IN der
   Beschreibung von Senior. Keine Datenbankaenderung noetig -- die
   Spalte ist absichtlich ein TEXT ohne CHECK.

3. DIE FARBEN SIND GERECHNET. Nachgemessen lagen "Probe" und
   "Standard" bei 0,0576 OKLab-Abstand; MINDEST_ABSTAND ist 0,090 --
   die beiden waren nebeneinander dieselbe Farbe, und alle drei lagen
   unter MINDEST_BUNTHEIT. Die neuen fuenf sind ein Faecher aus fuenf
   Farbwinkeln im Abstand von 72 Grad; der Versatz ist der, bei dem der
   kleinste Abstand am groessten wird. Ergebnis: 0,1531 untereinander,
   0,1108 zur Rollenmarke daneben, Kontrast 7,4 bis 8,6.

B8 -- "die sollen viel krasser geiler und übersichtlicher sein ... und
die kacheln sollen viel krass geiler und spezieller aussehen auch der
hintergrund, veränder das komplett"

4. DIE KARTE IST NEU: Kopfband in der Farbe der Stufe bis an die
   Kanten, Zeichen von 44 auf 52 px mit Ring, Zahlenband als eigene
   Flaeche, neuer Hintergrund (Farbschein unter dem Kopfband, feine
   Schraffur, dunklere Platte). 781 px hoch gemessen, danach 746.

5. DIE ROLLE STEHT JETZT DA -- als Marke auf der Karte und als
   Ueberschrift ueber jeder Gruppe. Sortiert war schon vorher nach
   Rolle; man konnte es nur nicht sehen.

DREI FEHLER, DIE DABEI AUFFIELEN

* `auto-fit` liess die einzelne Karte der rechten Hand ueber die ganze
  Bildschirmbreite laufen, sobald gruppiert wurde. `auto-fill` haelt
  die leeren Spalten offen.
* Der Name der Person trug `tperson__namen` statt `tperson__name` --
  ein Buchstabe, und damit die Klasse fuer graues Kleingedrucktes. Auf
  einer Seite ueber Personen war der Name kleiner als die Beschriftung
  darunter. Gefunden hat es die neue Pruefung, die ueberall "?" las.
* `stufeSetzen()` suchte das Stufen-Schild mit
  `[class*="tmerkmal--"]:not(...)` -- einer Aufzaehlung dessen, was es
  NICHT ist. Sobald die Rollenmarke davorstand, traf die Suche sie:
  Ein Druck auf "Standard" haette aus "Modi" das Wort "Standard"
  gemacht. Und die Karte faerbte sich beim Setzen nicht mit um.

DREI PRUEFUNGEN, ALLE MIT GEGENPROBE

* pruef-holen.mjs (NEU, 14): fuehrt die echte Datei aus und misst fuenf
  Wege; dieselben fuenf noch einmal an der ALTEN Fassung, die bei genau
  zwei durchfallen muss. Dazu: laedt jede der acht Seiten holen.js, und
  zwar VOR ihrem Skript.
* pruef-teamlage-karten.mjs (NEU, 22): im Browser. Gruppen, Rollenwort,
  Stufenknoepfe nur bei Modis, der Druck selbst (kein Sprung, ein
  Abruf, Schild und Kartenfarbe ziehen mit), Gegenprobe mit dem zweiten
  Druck, und die neuen Baender auf 390 px.
* pruef-team-stufen.mjs (28 -> 47): die abgeschriebene Liste
  ["probe","standard","senior"] ist raus -- geprueft werden jetzt
  Eigenschaften und die Farbabstaende, gelesen aus team.css. Gegenprobe
  ist der Stand von gestern, der durch dieselbe Messung faellt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 19:46:47 +02:00
DogFatherGitandClaude Opus 5 3b76a9aab5 screen1 + A5 + B6: „wer zuerst Zeit hat" gilt wieder, und Aufgaben entstehen dort, wo die Person steht
DREI SACHEN, EIN ZUSAMMENHANG.

--- screen1 --------------------------------------------------------
Filipe zu meinem eigenen Satz „wer zuerst Zeit hat — genau das geht ja
nicht mehr": „falls das nicht mehr geht mach das es geht wenn es wieder
geht ist alles gut."

Er hat recht, und ich hatte zu schnell aufgegeben. „Wer zuerst Zeit
hat" muss nicht heissen, dass man sich selbst bedient -- es kann
genauso heissen, dass die ERSTE BEWERBUNG zuerst drankommt. Damit gilt
beides: Die Leitung entscheidet (sein Wunsch von vorhin), und wer
schnell ist, hat den Vorteil (sein Wunsch von eben).

Die Bewerbungen werden jetzt nach EINGANG sortiert, nicht nach Namen
-- die Abfrage sortiert sonst alphabetisch, und dann haette nicht der
Schnelle den Vorteil, sondern Frida. Der Erste bekommt die Marke
„zuerst da" (nur bei mehr als einer -- sonst ist es keine Auskunft,
sondern Fuellwerk).

Geprueft mit Absicht gegen das Alphabet: Nele bewirbt sich zuerst und
steht vorn, obwohl Frida im Alphabet vor ihr kaeme.

--- B6: der Knopf auf dem Aufgabenbrett ----------------------------
Filipe: „dieser button kann da jetzt doch endlich verschwinden, auf
dieser seite sollen ja keine aufgaben mehr verteilt werden."

ER HAT DABEI AUF DEN TEAM-DOGI-BILDSCHIRM GESEHEN, und das ist der
Unterschied zwischen „weg damit" und „weg damit, aber gemessen":

    Rolle/Haus        aufgaben.html  entwicklung.html  darfAnlegen
    manager/agentur   ja             NEIN              ja
    creator/agentur   ja             NEIN              ja
    scout/agentur     ja             NEIN              ja
    spicy/agentur     ja             NEIN              ja

Haette ich den Knopf einfach entfernt, koennten vier Rollen gar keine
Aufgabe mehr anlegen. Der Server nennt deshalb den ORT, und er leitet
ihn aus den KACHELN der Person ab -- nicht aus dem Seitenrecht (dann
haette DogFather auf der Agenturadresse den Knopf verloren, denn
oeffnen darf er die Seite, nur hat er dort keine Kachel dorthin) und
schon gar nicht aus dem Haus.

--- A5: anlegen, wo die Person steht -------------------------------
Filipe: „dieser buttion da soll nicht einen zu der seite aufgaben
fuehren sondern da in dieser seite die aufgaben erstellen und vergeben
koennen. plus man soll die aufgaben hier in dieser seite auch sehen."

Der Knopf war ein Link auf `aufgaben.html?neu=1`. Jetzt oeffnet er ein
Formular an Ort und Stelle. DREI FELDER, NICHT ZWOELF: Wer hier steht,
hat die Person schon gewaehlt; was fehlt, ist was, bis wann und ob
noch jemand mitmacht. Das grosse Formular auf dem Brett bleibt fuer
den Fall, dass man eine Aufgabe fuer irgendwen irgendwo anlegt -- zwei
vollstaendige Masken fuer dieselbe Sache waeren zwei Gelegenheiten,
eine davon zu vergessen.

Dazu die Aufgaben der gewaehlten Person, auf derselben Seite. Sie
kommen beim Auswaehlen und nicht auf Knopfdruck: Wer jemanden
durchgeht, will wissen, was bei ihm liegt.

Ohne Person ist der Knopf AUS statt weg -- sonst springt die Seite beim
Auswaehlen -- und der Satz daneben sagt, was fehlt.

Gemeldet wird, was der Server WIRKLICH gesetzt hat: `zuteilen` kann
eine Person weglassen (gesperrter Zugang). Wer das verschweigt, laesst
jemanden im Glauben, er habe drei Leute eingetragen.

--- EIN FUND AUF DEM EIGENEN BILDSCHIRMFOTO ------------------------
Die Bestaetigung „Clips vom Samstag schneiden steht jetzt bei Rieke."
stand in WARNROT -- `melde` schreibt immer in denselben Absatz, und
der heisst `.fehler`. Nicht schlimm und genau deshalb heimtueckisch:
Wer Bestaetigungen in Rot liest, sucht den Fehler, und wer sich daran
gewoehnt, ueberliest die echte Warnung. `melde` kennt jetzt eine gute
Nachricht; die Vorgabe bleibt „Fehler", damit die neun vorhandenen
Aufrufe nicht stillschweigend umgefaerbt werden.

GEPRUEFT
pruef-bewerbung-aufgaben 84/0 (von 66) -- neu: die Reihenfolge nach
Eingang mit Gegenprobe gegen das Alphabet, und ein Abschnitt, der A5
und B6 am echten Bildschirm durchspielt (Knopf weg auf dem Brett, kein
Link mehr auf der Entwicklungsseite, Formular oeffnet dort, Aufgabe
steht sofort in der Liste darunter UND wirklich in der Liste des
Servers, Bestaetigung als gute Nachricht gekennzeichnet).

Gruen: pruef-entwicklung, pruef-aufgabenbrett, pruef-css-klassen,
pruef-formulare, pruef-struktur.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 19:09:16 +02:00
DogFatherGitandClaude Opus 5 43545e4acd A4: Bewerben statt selbst nehmen
Filipe, 22.09.2026: „die modis und linke hand sollen da nichts
uebernehmen koennen von aufgaben, ueberhaupt ueberall sollen die keine
aufgaben selber uebernehmen die ihnen nicht zugetragen sind. ich will
dass die sich fuer aufgaben bewerben koennen aber die rechte hand oder
dogfather muessen annehmen oder ablehnen koennen und das mit einem
kommentar als moeglichkeit sogar noch zum hinzufuegen."

ZWEI FRAGEN, DIE MAN AUSEINANDERHALTEN MUSS -- und das war der Schluessel:

    verteilen    eine Aufgabe an ANDERE geben
    entscheiden  bestimmen, wer sie am Ende macht

Sein Satz vom selben Tag („rechte hand linke hand und dogfather ...
koennen alle verteilen") widerspricht dem nicht, er beantwortet die
erste Frage. Die linke Hand verteilt, entscheidet aber nicht -- sie
bewirbt sich wie ein Modi. `entscheidetUeberAufgaben` steht neben
`darfAufgabenVerteilen`, und drei Stellen fragen ab jetzt dieselbe
Funktion.

DAS VERBOT HATTE DREI TUEREN, und die zweite und dritte waren beim
Planen nicht zu sehen:

  1. aus dem Pool „uebernehmen"  -- die offensichtliche
  2. beim Pool „annehmen"        -- dasselbe unter anderem Namen: Wer
                                    zusagt, nimmt sie den anderen weg.
                                    Bei „einzeln"/„mehrere" bleibt es
                                    erlaubt -- dort wurde sie ihm
                                    ZUGETRAGEN, und genau das Wort
                                    steht in seinem Satz.
  3. beim Verteilen sich selbst eintragen -- die linke Hand darf
                                    verteilen, haette sich also selbst
                                    nehmen koennen. Abgelehnt statt
                                    still gefiltert: Wer sich eintraegt
                                    und sich danach nicht findet, sucht
                                    den Fehler bei sich.

EIN FUND, OHNE DEN A4 GAR NICHT FUNKTIONIERT HAETTE
Die rechte Hand soll entscheiden -- und sah die Aufgabe nicht, um die
es ging. Gemessen an einer Pool-Aufgabe, die DogFather fuer zwei Modis
angelegt hat:

    DogFather    sieht sie    1 Bewerbung
    Modi         sieht sie    1 Bewerbung
    rechte Hand  SIEHT SIE NICHT (Liste leer)

Ihre Sichtregel sammelte Menschen mit einer TEAM_DOGI_ROLLE und fragte,
ob einer als Creator, Verantwortlicher oder Ersteller eingetragen ist.
Bei einer Pool-Aufgabe bleibt `verantwortlich_id` leer (das ist ihr
Sinn), und der Ersteller war DogFather -- der in dieser Liste nicht
steht. Alle drei Bedingungen liefen ins Leere.

Auf der Adresse von Team Dogi sehen die Haende jetzt alles. Das ist
zugleich sein Satz „sehen alle aufgaben". Die Haustrennung bleibt:
`sichtbar()` haengt fuer crew weiterhin `AND ohneAgentur(...)` davor.

WIE DIE BEWERBUNG GEBAUT IST
Kein zweiter Tisch, sondern ein weiterer Zustand derselben Zeile
(`beworben`). Die Frage „wie steht diese Aufgabe bei DIESEM Menschen"
wird dort schon beantwortet; eine zweite Tabelle haette zwei Wahrheiten
ueber dieselbe Beziehung.

Die Worte der Person (`grund`) und der Kommentar der Leitung
(`entscheid_text`) stehen in ZWEI Feldern. In dasselbe waere bequemer
und wuerde die Frage mit der Antwort ueberschreiben -- danach wuesste
niemand mehr, worum jemand gebeten hat. Dasselbe gilt, wenn eine
Bewerbung wegfaellt, weil jemand anders die Aufgabe bekommt: Der
Hinweis kommt in das Feld der Leitung, ihre Worte bleiben stehen.

Der Kommentar ist FREIWILLIG. Die Begruendung beim Ablehnen einer
zugeteilten Aufgabe bleibt Pflicht -- dort sagt jemand ab, der gefragt
wurde. Hier bittet jemand; ein „bitte" braucht keine Begruendung.
Filipes Wort ist „als moeglichkeit".

Die CHECK-Regel wurde ueber `checkListeErweitern` erweitert -- den Weg,
der seit dem 09.09. an einer Stelle steht, mit Sicherung vorher,
Spaltenliste aus PRAGMA und Indizes, die mitgehen.

UND EIN SATZ, DER NICHT MEHR STIMMTE
„Frei fuer 3 Leute — wer zuerst Zeit hat" war die Beschreibung des
Pools, solange sich jeder selbst bedienen durfte. Er sagt jetzt jedem,
was FUER IHN gilt.

GEPRUEFT
Neu: server/pruef-bewerbung-aufgaben.mjs, 66/0 -- die Regel selbst,
alle drei Tueren, der erlaubte Weg, die zwei Felder, das Zurueckziehen,
und ein Abschnitt am echten Bildschirm (ein Modi sieht „Ich bewerbe
mich" statt „Ich uebernehme das"; die rechte Hand sieht die Bewerbung
mit Annehmen und Ablehnen; die Bewerberin sieht KEINEN Block zum
Entscheiden -- sonst waere das Verbot einen Knopf weiter offen).

pruef-zuteilung auf die neue Regel umgestellt (sie hielt „Bea
uebernimmt sie" fest und wurde zu Recht rot) -- misst jetzt denselben
Effekt ueber den neuen Weg. Dazu gruen: pruef-aufgabenbrett,
pruef-meldungen, pruef-sicht, pruef-css-klassen.

ALTLAST, nicht von hier: pruef-rollen meldet einen Fehler an der
Kachel „Zu Team Dogi" (absolute Adresse). Mit `git stash` nachgemessen
-- vorher und nachher identisch.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 18:55:06 +02:00
DogFatherGitandClaude Opus 5 b79b75ab70 A3: Calls & Protokolle gibt es jetzt auch bei Team Dogi
Filipe, 22.09.2026: „ich will diese kachel vom workspace auch im team
dogi seite. ich will dass jeder immer nur seine eigenen sachen von
seinem kalender sieht mehr nicht. perfektioniere das bitte. jeder der
einen kalender hat soll auch sowas haben danke."

GEMESSEN, BEVOR GEBAUT WURDE:

    Rolle   Kacheln   Kalender   Calls
    admin      31       ja        NEIN
    hand       31       ja        NEIN
    linke      30       ja        NEIN
    modi       26       ja        NEIN
    gast       12       nein      nein

Die Community hat keinen Kalender. Sein Satz „jeder der einen kalender
hat" beschreibt die Lage also genau -- „alle bekommen es" waere falsch
gewesen.

ES IST EINE REGEL, KEINE VIERFACHE EINTRAGUNG. Hinter jeden Kalender
einer Liste kommt eine Calls-Kachel, in derselben Gruppe. Vier Stellen
von Hand zu pflegen waere die Stelle, an der es beim naechsten neuen
Rollenzuschnitt auseinanderlaeuft. Erkannt wird der Kalender am ZIEL,
nicht am Namen -- Namen sind im Haus schon gewandert, Ziele nicht.

„JEDER SIEHT NUR SEINE EIGENEN" GAB ES SCHON, seit dem 07.09.
(`termineSichtbar`). Es wird jetzt aber nicht mehr GELESEN, sondern am
laufenden Server ausprobiert: Zwei Leute legen je einen Call an und
sehen den des anderen nicht -- auch DogFather nicht. Wer als
Teilnehmer eingetragen ist, sieht ihn schon; das ist die Gegenprobe,
ohne die „niemand sieht etwas" auch bei einer kaputten Liste gruen
waere.

DER TON WAR EINE RECHNUNG UEBER DREI ANLAEUFE

  1. Ton 15, derselbe wie im anderen Haus. Als Zahl frei, auf dem
     BILDSCHIRM nicht: 0,0139 zu „Was ansteht", unter der Grenze 0,02.
  2. Ton 16, ausgerechnet als der entfernteste brauchbare. Die Pruefung
     kennt aber zwei Regeln mehr, die ich nicht beruecksichtigt hatte:
     Rohabstand >= 0,090 (er lag bei 0,0854) und Buntheit >= 0,12 (er
     lag bei 0,116). Und Ton 16 gehoert im anderen Haus zu
     „Start-Check" -- ihn umzufaerben haette dort eine Kachel
     veraendert, nach der niemand gefragt hat.
  3. Unter allen elf freien Toenen erfuellte KEINER alle drei Regeln.
     Eine 32. Kachel braucht einen 32. Ton. Also einen neuen gerechnet,
     additiv, ohne einen vorhandenen anzufassen:

         Ton 43  #027afb   Abstand 0,0925  Buntheit 0,212  Kontrast 4,63:1

     Es bleibt ein Blau -- die Kachel ist damit als dieselbe
     wiedererkennbar wie im anderen Haus.

EIN WIDERSPRUCH IM HAUS, DABEI GEFUNDEN
`tools/kachel-farbe-einzeln.mjs` suchte die Buntheit von 0,30 bis
herunter auf 0,04, `pruef-kachelfarben` verlangt mindestens 0,12. Das
Werkzeug lieferte fuer Ton 43 zuerst ein blasses #bcdbff (Buntheit
0,060) mit dem besten Abstand weit und breit -- und die Pruefung lehnte
es ab. Beide hatten recht; zwei Zahlen fuer dieselbe Regel in zwei
Dateien, die nichts voneinander wissen. Ein Werkzeug, dessen
Vorschlaege die Pruefung danach verwirft, ist schlimmer als keines --
man haelt das Ergebnis fuer fertig.

Die Schwellen stehen jetzt in tools/kachelton-regeln.mjs, und beide
Seiten lesen sie von dort.

NEU: server/pruef-calls-rudel.mjs, 32/0. Sie prueft die REGEL (Calls
genau dann, wenn Kalender -- und direkt dahinter, in derselben
Gruppe), dass Kachel und Zutrittsrecht zusammenpassen, und am
laufenden Server, dass jeder nur seine eigenen sieht.

pruef-kachelfarben 22/0, pruef-start-ansicht, pruef-willkommen,
pruef-struktur, pruef-treff, pruef-modi-checkliste gruen.

ZWEI ALTLASTEN DABEI GEFUNDEN, nicht von dieser Aenderung und noch
nicht behoben (beide vorher schon rot, nachgemessen mit `git stash`):
  pruef-kachelraster        3 Fehler (erwartet acht Community-Kacheln,
                            es sind zehn)
  pruef-jeder-hat-eine-seite 1 Fehler („fehlt: linke" -- die Rolle kam
                            dazu, die Pruefung nicht mit)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 15:15:00 +02:00
DogFatherGitandClaude Opus 5 7ccf904c3c Das Aufgaben-Formular: was aufklappt, bekommt jetzt auch Platz
Filipe, 22.09.2026, zum Bildschirmfoto: „wie scheisse sieht das aus,
verbesser das bitte." Zu sehen: „Anlegen" und „Abbrechen" lagen mitten
in der Personenliste.

GEMESSEN statt geraten, bei 1280 px mit aufgeklappter Liste:

    Zelle            Zeilen          Hoehe   Inhalt
    feld-verant      24px 44px          68      107
    feld-mehrere     43px 44px          87      261   <-- 174 zu viel

Jede Zelle des Formularrasters bekommt zwei Zeilen: Beschriftung oben,
Eingabe unten mit festen 44 px. Das ist richtig und der Grund, warum
alle Eingaben auf einer Linie sitzen (17.09.).

`feld-mehrere` ist aber keine Beschriftung mit Eingabe, sondern ein
Knopf mit einer Liste, die aufklappt. Ihr zweites Kind landet in der
44-Pixel-Zeile und laeuft heraus, sobald jemand sie oeffnet. Was
herauslaeuft, belegt keinen Platz -- also legt es sich ueber das
Naechste, und das Naechste sind die Knoepfe.

DIE MESSUNG HAT MICH VOR DEM NAHELIEGENDEN FEHLER BEWAHRT.
Erster Gedanke: „Zellen ohne eigene Eingabe brauchen die zwei Zeilen
nicht" -- `:has(> input, > select, > textarea)`. Die Messung sagt etwas
anderes: Von sieben Zellen haben SECHS ihre Eingabe nicht als direktes
Kind, weil der Auswahl-Baustein sie in ein <div> wickelt. Die Regel
haette fast das ganze Formular getroffen und genau die Ausrichtung
zerstoert, die sie schuetzen soll.

`aria-expanded` ist gemessen das einzige Merkmal, das nur bei dieser
Zelle steht -- und es ist das inhaltlich richtige: Es sagt „dieser
Bereich kann groesser werden". Etwas, das groesser werden kann, darf
keine feste Hoehe haben.

UND DIE PRUEFUNG, DIE ES HAETTE FINDEN MUESSEN
pruef-formulare war gruen -- sie klappt das Feld nie auf. Ein Zustand,
der nie hergestellt wird, kann nicht gemessen werden.

Neuer Abschnitt: Jedes Element mit `aria-expanded` im Formular wird
geoeffnet, danach darf keine Rasterzelle mehr Inhalt haben, als sie
hoch ist. Nicht diese eine Stelle, sondern die Eigenschaft -- damit
faellt auch die naechste auf, die es noch gar nicht gibt.

ZWEI ANLAEUFE DABEI WAREN FALSCH, und der zweite war der gefaehrliche:
  1. `scrollHeight` der Zelle meldete elf Zellen als kaputt, die alle
     in Ordnung sind: Der Hinweis unter einem Feld haengt seit dem
     17.09. absichtlich absolut darunter. Eine Warnung, die bei
     richtigem Verhalten anschlaegt, wird abgeschaltet.
  2. Nur die direkten Kinder im Fluss -- das war gruen, AUCH MIT DEM
     ECHTEN FEHLER. Nachgemessen mit zurueckgenommener Behebung:
     immer noch gruen. Das Raster staucht das Kind auf die feste
     Zeilenhoehe, das Kind bleibt also brav in der Zelle; was
     herauslaeuft, ist der Inhalt darin.

Jetzt misst sie in die Tiefe (ohne Teilbaeume unter absolut gesetzten
Elementen und ohne eigene Rollbereiche) und ist beidseitig belegt:
  mit Behebung    -> gruen
  ohne Behebung   -> FEHL „feld-mehrere: Inhalt reicht bis 169 px,
                     Zelle ist 87 px hoch"
Dazu eine Gegenprobe, die eine Zelle kuenstlich einklemmt.

Ueberlappungen im Formular: von 12 auf 4 -- und die vier sind Absicht
(der echte <select> liegt unsichtbar ueber seinem Knopf).

pruef-formulare, pruef-aufgabenbrett, pruef-css-klassen gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:58:45 +02:00
DogFatherGitandClaude Opus 5 beb6bc2d62 Die Willkommens-Kachel: bunte Punkte statt Balken
Filipe, 22.09.2026: „Ja ist cool mit den ganzen farben, aber ich finde
das passt nicht so gut zum eigentlichen Stil. Würde glaube ich schöner
wirken, wenn die Farben als bunte Punkte auf der gesamten Kachel wären,
vielleicht auch eng an eng und größere und kleinere Punkte, damit es vom
Stil her die Punkte der anderen Kacheln aufgreift, aber trotzdem extrem
heraussticht. Das mit den Farben ist mega. Aber irgendwie passen die
balken/streifen nicht."

ER HAT DEN STIL DES HAUSES GENAUER GELESEN ALS ICH. Jede Kachel der
Startseite ist ein Sternenfeld -- nahe Sterne mit Hof, mittlere Sterne,
ferner Staub, dazu ein schraeger Schleier. Steht so in start.css unter
"NAHE STERNE", seit dem 17.09. Die Streifen waren die einzige Flaeche
weit und breit mit harten Kanten: richtig in der Farbe, falsch in der
Form.

Jetzt 93 Punkte in drei Groessen, jede Groesse einmal alle 31 benutzten
Kacheltoene. Dieselbe Bauart wie ueberall, nur bunt statt weiss -- die
Kachel greift den Stil auf und ist trotzdem die einzige, deren Sterne
Farbe haben.

ABGELEITET, NICHT EINGETRAGEN: Punktzahl, Rasterweite und Reihenfolge
folgen aus der Anzahl der Farben. Der Sprung durch die Farbliste wird
so gewaehlt, dass er teilerfremd zur Laenge ist -- sonst laegen
Nachbarpunkte auf benachbarten Farbwinkeln und es entstuenden Flecken
aus fast gleichen Toenen. Eine feste Zahl wie 7 versagt still, sobald
die Anzahl ein Vielfaches davon ist. Die drei Rasterweiten (197/131/83)
haben bewusst keinen gemeinsamen Teiler; sonst faellt das Feld
regelmaessig aufeinander und man sieht ein Muster.

Der Zufall der Streuung ist ein fester: `Math.random` haette bei jedem
Lauf einen anderen Block ergeben, und jeder Vergleich "hat sich etwas
geaendert?" waere wertlos.

VIER ANLAEUFE FUER DEN LESBAREN TEXT, drei davon falsch:

1. Der Lesesaum der Streifenfassung blieb stehen. Gemessen: 8,27:1 bei
   einer Grenze von 4,5. Das war kein Saum, das war ein Deckel -- er
   verschluckte die untere Haelfte der Kachel, und genau dort sollten
   Punkte sein ("auf der gesamten kachel"). Zurueckgenommen.
2. Danach sass auf dem Handybild ein heller Punkt mitten unter dem Wort
   "gibt". Die Messung sagte weiter 8,2:1 und hatte recht: Sie mittelt
   ueber die Textflaeche. Ein Punkt hinter einem duennen Buchstaben
   verschwindet in diesem Mittel -- im Auge nicht.
3. Also ein dunkler Teich im Kachelhintergrund, 400 px breit. Auf dem
   grossen Bildschirm sass er richtig; die Kachel auf dem Handy ist
   aber selbst nur 366 px breit, und er hat fast alle Farben
   geschluckt. Eine Pixelzahl, die auf einem Geraet passt, ist auf dem
   naechsten falsch.
4. Richtig: der dunkle Grund haengt am TEXT, nicht an der Kachel. Dann
   ist er immer genau so breit wie das, was er lesbar machen soll --
   auf jedem Geraet, ohne eine einzige Schwelle. Und der Verlauf darin
   laeuft vor allen vier Kanten aus, sonst sieht man das Rechteck und
   es steht eine Karte in der Karte.

Nebenbei die alte Falle wieder getreten und behoben: Ein Backtick in
einem Kommentar, der INNERHALB einer Vorlagenzeichenkette steht,
beendet sie. Steht seit heute als Hinweis daneben.

Gemessen: Willkommen 8,36:1 (Grenze 4,5), schlechteste Kachel im Haus
unveraendert "Aufgaben" mit 4,80:1. pruef-kachelfarben 22/0,
pruef-willkommen, pruef-buehne (Kontrast an echten Bildpunkten, alle
Seiten) -- alle gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:43:56 +02:00
DogFatherGitandClaude Opus 5 25de892fdb screen5: Aus dem Treff wird das Rudel, aus der Zentrale die IrrenAnstalt
Filipe, 22.09.2026: "ersetze die zentrale durch, Die IrrenAnstalt.
genau so geschrieben bitte. und alles was treff heißt oder wo treff
steht soll durch Rudel ersetzt werden bitte."

Die Schreibweise "IrrenAnstalt" mit grossem A in der Mitte ist so
gewollt. Das steht als Hinweis daneben, damit sie beim naechsten Mal
niemand "korrigiert".

WAS UMBENANNT WURDE: alles, was jemand LIEST -- Kachelnamen,
Ueberschriften, Markenzeilen, Saetze, Meldungen, Aufgabenvorlagen.
116 Zeilen in 42 Dateien.

WAS BLEIBT: Adressen (treff-regeln.html), Bezeichner (TREFF_ROLLEN),
Datenbankwerte (bereich = 'treff'), Abfrageteile (b=treff). Eine
Adresse umzubenennen bricht jedes Lesezeichen, und ein Datenbankwert
umzuschreiben waere eine Umstellung ohne Gegenwert. Dieselbe
Entscheidung wie heute frueh bei Dogi-Media, wo material.html auch
material.html geblieben ist.

DREI GRAMMATIKFEHLER IM EIGENEN ENTWURF, alle vor dem Ausliefern
gefunden -- ein blindes Ersetzen reicht hier nicht:

1. "der Treff" ist maennlich, "das Rudel" saechlich. Ohne Tabelle
   waere ueberall "Der Rudel" gestanden. (Und "Treffer" waere zu
   "Rudeler" geworden, "Treffen" zu "Rudelen" -- deshalb greift die
   Regel nur bei Wortgrenze und nie vor einem Kleinbuchstaben.)

2. BINDESTRICH-ZUSAMMENSETZUNGEN. In "der Treff-Chat" gehoert der
   Artikel zu "Chat", nicht zu "Treff". Der erste Durchlauf machte
   daraus "das Rudel-Chat", "das Rudel-Kacheln" und "ein Rudel-Raum".
   Jetzt greift die Artikelregel nur, wenn das Wort allein steht.

3. GESCHUETZTE LEERZEICHEN. In den Markenzeilen steht
   `Der&nbsp;Treff`, damit die zwei Woerter nicht umbrechen. Das
   Muster hat daran vorbeigegriffen: "Der&nbsp;Rudel", auf fuenf
   Seiten. Jetzt wird das Trennzeichen mitgefasst und unveraendert
   wieder eingesetzt.

Gefunden wurden alle drei, weil jede einzelne der 116 Zeilen vor dem
Schreiben als ALT/NEU ausgegeben und gelesen wurde -- und danach
gezielt nach falschen Artikeln gesucht ("den Rudel", "der Rudel",
"einen Rudel"). Uebrig blieben sechs Treffer, und die sind alle
richtig: "einen Rudel-Raum", "der Rudel-Chat", "den Rudel-Regeln" --
Zusammensetzungen, bei denen der Artikel zum letzten Wort gehoert.

UND ZWEI PRUEFUNGEN, die die Umbenennung nicht mitbekommen haetten:
`/Treff/.test(...)` und `/Treff/i.test(...)`. Ein regulaerer Ausdruck
ist keine Zeichenkette -- sie haetten ab sofort nach einem Wort
gesucht, das die Seite nicht mehr sagt, und waeren still rot geworden,
ohne dass etwas kaputt ist.

Geprueft, alle gruen: pruef-treff, pruef-treffchat,
pruef-deutsche-texte, pruef-uebernahme, pruef-crew-adresse,
pruef-willkommen, pruef-wege-nach-draussen, pruef-vorlagen,
pruef-start-ansicht, pruef-struktur.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:25:56 +02:00
DogFatherGitandClaude Opus 5 091c5f9cd9 screen6: Bei DogFather steht jetzt eine Krone
Filipe, 22.09.2026: "bei dogi soll kein husky sein sondern eine krone.
die auch extrem auffaellt damit man den unterschied extrem erkennt."

WARUM ER RECHT HAT: Drei der fuenf Kacheln auf der Anmeldewand trugen
denselben Husky -- DogFather, rechte Hand, linke Hand. Drei gleiche
Zeichen untereinander sind kein Zeichen mehr, sondern Tapete; man
liest dann nur noch die Namen, und dafuer braucht es kein Bild.

WARUM GOLD: Die anderen vier Zeichen liegen alle im Blaubereich
(Husky silbern, Pfote blau, Community blaugrau). Eine Krone im selben
Farbkreis waere eine andere Form, aber kein anderer Eindruck. Gold ist
der einzige Hauston, der hier noch nicht vergeben ist -- und der, den
eine Krone ohnehin hat. Es sind vorhandene Hausfarben und kein
Leuchten: Der Unterschied kommt aus Form und Farbkreis, nicht aus
Helligkeit. Die Wand bleibt augenschonend.

WAS SIE NICHT HEISST: Der Untertitel bleibt "Ueberblick &
Entscheidungen" -- eine AUFGABE, kein Rang. Die vier anderen Rollen
behalten ihre Zeichen unveraendert, an den Texten aendert sich nichts.
Das Zeichen sagt "das ist die Rolle, die du suchst", nicht "der steht
ueber den anderen".

EIN FUND BEIM BAUEN: `.rolle__zeichen` faerbt jedes Rollenzeichen mit
dem Ton der Rolle ein -- gedacht fuer gezeichnete Striche. Der Husky
(ein Foto) und die Pfote (eigene Verlaeufe) merken davon nichts, weil
eine Flaeche ohne `stroke` die Regel stillschweigend ignoriert. Die
Krone haette sie sichtbar abbekommen: ein blauer Rand um eine goldene
Krone. Ausdruecklich abbestellt.

DIE PRUEFUNG HIELT DIE ALTE VORGABE FEST und wurde zu Recht rot: Sie
verlangte seit dem 10.09., dass die rechte Hand DASSELBE Zeichen
traegt wie DogFather. Beide Fassungen geben eine Anweisung von Filipe
wieder; dazwischen ist die linke Hand dazugekommen.

Statt die Paarliste umzuschreiben -- die beim naechsten Umbau wieder
danebenlaege -- prueft sie jetzt die Eigenschaft, um die es geht: Jede
Kachel traegt ein Zeichen, DogFathers kommt genau einmal vor, es ist
auf der Seite auch definiert (ein `use` auf eine vertippte Kennung
zeichnet lautlos nichts), und die zwei Haende lesen sich weiter als
Paar. Mit Gegenprobe.

pruef-crew-adresse 153/0 (von 148), pruef-css-klassen grün.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:19:30 +02:00
DogFatherGitandClaude Opus 5 a8e49496ad Der Installieren-Knopf war nie zu sehen — jetzt schon
Filipe, 22.09.2026: "und nochmal, ich will einen installieren button.
damit die leute es viel einfacher haben die seite auf dem pc oder auf
dem handy zu installieren!!! bitte das hab ich auch schon paar mal
gefragt. mach das es ist seeeeeeeehr wichtig."

Er hatte recht, und der Knopf war seit dem 20.09. gebaut. Er konnte
nur nie erscheinen. ZWEI URSACHEN, beide ausserhalb dessen, was
geprueft wurde:

1. DER SERVICE WORKER LIEF NIE. Er wurde ausschliesslich in glocke.js
   angemeldet -- also erst, wenn jemand Benachrichtigungen ERLAUBT.
   Auf Filipes Rechner stehen sie auf "Vom Browser blockiert"; das
   steht sogar in seiner Kopfleiste auf dem Bildschirmfoto von heute
   frueh. Ohne Service Worker macht Chrome kein Installationsangebot.

2. UND AUCH MIT WAERE ES NICHT GEGANGEN: Chrome verlangt einen Service
   Worker MIT `fetch`-Zuhoerer. Dieser hatte keinen.

Ohne Angebot kommt `beforeinstallprompt` nie, und der Knopf bleibt
`hidden`. Fuer immer.

WAS SICH GEAENDERT HAT

- Der Service Worker wird jetzt auf JEDER Seite angemeldet, unabhaengig
  von Benachrichtigungen. Das gehoert zum Installieren, nicht zur
  Glocke.
- sw.js bekommt einen `fetch`-Zuhoerer, der NICHTS ablegt. Das
  Versprechen im Kopf der Datei ("bewusst ohne Zwischenspeicher, der
  Workspace liegt hinter einer Anmeldung") bleibt damit wortwoertlich
  gueltig: Er reicht Seitenaufrufe durch und baut nur dann selbst eine
  Antwort, wenn das Netz weg ist. Keine Serverantwort wird aufgehoben.
- Der Knopf zeigt sich, sobald der Browser installieren KANN, statt
  erst nach dem Angebot. Geprueft wird die Faehigkeit
  (`'onbeforeinstallprompt' in window`), nicht der Name des Browsers.
- DIE ANMELDEWAND BEKOMMT IHN AUCH. Sie hat keine Kopfleiste und
  deshalb bisher gar kein Angebot -- dabei ist sie die Seite, auf der
  jeder zuerst landet. Genau die Leute, um die es Filipe geht.
- Dafuer steht der Knopf jetzt in einer eigenen Datei
  (assets/js/installieren.js) statt in kopf.js, das die Wand nicht
  laedt. Und sein Stil in gate.css statt in module.css -- vierter Fall
  derselben Art nach .knopf-still, dem Schalter und .feld-hinweis.
- Ohne `nachfrage.js` (also auf der Wand) erklaert er den Weg als
  Absatz unter sich. Der erste Entwurf rief `window.frageNach?.()`
  auf: Auf dem iPhone steht der Knopf dort von Anfang an da, und er
  haette beim Antippen stumm nichts getan.
- Der Aufruf haengt nicht mehr an der Reihenfolge der Skriptzeilen.
  chat.html und leistung.html laden kopf.js OHNE `defer`, dort waere
  installieren.js immer zu spaet gekommen -- zwei von 37 Seiten ohne
  Knopf, ohne Meldung.
- Chromes Manifest-Warnung zum `share_target` behoben (enctype).

WARUM DIE PRUEFUNG DAS NICHT GEFUNDEN HAT -- und was jetzt anders ist

Sie war gruen, die ganze Zeit. Sie hat `beforeinstallprompt` SELBST
zugestellt und gemessen, ob der Knopf darauf reagiert. Die eine Frage,
auf die es ankam -- "bietet der Browser es ueberhaupt an?" -- hat sie
nie gestellt.

Jetzt fragt sie Chrome direkt (`Page.getInstallabilityErrors`, sein
eigenes Urteil) und misst die Voraussetzungen statt der Reaktion:
laeuft ein Service Worker, OBWOHL Benachrichtigungen auf "denied"
stehen; hat sw.js einen fetch-Zuhoerer; legt er wirklich nichts ab;
steht der Knopf auf der Wand und tut er dort auch etwas.

Gemessen, mit Benachrichtigungen auf "denied":
  Service Worker: activated
  Chromes Urteil: kein einziges Hindernis
  Manifest:       nichts beanstandet
  Knopf:          124x45 px, sichtbar, genau einer

pruef-installieren 29/0 (von 14). Dazu gruen: pruef-css-klassen,
pruef-struktur, pruef-crew-adresse, pruef-start-ansicht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:16:03 +02:00
DogFatherGitandClaude Opus 5 774eeee3e5 Die Umstellung von Dogi-Media merkt jetzt, wenn sie nicht durchkam
BEIM AUSLIEFERN AUFGEFALLEN, NICHT BEIM BAUEN.

Nach Neustart und `git pull` standen die zwei neuen Spalten noch nicht
in der echten Ablage -- die Umstellung laeuft erst beim ersten
angemeldeten Zugriff. Das ist in Ordnung. Beim Nachsehen, WARUM sie
noch nicht da waren, fiel aber der eigentliche Mangel auf:

`bereit = true` stand UNBEDINGT hinter der Schleife, und der Fehler des
`ALTER TABLE` daneben ging still in die Konsole. Ein einziger
misslungener Versuch -- Datei gesperrt, Platte voll -- haette die
Umstellung damit fuer immer als erledigt vermerkt. Danach scheitert
JEDE Liste an `SELECT ... m.gilt_ab`, und zwar fuer alle, mit einem 503
und dem Satz "gerade nicht verfuegbar", der nirgends sagt, woran es
liegt. Bis zum naechsten Neustart.

Jetzt wird nach der Schleife nachgezaehlt. Fehlt etwas, wird geworfen
statt notiert, und der Vermerk bleibt aus -- der naechste Aufruf
versucht es also wieder. Ein Aufruf, der mit einer klaren Meldung
scheitert, ist besser als hundert, die raetseln.

AUF EINER KOPIE DURCHGESPIELT, nicht an den echten Daten erlebt:
Sicherung der laufenden Ablage gezogen (`.backup`, integrity_check ok,
Zeilenzahlen gegen live geprueft), darauf beide ALTER ausgefuehrt. Die
vorhandene Zeile ueberlebt mit leerem Fenster, die Listenabfrage des
Servers laeuft wortgleich durch, integrity_check danach ok.

pruef-material 159/0 (von 155). Neu ist eine Gegenprobe, die den
halb-umgestellten Zustand herstellt -- genau den, der vorher
"erledigt" geheissen haette -- und eine Zeile, die die Spalten in der
laufenden Ablage nachzaehlt statt sie anzunehmen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 14:03:11 +02:00
DogFatherGitandClaude Opus 5 fc823240ab screen4: Dogi-Media — bearbeiten, entfernen, von wann bis wann
Filipe, 22.09.2026: "wenn wir in der kategorie material was hochladen
will ich dass die rechte und linke hand es auch bearbeiten und loeschen
koennen. dogfather auch fals es ein fehler gab. ... uebrigens ersetz das
wort material durch Dogi-Media. und mach kategorien welche sind benutzt
welche nicht welche sind noch offen, welche laufen von wan bis wann."

WAS JETZT GEHT
- Rechte Hand, linke Hand und DogFather bearbeiten und entfernen jedes
  Stueck, nicht nur ihr eigenes. Bearbeitet wird Text und Zeitfenster,
  nicht die Datei: Sonst zeigte dieselbe Nummer etwas anderes als das,
  was sich jemand gerade angesehen hat.
- Ein vergebenes Stueck bleibt unberuehrt (409). Wer es genommen hat,
  hat sich auf diesen Text verlassen.
- Vier Zustaende, gerechnet statt gespeichert: jetzt frei, kommt noch,
  abgelaufen, schon benutzt. Die Kategorieleiste zeigt zu jedem die
  Anzahl aus den echten Daten und filtert BEIDE Listen.
- "Material" heisst ueberall "Dogi-Media", der Dateiname bleibt.

DREI FEHLER AUS DEM EIGENEN ENTWURF, ALLE VOR DEM AUSLIEFERN GEMESSEN

1. `tagLokal()` ohne Argument gab "NaN-NaN-NaN" zurueck -- eine
   Zeichenkette, die aussieht wie ein Datum. Im Vergleich gewinnt das N
   gegen jede Ziffer, also galt JEDES Stueck mit Enddatum vom ersten Tag
   an als abgelaufen, und "Kommt noch" gab es nie. Kein Absturz, keine
   Meldung. Die drei Kopien der Funktion waren hier auseinandergelaufen;
   alle drei haben jetzt die Vorbelegung und werfen bei einer Zahl, die
   keine ist.
2. `frageNach` liefert bei einer reinen Rueckfrage `true`, nicht
   `{ ok: true }`. Der Entwurf prueft auf `erg?.ok` -- "Entfernen" waere
   ein Knopf gewesen, der nichts tut.
3. Drei erfundene Klassennamen (`knopf--leise`, `m-kat__knopf`,
   `m-karte__weg-knopf`) statt der vorhandenen des Hauses. Jetzt
   `.knopf-still`, `.knopf-still--warn` und die Filterleiste `.filter`.

EIN FUND IM BESTAND, ZWEI WOCHEN ALT

In start.css fehlten an einer Stelle die zwei Zeichen, die einen
Kommentar schliessen. CSS-Kommentare schachteln nicht: Der Block lief
bis zum naechsten Abschluss weiter und verschluckte `.kacheln {`; die
Fehlerbehebung des Browsers nahm danach auch die Regel `.kachel` mit.
In Chromium gemessen, beide Fassungen nacheinander: 738 statt 740
Regeln.

Der Entwurf, der dadurch nie gewirkt hat, ist NICHT wiederhergestellt
worden: Seine Flaeche mischte den Kachelton mit 30/11/3 Prozent ein --
pruef-kachelfarben fiel sofort von 36,5 % auf 4,1 % angekommene Farbe,
und 31 Toene sahen gleich aus. Das ist das Gegenteil dessen, was am
22.09. verlangt war. Er ist geloescht, mit dem Grund daneben. Offen
bleibt eine Frage an Filipe, keine Entscheidung von mir: zu demselben
Entwurf gehoerte ein schmaleres Kachelraster (fuenf bis sechs statt
drei pro Reihe). Das aendert das Aussehen der Startseite sichtbar und
bleibt deshalb, wie es ist.

GEMEINSAME BAUSTEINE AUS DEN SEITENDATEIEN GEHOLT
`.filter` stand Zeichen fuer Zeichen doppelt in dateien.css und
bereich.css, `.feld-hinweis` in aufgaben.css und leistung.css (und die
zwei waren schon auseinandergelaufen). Dogi-Media war jeweils die
dritte Seite, die sie braucht, und laedt keine davon. Derselbe Fehler
wie damals bei .knopf-still und beim Schalter -- jetzt in gate.css
bzw. start.css.

GEPRUEFT
pruef-material 155/0 (von 126, neu: Zeitfenster, Bearbeiten, Entfernen,
Rechte in der Liste und ein Abschnitt am echten Bildschirm mit Browser).
pruef-css-klassen um eine Pruefung erweitert, die genau den
start.css-Fehler findet -- mit sieben Gegenproben, darunter der echte
Fall. pruef-kachelfarben 22/0, pruef-start-ansicht, pruef-struktur,
pruef-meldungen, pruef-zeitraum, pruef-content, pruef-serien 69/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 13:59:55 +02:00
DogFatherGitandClaude Opus 5 fe1dad48e5 screen1: Wohin ein geholtes Video gelegt wird, darf man waehlen
Filipe: "ich will das wenn man da video holt das man auch aussuchen
kann in welcher account es unten angezeigt werden soll."

Bis heute entschied allein der Link: kanalVonHandle liest den Account
aus der TikTok-Adresse, und dort landete das Video. Das ist gut
geraten, aber es IST geraten -- ein Ausschnitt vom Hauptkanal gehoert
oft unter "Clips", und seit dem 21.09. hat jeder Account seine eigene
Spalte, in der das sichtbar wird.

DIE SCHRANKE BLEIBT UNANGETASTET. Der ABSENDER muss weiterhin einer
der drei eigenen Kanaele sein; gewaehlt wird nur die SPALTE. Sonst
waere aus einer Ablagehilfe ein Loch fuer fremde Inhalte geworden --
die Pruefung haelt genau das fest ("ein fremder Absender kommt auch
MIT Wahl nicht herein", 403).

Ohne Angabe bleibt alles wie bisher. Das ist der haeufigste Fall und
soll keinen zusaetzlichen Handgriff kosten; die Vorgabe heisst "Aus
dem Link erkennen".

ZWEI FUNDE BEIM PRUEFEN
  - Die Antwort meldete `auskunft.kanal` -- also das ERKANNTE, nicht
    das, wohin der Eintrag wirklich ging. Seit beides auseinanderfallen
    kann, haette die Seite "DogFather" gemeldet, waehrend das Video
    unter "Clips" steht.
  - `coverAbrufe === 3` in pruef-video war eine Rechnung von dem Tag,
    an dem die Pruefung drei Videos anlegte. Der neue Abschnitt legte
    vier weitere an, und die Zeile wurde rot, ohne dass etwas kaputt
    war. Gemeint war nie eine Summe, sondern eine DIFFERENZ: holt
    derselbe Link ein zweites Mal? Das bleibt richtig, egal wie viele
    Videos davor liefen.

Die Wahl steht UNTER der Zeile, nicht darin: Am 21.09. hat genau so
ein drittes Element in derselben Reihe das Chat-Eingabefeld auf einen
Buchstaben zusammengedrueckt. Am Bildschirm gemessen (1044 px).

Gemessen: pruef-video 71/0 (vier neue Aussagen samt Gegenprobe, dass
ohne Wahl weiterhin der Link entscheidet), pruef-highlights 31/0
(fuenf neue am echten Bildschirm), pruef-meldungen 8/0, pruef-teilen
27/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 13:25:28 +02:00
DogFatherGitandClaude Opus 5 1a7d074e94 Auf dem iPhone trug Team Dogi das Zeichen der Agentur
DIE ZWEITE HAELFTE EINER ENTSCHEIDUNG VOM 10.09.2026
  Der Block, der /workspace/app.webmanifest auf crew.webmanifest
  umbiegt, begruendet sich selbst so: "Sonst hiesse die App auf dem
  Startbildschirm eines Modis 'Creator Workspace' und traege das
  Zeichen mit der Chili -- die zu Spicy Media gehoert, nicht zu
  ihnen."

  Genau das passierte trotzdem -- auf dem iPhone. Android nimmt das
  Symbol aus dem Manifest (crew-192.png, richtig). iOS Safari nimmt es
  NICHT von dort, sondern aus <link rel="apple-touch-icon">, und diese
  Zeile steht in jeder HTML-Datei auf workspace-180.png.

  Gemessen: crew-180.png und workspace-180.png sind verschiedene
  Dateien (30 899 gegen 34 850 Byte). Ein Modi mit iPhone bekam die
  Chili auf den Startbildschirm, derselbe Modi mit Android das richtige
  Zeichen. So etwas faellt beim Ansehen nie auf -- man braeuchte beide
  Geraete nebeneinander.

  Behoben mit derselben Loesung wie beim Manifest: umbiegen an EINER
  Stelle, statt in 37 Dateien eine zweite Zeile zu setzen. Wer eine
  Seite anlegt, schreibt weiterhin workspace-*.png und bekommt auf
  crew. trotzdem das richtige Symbol.

  ABGELEITET, NICHT AUFGEZAEHLT: Umgebogen wird nur, wo es die
  Crew-Fassung wirklich gibt -- gemessen sind das 32, 180, 192, 512 und
  die beiden maskable. workspace-1024.png (TikTok) hat keine und bleibt
  unangetastet; eine kuenftige Groesse kommt von selbst dazu, sobald
  jemand die Datei anlegt.

DREI BEFUNDE VON pruef-struktur, alle aus meiner eigenen Arbeit
  - material.html und willkommen.html hatten weder theme-color noch
    apple-touch-icon. Auf dem iPhone waere das Startbildschirm-Symbol
    ein Bildschirmfoto der Seite gewesen, auf Android die Leiste weiss.
    Beide binden jetzt app.webmanifest statt crew.webmanifest direkt --
    die Adresse biegt es um, und zwei Stellen laufen sonst auseinander.
  - 20 tote CSS-Regeln (.b-analyse*) in entwicklung.css. Am 22.09.
    wurde der Block "Resuemee je Frage" aus dem Skript entfernt, die
    Gestaltung blieb stehen. Das ist nicht nur Ballast auf jeder Seite,
    sondern eine Falle: Wer spaeter .b-analyse im CSS findet, haelt den
    Block fuer lebendig. Vor dem Entfernen geprueft, dass im Bereich
    keine fremde Klasse steht.

EIN RUECKSTAND VOM 21.09. NACHGETRAGEN
  pruef-crew-adresse erwartete vier Rollenkacheln auf der Wand; seit
  die linke Hand dazukam (Commit 21793b6) sind es fuenf. Die Pruefung
  war seitdem rot an einer Stelle, an der NICHTS kaputt war -- und die
  Zeile daneben ("so viele, wie es Rollen auf der Wand gibt") war die
  ganze Zeit gruen und hat den Fehler damit verdeckt.

Gemessen: pruef-crew-adresse 148/0 (war 147/1, neu: vier Aussagen zum
Startbildschirm-Symbol samt Gegenprobe, dass die Agenturadresse
unveraendert bleibt und Groessen ohne Crew-Fassung nicht umgebogen
werden), pruef-struktur 35/0 (war 32/3), pruef-css-klassen 30/0,
pruef-befinden 116/0, pruef-willkommen 67/0, pruef-installieren 14/0,
pruef-textform 50/0, pruef-zwischenspeicher 27/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 13:14:19 +02:00
DogFatherGitandClaude Opus 5 80dee4d0c8 Highlights nach vorn, kraeftige Chatfarben, alle Farben in einer Kachel
screen1 -- HIGHLIGHTS AUF ANSCHLAGBRETTS PLATZ
  Kein Tausch, sondern ein Aufruecken: Highlights nimmt die Stelle,
  alle anderen wandern eine weiter. Inhaltlich stimmt das auch --
  was die Leute selbst gemacht haben, steht vor dem, was ihnen
  angesagt wird.

screen2 -- DIE CHATFARBEN SIND GERECHNET, NICHT GEGRIFFEN
  Gemessen, was drinstand: Buntheit 0,002 bis 0,048, im Mittel 0,028
  -- auf dem Bildschirm zwoelf Grautoene. Das lag nicht an fehlendem
  Mut, sondern an der Fusszeile der Blase: Sie stand auf der leisen
  Hausschrift, und gegen die darf die Flaeche kaum Farbe haben.

  Deshalb ZUERST die Schrift (--blase-text/--blase-leise, eigene
  Farben der Blase), DANN die Flaeche. Andersherum waere es der
  Fehler vom selben Vormittag gewesen, als 27 von 31 Startkacheln
  unlesbar wurden.

  tools/chat-kacheln-rechnen.mjs liest beide Schriftfarben aus dem
  CSS und rechnet daraus die hellste Flaeche, die sie noch tragen.
  Ergebnis: Buntheit 0,072 bis 0,268, alle zwoelf auf DERSELBEN
  Leuchtdichte -- also exakt demselben Kontrast (7,02 bis 7,13:1).

  Zwei Anlaeufe waren falsch und stehen im Werkzeug begruendet:
    - hoechste Buntheit nehmen, dann Kontrast pruefen. Musste
      scheitern: gesaettigtes Gelb ist bei gleicher empfundener
      Helligkeit viel heller als Blau.
    - gleiche OKLab-Helligkeit statt gleicher Leuchtdichte. Das
      Versprechen der zwoelf lautet "ueberall gleich gut lesbar",
      und Lesbarkeit haengt an der Leuchtdichte, nicht am Eindruck.

  WER NICHTS EINSTELLT, BEKOMMT TROTZDEM EINE FARBE. Gemessen an der
  Live-Datenbank hatten vier von fuenfzehn eine gewaehlt -- der Chat
  war fuer alle anderen einfarbig. Jetzt vergibt der Server einen der
  elf bunten Toene aus der Personennummer, stabil. Schrittweite 4:
  elf ist prim, also laufen alle Toene durch, und vier Schritte sind
  131 Grad im Farbkreis -- aufeinanderfolgende Nummern landen so weit
  auseinander wie moeglich. Mit id % 11 sassen zwei Nachbarn im
  selben Gespraech magenta und rot nebeneinander.

  Niemand verliert seine Wahl: veilchen, ziegel und moos sind die
  drei gewaehlten und behalten ihren Farbbereich.

  Dazu: Blasen mit 22px runden Kanten (nur die Ecke zur Person bleibt
  spitz -- sie sagt, wer spricht), Lichtsaum oben innen, weicher
  Schatten. Der Name hell und fett mit Rollenpunkt davor; er stand
  auf leisem Grau mit 85 Prozent Deckung und war der schwaechste Text
  der Seite, ausgerechnet der, der sagt, wer spricht.

  ZWEI REGELBLOECKE FUER DIESELBE BLASE ZUSAMMENGELEGT. Der untere
  gewann und hat an einem Tag zweimal Schaden angerichtet: Er stellte
  die runden Kanten auf 16px zurueck (die Aenderung waere wirkungslos
  ausgeliefert worden), und er mischte 26 Prozent Akzentfarbe in die
  eigene Blase -- die hatte damit eine Farbe, die in CHAT_KACHELN
  nicht vorkommt und die die Kontrastpruefung nie angesehen hat.

screen3 -- ALLE FARBEN DES HAUSES IN EINER KACHEL
  tools/kachel-regenbogen.mjs leitet die 31 benutzten Toene ab
  (bereicheFuer/zusatzBereicheFuer ueber alle Rollen und beide
  Haeuser) und schreibt daraus einen Streifenverlauf mit harten
  Kanten -- "nicht gemischt" war die eigentliche Ansage. Ein Verlauf
  ergaebe Zwischentoene, die es im Haus nicht gibt.

  Gegen einen deckenden Grund gemischt, nicht gegen --flaeche: Die
  ist halbdurchsichtig, und durch 31 schmale Baender schien das
  Buehnenbild -- sie verloren genau das, wofuer sie da sind.

  Der Lesesaum ist staerker als auf den anderen Kacheln, und zwar
  gemessen: Mit deren Werten kam der Text auf 4,45:1, fuenf
  Hundertstel unter der Grenze. Gefunden hat das pruef-kachelfarben,
  nicht der Blick -- 4,45 gegen 4,50 sieht man nicht.

pruef-buehne -- DIE ZAHL GEHOERT IN DIE BEDINGUNG
  Die Abtastung wurde nachsichtiger (fremde Flaechen zaehlen nicht
  mehr als Untergrund eines Textes). Das war richtig und hat einen
  Fehlalarm beseitigt, der seit Tagen kam. Eine Lockerung kann aber
  zu weit gehen, deshalb muss jetzt jeder gefundene Text in genau
  einem von drei Toepfen landen: gemessen, ohne freien Untergrund,
  oder aussortiert. Geht die Rechnung nicht auf, ist unterwegs etwas
  still verschwunden.

  Erster Anlauf war "mindestens 5 Stellen" -- und wurde auf
  uebersicht.html sofort rot, weil die Seite nur vier Texte hat.
  Eine feste Schwelle ist eine Rechnung von gestern; diese war keine
  fuenf Minuten alt.

Gemessen: pruef-kachelfarben 22/0 (war 18, neu: die Willkommenskachel
traegt wirklich alle benutzten Farben, in beide Richtungen geprueft),
pruef-buehne 192/0, pruef-chatkachel 32/0, pruef-chat-optik 45/0,
pruef-chat 48/0, pruef-erwaehnung 69/0, pruef-start-ansicht 153/0,
pruef-treff 80/0, pruef-willkommen 67/0, pruef-treffchat 110/0,
pruef-css-klassen 30/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 12:57:56 +02:00
DogFatherGitandClaude Opus 5 e12392a289 Die Kachelfarben kommen jetzt WIRKLICH auf dem Bildschirm an
Filipe: "ich raste aus im ernst, was verstehst du nicht darunter wenn
ich sage das alle kacheln eine andere farbe haben sollen ich seh
immer wieder sehr viele die einfach komplett die gleiche farbe haben."

ER HATTE RECHT, UND MEINE PRUEFUNG WAR TROTZDEM GRUEN.
Der Grund war ein Messfehler, und zwar meiner: pruef-kachelfarben las
`--ton` aus start.css -- die ROHFARBE. Die lag zwischen allen 31
Kacheln weit auseinander (0,0978 in OKLab). Nur steht sie so nie auf
dem Bildschirm.

GEMESSEN an echten Bildpunkten (neu: tools/kachel-echtfarbe.mjs):
  Rohfarben:              0,0978 auseinander
  Auf dem Bildschirm:     0,0141
  Es kamen an:            14,4 Prozent
  Fuer ein Auge gleich:   ACHT Paare

Drei Stellen haben die Farbe geschluckt, alle in .kachel:
  1. Eine Wolke mit 16 Prozent -- in immer DEMSELBEN Blau, auf jeder
     Kachel. Der staerkste Gleichmacher der ganzen Wand. Sie traegt
     jetzt den Ton der Kachel.
  2. Die Vignette legte bis zu 55 Prozent Dunkelblau darueber.
  3. Der Grund trug den Ton zu 24 Prozent und ging ab 58 Prozent in
     fast reines Schwarz. Zwei Drittel jeder Kachel waren damit
     dieselbe Farbe, egal welcher Ton darueber stand.

Danach: 51,1 Prozent kamen an, NULL ununterscheidbare Paare.

UND DANN HAETTE ICH EINEN FEHLER GEGEN EINEN ANDEREN GETAUSCHT.
Gemessen an jedem einzelnen Kacheltext: VORHER war 1 von 31 unter
4,5:1, DANACH 27 von 31. Also genau das, was Filipe schon zweimal
gemeldet hat ("man bekommt fast nichts gelesen"). Kein Messwert hat
es angezeigt -- pruef-buehne nimmt Stichproben und traf die
Kacheltexte nicht.

Behoben mit einem Lesesaum: ein dunkler Verlauf VON UNTEN, der genau
den Streifen abdunkelt, auf dem gelesen wird, und die oberen zwei
Drittel in Ruhe laesst. Dasselbe Mittel, mit dem jede Bildunterschrift
auf einem Foto lesbar gemacht wird.

  Texte unter 4,5:1:   1 -> 27 -> 0
  Farbe kommt an:      14,4 % -> 51,1 % -> 36,5 %

VERTRAULICH MELDEN IST JETZT KNALLROT.
Filipe: "nicht die kachel draussen soll rot sein sondern die kachel
vertraulich melden nur die soll knall rot sein!!!" Ich hatte screen5
und screen6 vertauscht. Ringtausch ohne neue Farbe:
  Vertraulich melden  28 -> 38  (#ff1a1a, knallrot)
  Draussen            38 -> 39  (die Farbe, die Regeln & Hilfe hatte)
  Regeln & Hilfe      39 -> 28  (das frei gewordene Gruen)

NEU, UND DER EIGENTLICHE LERNEFFEKT:
server/helfer-kachel-echtfarbe.mjs misst beides in EINER Messung --
Farbunterschied UND Lesbarkeit. Wer sie trennt, verbessert das eine
und verliert das andere; genau das ist heute passiert. Benutzt von
der Pruefung und vom Werkzeug, damit es nur eine Fassung gibt.

pruef-kachelfarben 18/0 (war 13), davon fuenf am echten Bildschirm:
  - kein Paar sieht auf dem Bildschirm gleich aus (0,0357)
  - mindestens ein Drittel der Rohfarbe kommt an (36,5 %)
  - jeder Kacheltext erreicht 4,5:1 (schlechtester: 4,80:1)
Mit drittem Ausgang: kein Browser heisst "konnte nicht nachsehen",
nicht "in Ordnung".

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 10:26:49 +02:00
DogFatherGitandClaude Opus 5 65d278a18e Der Handy-Rundgang ist zum ersten Mal bei null Befunden
SECHS SACHEN, UND KEINE DAVON WAR DAS, WONACH ICH GESUCHT HABE.

1. ZWEI NATIVE prompt() IN teamlage.js -- die letzten im Haus.
   Sie halten die ganze Seite an, sehen auf jedem Browser anders aus
   als der Rest und koennen nicht sagen, was BLEIBT, wenn man absagt.
   Genau das ist dort die Frage, die jemand vor dem Klicken hat. Jetzt
   derselbe Dialog wie an den 42 anderen Stellen.

2. UND DER GRUND, WARUM SIE NIEMAND GEFUNDEN HAT.
   pruef-nachfrage suchte mit `(?:^|[^.\w])(confirm|prompt)\s*\(`.
   Das `[^.\w]` sollte fremde Methoden ausschliessen -- `angebot
   .prompt()` ist die Installations-Aufforderung des Browsers und kein
   nativer Dialog. Nur trifft dieser Ausschluss ausgerechnet die
   HAEUFIGSTE Schreibweise: `window.prompt(` hat einen Punkt davor.
   Die Pruefung war gruen, waehrend zwei native prompt() dastanden.
   Genau das Muster, vor dem dieses Haus warnt: eine Pruefung, die
   laeuft, gruen ist und das Falsche prueft. Die Gegenprobe kennt
   jetzt beide Schreibweisen -- haette sie das vorher getan, waere es
   am selben Tag aufgefallen.

3. willkommen.html LUD nachfrage.js NICHT.
   Gefunden von der geschaerften Pruefung. kopf.js ruft `frageNach(`
   ohne Absicherung -- auf dieser einen Seite haette ABMELDEN einen
   Absturz ausgeloest. Die Seite ist vom 21.09., die Luecke also
   einen Tag alt.

4. ZWEI FEHLALARME IM HANDY-RUNDGANG ABGESTELLT.
   Er meldete bei JEDEM Lauf dieselben drei Befunde: `button.schnitt
   bis 481px`, die Rechtetafel `table bis 877px`, `a.k-pille 8x8`.
   Nachgemessen bei 390 px: Das Dokument ist exakt 390 px breit,
   NICHTS laeuft ueber -- beide stehen in einem Kasten mit
   `overflow-x: auto`, und der rollt absichtlich. Die Kalenderpunkte
   tragen `pointer-events: none`; der Tipp gehoert der Tageszelle.
   Eine Warnung, die immer kommt, ist keine Warnung mehr (Hausregel
   vom 03.09.). Beide Regeln sind SCHMAL: nur ausdrueckliches
   `overflow-x: auto|scroll` (nicht `hidden` -- dort ist der Inhalt
   wirklich weg), nur ausdrueckliches `pointer-events: none`.
   Die Gegenprobe hat jetzt vier Faelle statt zwei: zwei, die gemeldet
   werden MUESSEN, und zwei, die es NICHT duerfen. Eine engere Messung
   kann auch zu eng sein.

5. DER LETZTE ECHTE BEFUND: 404 BEI JEDEM MODI.
   Der Rundgang meldete "404 (Not Found)" ohne Adresse -- eine
   Pruefung, die einen Fehler findet, ihn aber nicht auffindbar macht,
   kostet mehr Zeit als sie spart. Sie nennt jetzt die Adresse, und
   damit war es in einer Minute klar: `/workspace/api/werdegang/liste`.
   Der Code BEHANDELTE den 404 richtig, der Browser protokolliert ihn
   trotzdem -- derselbe Fall wie am 19.09. bei /anruf/adressen.
   Jetzt sagt der Server in /api/ich, ob jemand Team Dogi fuehrt.
   EIGENES FELD, kein Stellvertreter: `darf_verteilen` sieht aehnlich
   aus, ist aber nicht dasselbe -- ein Manager darf verteilen und
   fuehrt Team Dogi nicht.

   Dabei EINE Wartestelle statt zwei: `window.wennIchDaBin()`.
   `window.__ich` kommt ueber das Netz; zwei Seiten hatten dafuer
   jeweils ein eigenes setInterval. Zwei Fassungen desselben Wartens
   altern unterschiedlich.

6. pruef-werdegang MASS AUF DER FALSCHEN ADRESSE.
   Drei Pruefungen waren dauerhaft rot (`data-ton=null`) -- an einer
   Seite, die in Ordnung ist. Sie oeffnete `127.0.0.1`, also die
   Adresse der AGENTUR; dort ist `person.haus` nicht "crew" und die
   Kachelliste eine andere. Nachgemessen: Alle vier Rollen HABEN die
   Kachel, sobald das Haus stimmt. Jetzt derselbe https-Vorbau wie in
   pruef-willkommen und pruef-zuteilung.

   Beinahe haette ich hier etwas "repariert", das nicht kaputt war:
   Meine erste Messung rief `bereicheFuer(p, "crew")` auf -- das Haus
   wird aber aus `person.haus` gelesen, nicht als Argument. Sie sagte
   "DogFather hat keine Kachel". Eine plausible Herleitung ersetzt
   keine Messung, und eine falsch aufgesetzte Messung auch nicht.

GEMESSEN: pruef-handy-teamdogi 214 Seitenaufrufe, 108.564 Elemente,
4.126 Bedienelemente -- 0 Befunde. Alle vier Rollen, beide Breiten.
Zum ersten Mal.

pruef-werdegang 103/0 (war 100/3), pruef-nachfrage 51/0 (war 49),
pruef-stelle 15/0, pruef-entwicklung 48/0, pruef-start-ansicht 153/0,
pruef-wege-nach-draussen 67/0, pruef-tippziele 11/0, pruef-treff 80/0,
pruef-willkommen 67/0, pruef-sackgassen 13/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 10:14:25 +02:00
DogFatherGitandClaude Opus 5 af56f97f4c screen2: EIN Resuemee statt neun -- mit Schritt und Team-Bezug
Filipe: "ich will dass das viel schoener aussieht und nicht so ein
scheiss durcheinander, man wird ja bekloppt. das resume unten auf
jeder frage hab ich auch schon mehrmals gesagt muss weg ich will ein
ganzes gesamtresume was die leute animiert und pusht immer und mega
geile super team loesungen findet aber auch individuel so dass jeder
sich selber auch verbessert und steigert fuers team."

WAS WEG IST
Der Block "Was dein Verlauf sagt" -- eine Zeile JE FRAGE, jede mit
Titel, Marke, Einordnung aus der Forschung und einem "Was hilft". Bei
neun Fragen neun Kaesten untereinander. Genau das meint "man wird ja
bekloppt": Wenn alles gleich wichtig aussieht, ist nichts wichtig,
und man liest keinen davon.

WAS AN SEINE STELLE TRITT -- UND NICHTS VERLIERT
Die Erkenntnisse sind nicht weg, sie sind zusammengefasst:

  DEIN NAECHSTER SCHRITT. Genau EINER, zu der Sache, die am meisten
  haengt. Kernfragen zuerst -- sie werden in jeder Runde gestellt, ihr
  "hakt" wiegt schwerer als das einer Zusatzfrage, die alle vier
  Runden vorbeikommt. Haengt nichts, nimmt er die Sache, die noch
  WAECHST: "nichts zu tun" ist nur fuer den richtig, bei dem alles
  laeuft. Die Einordnung aus der Forschung steht daneben -- einmal
  statt neunmal, als Grund, warum es dieser Schritt ist.

  WAS DAS TEAM DAVON HAT. Abgeleitet aus der Lage, nicht erfunden.
  Ein "gemeinsam schaffen wir das" an jemanden, bei dem fuenf von
  neun Sachen haken, ist das Gegenteil von Hilfe -- in der schwersten
  Lage ist der Team-Bezug deshalb eine Entlastung ("im Team ist
  gerade nichts von dir gefragt"), keine Aufforderung. Vier Lagen,
  vier Saetze. Die Pruefung verlangt ausdruecklich, dass es KEIN
  Spruch ist, der immer passt.

ZWEI DINGE, DIE ERST DAS BILD GEZEIGT HAT
1. "Die Menge passt gerade" stand ZWEIMAL untereinander -- einmal im
   Thema-Block, gleich darunter als Schritt. Kein Messwert meldet das;
   im Bildschirmfoto sah es aus wie ein Fehler. Der Thema-Block nennt
   die Titel jetzt nur noch, wenn es mehrere sind.
2. "Wenn du eine Sache angehst, dann die: Die Menge passt gerade" --
   die Fragetitel im Katalog sind SAETZE, keine Substantive. Jetzt
   "Fang hier an: 'Die Menge passt gerade'".

EIN FUND DER PRUEFUNG: Die TikTok-Quelle war beim Umzug ins Fazit
verlorengegangen. Filipe hatte sie ausdruecklich bestellt ("eine
professionelle auch mit infos und so aus aller welt was tiktok
angeht"). pruef-befinden hat es gemeldet.

Die Pruefung verlangte bis heute das GEGENTEIL -- eine Zeile je
Frage, zu jeder eine Einordnung. Sie ist beim Umbau rot geworden,
richtig so. Jetzt prueft sie, dass unter den Fragen KEIN Resuemee
mehr steht, dass es GENAU EINEN Schritt gibt (nicht "mindestens
einen" -- das waere auch bei neun gruen) und dass der Schritt Inhalt
hat, nicht nur einen Kasten.

pruef-befinden 116/0 (war 113), pruef-resuemee 35/0,
pruef-entwicklung 48/0, pruef-css-klassen 30/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:35:36 +02:00
DogFatherGitandClaude Opus 5 39276ef2ee screen6/7/8: der LIVE-Punkt, und eine Benachrichtigung, die stimmt
Filipe: "in dieser kachel soll wenn ich live bin um 20h bis 22h ein
live button der richtig geil ist mit einem live roten punkt symbol am
besten, das soll aufblinken fuer zwei stunden. man soll nicht drauf
druecken koennen aber so dass es auffaellt. ... die leute sollen auch
automatisch eine benarichtigung bekommen um 20 uhr dass ich live bin."

EINE AUSKUNFT, EINE AUSLEGUNG (workspace/assets/js/live.js)
Drei Stellen sollen dasselbe wissen: die Kachel "Draussen" auf der
Startseite, die Kanalkarten auf der Draussen-Seite, die Pulskarte
darunter. Drei Abfragen waeren drei Auslegungen -- und spaetestens
beim naechsten Umbau steht auf der Kachel LIVE und daneben "wartet".

DER DRITTE AUSGANG IST HIER DIE EIGENTLICHE ARBEIT
Die oeffentliche Seite (assets/js/streamplan.js) faengt jeden Fehler
ab und setzt istLive = false. Aus "wir konnten nicht fragen" wird
dort "er sendet nicht" -- wer das liest, macht zu und verpasst den
Stream. Der Dienst SAGT sogar, ob er nachsehen konnte (autoHealthy);
gelesen wird es dort nicht.
Hier gibt es drei Antworten: live / wartet / weiss-nicht. Bei
"weiss nicht" blinkt nichts -- aber es behauptet auch niemand, dass
nichts laeuft. Sechs Antworten des Dienstes durchgespielt.

BLINKEN OHNE FLACKERN
Hausregel vom 12.08.2026: keine aggressiven Flacker-Effekte. Das ist
kein Widerspruch zu "richtig geil", sondern dieselbe Sache: Ein Rot,
das im Sekundentakt umspringt, liest man als "Alarm, ich sehe weg".
Eins, das atmet und einen Saum nach aussen schickt, liest man als
"jetzt gerade". 1,4 Sekunden, ueberall derselbe Takt -- zwei Rhythmen
nebeneinander waeren Unruhe, einer ist ein Herzschlag. Die Pruefung
verlangt ausdruecklich >= 1 s und einen einheitlichen Takt; nach dem
Wort "animation" zu suchen waere auch bei 0,1 s gruen.
Bei Bewegungsarmut steht alles still -- der rote Punkt bleibt
sichtbar, er bewegt sich nur nicht. Im Kontrastmodus sagt es ein
Rahmen, weil Farben dort nichts tragen.

KEIN KNOPF, UND ES SIEHT AUCH NICHT SO AUS
pointer-events: none ist die halbe Antwort; die andere ist die Form.
Etwas, das wie ein Knopf aussieht und nichts tut, ist eine Sackgasse.
Deshalb eine Marke wie auf einer Kamera: Punkt plus Wort. Das Wort
steht auch fuer Vorleseprogramme da -- ein stummer roter Kreis waere
die halbe Auskunft.

DIE KACHEL WIRD UEBER IHR ZIEL ERKANNT, NICHT UEBER DEN NAMEN.
Der Name hat sich in diesem Haus schon zweimal geaendert ("Unsere
Seiten" -> "Draussen"), das Ziel nie. Am 21.09. hat genau dieser
Unterschied eine ganze Hinweisspalte lahmgelegt.

DIE BENACHRICHTIGUNG ENTSCHEIDET DER DIENST, NICHT DIE UHR.
Eine Meldung "er ist live", waehrend er nicht sendet, funktioniert
genau einmal: Beim zweiten Mal weiss jeder, dass sie nichts bedeutet.
Deshalb prueft der Lauf (alle fuenf Minuten) den echten Status; bei
"weiss nicht" wird NICHTS verschickt. Ein Merkmal mit Datum haelt es
bei einer pro Abend -- sonst kaemen in zwei Stunden 24.
Eigene Art "dogfather_live", vorgegeben an und trotzdem abschaltbar:
Wer jeden Abend dieselbe Meldung bekommt und nie hinschaut, schaltet
sonst ALLES ab, und dann erreicht ihn auch keine Aufgabe mehr.

EIN FEHLER, DEN DIE PRUEFUNG GEFANGEN HAT: Der Versand las aus
"push_geraete" -- diese Tabelle gibt es nicht, sie heisst
push_anmeldungen. Der Block steht in einem try/catch; der Fehler
waere still geblieben, und die Benachrichtigung waere nie gekommen.
Die Pruefung verlangt jetzt ausdruecklich, dass die Tabelle im
Schema existiert.

NEU: pruef-livepunkt 49/0, mit drei Gegenproben.
Daneben gruen: pruef-css-klassen 30/0, pruef-push 24/0,
pruef-draussen 39/0, pruef-zwischenspeicher 27/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:28:29 +02:00
DogFatherGitandClaude Opus 5 227c6c0425 screen5 und screen4: zwei Farben gesetzt, 14 auseinandergezogen
screen5 (ausdruecklich VOR screen4, wie gewuenscht):
  "Vertraulich melden" traegt jetzt Ton 28 -- die Farbe, die "Regeln
  & Hilfe" hatte. Beide gehoeren zusammen: Wer Hilfe sucht, landet
  bei einem von beiden. "Regeln & Hilfe" bekam dafuer einen eigenen
  Ton; zwei Kacheln mit derselben Farbe in derselben Ansicht waeren
  genau das, was screen4 abschaffen soll.
  "Draussen" ist knallrot: Ton 38 = #ff1a1a, voll gesaettigt,
  Kontrast 4,84:1 gegen den Grund. Gemessen, nicht geschaetzt -- von
  zehn Rotwerten zwischen #ff0000 und #ff5555 erfuellen alle die
  4,5:1, dieser ist der knalligste, der auf dunklem Grund nicht
  flimmert. Er traegt ab 20 Uhr den LIVE-Punkt.
  Beide sind ab jetzt GESETZT: pruef-kachelfarben wird rot, wenn ein
  Farblauf sie anfasst. Eine Festlegung, die nur im Kommentar steht,
  ist eine Bitte.

screen4: neues Werkzeug tools/kachel-farben-entzerren.mjs.
  Der Unterschied zu den zwei vorhandenen: Es rechnet nur mit den
  BENUTZTEN Toenen. In start.css stehen 42, benutzt werden 31 -- die
  anderen Werkzeuge weichen also Farben aus, die kein Mensch sieht,
  und machen dadurch die Abstaende zwischen den sichtbaren unnoetig
  klein. Welche benutzt werden, wird aus den Kachellisten ABGELEITET.
  Von jedem aehnlichen Paar aendert sich genau EINER -- der, der
  nicht gesetzt ist.
  Ergebnis: engstes Paar 0,0741 -> 0,0978 (Faktor 1,32), 14 Toene
  geaendert, alle 31 erreichen 4,5:1.

ZWEI DINGE, DIE ERST DAS MESSEN GEZEIGT HAT
1. Der erste Lauf schlug fuer "Dateien" ein #ffe5ae vor -- Buntheit
   0,076, ein helles Creme. Rechnerisch die beste Stelle im Farbraum,
   auf dem Bildschirm genau das, was Filipe seit Wochen abschafft.
   Mindestbuntheit eingebaut, Schwelle GEMESSEN: Median aller Toene
   0,168, die fuenf blassesten 0,064-0,088. 0,12 liegt dazwischen.
2. Die Abstandsrechnung fasst einen Ton nie an, der weit weg von
   allen liegt -- auch wenn er blass ist. So blieben drei benutzte
   Toene unter 0,12 stehen. Zweite Runde: jeder blasse wird kraeftig
   gemacht, solange das Minimum ueber 0,095 bleibt. Gemessener Preis
   0,1028 -> 0,0978, also 5 Prozent; auf dem Bildschirm nicht zu
   sehen, waehrend Filipes Klage ueber helle Kacheln konkret ist.

NEU: pruef-kachelfarben 13/0 -- getrennt, eindeutig je Ansicht,
festgelegt, lesbar und nicht blass. Mit vier Gegenproben, damit sie
auch rot werden KANN.
NEU: tools/farben-blick.mjs -- sieht die Wand mit echten Augen an und
misst das, was eine Abstandstabelle nicht beantwortet: ob zwei
NEBENEINANDER liegende Kacheln aehnlich aussehen. Gemessen bei
DogFather und Community: kein Nachbarpaar unter 0,09.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:21:54 +02:00
DogFatherGitandClaude Opus 5 5bde49e0cd Was unten im Brett steht, steht jetzt auch oben im Band
Filipe am 22.09.: "die aufgaben die man unten sieht soll man auch
oben sehen."

GEMESSEN an den echten Daten: aufgaben_zuteilung hatte NULL Zeilen,
waehrend im Brett zwei Aufgaben standen (OFFEN 1, IN ARBEIT 1). Jede
Person las oben "nichts zugeteilt". Die Aufgaben hingen am aelteren
Feld aufgaben.verantwortlich_id -- genau dem Feld, nach dem das Brett
gruppiert. Die Uebersicht las eine andere Quelle als die Liste
darunter.

resuemeeFuer() zaehlt jetzt BEIDE Wege und keinen doppelt: Gibt es zu
einer Aufgabe eine Zuteilungszeile fuer die Person, gewinnt die
Zuteilung (genauerer Zustand). Nur wo keine Zeile existiert, zaehlt
das alte Feld. Die Zuordnung status->zustand steht an EINER Stelle;
"review" zaehlt wie "arbeit", "abgebrochen" zaehlt nirgends -- so wie
im Brett auch.

Die Personenliste wird nicht mehr aufgezaehlt, sondern abgeleitet:
die Rollen des Hauses (immer, auch mit null Aufgaben -- wer frei ist,
ist die haeufigste Frage) PLUS jede aktive Person, der eine Aufgabe
gehoert. Ohne den zweiten Teil koennte im Brett eine Aufgabe stehen,
deren Mensch oben fehlt.

pruef-zuteilung 71/0 (war 65). Der neue Abschnitt legt eine Aufgabe
GENAU SO an wie die echten alten -- verantwortlich_id, keine
Zuteilungszeile -- und misst Filipes Satz direkt: "unten im Brett
stehen genauso viele wie oben (2 = 2)". Zahl in der Bedingung, nicht
nur im Meldetext.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:12:20 +02:00
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 ef0fddc724 Aufgaben an Menschen: zuteilen, annehmen, ablehnen, bewerten
Auftrag vom 21.09.2026, Abschnitte 2 bis 5 -- der Serverteil.

DREI ARTEN ZU VERTEILEN, und der Unterschied zwischen den letzten
beiden ist der ganze Punkt:

  einzeln   eine Person, sie macht es
  mehrere   mehrere Personen, JEDE macht ihren Teil
  pool      mehrere sehen es, EINE nimmt es -- danach ist es fuer die
            anderen weg, damit niemand doppelt arbeitet

EINE EIGENE TABELLE, KEINE SPALTEN AN DER AUFGABE. Abschnitt 4
verlangt ausdruecklich: *"Die Aufgabe muss in der Auswertung auf die
einzelnen zugewiesenen Personen aufgeteilt werden"* -- und gleichzeitig
soll "die urspruengliche gemeinsame Aufgabe ihre uebergeordnete
Struktur" behalten. Eine Aufgabe hat EINEN Titel und EINE Frist, aber
je Mensch einen eigenen Stand, einen eigenen Grund beim Ablehnen, ein
eigenes Erledigt-Datum und eine eigene Rueckmeldung. Das in Spalten zu
pressen hiesse, dieselbe Aufgabe mehrfach anzulegen.

`aufgaben.status` bleibt daneben unberuehrt. Zwei Ebenen, weil es zwei
Fragen sind: "Wie steht die Aufgabe?" und "Wie steht sie bei IHM?" Ein
einziges Feld koennte bei drei Leuten nicht gleichzeitig "angenommen"
und "abgelehnt" sein.

DER WICHTIGSTE EINZELNE HANDGRIFF -- und er steht nicht im Auftrag:
Wer eine Aufgabe BEKOMMEN hat, sieht sie jetzt immer. Bei "mehrere"
und "pool" bleibt `verantwortlich_id` leer, und die alten Sichtregeln
fragen genau danach. Ohne die Erweiterung stuende eine Aufgabe im
Resuemee der Leitung und waere fuer den, der sie machen soll,
unsichtbar -- der unangenehmste denkbare Fehler in einem
Aufgabensystem, und man sieht ihn nirgends. Die Erweiterung ist ein
ODER, kein UND: Sie erweitert die Sicht, die Haustrennung darueber
bleibt ein UND und wirkt weiter.

WAS SONST NOCH ENTSCHIEDEN WURDE, mit Grund im Code:

  - Ablehnen braucht eine Begruendung (mind. 3 Zeichen). Ein leeres
    Nein ist fuer den, der verteilt hat, keine Information -- er muss
    dann nachfragen, und genau das sollte die Nachricht ersparen.
  - "Verbesserungsmoeglichkeiten" braucht einen Text. Ein leeres
    "kann besser" sagt nichts ausser, dass jemand unzufrieden war.
  - Bewertet wird erst, wenn jemand FERTIG ist. Eine Rueckmeldung auf
    etwas, das noch laeuft, ist keine Bewertung, sondern eine
    Einmischung.
  - Beim Pool wird VOR dem Schreiben gefragt, ob schon jemand zugesagt
    hat -- sonst nehmen zwei im selben Moment dieselbe Aufgabe und
    beide sehen "hat geklappt".
  - Wer schon geantwortet hat, behaelt seinen Stand, wenn die Aufgabe
    noch einmal gespeichert wird. Sonst muesste er ohne Grund erneut
    zusagen.
  - Wer nicht mehr dabei ist, faellt raus -- aber nur, solange er noch
    nicht geantwortet hat. Jemandem eine angenommene Aufgabe
    wegzunehmen, ohne dass er es erfaehrt, waere die unangenehmste Art,
    Arbeit zu verlieren.
  - "pool" mit einer Person wird "einzeln". Ein Pool aus einem
    Menschen ist keiner.

`verantwortlich_id` bleibt und wird mitgefuehrt (einzeln = die Person,
pool = der Uebernehmer, mehrere = leer): Brett, Startseite und
Uebersicht gruppieren danach. Drei gewachsene Ansichten gleichzeitig
umzubauen waere der groessere Eingriff -- und im haeufigsten Fall
sagen beide dasselbe.

KEIN CHECK an der nachgetragenen Spalte `verteilart`, mit Absicht: Ein
CHECK auf einer nachgetragenen Spalte hiesse, die Tabelle neu zu bauen
-- der Weg, der in diesem Haus am 11.09. und heute schon Spalten
gekostet hat. Geprueft wird beim Schreiben.

pruef-zuteilung.mjs, 48 Aussagen -- ein Arbeitstag durchgespielt.

Ein Fehlschlag beim ersten Lauf, und er war lehrreich: "Cem hat keinen
eigenen Stand" schlug fehl, weil Cem die Aufgabe gar nicht SIEHT
(`null?.x` ist `undefined`, nicht `null`). Die Zusicherung konnte
"sieht sie nicht" und "sieht sie ohne Stand" nicht unterscheiden --
also pruefte sie beides nicht richtig. Dass er sie nicht sieht, ist
genau Abschnitt 1: *"Eine Modi darf nicht automatisch die
vollstaendige Aufgabenuebersicht aller anderen Modis sehen."* Beide
Faelle stehen jetzt einzeln da, mit einer Gegenprobe, dass seine Liste
ueberhaupt laedt.

Nachbarn gruen: pruef-verteilen 16/0, pruef-aufgabenbrett 49/0,
pruef-umstellung 18/0.
2026-09-21 17:52:52 +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 2c2c42d4aa Drei rote Zeilen im Werdegang -- alle drei verlangten Altes
Keine davon war ein Mangel an der Seite. Alle drei verlangten einen
Zustand, den Filipe am 19.09.2026 ausdruecklich geaendert hat.

1. "alphabetisch (Rieke, Diene)"

   Filipe am 19.09.: "die reihenfolge der listen soll immer angepasst
   sein hatten wir doch schon. die rechte hand rolle immer zuerst und
   dan die modis." Der Server sortiert seitdem nach ROLLEN_SORTIERUNG,
   dann nach Namen -- die Pruefung verlangte weiter rein alphabetisch.

   Sie prueft jetzt dieselbe Ordnung, abgeleitet aus derselben
   Konstante wie der Server. Wer dort eine Rolle verschiebt,
   verschiebt sie hier mit. Was bleibt, ist die eigentliche Aussage:
   sortiert wird nach etwas, das nichts ueber die Person sagt -- eine
   Liste nach Aktivitaet waere eine Rangliste mit anderem Namen, eine
   nach Rolle ist es nicht.

2. "jede Zelle traegt ihr Zeichen, nicht nur ihre Farbe"

   Im Quelltext der Seite steht seit dem 19.09. woertlich: "Leer ist
   jetzt WIRKLICH leer -- kein Zeichen, dafuer ein gestrichelter
   Rahmen. Man sieht das Fehlen, statt es zu lesen." Die Pruefung
   verlangte das Gegenteil.

   Gemessen werden jetzt beide Haelften, und die zweite ist die
   wichtigere: Stuende in einer leeren Zelle doch ein Zeichen, waere
   "noch nichts gesetzt" nicht mehr von "gesetzt" zu unterscheiden --
   und das faellt beim Hinsehen nicht auf, weil es nach Inhalt
   aussieht.

3. "unter dem Diagramm steht eine Legende (7 Eintraege)"

   Hier stand `=== 2`. Inzwischen sind es sieben: zwei fuer die
   Bewegungsrichtung, vier Stufen und der leere Zustand. Wieder eine
   Rechnung von gestern.

   Gefragt wird jetzt, was die Legende leisten muss: zu JEDER Stufe,
   die der Server kennt, ein Eintrag -- und einer fuer den leeren
   Zustand. Kommt eine Stufe dazu, waechst die Erwartung mit.

ZWEIMAL HAT MICH DABEI DIE ZAHL IN DER BEDINGUNG GERETTET. Erst
fragte ich die Stufen an der Liste ab -- die liefert sie gar nicht,
sie stehen an der einzelnen Karte. Ohne `stufenSoll.length > 0` waere
der Vergleich gegen eine leere Liste gelaufen und haette "die Legende
nennt jede davon" bestaetigt, ohne eine einzige zu kennen. Dieselbe
Zeile hatte zuvor schon in pruef-modi-checkliste einen stillen
Totalausfall verhindert.

pruef-werdegang: 103 Pruefungen, 0 Fehler (war 95, davon 3 rot)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:15:35 +02:00
DogFatherGitandClaude Opus 5 9d4a40ff58 Zwei Pruefungen waren rot, weil etwas richtig gemacht wurde
pruef-auskunft und pruef-treff-werkzeuge -- beide bestraften eine
Verbesserung. Das ist die unangenehmste Sorte roter Pruefung: Wer sie
zweimal so erlebt, faengt an, rote Laeufe zu erklaeren statt sie zu
lesen.

1. "DIE COMMUNITY HAT KEINEN STECKBRIEF"

   So stand es woertlich in der Bedingung. Am 19.09. hat Filipe genau
   das Gegenteil entschieden -- "jeder soll ein steckbrief haben, jeder
   der ein account hat ... jeder soll genau wie ich foto und so
   hinzufuegen koennen" -- und die Community hat seitdem einen.

   Was die Zeile schuetzen wollte, steht in ihrem eigenen Kommentar:
   "Ohne die zweite Stelle haette die Gruppe mit den wenigsten Rechten
   auch dieses nicht -- und sie ist die groesste." Die Sorge ist
   richtig und hat mit der Anzahl der Seiten nichts zu tun. Die Frage
   lautet: KOMMT JEDE ROLLE AN IHRE AUSKUNFT?

   Genau das wird jetzt gemessen -- welche Seiten den Knopf tragen,
   aus den Dateien gelesen statt aufgezaehlt, und ob jede der acht
   Rollen mindestens eine davon erreichen darf, aus der Rechtetafel
   gelesen statt angenommen. Mit Gegenprobe (eine erfundene Rolle
   erreicht keine) und mit der Zahl in der Bedingung.

2. "DIE COMMUNITY STEHT BEI 8 VON 33"

   Hier stand `community.seiten < 5`. Die Zahl stimmte an dem Tag, an
   dem sie geschrieben wurde. Seither hat der Treff eigene Seiten
   bekommen -- Regeln, Steckbrief, Hilfe, Draussen -- und die
   Community steht bei acht. Die Pruefung war rot, WEIL der Treff
   gewachsen ist. Dieselbe Fehlerklasse wie die Umbruchschwelle vom
   06.09.: Wer eine Zahl notiert, notiert einen Zustand, keine Regel.

   Gemeint war eine ORDNUNG: Ein Mitglied sieht weniger als die
   Moderation, die weniger als die rechte Hand, die weniger als
   DogFather. Nachgemessen 8 / 19 / 25 / 32 von 33. Geprueft wird
   jetzt das Verhaeltnis -- und zusaetzlich, dass die Community das
   Minimum ueber ALLE acht Rollen ist, nicht nur in dieser Kette. Das
   bleibt richtig, wenn der Treff weiterwaechst, und faellt sofort
   auf, wenn jemand die Reihenfolge versehentlich umdreht.

pruef-auskunft         46/0  (war 46, davon 1 rot)
pruef-treff-werkzeuge  73/0  (war 70, davon 1 rot)

Damit sind alle vier Pruefungen gruen, die heute frueh rot waren.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:12:36 +02:00
DogFatherGitandClaude Opus 5 95d753791d Die dritte Fassung derselben Pruefung -- diesmal ohne Liste
pruef-modi-checkliste war rot: "und alle stehen in einer Gruppe fuer
euch beide -- ausser: Der Treff, Treff-Chat, Anschlagbrett, ..."

DIE URSACHE WAR EINE GEPFLEGTE LISTE, zum zweiten Mal. Erst stand dort
`["Team Dogi"]`, dann `["Team Dogi", "Entwicklung & Nachwuchs"]`, und
daneben der Satz: "Kommt eine dritte Gruppe, wird diese Zeile rot. Das
ist Absicht." Am 21.09. kam sie -- der Treff -- und nichts daran war
falsch.

WARUM DIE FRAGE SELBST NICHT MEHR PASSTE: `bereiche_zusatz` hiess
einmal "die eine Kachel, die nur ihr zwei habt". Seit es den Treff
gibt, steht dort fuer DogFather auch der GANZE Treff -- zehn Kacheln
in der Gruppe "Community", die die rechte Hand, die Moderation und
jedes Mitglied ebenso sehen. Das ist der zweite Haushalt, kein Mangel:
Fuer ihn ist der Treff eine Zugabe, fuer sie das Zuhause.

MEIN ZWEITER VERSUCH WAR SCHLECHTER ALS DER ERSTE, und gefangen hat
das nur die Gegenprobe. Ich wollte die verbotenen Gruppen MESSEN statt
sie aufzuzaehlen: "welche Gruppen sieht ein Creator, welche Spicy
Media?" Nachgemessen sind das in dieser Pruefdatenbank NULL -- beide
haben dort gar keine Kacheln. Die Bedingung waere damit immer wahr
gewesen, und aus einer roten Pruefung waere eine gruene geworden, die
nichts mehr misst. Gefangen hat es allein die Zahl in der Bedingung
(`sehenAlle.size >= 2`). Ohne sie haette ich eine Pruefung stillgelegt
und es fuer eine Reparatur gehalten.

JETZT WIRD NACH DER KACHEL GEFRAGT, NICHT NACH IHRER GRUPPE: Gibt es
unter den Zugaben mindestens eine, die sonst NIEMAND hat? Gemessen am
Ziel, gegen Modi, Spicy Media und Creator zusammen. Das ist die
urspruengliche Aussage, und sie altert nicht -- die Gruppe war immer
nur ein Hilfsmerkmal.

Die alte Gruppen-Zeile steht nicht mehr daneben. Sie waere jetzt immer
wahr, und eine Zeile, die immer bestaetigt, bestaetigt nichts.

Die Meldung sagt seitdem auch etwas:
  DogFather    davon 3, die sonst niemand hat (Dein Team, Wer sieht
               was, Talente), erwartet mindestens eine
  Creator      davon 0, die sonst niemand hat, erwartet keine

75 Pruefungen, 0 Fehler (war 70, davon 2 rot)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:10:41 +02:00
DogFatherGitandClaude Opus 5 25b5cf6224 "Unveraenderlich" stand auch auf Adressen, die sich aendern
Beim Nachmessen der Crew-Sperre von vorhin: Der Ursprung lieferte
korrekt 404 und eine bereinigte gate.css -- Cloudflare lieferte
weiterhin die ALTE Fassung, 27 806 Byte, `cf-cache-status: HIT`.

DIE URSACHE STAND IM EIGENEN KOMMENTAR. In index.js hiess es:
"`originalUrl` steht hier nicht zur Verfuegung -- geprueft wird
deshalb die Dateiart." Nachgemessen stimmt das nicht: `res.req
.originalUrl` ist da und liefert "/start.html?v=123". Die Annahme war
nie geprueft worden, und aus ihr folgte eine Zusage, die das Haus
nicht halten kann: JEDE CSS- und JS-Datei ging mit
`max-age=31536000, immutable` hinaus -- auch unter ihrer Adresse OHNE
Stempel.

"immutable" heisst woertlich: Der Inhalt unter DIESER Adresse aendert
sich nie. Fuer `gate.css?v=...` stimmt das, der Name wechselt ja mit
dem Inhalt. Fuer `gate.css` ist es falsch -- und dort haette die alte
Fassung ein Jahr im Zwischenspeicher gelegen, waehrend der Server
laengst etwas anderes sagt. Ein Zwischenspeicher, der etwas Falsches
zeigt, ist schlimmer als gar keiner: man glaubt ihm.

Jetzt haengt die Zusage an der Bedingung, die sie traegt. Mit Stempel
bleibt alles wie bisher -- die Seiten rufen ohnehin immer `?v=...`
auf, dort kostet es nichts. Ohne Stempel wird nachgefragt. Die
oeffentliche Seite benutzt ebenfalls `?v=` (mit Buchstabe am Ende);
geprueft wird nur, OB einer da ist, nicht wie er aussieht.

DIESELBE SORTE FEHLER GLEICH NEBENAN: pruef-zwischenspeicher hat einen
Abschnitt "Was einen Stempel traegt, darf liegenbleiben" -- und rief
die Dateien OHNE Stempel ab. Auch hier beschrieb der Text etwas, das
der Code nicht tat. Er liest den Stempel jetzt aus der Seite und misst
damit genau die Adresse, die ein Browser anfordert. Dazu vier neue
Zeilen fuer den umgekehrten Fall, mit Gegenprobe an derselben Datei --
sonst waere "ohne Stempel: no-cache" auch dann gruen, wenn ALLES auf
no-cache stuende, und jeder Seitenaufruf waere unnoetig langsam.

UND MEIN EIGENER FEHLER VON GESTERN, behoben: Die Stempelpruefung
verglich seit dem 20.09. den Stempel mit dem ZEITPUNKT des letzten
Commits an assets/. Das kann gar nicht aufgehen -- der Stempel wird
immer VOR dem Committen gezogen, die Commit-Zeit ist also immer die
juengere. Stempeln um 12:59 und Committen um 13:00 genuegte fuer einen
Fehlalarm; heute ist genau das passiert.

Gefragt wird jetzt die REIHENFOLGE der Commits, die hat keine Uhr:
Liegt der letzte Commit an den HTML-Seiten (dort steht der Stempel)
auf oder nach dem letzten an assets/? `merge-base --is-ancestor`
beantwortet das ohne Zeitstempel. Mit Gegenprobe ueber das Elternteil
-- und mit drittem Ausgang, wenn es keines gibt.

pruef-zwischenspeicher: 27 Pruefungen, 0 Fehler (war 22, davon 2 rot)

NOCH OFFEN und nur von Filipe zu machen: Cloudflare haelt die alten
Fassungen unter den stempellosen Adressen weiter im Zwischenspeicher.
Der Ursprung ist sauber; geleert werden muss der Rand einmal von Hand.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 13:04:38 +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 9a71f3a242 Eine Null zu viel -- HasiDog-Videos waeren abgelehnt worden
In KANAELE stand "@hasidog00804". Der Account heisst "@hasidog0804".
Nachgemessen bei TikTok selbst: der richtige hat 65 Follower, der
andere liefert "Couldn't find this account".

Das war nicht kosmetisch. `kanalVonHandle` ordnet ein hochgeladenes
Video ueber genau diesen Text einem Kanal zu. Ein echtes
HasiDog-Video waere mit 403 abgelehnt worden -- und die Begruendung
haette gelautet: "ist keiner deiner Kanaele. Moeglich sind:
@dogfather0804, @hasidog00804, @dogis.modi.gang." Eine Sackgasse, die
zusaetzlich eine Adresse nennt, die es nicht gibt.

WARUM ES KEINE PRUEFUNG GEFUNDEN HAT: pruef-kanalzeile und
pruef-teilen hatten denselben Handle abgeschrieben. Zwei Abschriften
desselben Tippfehlers bestaetigen sich gegenseitig -- beide waren
gruen. Sie leiten ihn jetzt aus KANAELE ab und koennen ihn damit gar
nicht mehr eigenstaendig falsch haben.

Gefunden hat es ein Vergleich: Die oeffentliche Website verlinkt
dieselben Accounts und hatte die richtige Schreibweise. Genau das ist
jetzt Abschnitt 7 von pruef-kanaele -- alle Handles muessen auch
draussen vorkommen, mit Gegenprobe, dass eine falsche Adresse
durchfaellt. Ohne Netz, damit eine Stoerung bei TikTok nicht zu einem
roten Alarm im Haus wird.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:51:06 +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 8bd6474844 Die Farbkacheln im Chat waren mit dem Daumen zu klein
30x30 ist mit der Maus bequem und am Handy zu klein; die Grenze im Haus
sind 44px. Angehoben wird nur auf Fingergeraeten (pointer: coarse),
sonst staende der Knopf am Rechner unnoetig gross neben einer Zeile,
die selbst nur 30 hoch ist. Sichtbar bleibt die Kachel gleich gross --
gewachsen ist die Flaeche, die den Finger annimmt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:45:06 +02:00
DogFatherGitandClaude Opus 5 e12074c32c Der Stempel wird mit der Uhr verglichen, nicht mit dem Commit
pruef-zwischenspeicher verlangte, dass derselbe Commit die Stilvorlage
UND die HTML aendert. Das ist der Normalfall, aber nicht die Regel:
Wird der Stempel in einem Folge-Commit nachgezogen, kommt die Aenderung
genauso an -- die Pruefung blieb trotzdem rot und beschuldigte einen
Commit, an dem nichts falsch war. Eine rote Zeile, die rot bleibt,
bringt Menschen dazu, Rot zu uebersehen.

Verglichen wird jetzt der Stempel selbst mit dem Zeitpunkt der letzten
Aenderung an assets/. Ein Stempel, der juenger ist, wurde danach
gezogen -- egal in welchem Commit. Das ist strenger als vorher, nicht
lockerer: Eine HTML-Aenderung aus einem ganz anderen Grund (ein
Tippfehler im Text) haette die alte Pruefung besaenftigt, ohne dass der
Stempel gezogen wurde.

Dazu ein Fund am Rand: anruf-probe.html trug ein handgeschriebenes
?v=202609191018 am Manifest-Link. Kein Werkzeug pflegt diese Stelle,
keine der 20 anderen Seiten hat so etwas -- sie waere still veraltet.
Entfernt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:45:06 +02:00
DogFatherGitandClaude Opus 5 200728c8e7 Der leere Ring zeigte "100 %" -- das las sich wie "alles geschafft"
Die Pruefung verlangte prozent === 100, wenn gar nichts zu tun war. Der
Gedanke war richtig (ein leerer Ring darf nicht wie Versagen aussehen),
die Umsetzung nicht: Gelesen wird zuerst die Zahl in der Mitte, und
"100 %" heisst fuer jeden Menschen "fertig". Am ersten Tag, ohne eine
einzige Aufgabe, stand das als groesstes Element der Startseite.

Seit dem 19.09. steht dort ein Strich. Ein Anteil von nichts ist keine
Null und keine Hundert, sondern nicht definiert. Die Pruefung fragt
jetzt danach -- und damit gleichzeitig schaerfer: Solange gar keine Zahl
dasteht, kann dort auch nicht versehentlich der Uhrzeitwert stehen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:44:55 +02:00
DogFatherGitandClaude Opus 5 782a9116f2 Zwei Pruefungen rechneten in UTC und schlugen abends falschen Alarm
pruef-zeitraum und pruef-highlights bildeten ihren Tagesstempel mit
toISOString(). Das ist UTC. Zwischen 22:00 und Mitternacht deutscher
Zeit ist das schon der naechste Tag -- die Pruefungen verglichen dann
einen Eintrag von heute mit dem Datum von morgen und meldeten einen
Fehler, wo keiner war.

Der Zeitraum-Filter im Haus rechnet richtig; er benutzt tagLokal() aus
helfer-zeit.mjs. Nur die Pruefungen darueber hatten ihre eigene, falsche
Rechnung. Jetzt benutzen sie denselben Helfer wie der Code, den sie
pruefen -- damit koennen die beiden gar nicht mehr auseinanderlaufen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:44:55 +02:00
DogFatherGitandClaude Opus 5 acd3e1f385 Zwei Tabellenumbauten haetten 15 Spalten still geloescht
`personen` und `aufgaben` wurden beim Freischalten eines neuen
CHECK-Werts von Hand neu gebaut -- die Spaltenliste stand zweimal im
Code abgeschrieben (CREATE und INSERT). Gemessen:

  aufgaben: 23 Spalten, 18 aufgezaehlt -> vorlage, kategorie,
            aus_eintrag_id, aufwand, aus_punkt weg
  personen: 19 Spalten,  9 aufgezaehlt -> bild, ueber_mich, tiktok,
            instagram, youtube, twitch, chat_kachel, code_kennung,
            stufe, alter_bestaetigt_am weg

Bei `personen` haengen daran die Profilfotos und die
Altersbestaetigung: Alle waeren nach einem Rueckspielen still wieder
unbestaetigt gewesen, ohne Fehlermeldung, bei unveraenderter
Zeilenzahl. Die Zeilenzaehlung, die als Sicherung gedacht war, kann
einen Spaltenverlust gar nicht sehen.

Es ist derselbe Fehler wie am 11.09. an der Eintragstabelle (24 hinein,
21 heraus). Damals wurde `checkListeErweitern` gebaut, das die Spalten
aus PRAGMA table_info ABLEITET -- eine Liste, die niemand pflegt, kann
nicht veralten. Diese beiden Bloecke waren aelter und wurden bei der
Umstellung uebersehen. Jetzt gehen alle 16 Umstellungen denselben Weg,
kein Neubau zaehlt mehr von Hand.

Auf dem laufenden Server ist nichts verloren (24 Spalten, CHECK
vollstaendig) -- die Falle stand fuer den Tag, an dem jemand eine
Sicherung zurueckspielt.

Gefunden hat es nicht das Lesen, sondern pruef-abbrechen: Sie baut
absichtlich eine ALTE Datenbank und liess die Umstellung darauf laufen
-- danach meldete der Server "no such column: a.aufwand".

Neu: pruef-umstellung.mjs (18 Pruefungen) haelt die Fehlerklasse
dauerhaft zu. Sie baut eine echte alte Datenbank mit gefuellten
Spalten, laesst die Umstellung laufen und zaehlt danach Spalten UND
Inhalte. Mit Gegenprobe: ein absichtlich fehlerhafter Umbau zeigt, dass
die Zeilenzahl dabei stimmt und trotzdem Daten fehlen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-21 11:44:45 +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 67a0eb8717 DogFather konnte einen zweiten DogFather nicht mehr herabstufen
Gefunden beim Durchsehen der schnellen Pruefungen: pruef-haus-trennung
stand auf 60 ok / 6 Fehler. Drei Ursachen, eine davon ein echter
Rueckschritt von gestern.

--- 1. DER RUECKSCHRITT ---------------------------------------------

In darfRolleAendern stand seit gestern:

  if (person.rolle === "admin") return ziel.rolle !== "admin";

Das macht aus "DogFather ist nicht mehr VERGEBBAR" ein "an einem
DogFather ist nichts mehr zu aendern". Ein zweiter Zugang liess sich
damit nie wieder zuruecksetzen -- er waere fuer immer DogFather
geblieben. Die Pruefung sagte es woertlich: "solange es zwei gibt,
darf einer wechseln (403)".

Die beiden echten Gefahren haengen woanders und bleiben unberuehrt:
Niemand KANN 'admin' vergeben, und der LETZTE DogFather laesst sich
nicht herabstufen.

--- 2. ZWEI SCHLOESSER FUER DIESELBE TUER ---------------------------

Ich hatte gestern `rollenZumAendern` mit 403 VOR die vorhandene
Pruefung gesetzt, die mit 400 "Unbekannte Rolle." antwortet. Damit war
die Luecke wieder offen, vor der der Kommentar vom 17.09. direkt
daneben warnt: Zwei verschiedene Antworten -- "gibt es nicht" gegen
"darfst du nicht" -- verraten beim Durchprobieren, WELCHE Rollen
existieren.

Jetzt eine Regel an einer Stelle. `darfAnlegen` ist dort raus, weil
Vergeben und Anlegen seit gestern verschiedene Dinge sind. Gemessen:

  admin   anlegen = aendern (sieben Rollen)
  spicy   anlegen = aendern (vier)
  hand    anlegen = —        aendern = modi, gast
  manager anlegen = creator  aendern = —

Und die eigene Zeile bekommt jetzt 400 mit einem Satz statt 403:
Es ist keine Rechtefrage, sondern eine unsinnige Bitte.

--- 3. DREI ERWARTUNGEN, DIE AELTER WAREN ALS DIE REGEL --------------

Die Pruefung verlangte 403, wo seit dem 17.09. 400 richtig ist --
ihre Zeile stammt vom 10.09., sieben Tage aelter als die Regel. Und
sie verlangte 404 fuer "die rechte Hand vergibt keine Rolle", was bis
vorgestern stimmte.

Dabei fiel auf, dass NICHTS geprueft hat, ob die rechte Hand ihre neue
Faehigkeit ueberhaupt ausueben kann -- nur, dass sie es nicht darf.
Eine Pruefung, die nur das Verbotene misst, laesst offen, ob das
Erlaubte geht. Jetzt beide Richtungen:

  an einer anderen rechten Hand aendert sie nichts (403)
  und an DogFather erst recht nicht (403)
  einen Modi macht sie sehr wohl zur Community (200)
  und es steht so in der Datenbank (gast)
  eine zweite rechte Hand ernennt sie nicht (400)

Nebenbei: `unbekannte_kachel` (gestern eingefuehrt) hatte keinen Satz
in meldung.js -- die Kennung waere woertlich auf dem Bildschirm
gelandet. pruef-meldungen hatte es gemeldet.

Und ein Absturz beim Bauen: `const anlegen = await hole(...)` weiter
unten im selben Block verdeckt die gleichnamige Funktion im GANZEN
Block, auch oberhalb seiner eigenen Zeile.

pruef-haus-trennung: 70 ok, 0 Fehler (vorher 60/6).
Dazu gruen: rollen-anlegen 11/0, personen-loeschen 40/0,
rechte-umstellen 46/0, verteilen 11/0, meldungen 8/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 23:13:27 +02:00
DogFatherGitandClaude Opus 5 445ea88f2b fetch verweigert Port 5060 -- und sagt dasselbe wie ein toter Server
Nach der Umstellung auf abgeleitete Nummern bekam pruef-chat-kanaele
die 5060 und stuerzte ab:

  TypeError: fetch failed

Der Server lief nachweislich ("Server laeuft auf http://127.0.0.1:5060"),
die Anmeldung ueber `http.request` hatte sogar geklappt, und BASIS war
sauber ("http://127.0.0.1:5060", 21 Zeichen, PORT eine Zahl). Nur die
`fetch`-Aufrufe scheiterten.

5060 ist SIP und steht auf der "bad ports"-Liste der
Fetch-Spezifikation. Node hat sie uebernommen: `fetch` baut dorthin
keine Verbindung auf, noch bevor ein Paket fliegt. Die Ursache steht
nur in `.cause` -- "bad port" statt "ECONNREFUSED". Die Meldung
obendrueber ist beide Male dieselbe, und wer sie liest, sucht am
Server.

Gegengeprueft mit einem echten Zuhoerer auf beiden Nummern:
  5060 -> fetch failed (bad port)
  5062 -> fetch failed (ECONNREFUSED)   <- also normal erreichbar

`eigenerPort` ueberspringt die gesperrten Nummern jetzt (portNummer).
Uebersprungen wird nach der REGEL, nicht nach einer Tabelle von
Sonderfaellen: die n-te brauchbare Nummer ab 5000. Eindeutig bleibt es,
weil die Reihenfolge feststeht.

pruef-portnummern (11 statt 8) prueft es doppelt: gegen die Liste UND
am echten Verhalten -- ein Zuhoerer auf 5060 muss fuer `fetch` tot
sein, einer auf einer abgeleiteten Nummer erreichbar. Ohne die zweite
Haelfte waere die Liste nur eine Behauptung ueber Node, und
Behauptungen altern.

Nebenbefund: Auch im alten, von Hand vergebenen Bereich lag eine
gesperrte Nummer -- die 4190. Sie war nie vergeben, rein zufaellig.

pruef-chat-kanaele: 79 Pruefungen, 0 Fehler -- wieder auf der
Grundlinie, die vor der Umstellung gemessen wurde.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 23:06:52 +02:00
DogFatherGitandClaude Opus 5 aa8842e72e Zwei Pruefungen waren rot, weil Namen sich geaendert hatten
Beide meldeten seit Tagen einen Fehler, den es nicht gab. Eine rote
Pruefung, die rot BLEIBT, gewoehnt einem das Hinsehen ab -- ab da
uebersieht man auch die echte.

--- pruef-teilen: 14 ok / 3 Fehler -> 27 ok / 0 --------------------

Sie suchte `.teilen__brett`. Die Seite baut `.tl-brett`; die Klassen
wurden irgendwann umbenannt, und die Pruefung suchte seitdem nach
Elementen, die es nicht gibt. Gemeldet hat sie das sogar richtig --
"drei Ziele zur Auswahl (0)" --, nur hat niemand die Klammer gelesen.
Danach lief sie in einen Klick-Zeitablauf und brach ab, weswegen
DREIZEHN weitere Pruefungen nie stattfanden.

--- pruef-crew-wand-bild: 41 ok / 4 Fehler -> 45 ok / 0 ------------

Zwei feste Erwartungen aus einer Zeit, die vorbei ist:

1. `/Team Dogi/` im Reiter. Die App heisst seit dem Treff-Umzug
   "DogFather Universe". Statt den neuen Namen einzutragen -- und
   damit dieselbe Zeitbombe mit neuem Datum zu stellen -- kommt er
   jetzt aus `crew.webmanifest`. Benennt jemand die App um, folgt der
   Reiter, und beides bleibt gruen. Weichen sie auseinander, sieht der
   Mensch im Reiter einen anderen Namen als auf seinem
   Startbildschirm, und genau das soll die Pruefung finden.

2. `kacheln === 3`, seit Filipe am 10.09. sagte "3 rollen. dogfather.
   rechte hand und modis". Am 19.09. zog der Treff in Team Dogi ein
   und die Community kam als vierte dazu -- die Zahl war ab da falsch,
   die Wand richtig. Verglichen wird jetzt die MENGE der Rollen, nicht
   ihre Anzahl: Eine Zahl sagt beim Scheitern "3 erwartet, 4
   gefunden" und verschweigt, WELCHE.

Beide Male war die Seite richtig und die Pruefung veraltet -- das ist
dieselbe Krankheit wie bei den Portnummern und bei pruef-entwicklung:
ein Name oder eine Zahl, abgeschrieben an einer zweiten Stelle, die
niemand mitpflegt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 22:55:41 +02:00
DogFatherGitandClaude Opus 5 6e46a08543 Portnummern werden abgeleitet, nicht mehr vergeben
Gemessen: 165 Pruefdateien, 129 verschiedene Nummern -- NEUNZEHN
doppelt, vier davon dreifach. Niemand hatte das gewollt; jede neue
Pruefung wurde von einer vorhandenen abgeschrieben, und die Nummer kam
mit. Meine eigene Notiz sagte "sieben" -- auch eine Bestandsliste
altert.

Der Waechter faengt den Schaden ab, aber er kann nur melden, was schon
passiert ist: Zwei Pruefungen mit derselben Nummer koennen nie
gleichzeitig laufen, und ein liegengebliebener Prozess der einen laesst
die andere abbrechen mit einer Meldung, die wie ein Befund aussieht.
Genau das ist mir am 20.09. zweimal passiert.

Jetzt leitet jede Datei ihre Nummer aus ihrer STELLE IM ALPHABET ab
(eigenerPort in helfer-port.mjs), zwei je Datei. Nicht ueber eine
Pruefsumme: Bei 165 Namen in 4900 Nummern waeren nach dem
Geburtstagsproblem rund DREI Zusammenstoesse zu erwarten -- ein Hash
tauscht eine sichtbare Doppelung gegen eine unsichtbare. Die Stelle im
Alphabet ist eindeutig von der Bauart her.

--- ZWEI FEHLER AUF DEM WEG, BEIDE LEHRREICH -------------------------

1. DER ERSTE VERSUCH WAR GRUEN UND KAPUTT. Ersetzt wurde mit einem
   Muster: "([^"]*4231[^"]*)". Das hielt

     { host: "127.0.0.1", port: 4231, path: "/404.html" }

   fuer eine Zeichenkette -- ein Muster kann eine oeffnende nicht von
   einer schliessenden Anfuehrung unterscheiden. Heraus kam

     { host: "127.0.0.1`, port: ${PORT}, path: `/404.html" }

   also GUELTIGER Code ohne port-Feld. `node --check` sagte gruen fuer
   alle 164 Dateien. Aufgefallen ist es erst, weil ich vier Vertreter
   gegen eine vorher gemessene Grundlinie laufen liess: pruef-schranke
   39/0 vorher, 38/1 nachher.

   Alles zurueckgenommen und mit einem Zerleger neu gemacht, der weiss,
   ob eine Stelle Code, Zeichenkette, Vorlage, Kommentar oder
   regulaerer Ausdruck ist. In pruef-ics stand die Nummer in einem
   regulaeren Ausdruck -- der wird jetzt gebaut statt hingeschrieben.

2. EIN MODUL, DAS BEIM IMPORTIEREN ARBEITET, IST EINE FALLE. Der
   zweite Durchgang importierte den ersten, um seine Mechanik zu
   benutzen -- und fuehrte dessen Hauptlauf gleich mit aus. Die
   zweiten Nummern wurden dadurch als erste behandelt, zwei Aufrufe
   bekamen dieselbe Nummer, und in pruef-content stand `const PORT`
   zweimal.

--- WAS DAS DAUERHAFT HAELT -----------------------------------------

pruef-portnummern.mjs (neu, 8 Pruefungen) fragt nicht "welche Nummern
sind doppelt", sondern "wer traegt ueberhaupt noch eine von Hand ein"
und "wer startet einen Server, ohne seine Nummer abzuleiten". Die
zweite Frage hat sofort etwas gefunden, das in KEINER Doppelungsliste
stand: pruef-push-weg belegte 4341 und 4342, rief den Waechter aber
gar nicht auf -- dieselbe Nummer wie pruef-agentur. Eine Liste zeigt
nur, was auf ihr steht.

Mit Gegenprobe: Eine unbekannte Datei bekommt keine geratene Nummer,
sondern einen Abbruch, und eine dritte Nummer je Datei gibt es nicht.

--- NACHGEMESSEN ----------------------------------------------------

Sechzehn Pruefungen gegen ihre vorher gemessene Grundlinie, je eine
Vertreterin jeder umgestellten Bauweise (eine Nummer, zwei Nummern,
Nummer in einer Zeichenkette, in einer Vorlage, in einem regulaeren
Ausdruck, dynamische Einfuhr, Nachtlauf mit zwei Laeufen):

  crew-adresse 132/0 · schranke 39/0 · content 45/0 · entwicklung 46/0
  anruf 127/0 · ics 37/0 · push-weg 20/0 · arten 28/0 · video 67/0
  kanalzeile 14/0 · agentur 62/0 · spicy 83/0 · creator-anlegen 50/0
  push-ziel 10/0 · portnummern 8/0

Alle exakt wie vorher. Zwei waren schon vorher rot und sind es
unveraendert geblieben (crew-wand-bild 41/4, teilen 14/3) -- per
`git stash` belegt, nicht angenommen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 22:51:21 +02:00
DogFatherGitandClaude Opus 5 d79cb9196b Die Entwicklungs-Pruefung war rot, ohne dass etwas kaputt war
Sie hielt seit dem 19.09. eine Namensliste fest:

  !["Eure Aufgaben", "Talente"].includes(k.name)

Als ein Modi eine eigene Kachel bekam -- "Deine Aufgaben", weil
"Eure" aus seiner Sicht falsch ist -- wurde sie rot. Nichts war
kaputt, der Name hatte sich geaendert. Das ist die abgeschriebene
Liste zum dritten Mal in diesem Haus, und diesmal traf sie eine
Pruefung: Eine rote Pruefung, die rot BLEIBT, gewoehnt einem das
Hinsehen ab und ist damit schaedlicher als gar keine.

Erst nachgemessen, ob die Kachel ueberhaupt falsch ist: In
workspace-entwicklung.js steht

  const personen = leitung ? db().prepare(...) : [];

Ein Modi bekommt dort eine LEERE Liste -- er sieht auf der Seite nur
sich selbst. Die Kachel war also richtig, die Pruefung nicht.

An ihre Stelle treten zwei Messungen:

1. DAS VERSPRECHEN STATT DES NAMENS. Filipe hatte gemeldet, dass auf
   der Kachel "die Antworten sieht nur du" stand und sie trotzdem auf
   eine Seite mit fremden Namen fuehrte. Das ist eine Eigenschaft des
   Untertitels, nicht des Namens. Wer morgen eine Kachel "Dein Kopf"
   nennt und dasselbe verspricht, ist mitgeprueft -- die Namensliste
   haette ihn durchgelassen.

2. DIE ECHTE GRENZE, die bisher NIEMAND gemessen hat. Ob eine Kachel
   richtig zeigt, ist Beschriftung; ob die Seite dahinter fremde Namen
   herausgibt, sind Daten -- und nur das schuetzt jemanden wirklich.
   Gemessen wird jetzt beides: Ein Modi bekommt auf /entwicklung/lage
   NIEMANDEN (0), DogFather und die rechte Hand bekommen sehr wohl
   welche (2). Die zweite Zeile ist die Gegenprobe zur ersten -- waere
   der Filter einfach zu, saehe auch die Leitung nichts, und die
   Modi-Zeile waere trotzdem gruen.

Nebenbei: Beim ersten Lauf stand `lage.code === 200` statt
`lage.status` -- der Helfer heisst anders. Beide Zeilen wurden dadurch
ROT, obwohl die Zahlen (2 und 0) von Anfang an stimmten. Der richtige
Ausgang: lieber laut scheitern als still bestaetigen.

pruef-entwicklung: 46 Pruefungen, 0 Fehler (vorher 43 mit 1 Fehler).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 22:32:44 +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 9d086eccaf Chat: das Buehnenbild scheint durch, jeder Account bekommt seine Kachel
Hinter jeder Seite steht ohnehin eine Buehne (neun Szenen, fuer den
Chat die Lounge). Sie lag bisher hinter einer deckenden Flaeche --
vorhanden, geladen, unsichtbar. Sie durchscheinen zu lassen kostet
keine einzige Datei mehr, und auf der Adresse von Team Dogi kommt
damit von selbst deren eigene Fassung.

Das geht aber NUR, wenn der Text auf einer deckenden Kachel steht.
Sonst liegt Schrift auf einem Foto: an der dunklen Stelle lesbar, an
der hellen nicht, und beim Scrollen wechselt es. Filipes zweiter Satz
("die texte sollen immer in einer kachel sein") ist deshalb kein
Zusatzwunsch, sondern die Bedingung fuer den ersten.

Und jeder Account waehlt seinen Ton. Zwoelf Stueck, alle gleich
dunkel und gleich gesaettigt -- sie unterscheiden sich im Farbton und
in sonst nichts. Ein freier Farbwaehler klingt grosszuegiger und ist
die schlechtere Loesung: Mit ihm laesst sich Schwarz auf Schwarz
einstellen oder Neongelb, das allen anderen in die Augen sticht. Die
Kachel gehoert einem selbst, GESEHEN wird sie von allen anderen.
Gemessen: der schlechteste Kontrast liegt bei 13,9:1 (noetig 7).

Drei eigene Fehler beim Bauen, alle von der Pruefung gefunden:

1. Es gibt ZWEI Regeln fuer dieselbe Kachel (Grundform und
   Feinschliff). Ich hatte nur die erste umgestellt, die zweite gewann
   -- die eigene Kachel waere durchsichtig geblieben.
2. Die Pruefung las backgroundColor und pruefte den Alphawert. Eine
   Kachel mit einem VERLAUF hat dort rgba(0,0,0,0); sie meldete
   "durchsichtig" bei einer Kachel, die voellig deckt. Jetzt werden
   zwei Bildpunkte verglichen, einmal mit und einmal ohne Buehnenbild
   -- das misst die Sache selbst, nicht ihren Stellvertreter.
3. Dieselbe Pruefung suchte nur die rgba-Schreibweise. Chrome gibt
   das Ergebnis von color-mix als color(srgb r g b / a) zurueck; der
   Rueckfall war "Alpha 1", und sie meldete "deckt" bei einer
   Flaeche, die durchscheint. Genau das Gegenteil.

pruef-chatkachel.mjs: 27 Pruefungen, mit eingebauter Gegenprobe (auf
der freien Flaeche MUSS sich etwas aendern, sonst misst der Vergleich
nichts). pruef-chat-optik und pruef-erwaehnung unveraendert gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:58:50 +02:00
DogFatherGitandClaude Opus 5 9c96612321 Am Handy lag Text auf Text -- im Satz ueber Vertraulichkeit
Auf der Befindens-Seite ueberlagerten sich bei 430 px zwei Absaetze
um 18 Pixel. Betroffen war ausgerechnet "Deine Antworten liest
niemand ausser dir" -- also der Satz, in dem das Vertrauen entsteht,
das die ganze Seite braucht.

Ursache war eine feste Zahl: -18px Abstand, gerechnet gegen die
26 px, die das Element darueber mitbringt. In einer Kopfzeile setzt
start.css dieses margin-bottom aber auf 0. Aus 26 minus 18 wurde
0 minus 18. Zwei fuer sich richtige Regeln, und dazwischen ein
Schaden, den keine von beiden verursacht.

Die Lehre ist nicht "-18 auf -8 aendern" -- das waere dieselbe Zahl
mit anderem Wert und beim naechsten Zusammentreffen wieder falsch.
Jetzt bestimmt der Absatz davor seinen Abstand selbst, und nur dann,
wenn der Zusatz wirklich folgt (:has). Acht Pixel, in jeder Umgebung.

Gefunden hat es ein Bildschirmfoto, nicht das Lesen: Beide Regeln
sehen einzeln vernuenftig aus. Die Messung steht jetzt fest in
pruef-befinden.mjs (113/0), mit Gegenprobe: Mit dem alten Wert wird
sie rot, ohne ihn gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:48:46 +02:00
DogFatherGitandClaude Opus 5 2719bd9b88 Wie geht es dir: achtzehn Fragen in sechs Feldern, eine Zusammenfassung
Sechs Fragen mehr (jetzt 18), und alle in sechs Feldern gegliedert:
Last & Erholung, Miteinander, Sinn & Anerkennung, Klarheit &
Rueckhalt, Grenzen & Sicherheit, Weiterkommen & Ausblick. Die Felder
sind nicht ausgedacht -- es sind die Gebiete, die die Forschung zu
belasteten Rollen durchgehend abfragt.

Die drei neuen Luecken, die sie schliessen: Schlaf (zeigt Erschoepfung
frueher als jede andere Frage), Widersprechen (der Kern dessen, was
psychologische Sicherheit heisst) und Mitreden (viel Anforderung bei
wenig Einfluss ist die Kombination, aus der Erschoepfung entsteht).
Jede neue Frage hat ihre belegte Einordnung -- eine Frage ohne
Grundlage ist eine Frage, die jemand gut fand.

DIE ROTATION MUSSTE NEU. Der Katalog ist nach Themen sortiert; wer
daraus drei aufeinanderfolgende nimmt, bekommt drei aus demselben
Feld. Jetzt wird der Ring vorher verzahnt -- erst je eine Frage aus
jedem Feld, dann je eine zweite. Ein Fenster trifft damit von selbst
verschiedene Felder.

Ein erster Anlauf reservierte feste Plaetze fuer die kernlosen
Felder. Begruendet mit einer Auswertung je Feld, die es gar nicht
gibt -- und er kostete: zwoelf Runden, bis jede Frage einmal gestellt
war, fast ein halbes Jahr. Gefunden hat das pruef-befinden.mjs, nicht
das Nachdenken. Mit dem verzahnten Ring und vier Plaetzen je Runde
sind es vier Runden.

DIE EINE ZUSAMMENFASSUNG AM ENDE, nicht eine je Kategorie. Sie sagt
in dieser Reihenfolge: die Lage in einem Satz, was traegt (benannt,
nicht als Zahl), hoechstens EINE Sache zum Hinschauen, ein Schluss,
der zur Lage passt. Umgekehrt waere es eine Maengelliste mit
Trostpflaster, und so etwas beantwortet man beim naechsten Mal nicht
mehr ehrlich.

ZUR FRAGE NACH DER BESTEN KOSTENLOSEN MOEGLICHKEIT: bewusst KEINE
KI. Das sind Gesundheitsdaten (wer nachts wach liegt, wer angefeindet
wird, wer ans Aufhoeren denkt) -- deshalb sind sie im ganzen Haus als
nurSelbst markiert. Kostenlose KI-Angebote bezahlt man mit den Daten.
Ein Sprachmodell erfindet ausserdem, und zwar ueberzeugend. Und ein
fremder Dienst faellt aus. Jeder Grund reicht einzeln. Die
Begruendung steht ausfuehrlich in workspace-befinden-resuemee.js.

Nebenbefund behoben: Die Zusammenfassung blieb direkt NACH einer
abgeschlossenen Runde leer -- da ist keine Antwort mehr "frisch".
Genau der Moment, in dem man sie sehen will.

Auch eine Pruefung korrigiert: Sie verbot den Text "entwicklung.js"
irgendwo in der Datei und schlug an einem Kommentar an, der die
Serverdatei benennt. Sie misst jetzt die Skript-Quellen.

pruef-befinden.mjs 112/0, pruef-resuemee.mjs 35/0 (neu).

Offener Befund, aelter als diese Aenderung: pruef-entwicklung.mjs
meldet "ein Modi: keine Kachel fuehrt mehr ersatzweise auf die
Entwicklungsseite" -- auch ohne diese Commits.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:45:14 +02:00
DogFatherGitandClaude Opus 5 1bdeccc054 Highlights: drei Accounts nebeneinander, nach Zeit geteilt
DogFather, HasiDog und DogFather Clips haben eigene Zuschauer und
einen eigenen Ton -- das steht so schon an KANAELE im Server. Eine
gemeinsame Galerie behauptete, sie waeren ein Topf; wer fuer Clips
schneidet, suchte in jeder Reihe nach den Kacheln, die ihn angehen.

Jetzt drei Spalten nebeneinander, jede zuklappbar, jede mit ihrem
Handle und ihrer Zahl. Eine vierte Spalte gibt es nur, wenn sie
gebraucht wird: Bilder ohne TikTok-Link gehoeren zu keinem Account,
und sie verschwinden zu lassen waere der schlimmere Fehler.

Die Reihenfolge kommt vom SERVER. Der Browser hatte dafuer eine
eigene kleine Liste (KANAL_WORT) -- dieselben drei Namen in anderer
Reihenfolge, ohne Handles. Beim vierten Account waere genau diese
Kopie die vergessene.

Dazu eine Zeitleiste: Aktuell (heute), Diese Woche, Dieser Monat,
Dieses Jahr, Alles. Kalenderzeitraeume, keine Rueckblicke -- wer am
Dienstag "diese Woche" fragt, meint Montag und Dienstag. Jeder
Knopf traegt seine Zahl; ohne sie klickt man ins Leere und weiss
nicht, ob es am Filter lag.

Und beim Anlegen laesst sich der Account waehlen -- fuer Bilder und
Momente ohne Link. Bei einem TikTok-Link leitet der Server ihn
weiterhin aus dem Handle ab; das ist genauer, weil niemand sich
vertippen kann.

Beim Bauen gemessen statt vermutet: Der Spaltenkasten lag IM
Galerie-Raster von #liste und bekam eine Zelle von 376 px --
Elternbreite 1160. Die drei standen untereinander. Die Galerie
gehoert jetzt in die Spalte, nicht um sie herum.

pruef-highlights.mjs: 26 Pruefungen, mit Gegenproben (Gast bekommt
die Liste nicht, erfundener Account wird abgelehnt, zweiter Klick
hebt den Filter auf). pruef-video.mjs weiterhin 67/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:28:22 +02:00
DogFatherGitandClaude Opus 5 d77dd216c5 Ein Termin von-bis belegt jeden Tag dazwischen
Zwei Fehler, nicht einer.

Der sichtbare: Die Kachel stand nur am Anfangstag. Wer im
Monatsraster auf den Mittwoch sah, sah nichts -- obwohl die Aktion
von Montag bis Freitag lief.

Der unsichtbare, und der ist der schlimmere: Der SERVER suchte
Eintraege, deren ANFANG im sichtbaren Fenster liegt. Eine Aktion vom
28.09. bis zum 05.10. kam im Oktober deshalb ueberhaupt nicht an --
nicht "nur am ersten Tag markiert", sondern gar nicht da. Wer im
Oktober plante, sah eine freie Woche, die belegt war. Jetzt
entscheidet die UEBERSCHNEIDUNG, nicht der Anfang.

Gebaut wurde es in nachTag() -- der einzigen Stelle, an der
Eintraege auf Tage verteilt werden. Monat, Woche, Liste und
Zeitstrahl holen sich alle dort; vier Ansichten einzeln
nachzuruesten waeren vier Stellen, an denen die fuenfte vergessen
wird.

Das Ende wird abgeleitet, nicht gepflegt: aus event_ende ODER aus
Uhrzeit plus Dauer. Ein Live von 22:00 ueber vier Stunden endet um
02:00 am naechsten Tag -- das stand bisher nirgends, obwohl die
Zahlen da waren.

Der Tagesdialog filterte selbst auf den Anfangstag. Im Raster war
der Mittwoch markiert, tippte man ihn an, stand da "An diesem Tag
steht nichts." Jetzt fragt er dieselbe Stelle wie das Raster.

pruef-zeitraum.mjs: 16 Pruefungen, beide Fehler einzeln, mit drei
Gegenproben (vor dem Anfang, nach dem Ende, Punkttermin).
pruef-terminregel.mjs weiterhin 35/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:20:18 +02:00
DogFatherGitandClaude Opus 5 947ea7ff49 Fertige Vorschlaege lassen sich wechseln
Bisher kamen ALLE auf einmal -- damit gab es nichts zu wechseln, die
Liste war entweder ganz da oder ganz weg. Bei 17 Vorschlaegen (Brett
"regeln") ist eine Wand aus Karten ausserdem das Gegenteil von
"uebernehmen, was passt".

Jetzt vier auf einmal, und ein Knopf holt die naechsten vier. Der
Server rechnet die Stelle mit Rest -- nach dem letzten kommt wieder
der erste. Es gibt also keinen Zustand "durchgeklickt, jetzt leer".

Bei hoechstens vier offenen Vorschlaegen erscheint der Knopf gar
nicht: Ein Knopf, der dieselben Karten noch einmal malt, ist ein
Knopf, der nichts tut.

Was es NICHT ist: Die Vorschlaege werden nicht erzeugt. Sie sind ein
geschriebener Vorrat von 113 Stueck auf 16 Brettern.

pruef-vorschlaege.mjs: 21 Pruefungen. Die entscheidende vergleicht
die Titel vorher und nachher -- ein Knopf, der nur gedrueckt werden
kann, besteht jede Pruefung, die nur nach dem Knopf sucht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:15:49 +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 9e9ed67c4a Keine Sackgassen -- fuer JEDE Rolle, nicht nur fuer den Gast
Filipe: "Es darf keine Sackgassen geben."

pruef-community-sicht prueft genau das -- aber nur fuer den GAST.
Ein Modi hat 25 Kacheln, eine rechte Hand 30, DogFather 39. Keine
dieser drei Rollen war je darauf geprueft worden, ob ihre Seiten auf
etwas verweisen, das sie nicht oeffnen darf.

Und genau dort ist es zweimal passiert: Am 19.09. warf "Klingelt
nichts?" ALLE DREI Team-Rollen auf die Startseite zurueck, und der
Kalender-Verweis fuehrte die Community seit jeher ins Leere. Beides
hat jemand zufaellig gefunden, nicht eine Pruefung.

Neu: server/pruef-sackgassen.mjs -- 11/0.
  4 Rollen, 126 Seitenansichten, 582 sichtbare Wege, 0 ins Leere.

DREIMAL ABGELEITET STATT AUFGEZAEHLT:
  Die ROLLEN kommen aus der Anmeldewand (data-rolle), nicht aus einer
    Liste. Kaeme eine fuenfte dazu, stuende sie sonst nicht drin und
    niemand wuerde es merken.
  Die SEITEN kommen aus der Rechtetafel -- derselben, nach der der
    Server entscheidet. Keine zweite Liste, die auseinanderlaufen kann.
  Die BRETTER hinter bereich.html kommen aus den Kacheln dieser Rolle.

Die Altersbestaetigung des Gastes wird an der ANTWORT erkannt
(400 + alter_offen), nicht an der Rolle: Eine Liste "wer bestaetigen
muss" waere morgen falsch, wenn die Schranke noch woanders gilt.

Und sie braucht weder HTTPS-Front noch umgebogenen Namensdienst: Das
Haus einer Person kommt aus ihrer ROLLE, nicht aus der Adresse. Ein
Modi ist auch auf 127.0.0.1 im Crew-Haus.

GEGENPROBE: Ein erfundener Weg auf eine gesperrte Seite wird gefunden.
Ohne sie waere "0 ins Leere" auch dann wahr, wenn nichts geladen haette
-- deshalb steht die Zahl der Wege zusaetzlich in der Bedingung.
2026-09-20 12:52:51 +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