Benachrichtigungen wecken das Telefon wieder: Urgency je Art

Diene hat gemeldet: "Die Benachrichtigungen werden nicht angezeigt,
wenn neue Nachrichten reinkommen. Erst, wenn man die App oeffnet."

Alles Messbare war gruen: Der Service Worker zeigt die Meldung bei
geschlossener App (pruef-push-zu, 13 Pruefungen), jede Anmeldung im
Haus stand auf fehler = 0, der Push-Dienst quittierte mit 201. Nur
den Kopf auf der Leitung hat nie jemand gemessen:

    Urgency: normal

Beide Dienste behandeln das ausdruecklich als "darf warten".
Android/FCM haelt solche Meldungen zurueck, solange das Telefon
doest, und stellt sie zu, wenn es aufwacht -- typischerweise beim
Entsperren oder Oeffnen der App. Apple/APNs nennt es "verzoegert,
gebuendelt oder gedrosselt". Das ist Dienes Satz, Wort fuer Wort,
und es stand als Vorgabe im eigenen Quelltext.

zuletzt_ok konnte das nie zeigen: Es beweist, dass der DIENST
angenommen hat, nicht dass das GERAET etwas angezeigt hat.

Bis hierher hing die Dringlichkeit an der Ruheregel (dringend =
regel === "nie"), mit der Begruendung, "darf das nachts stoeren?"
und "darf das warten?" haetten dieselbe Antwort. Haben sie nicht:
Ein Chat um 3 Uhr soll schweigen, um 14 Uhr aber nicht vierzig
Minuten liegen bleiben. Jetzt zwei Felder -- in DERSELBEN Zeile
derselben Artenliste, damit sie nicht auseinanderlaufen koennen.

10 von 19 Arten sind eilig (Anruf, Chat, Erwaehnung, Support, Hilfe,
Termin, Wecker, zweimal Live, Probe). Die anderen neun duerfen
warten -- waere alles eilig, waere nichts mehr eilig.

DIE FALLE BEIM BEHEBEN: dringend steuerte auch die Haltbarkeit
(TTL 150). Ein einfach auf "dringend" gestellter Chat waere nach
150 s verfallen -- wer sein Telefon drei Minuten aus hat, haette die
Nachricht GAR nicht mehr bekommen. Aus "zu spaet" waere "nie"
geworden. Deshalb sind eilig und kurzlebig getrennt; kurzlebig
bleibt genau beim Anruf und der Probe.

Der alte Name kracht jetzt, statt still "normal" zu liefern.

pruef-push-eilig.mjs (neu, 13 Pruefungen): die Entscheidung je Art
unabhaengig notiert statt aus der Artenliste abgelesen, jede Art
muss eine Entscheidung haben, und der Kopf wird durch
benachrichtige() hindurch an einem nachgebauten Push-Dienst
gemessen. Gegenprobe gelaufen: ohne das Feld meldet sie
"chat_nachricht geht mit Urgency: normal hinaus", 4 Fehler.
Die Uhr ist dort eine Eingabe, keine Annahme -- die Zeitzone wird so
gewaehlt, dass der Lauf immer auf 12 Uhr faellt, sonst waere die
Pruefung nachts rot ohne Befund.

pruef-anruf-klingelt 25 -> 26. Dabei aufgefallen: Eine ihrer
Pruefungen war gruen, obwohl die Zeile aus dem Code verschwunden war
-- sie stand nur noch in einem Kommentar, der die alte Fassung
zitiert. Quelltextpruefungen lesen dort jetzt ohne Kommentare.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-10-03 12:58:01 +02:00
co-authored by Claude Opus 5
parent db8dd2fbea
commit 73f9b24793
4 changed files with 420 additions and 36 deletions
+50 -14
View File
@@ -63,6 +63,24 @@ import { fileURLToPath } from "node:url";
const REPO = join(dirname(fileURLToPath(import.meta.url)), "..");
const lies = (p) => readFileSync(join(REPO, p), "utf8");
/* ---- NUR DER CODE, OHNE DIE ERZAEHLUNG DRUMHERUM (03.10.2026) -------
Diese Datei prueft Quelltext mit Mustern. Das ist schnell und
braucht keinen Server -- hat aber eine Luecke, die heute
aufgefallen ist: Die Pruefung "und zwar an derselben Bedingung wie
die Nachtruhe" war gruen, OBWOHL die Zeile aus dem Code
verschwunden war. Sie stand nur noch in einem Kommentar, der die
alte Fassung zitiert -- und ein Muster sieht den Unterschied
nicht.
Das ist die dritte Sorte gruener Haken: nicht uebersprungen, nicht
falsch geprueft, sondern am Beleg vorbei. Deshalb werden
Kommentare vorher entfernt. Was hier geprueft wird, muss laufender
Code sein. */
const nurCode = (t) => t
.replace(/\/\*[\s\S]*?\*\//g, " ")
.replace(/(^|[^:])\/\/.*/g, "$1");
let ok = 0, fehl = 0;
const pruef = (name, bedingung, zusatz = "") => {
if (bedingung) { ok++; console.log(` OK ${name}`); }
@@ -104,29 +122,47 @@ pruef("und für alles andere bleibt es ruhig",
/* =====================================================================
2. DER VERSAND — Dringlichkeit und Haltbarkeit
===================================================================== */
const krypto = lies("server/workspace-push-krypto.js");
const versand = lies("server/workspace-push.js");
const krypto = nurCode(lies("server/workspace-push-krypto.js"));
const versand = nurCode(lies("server/workspace-push.js"));
pruef("der Transport kennt überhaupt eine Dringlichkeit",
/dringend\s*=\s*false\s*\}\s*=\s*\{\}/.test(krypto),
/eilig\s*=\s*false/.test(krypto),
"vorher stand Urgency fest auf \"normal\"");
pruef("ein dringender Push geht mit Urgency: high hinaus",
/Urgency:\s*dringend\s*\?\s*"high"\s*:\s*"normal"/.test(krypto));
pruef("ein eiliger Push geht mit Urgency: high hinaus",
/Urgency:\s*eilig\s*\?\s*"high"\s*:\s*"normal"/.test(krypto));
pruef("und verfällt, wenn der Anruf vorbei ist",
/TTL:\s*String\(dringend\s*\?\s*Math\.min\(ttl,\s*\d+\)/.test(krypto),
/TTL:\s*String\(kurzlebig\s*\?\s*Math\.min\(ttl,\s*\d+\)/.test(krypto),
"sonst ploppt ein Anruf von vor einer Stunde nachträglich auf");
pruef("der Anruf wird als dringend verschickt",
/schicken\(a,\s*inhalt,\s*paar,\s*ABSENDER,\s*\{\s*dringend\s*\}\)/.test(versand));
pruef("der Anruf wird eilig UND kurzlebig verschickt",
/schicken\(a,\s*inhalt,\s*paar,\s*ABSENDER,\s*\{\s*eilig,\s*kurzlebig\s*\}\)/.test(versand));
/* DIESELBE BEDINGUNG WIE BEI DER RUHEZEIT. „Darf das nachts stören?"
und „darf das warten?" haben dieselbe Antwort -- zwei getrennte
Bedingungen wären die, die beim nächsten Nachschärfen auseinander
laufen. */
pruef("und zwar an derselben Bedingung wie die Nachtruhe",
/const dringend = art === "test" \|\| art === "anruf";/.test(versand));
/* ---- ZWEI FRAGEN, ZWEI FELDER (geändert 03.10.2026) -----------------
Hier stand bis heute das Gegenteil: „Darf das nachts stören?" und
„darf das warten?" hätten dieselbe Antwort, zwei getrennte
Bedingungen wären die, die auseinanderlaufen. Die Vorhersage war
richtig, nur in die andere Richtung — sie laufen auseinander, WEIL
es zwei Fragen sind:
Chat um 3 Uhr nachts -> nicht stören (Ruhezeit greift)
Chat um 14 Uhr -> nicht warten (eilig)
Genau diese Gleichsetzung hat Dienes Meldung verursacht: Weil der
Chat nicht nachts stören darf, bekam er auch tagsüber
`Urgency: normal` — und Android legt das beiseite, bis jemand die
App öffnet. Das Zusammenlegen war die Ursache, nicht der Schutz.
Auseinanderlaufen können die beiden trotzdem nicht: Sie stehen als
`eilig` und `ruhe` in DERSELBEN Zeile derselben Artenliste. */
pruef("der Anruf ist eilig und kurzlebig, beides in einer Zeile",
/\{\s*schluessel:\s*"anruf",\s*eilig:\s*true,[^}]*ruhe:\s*"nie"/.test(versand));
pruef("und die Dringlichkeit wird aus der Artenliste abgeleitet",
/const eilig = eiligRegel\(art\);/.test(versand),
"nicht aus einer zweiten Aufzählung daneben");
/* =====================================================================
3. DER WEG DORTHIN — wird beim Anruf überhaupt geweckt?