Commit Graph
594 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 018d02c3b8 Vorlagen anpassen: Frist, dauerhaft und eine Anmerkung
VanVan im Support, Meldung #6, zweite Haelfte -- der Rest, der heute
frueh ausdruecklich offen stehen blieb: „Bei den Vorlagen laesst sich
weder die Frist anpassen noch ‚dauerhaft' einstellen, und eine
Anmerkung fehlt auch."

EIN ZWEITER KNOPF, NICHT EIN FENSTER FUER ALLE

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

DAS FENSTER IST DAS DES HAUSES

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

DREI ENTSCHEIDUNGEN, DIE NICHT NAHELIEGEND WAREN

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

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

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

EIN FUND, DEN DIE PRUEFUNG GEMACHT HAT

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

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

GEPRUEFT

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

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

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

EINE TABELLE STATT NEUER SPALTEN

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

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

DREI BILDER IN EINER ANFRAGE

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

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

ZWEI FUNDE, DIE DIE PRUEFUNG GEMACHT HAT UND NICHT ICH

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

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

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

DREI WEITERE ROTE ZEILEN, DIE NICHT ZU DIESEM UMBAU GEHOERTEN

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

GEPRUEFT

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

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

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

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

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

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

GEAENDERT

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

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

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

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

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

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

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

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

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

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

pruef-struktur meldete:

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

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

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

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

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

    Server-Routen eingelesen:  401 -> 414

GEAENDERT

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

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

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

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

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

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

GEPRUEFT: pruef-struktur 102 ok, 0 Fehler.

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

DIE WICHTIGSTE FRAGE STAND GLEICH AM ANFANG

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

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

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

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

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

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

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

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

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

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

WAS DABEI AUFGEFALLEN IST -- zwei Fehler, beide stumm

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

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

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

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

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

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

AUSSERDEM BERICHTIGT

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

GEPRUEFT: 216 + 41 = 257 Pruefungen, 0 Fehler

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

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

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

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

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

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

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

GEPRUEFT: 206 Pruefungen, 0 Fehler (vorher 194)

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

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

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

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

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

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

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

JETZT

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

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

DREI ENTSCHEIDUNGEN DAHINTER

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

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

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

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

WAS MIR DABEI AUFGEFALLEN IST

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

AUSSERDEM

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

GEPRUEFT: 194 Pruefungen, 0 Fehler (vorher 168)

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

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

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

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

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

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

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

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

DIE VIER OFFENEN PUNKTE DER VORLAGE

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

WAS DER SAUM MICH GELEHRT HAT

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

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

AUSSERDEM BEHOBEN

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

GEPRUEFT: 168 Pruefungen, 0 Fehler (vorher 141)

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

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

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

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

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

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

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

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

WAS ANDERS GEBAUT IST, ALS ES NAHELAG

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

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

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

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

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

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

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

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

ZWEI BEFUNDE KAMEN AUS DER MESSUNG, NICHT AUS DEM NACHDENKEN

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

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

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

SIE HAT ETWAS GROESSERES GEFUNDEN ALS ZWEI UEBERFLUESSIGE KNOEPFE.

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

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

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

WAS ICH BEINAHE FALSCH GEMACHT HAETTE

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

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

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

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

ALSO WIRD IHR SATZ WAHR GEMACHT

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

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

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

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

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

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

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

    eine Bewerbung bleibt eine Bewerbung (abgelehnt -> abgelehnt)

ZWEI EIGENE FEHLER, BEIDE VON DER MESSUNG GEFUNDEN:

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

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

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

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

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

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

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

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

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

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

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

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

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

DER DRITTE AUSGANG, UND ER WAR NOETIG

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

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

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

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

AM LAUFENDEN SYSTEM NACHGESEHEN (nur gelesen)

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

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

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

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

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

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

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

DERSELBE WEG WIE BEIM MELDEN, NICHT EIN ZWEITER

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

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

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

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

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

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

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

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

GEPRUEFT

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

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

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

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

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

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

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

DIE URSACHE STAND IM QUELLTEXT, mit Kommentar und allem:

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

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

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

    👍 Patrick · ❤️ VanVan, Miss

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

GEMESSEN DANACH:

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

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

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

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

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

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

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

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

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

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

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

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

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

GEAENDERT

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

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

NACH DEM UMBAU GEMESSEN:

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

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

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

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

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

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

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

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

WAS WIRKLICH DASTEHT (320x568, laufende Sendung):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

AM PRODUKT IST NICHTS GEAENDERT.

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

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

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

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

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

    pruef-fingermass: 5 Pruefungen, 0 Fehler

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

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

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

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

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

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

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

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

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

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

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

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

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

1. ER HAT OHNE FINGER GEMESSEN

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

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

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

Gemeldet wurde viermal (einmal je Rolle) dasselbe:

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

Am echten Bildschirm nachgemessen statt der Zahl geglaubt:

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

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

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

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

3. UND DIE AUSNAHME PRUEFT SICH IN BEIDE RICHTUNGEN

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

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

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

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

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

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

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

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

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

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

WAS GEAENDERT IST

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ES LAG AM SYSTEM.

WAS GEMESSEN WURDE (nicht vermutet)

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

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

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

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

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

WAS GEAENDERT IST

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

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

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

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

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

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

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

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

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

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

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

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

WAS JETZT NACHGEZAEHLT WIRD

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

WAS NICHT NACHGESEHEN WERDEN KONNTE

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

GEPRUEFT (alles einzeln, kein Gesamtlauf)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DABEI IST MIR DAS EIGENTLICHE PROBLEM AUFGEFALLEN

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

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

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

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

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

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

ZWEI DINGE AM DETEKTOR IN pruef-struktur

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

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

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

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

SCHRITT FUER SCHRITT NACHGEMESSEN, statt der Meldung zu glauben:

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

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

DER FEHLER WAR EIN NOTNAGEL IN DER PRUEFUNG:

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

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

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

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

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

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

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

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

DIE FRAGE IST EINE MESSUNG, KEINE ZUSTAENDIGKEIT

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

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

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

AN DER NOTBREMSE, NICHT IN 179 DATEIEN

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

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

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

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

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

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

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

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

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

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

1. DER HAKEN HAT KEINE DATEIENDUNG

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

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

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

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

2. EIN MESSFEHLER VON MIR, UND ER GEHOERT AUFGESCHRIEBEN

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

LOCH 2 — IHR AUSDRUCK GILT JE ZEILE

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

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

Beim letzten laeuft das Zitat ueber eine Zeichenketten-Verkettung.

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

LOCH 3 — EINE AUSNAHME, DIE EINEN FUND VERSCHLUCKT HAT

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

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

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

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

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

UND EIN VIERTES, BEIM MESSEN AUFGEFALLEN

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

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

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

Sechs echte Stellen berichtigt, vier neue Gegenproben.

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

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

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

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

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

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

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

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

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

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

1. pruef-browser — WINDOWS BLOCKIERT WEBKIT

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

JEDE EINZELN NACHGELAUFEN — 37 Laeufe:

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

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

EINE ZEITBOMBE GEFUNDEN UND ENTSCHAERFT

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

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

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

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

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

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

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

1. pruef-breiten MASS OHNE FINGER

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

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

2. DER VERDECKUNGS-FINDER KANNTE KEINE ROLLKAESTEN

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

3. UND EIN ECHTER BEFUND, ZWEIMAL

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

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

4. MEINE EIGENE WACHE WAR BLIND — ZWEIMAL

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

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

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

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

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

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

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

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

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

WARUM EIN ERSTER ANLAUF ZURUECKGENOMMEN WURDE

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

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

DIE UNTERSCHEIDUNG LAEUFT AN MERKMALEN, NICHT AN EINER LISTE

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

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

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

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

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

DIE WACHE DAZU

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

GEPRUEFT

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

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

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

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

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

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

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

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

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

URSACHE

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

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

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

WARUM ES NIEMAND GEMERKT HAT

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

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

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

EINE ZWEITE WACHE, WEIL ICH SELBST HINEINGELAUFEN BIN

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

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

pruef-kreislauf STELLT JETZT DIE RICHTIGE FRAGE

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

NEBENBEFUND IN pruef-ics

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

GEPRUEFT

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

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

GEGENPROBEN, DIE WIRKLICH ROT WERDEN

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

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

Datenbank vorher gesichert. Keine Schemaaenderung.

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

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

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

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

WAS JETZT GILT

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

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

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

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

NEBENBEI GEFUNDEN UND MIT REPARIERT

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

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

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

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

GEPRUEFT

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

GEMESSEN, beide Faelle:

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

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

ZWEI NACHZUEGLER AUS DEM SICHT-WEG VON GESTERN

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DANN NACHGESTELLT (pruef-abzeichen, Abschnitt 8):

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

Genau sein Befund.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ZWEI FOLGEN, und die zweite faellt leicht durchs Raster

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

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

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

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

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

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

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

ZWEI EIGENE FEHLER, beide von Pruefungen gefunden

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

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

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

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

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

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

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

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

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

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

WAS JETZT DASTEHT

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

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

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

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

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

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

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

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

Haustrennung gilt: `darfSchreibenMit` je Zeile.

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

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

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

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

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

    Aufgaben mit Verantwortlichem:     11
    davon OHNE Zuteilungszeile:         8

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

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

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

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

DREI TEILE

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ZWEI DINGE WAREN EINS, DIE GETRENNT GEHOEREN

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

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

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

UND DIE ANDERE HAELFTE: NIEMAND SAGTE ES IHR

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

IHRE ZWEITE BEOBACHTUNG, EBENFALLS GEMESSEN

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

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

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

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

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

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

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

DER SCHLIMMSTE FUND: DIE UHR DES TELEFONS

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

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

WEITER

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

DREI EIGENE FEHLER UNTERWEGS, alle im Text festgehalten

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

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

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

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

ZWEI ENTSCHEIDUNGEN

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

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

DER FUND NEBENBEI

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

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

GEPRUEFT

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-30 12:14:23 +02:00