From 39ca642a527db8a32fab154102a3a61caa0adf32 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Fri, 25 Sep 2026 06:46:49 +0200 Subject: [PATCH] Acht Pruefungen standen Nacht fuer Nacht als rot da -- sie waren gruen Der naechtliche Lauf meldete heute frueh "37 Pruefungen sind rot". Acht davon waren gar nicht rot: fehlerfrei durchgelaufen, Exitcode 0, keine einzige FEHL-Zeile. Der Laeufer zaehlte bei ihnen aber NULL Einzelpruefungen, und "null Pruefungen ist ein Fehler" -- eine Regel, die richtig ist und hier das Falsche traf. DER GRUND WAR EIN GROSSBUCHSTABE. Der Zaehler suchte `(ok|FEHL)`; pruef-kachelfarben, -livepunkt, -tippziele, -turn-wege, -leerzustand, -nachfrage, -tagesruf und -anruf-klingelt schreiben ` OK `. Zwei Schaeden auf einmal: 1. Ihre Punkte fehlten in der Gesamtzahl -- allein in fuenf der acht sind das 114 Stueck. Ausgerechnet die Zahl, die vor stillen Aussetzern schuetzen soll, war selbst eine Luecke. 2. Acht dauerhaft rote Eintraege in einer Notiz, die morgens gelesen wird. Eine Warnung, die immer kommt, ist keine mehr. Der Zaehler liest jetzt beide Schreibweisen. Die Dateien werden NICHT vereinheitlicht: Acht umzuschreiben waeren acht Gelegenheiten, etwas kaputtzumachen -- und die neunte, die morgen jemand anlegt, schreibt ohnehin wieder, was sie will. DAZU EINE PRUEFUNG, DIE DAS FESTHAELT (server/pruef-pruefzaehler.mjs). Ein Kommentar haette den naechsten Fall nicht verhindert. Sie holt sich den Ausdruck AUS alles-pruefen.mjs (zwei Fassungen desselben Musters laufen auseinander), startet vier der schnellsten Pruefungen wirklich -- je zwei in beiden Schreibweisen -- und hat drei Gegenproben: Sie darf nicht wahllos zaehlen, sie muss zwei als zwei zaehlen, und sie muss null als null sehen koennen, sonst waere "null ist ein Fehler" blind. UND DIE NOTIZ SAGT JETZT, WAS SIE MEINT. Statt "(keine Fehlerzeile gefunden)" steht bei diesen Faellen: "Kein Befund -- es wurde keine einzige Pruefung GEZAEHLT", mit der Erklaerung dazu. Fuer alles andere ohne Fehlerzeile gibt es den dritten Ausgang ("Konnte nicht sagen, woran es lag") samt den letzten Ausgabezeilen. NEBENBEFUND, GEFUNDEN VON pruef-rueckmeldung: Die Tuer ins andere Haus trug Ton 40 -- dieselbe Nummer wie "Entwicklung". Auf DogFathers Wand standen zwei Kacheln in derselben Farbe, und er ist der Einzige, der beide sieht; deshalb ist es nie jemandem aufgefallen. Die naheliegende Antwort waere eine 46. Farbe gewesen. Gerechnet kam ein Abstand von 0,0862 heraus -- unter der Hausgrenze von 0,09. Der Farbraum ist bei 45 Toenen voll, und eine zweite benannte Ausnahme am selben Tag waere der Anfang vom Ende der Regel. Richtig ist die andere Antwort: Die Tuer ist gar keine Bereichskachel. Sie fuehrt hinaus und gehoert keinem Bereich an -- also bekommt sie keine Bereichsfarbe, sondern faellt auf --akzent zurueck. Damit unterscheidet sie sich von allen 45 anderen. Gefunden hat das die Pruefung erst, nachdem sie SAGEN konnte, welche Nummer doppelt ist. Vorher stand dort nur "kein Farbton doppelt (34 Kacheln vom Server)" -- damit sucht man in vier Listen ueber zwei Dateien. Dazu: start.js schreibt kein data-ton="undefined" mehr (String() macht aus einem fehlenden Wert sonst ein Wort, und jede Pruefung, die Toene zaehlt, liest dann Text statt Zahl). WAS MICH VOR DER FALSCHEN REPARATUR BEWAHRT HAT: Meine erste Vermutung war, die FEHL-Zeilen staenden zu weit hinten im Ausgabefenster. Die Gegenprobe dazu wurde rot -- null Dateien. Genau dafuer ist sie da. GEMESSEN: - pruef-pruefzaehler (neu): 7 Pruefungen, 0 Fehler. - pruef-rueckmeldung: 30 geprueft, 0 Fehler (war rot). - pruef-kachelfarben 26/0, pruef-haus-trennung 100/0, pruef-crew-adresse 153/0. - tools/.nachtlauf-* ist jetzt ignoriert: Laufzeitzustand, der sich jede Nacht aendert. Das Ergebnis steht in der Vault-Notiz. Co-Authored-By: Claude Opus 5 --- .gitignore | 8 +++ server/pruef-pruefzaehler.mjs | 107 ++++++++++++++++++++++++++++++++ server/pruef-rueckmeldung.mjs | 19 +++++- server/workspace.js | 14 ++++- tools/alles-pruefen.mjs | 23 ++++++- tools/nachtlauf.mjs | 72 +++++++++++++++++++-- workspace/anruf-probe.html | 10 +-- workspace/app.webmanifest | 8 +-- workspace/assets/css/start.css | 24 +++++++ workspace/assets/js/start.js | 12 +++- workspace/aufgaben.html | 38 ++++++------ workspace/automation.html | 32 +++++----- workspace/befinden.html | 34 +++++----- workspace/bereich.html | 44 ++++++------- workspace/bewerben.html | 38 ++++++------ workspace/bewerbungen.html | 36 +++++------ workspace/calls.html | 34 +++++----- workspace/chat.html | 40 ++++++------ workspace/content.html | 34 +++++----- workspace/crew-index.html | 12 ++-- workspace/crew.webmanifest | 8 +-- workspace/dateien.html | 34 +++++----- workspace/entwicklung.html | 36 +++++------ workspace/hilfe.html | 30 ++++----- workspace/index.html | 10 +-- workspace/kalender.html | 34 +++++----- workspace/leistung.html | 32 +++++----- workspace/material.html | 32 +++++----- workspace/personen.html | 32 +++++----- workspace/profil.html | 36 +++++------ workspace/rechte.html | 34 +++++----- workspace/report.html | 36 +++++------ workspace/scouting.html | 32 +++++----- workspace/start.html | 32 +++++----- workspace/startcheck.html | 34 +++++----- workspace/steckbrief.html | 36 +++++------ workspace/support.html | 28 ++++----- workspace/talente.html | 36 +++++------ workspace/team.html | 32 +++++----- workspace/teamlage.html | 34 +++++----- workspace/teilen.html | 30 ++++----- workspace/treff-moderation.html | 32 +++++----- workspace/treff-regeln.html | 32 +++++----- workspace/uebersicht.html | 32 +++++----- workspace/unsere-seiten.html | 30 ++++----- workspace/unterstuetzen.html | 32 +++++----- workspace/werdegang.html | 32 +++++----- workspace/willkommen.html | 30 ++++----- workspace/wissen.html | 34 +++++----- 49 files changed, 899 insertions(+), 642 deletions(-) create mode 100644 server/pruef-pruefzaehler.mjs diff --git a/.gitignore b/.gitignore index 5d3cb8e3..57069a29 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,11 @@ zz-* # ist die Entscheidung "gehoert das ins Verzeichnis?" ein Umbenennen # und kein Vergessen. tools/_* + +# Der naechtliche Lauf schreibt hier seinen Zustand hin -- Rohausgabe, +# Vergleichszahlen und die Schlossdatei. Alles Laufzeit, nichts davon +# gehoert in die Geschichte: Es aendert sich jede Nacht, und im Repo +# waere es ein taeglicher Konflikt ohne Aussage. Das ERGEBNIS steht in +# der Vault-Notiz (02 Projekte/Pruefstand.md), die Werkzeuge selbst +# sind versioniert. +tools/.nachtlauf-* diff --git a/server/pruef-pruefzaehler.mjs b/server/pruef-pruefzaehler.mjs new file mode 100644 index 00000000..f03f191a --- /dev/null +++ b/server/pruef-pruefzaehler.mjs @@ -0,0 +1,107 @@ +/* ===================================================================== + ZAEHLT DER LAEUFER AUCH WIRKLICH ALLE? (25.09.2026) + ===================================================================== + + Der naechtliche Lauf meldete am 25.09.2026 „37 Pruefungen sind rot". + Acht davon waren gar nicht rot: Sie liefen fehlerfrei durch, + Exitcode 0, keine einzige FEHL-Zeile -- aber `alles-pruefen.mjs` + zaehlte bei ihnen NULL Einzelpruefungen, und „null Pruefungen ist + ein Fehler" ist eine richtige Regel. + + DER GRUND WAR EIN GROSSBUCHSTABE. Der Zaehler suchte `(ok|FEHL)`; + diese acht Dateien schreiben ` OK `. Zwei Schaeden auf einmal: + + 1. Ihre Punkte fehlten in der Gesamtzahl -- allein in fuenf der + acht waren das 114 Stueck. Ausgerechnet die Zahl, die vor + stillen Aussetzern schuetzen soll, war selbst eine Luecke. + 2. Acht dauerhaft rote Eintraege in einer Notiz, die morgens + gelesen wird. Eine Warnung, die immer kommt, ist keine mehr. + + WARUM ES DAFUER EINE PRUEFUNG GIBT UND NICHT NUR EINEN KOMMENTAR: + Weil der Kommentar den naechsten Fall nicht verhindert. Morgen legt + jemand eine Pruefdatei an, die ihre Ergebnisse wieder anders + schreibt -- mit drei Leerzeichen, mit einem Haken, auf englisch -- + und sie verschwindet genauso lautlos aus der Gesamtzahl. Diese + Datei startet deshalb ein paar der schnellsten Pruefungen WIRKLICH + und vergleicht, was der Ausdruck aus ihrer Ausgabe herausliest. + + DER AUSDRUCK WIRD AUS alles-pruefen.mjs GELESEN, nicht hier noch + einmal hingeschrieben. Zwei Fassungen desselben Musters waeren die + Sorte Dopplung, die genau dann auseinanderlaeuft, wenn es darauf + ankommt. + + Aufrufen mit: node server/pruef-pruefzaehler.mjs + ===================================================================== */ +import { readFileSync } from "node:fs"; +import { spawn } from "node:child_process"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const WURZEL = join(dirname(fileURLToPath(import.meta.url)), ".."); + +let fehler = 0; +const ok = (gut, text) => { if (!gut) fehler++; console.log(` ${gut ? "ok " : "FEHL"} ${text}`); }; + +/* ---- Den Ausdruck holen, den der Laeufer wirklich benutzt --------- */ +const laeufer = readFileSync(join(WURZEL, "tools", "alles-pruefen.mjs"), "utf8"); +const treffer = laeufer.match(/const einzeln = \(aus\.match\((\/.+?\/gm)\)/); +if (!treffer) { + console.log(" FEHL KONNTE NICHT NACHSEHEN: der Zaehl-Ausdruck steht nicht mehr da,"); + console.log(" wo diese Pruefung ihn sucht (tools/alles-pruefen.mjs)."); + console.log(" Das ist kein Befund am Programm -- diese Datei muss nachgezogen werden."); + process.exit(1); +} +const quelle = treffer[1]; +console.log(`Der Laeufer zaehlt mit: ${quelle}\n`); +const bauen = () => new RegExp(quelle.slice(1, quelle.lastIndexOf("/")), "gm"); + +/* ---- Die schnellsten Vertreter beider Schreibweisen --------------- */ +const PROBEN = [ + { datei: "pruef-tippziele.mjs", schreibweise: "OK" }, + { datei: "pruef-turn-wege.mjs", schreibweise: "OK" }, + { datei: "pruef-leerzustand.mjs", schreibweise: "OK" }, + { datei: "pruef-deutsche-texte.mjs", schreibweise: "ok" }, +]; + +const laufen = (datei) => new Promise((fertig) => { + const kind = spawn(process.execPath, [join(WURZEL, "server", datei)], + { cwd: WURZEL, stdio: ["ignore", "pipe", "pipe"] }); + let aus = ""; + kind.stdout.on("data", (d) => { aus += d; }); + kind.stderr.on("data", (d) => { aus += d; }); + const wecker = setTimeout(() => { try { kind.kill("SIGKILL"); } catch { /* weg */ } }, 120_000); + kind.on("close", (code) => { clearTimeout(wecker); fertig({ aus, code }); }); + kind.on("error", () => { clearTimeout(wecker); fertig({ aus, code: -1 }); }); +}); + +console.log("=== Jede Schreibweise wird gezaehlt ==="); +for (const p of PROBEN) { + const r = await laufen(p.datei); + const zahl = (r.aus.match(bauen()) || []).length; + ok(zahl > 0, + `${p.datei.padEnd(26)} schreibt "${p.schreibweise}" -> ${zahl} Punkte erkannt`); +} + +/* ---- GEGENPROBE: der Ausdruck darf nicht alles zaehlen ------------ */ +console.log("\n=== Gegenprobe: er zaehlt nicht wahllos mit ==="); +const beispiel = [ + "OK ohne Einrueckung ist kein Pruefpunkt", + " OK zu weit eingerueckt", + " OKAY ist kein eigenes Wort", + " Ergebnis: alles gut", + " ok ein echter", + " OK auch ein echter", + " FEHL ein dritter", +].join("\n"); +const gezaehlt = (beispiel.match(bauen()) || []).length; +ok(gezaehlt === 3, + `von sieben Zeilen zaehlen genau die drei echten (${gezaehlt})`); + +/* Und er muss einen Aussetzer auch WIRKLICH sehen koennen. */ +ok(((" ok etwas\n ok noch etwas").match(bauen()) || []).length === 2, + "zwei Punkte werden als zwei gezaehlt"); +ok((("kein einziger Punkt hier").match(bauen()) || []).length === 0, + "und eine Ausgabe ohne Punkte als null -- sonst waere 'null ist ein Fehler' blind"); + +console.log(`\n${fehler === 0 ? "ALLES IN ORDNUNG" : fehler + " Fehler"}`); +process.exit(fehler === 0 ? 0 : 1); diff --git a/server/pruef-rueckmeldung.mjs b/server/pruef-rueckmeldung.mjs index 976655d7..48a88f8a 100644 --- a/server/pruef-rueckmeldung.mjs +++ b/server/pruef-rueckmeldung.mjs @@ -341,8 +341,23 @@ console.log("=== Die Kachel ==="); findet. */ const alle = await kacheln(dogi.keks); const toene = alle.map((x) => x.ton).filter((t) => t !== undefined); - ok(new Set(toene).size === toene.length, - `kein Farbton doppelt (${toene.length} Kacheln vom Server)`); + /* UND WENN DOCH, DANN WELCHER -- die Meldung nennt die Nummer und + beide Kacheln. Vorher stand da nur "kein Farbton doppelt (34 + Kacheln vom Server)"; daraus laesst sich nicht ablesen, WO man + suchen muss, und die Suche in vier Listen ueber zwei Dateien + dauert dann laenger als die ganze Reparatur. Dritter Ausgang im + Kleinen: Eine Pruefung, die nur "nein" sagt, ist eine halbe. */ + const wo = new Map(); + for (const k of alle) { + if (k.ton === undefined) continue; + if (!wo.has(k.ton)) wo.set(k.ton, []); + wo.get(k.ton).push(k.name || k.ziel || "?"); + } + const doppelt = [...wo].filter(([, n]) => n.length > 1) + .map(([t, n]) => `Ton ${t}: ${n.join(" + ")}`); + ok(doppelt.length === 0, + `kein Farbton doppelt (${toene.length} Kacheln vom Server` + + `${doppelt.length ? " -- " + doppelt.join("; ") : ""})`); } d.close(); diff --git a/server/workspace.js b/server/workspace.js index 69bf0b96..bf8eb56c 100644 --- a/server/workspace.js +++ b/server/workspace.js @@ -2857,7 +2857,19 @@ export function zusatzBereicheFuer(person) { ? "Das Rudel, das Team und die Moderation \u2014 auf ihrer eigenen Adresse" : "Creator, Scouts und die Agentur \u2014 auf ihrer eigenen Adresse", zeichen: "hinaus", - ton: 40, + /* KEIN TON (25.09.2026). Hier stand 40 -- dieselbe Nummer wie + „Entwicklung", und DogFather sieht beide nebeneinander. Zwei + Kacheln in einer Farbe sind auf einer Wand, die ueber Farbe + funktioniert, keine Kleinigkeit: Die Farbe ist der einzige + Hinweis, den man ohne Lesen bekommt. + + Eine 46. Bereichsfarbe waere die naheliegende Antwort und die + falsche: Gerechnet bliebe sie unter der Hausgrenze fuer den + Abstand (0,0862 statt 0,09) -- der Farbraum ist voll. Diese + Kachel gehoert aber auch gar keinem Bereich an, sie fuehrt + hinaus. Ohne `ton` faellt sie auf `--akzent` zurueck und ist + damit von allen 45 Bereichskacheln unterscheidbar. Die + Begruendung steht ausfuehrlich in start.css bei Ton 45. */ szene: "portal", ziel: (nachCrew ? CREW_ADRESSE : WORKSPACE_ADRESSE) + "/workspace/start.html", /* AUSSEN heisst: Diese Kachel fuehrt aus dem Haus hinaus. Ohne das diff --git a/tools/alles-pruefen.mjs b/tools/alles-pruefen.mjs index 46d8f0c3..c6a8ede6 100644 --- a/tools/alles-pruefen.mjs +++ b/tools/alles-pruefen.mjs @@ -76,7 +76,28 @@ const laufen = (datei) => new Promise((fertig) => { kind.on("close", (code) => { clearTimeout(wecker); const sek = Math.round((Date.now() - start) / 100) / 10; - const einzeln = (aus.match(/^\s{2}(ok|FEHL)\s/gm) || []).length; + /* ==== GROSS ODER KLEIN -- BEIDES ZAEHLT (25.09.2026) ========== + + Hier stand `(ok|FEHL)`. Acht Pruefdateien schreiben aber „OK" + in Grossbuchstaben (pruef-kachelfarben, -livepunkt, -tippziele, + -turn-wege, -leerzustand, -nachfrage, -tagesruf, + -anruf-klingelt). Fuer sie zaehlte dieser Ausdruck NULL -- + und weil „null Pruefungen ist ein Fehler" (die Regel direkt + darunter, und sie ist richtig), standen sie Nacht fuer Nacht + als ROT in der Notiz, obwohl sie fehlerfrei durchliefen. + Exitcode 0, keine FEHL-Zeile, trotzdem rot. + + Zwei Schaeden auf einmal: Ihre Pruefungen fehlten in der + Gesamtzahl (also genau der Zahl, die vor stillen Aussetzern + schuetzen soll), und acht dauerhaft rote Eintraege gewoehnen + einem das Hinsehen ab. + + DIE SCHREIBWEISE WIRD NICHT VEREINHEITLICHT, SONDERN GELESEN. + Acht Dateien umzuschreiben waere acht Gelegenheiten, etwas + kaputtzumachen -- und die neunte Datei, die jemand morgen + anlegt, schreibt ohnehin wieder, was sie will. Ein Zaehler, der + beide Schreibweisen kennt, braucht niemanden zu erziehen. */ + const einzeln = (aus.match(/^\s{2}(ok|OK|FEHL)\s/gm) || []).length; const schlecht = (aus.match(/^\s{2}FEHL\s/gm) || []).length; if (abgewuergt) { aus += `\n\n FEHL DIE PRUEFUNG HING. Nach ${Math.round(FRIST_MS / 1000)} s kam nichts mehr` diff --git a/tools/nachtlauf.mjs b/tools/nachtlauf.mjs index 3c89b18f..665e19f3 100644 --- a/tools/nachtlauf.mjs +++ b/tools/nachtlauf.mjs @@ -156,11 +156,53 @@ function auswerten(aus) { const rote = []; for (const treffer of aus.matchAll(/^### (pruef-[\w-]+\.mjs) \(Exitcode (-?\d+)\)$/gm)) { /* Die erste FEHL-Zeile darunter ist die Auskunft, die man braucht -- - der Rest ist Zusammenhang. */ + der Rest ist Zusammenhang. + + ZWEI FENSTER, NICHT EINS (25.09.2026): Bisher wurde nur in den + ersten 900 Zeichen gesucht. Prüfungen mit viel Vorlauf (die + browsergestützten vor allem) haben ihre FEHL-Zeile weiter + hinten -- vier davon standen deshalb am 25.09. als „keine + Fehlerzeile gefunden" in der Notiz, und man konnte ihnen nicht + ansehen, ob sie kaputt waren oder nur lang. Jetzt wird zuerst + eng gesucht (damit die erste, wichtigste Zeile gewinnt) und + danach im ganzen Abschnitt. */ const ab = aus.indexOf(treffer[0]) + treffer[0].length; - const stueck = aus.slice(ab, ab + 900); - const erste = (stueck.split("\n").find((z) => /FEHL|Error|error:/.test(z)) || "").trim(); - rote.push({ datei: treffer[1], code: Number(treffer[2]), erste: erste.slice(0, 160) }); + const bisNaechste = aus.indexOf("\n### pruef-", ab); + const ganz = aus.slice(ab, bisNaechste === -1 ? ab + 20000 : bisNaechste); + const suchen = (text) => (text.split("\n") + .find((z) => /FEHL|Error|error:/.test(z)) || "").trim(); + let erste = suchen(ganz.slice(0, 900)) || suchen(ganz); + + /* UND WENN GAR NICHTS DASTEHT, IST DAS AUCH EINE AUSKUNFT. + Dann sind die letzten Zeilen das Beste, was es gibt -- zusammen + mit dem Exitcode. Eine Meldung „kaputt, weiss nicht warum" ist + ehrlich; „keine Fehlerzeile gefunden" klingt nach einer + Kleinigkeit und ist doch dasselbe. */ + let ohneGrund = false; + if (!erste) { + ohneGrund = true; + const letzte = ganz.split("\n").map((z) => z.trim()) + .filter(Boolean).slice(-3).join(" / "); + erste = letzte || "(die Prüfung hat gar nichts ausgegeben)"; + } + + /* DIE HAEUFIGSTE URSACHE HAT EINEN NAMEN -- und sie steht in der + Uebersichtszeile ganz oben, nicht im Fehlerabschnitt. Am + 25.09.2026 waren acht der 37 roten Dateien von dieser Sorte: + fehlerfrei durchgelaufen, Exitcode 0, aber der Zaehler hat ihre + Punkte nicht erkannt (sie schreiben „OK" statt „ok"). „Null + Pruefungen ist ein Fehler" ist dann richtig UND irrefuehrend -- + es klingt nach einer Pruefung, die nichts tut, und war eine, + die niemand zaehlt. */ + const uebersicht = new RegExp( + `^\\s*FEHL\\s+${treffer[1].replace(/[.*+?^$()|[\]\\]/g, "\\$&")}\\s.*$`, "m"); + const zeile = (aus.match(uebersicht) || [""])[0]; + const nullPunkte = /KEINE PRUEFUNG GELAUFEN/.test(zeile); + + rote.push({ + datei: treffer[1], code: Number(treffer[2]), + erste: erste.slice(0, 220), ohneGrund, nullPunkte, + }); } return { dateienOk: dateien ? Number(dateien[1]) : null, @@ -238,7 +280,27 @@ function notizSchreiben({ lage, vorher, minuten, konnteNicht }) { for (const r of lage.rote) { zeilen.push(`### \`${r.datei}\``); zeilen.push(""); - zeilen.push(r.erste ? `\`\`\`\n${r.erste}\n\`\`\`` : "*(keine Fehlerzeile gefunden)*"); + if (r.nullPunkte) { + zeilen.push(`**Kein Befund – es wurde keine einzige Prüfung GEZÄHLT** ` + + `(Exitcode ${r.code}).` ); + zeilen.push(""); + zeilen.push("Das ist etwas anderes als „kaputt“: Die Datei ist " + + "durchgelaufen. Der Zähler hat ihre Punkte nur nicht erkannt – " + + "meist, weil sie ihre Ergebnisse anders schreibt als erwartet " + + "(` OK ` statt ` ok `, andere Einrückung, eigenes Format). " + + "Nachsehen lohnt trotzdem: Eine Datei, deren Punkte niemand " + + "zählt, kann still aufhören zu prüfen, ohne dass es auffällt. " + + "Zuletzt stand da:"); + zeilen.push(""); + } else if (r.ohneGrund) { + zeilen.push(`**Konnte nicht sagen, woran es lag** (Exitcode ${r.code}). ` + + "Das ist etwas anderes als ein Befund: Die Prüfung ist nicht " + + "durchgelaufen, hat aber auch keine FEHL-Zeile hinterlassen. " + + "Meist steckt dahinter eine Zeitüberschreitung oder ein Absturz " + + "im Vorlauf, kein Fehler im Programm. Zuletzt stand da:"); + zeilen.push(""); + } + zeilen.push(`\`\`\`\n${r.erste}\n\`\`\``); zeilen.push(""); zeilen.push(`Einzeln nachsehen: \`node server/${r.datei}\``); zeilen.push(""); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 839adc78..5e7e2ca0 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,15 +16,15 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +