Der Handy-Rundgang ist zum ersten Mal bei null Befunden

SECHS SACHEN, UND KEINE DAVON WAR DAS, WONACH ICH GESUCHT HABE.

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

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

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

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

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

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

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

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

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

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

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-22 10:14:25 +02:00
co-authored by Claude Opus 5
parent af56f97f4c
commit 65d278a18e
47 changed files with 830 additions and 558 deletions
+8 -8
View File
@@ -317,14 +317,14 @@
Ein festes `setTimeout` waere eine Zahl aus dem Kopf. Gewartet
wird stattdessen darauf, dass die Auskunft DA ist, und laengstens
drei Sekunden. */
if (window.__ich === undefined) {
let versuche = 0;
const uhr = setInterval(() => {
if (window.__ich !== undefined || ++versuche > 30) {
clearInterval(uhr);
if (window.__ich !== undefined) verteilBandZeigen(personId, name);
}
}, 100);
if (window.__ich === undefined && window.wennIchDaBin) {
/* Benutzt seit dem 22.09.2026 die gemeinsame Wartestelle aus
kopf.js. Vorher stand hier ein eigenes setInterval -- dasselbe
Warten ein zweites Mal geschrieben, und damit die Fassung, die
beim naechsten Umbau nur halb nachgezogen wird. */
window.wennIchDaBin().then((da) => {
if (da) verteilBandZeigen(personId, name);
});
return;
}
const darf = window.__ich?.darf_verteilen === true;
+49
View File
@@ -2361,3 +2361,52 @@
try { zurueckMerken(location.pathname + location.search); } catch (e) { /* egal */ }
};
})();
/* =====================================================================
AUF DIE AUSKUNFT WARTEN (22.09.2026)
=====================================================================
`window.__ich` kommt ueber das Netz. Jede Seite, die etwas davon
abhaengig machen will, steht beim ersten Aufruf vor `undefined` --
und `undefined` ist weder "darf" noch "darf nicht".
Gemessen an zwei Stellen an einem Tag: Auf der Entwicklungsseite
blieb das Verteil-Band unsichtbar, bis man eine Person anklickte;
auf derselben Seite fragte die Kartenliste eine Route ab, die es
fuer einen Modi nicht gibt, und der Browser protokollierte einen
404 bei jedem Aufruf.
Beide hatten dieselbe Ursache und bekamen fast dieselbe Loesung --
ein eigenes `setInterval` je Datei. Zwei Fassungen desselben
Wartens altern unterschiedlich. Deshalb hier EINE:
const ich = await window.wennIchDaBin();
if (!ich) { ... } // auch nach drei Sekunden nichts
KEIN FESTES `setTimeout`. Gewartet wird darauf, dass die Auskunft
DA ist -- und laengstens drei Sekunden, damit eine Seite nicht
ewig haengt, wenn die Anmeldung abgelaufen ist. Der dritte
Ausgang: `null` heisst "wir konnten nicht nachsehen", nicht
"darf nicht".
===================================================================== */
(function () {
'use strict';
var wartende = null;
window.wennIchDaBin = function wennIchDaBin() {
if (window.__ich !== undefined) return Promise.resolve(window.__ich);
/* Mehrere Aufrufe teilen sich dieselbe Wartezeit -- sonst laufen
drei Uhren nebeneinander und wecken dreimal. */
if (wartende) return wartende;
wartende = new Promise(function (fertig) {
var versuche = 0;
var uhr = setInterval(function () {
if (window.__ich !== undefined || ++versuche > 30) {
clearInterval(uhr);
wartende = null;
fertig(window.__ich !== undefined ? window.__ich : null);
}
}, 100);
});
return wartende;
};
}());
+37 -10
View File
@@ -448,12 +448,30 @@
nein.addEventListener('click', async () => {
/* EINE ABSAGE OHNE GRUND IST KEINE ANTWORT. Deshalb wird
gefragt -- und ein leeres Feld bricht ab, statt still nichts
zu tun. */
const grund = window.prompt(
`Warum machen wir das nicht?
zu tun.
„${m.titel}“`, '');
if (grund === null) return;
WAR BIS ZUM 22.09.2026 EIN window.prompt(). Der letzte im
Haus, und er hatte drei Nachteile, die man erst am Handy
sieht: Er haelt die ganze Seite an, er sieht auf jedem
Browser anders aus als der Rest der Oberflaeche, und sein
Text laesst sich nicht gliedern -- Titel, Erklaerung und
Feld standen als ein Absatz untereinander.
`frageNach` ist derselbe Dialog wie an den 42 anderen
Stellen. Er kann ausserdem etwas, das prompt() nicht kann:
sagen, was BLEIBT, wenn man absagt. Genau das ist hier die
Frage, die jemand vor dem Klicken hat. */
const antwort = await window.frageNach({
titel: 'Nicht nötig?',
was: '„' + m.titel + '“',
bleibt: 'Die Meldung verschwindet aus der Liste. Dein Grund steht '
+ 'dabei, damit spaeter nachvollziehbar ist, warum.',
ja: 'Absagen',
grund: 'Warum machen wir das nicht?', grundPflicht: true,
platzhalter: 'z. B. Haben wir letzte Woche schon anders geloest.',
});
if (!antwort) return;
const grund = antwort.grund || '';
if (!grund.trim()) { melden('Ohne Grund bleibt die Meldung stehen.'); return; }
nein.disabled = true;
try {
@@ -535,11 +553,20 @@
const nein = el('button', 'abmelden', 'Nicht umsetzen');
nein.type = 'button';
nein.addEventListener('click', () => {
const grund = window.prompt(`Warum nicht?
„${a.titel}“`, '');
if (grund === null) return;
nein.addEventListener('click', async () => {
/* Derselbe Dialog wie ueberall sonst (22.09.2026). Vorher ein
window.prompt() -- der zweite und letzte im Haus. */
const antwort = await window.frageNach({
titel: 'Nicht umsetzen?',
was: '„' + a.titel + '“',
bleibt: 'Das Angebot verschwindet aus der Liste. Dein Grund steht '
+ 'dabei, damit die Person weiss, woran es lag.',
ja: 'Nicht umsetzen',
grund: 'Warum nicht?', grundPflicht: true,
platzhalter: 'z. B. Passt gerade nicht zum Plan – vielleicht spaeter.',
});
if (!antwort) return;
const grund = antwort.grund || '';
if (!grund.trim()) { melde('Ohne Grund bleibt das Angebot stehen.'); return; }
entscheiden(nein, { id: a.id, art: 'abgelehnt', grund: grund.trim() });
});
+15
View File
@@ -453,6 +453,21 @@
}
async function listeZeigen() {
/* GAR NICHT ERST FRAGEN, WENN ES SIE NICHT GIBT (22.09.2026).
==============================================================
Die Zeile darunter behandelt den 404 richtig -- der Browser
protokolliert ihn aber UNABHAENGIG davon. Im Handy-Rundgang
stand deshalb bei jedem Modi, auf beiden Bildschirmbreiten,
"404 (Not Found)" in der Konsole. Kein Schaden fuer den
Menschen, aber eine Meldung, die bei jedem Lauf kommt -- und
die verdeckt die naechste, die echt ist.
Derselbe Fall wie am 19.09.2026 bei /anruf/adressen, und
dieselbe Loesung: Der Server sagt in /api/ich, ob jemand Team
Dogi fuehrt. Die 404-Behandlung bleibt trotzdem stehen -- sie
ist die Sicherung fuer den Fall, dass die Auskunft mal fehlt. */
const ich = window.wennIchDaBin ? await window.wennIchDaBin() : window.__ich;
if (ich && ich.fuehrt_team === false) return false;
const a = await hole('/workspace/api/werdegang/liste');
if (a.status === 404) return false; /* kein Leitungszugang */
if (!a.ok) { melde('Die Karten lassen sich gerade nicht laden.'); return true; }