Kapitel 04: der Knopf heisst "Hingehen" -- und das Datum war gar keins

Zwei kleine Dinge aus dem Bauplan, Kapitel 04. Das zweite war ein
echter Fehler, und er war auf dem Weg nach draussen.

"AKTUALISIERT AM" -- UND DANN STUENDE DA EIN ZEITSTEMPEL
`datumKurz` prueft mit einem Ausdruck, der ein `$` am Ende hatte. Die
Stufenkarte schickt einen reinen Tag ("2026-10-13"), die Karte aber
einen ganzen Zeitstempel ("2026-10-06T18:22:31.123Z", aus
`new Date().toISOString()` -- siehe anleitung-tabellen.js und
workspace-anleitung.js). Die zweite Form bestand die Pruefung nicht
und waere UNVERAENDERT durchgereicht worden: Auf der Karte haette
woertlich "aktualisiert am 2026-10-06T18:22:31.123Z" gestanden. Kein
Fehler, kein Absturz, keine rote Meldung -- genau die Sorte Schaden,
die `node --check` nicht sehen kann, und die hier auch niemand
gesehen haette, weil die Zeile nur in der Pflege steht.

Gefunden hat es keine Eingebung, sondern das Nachsehen, WAS der
Server wirklich schickt. Die Pruefung fragt ihn jetzt selbst und
rechnet nicht gegen eine Erinnerung.

"HINGEHEN" STATT "ZUR KACHEL"
So steht es im Plan, und es ist die Sprache der Seite: Sie duzt,
begruesst mit Namen und sagt "Schoen, dass du da bist". "Kachel" ist
das Wort, mit dem wir INTERN ueber die Dinge reden; wer neu ist, hat
es noch nie gehoert.

"AKTUALISIERT AM" STEHT NUR IN DER PFLEGE -- eine Entscheidung, die
der Plan so nicht trifft. Fuer ein Mitglied beantwortet das Datum
keine Frage; DASS sich etwas geaendert hat, sagt ihm die Marke "Neu"
daneben, die von selbst wieder verschwindet. Fuer DogFather
beantwortet es eine sehr konkrete: "Habe ich die schon angefasst?"
Eine Zeile, die auf jeder der 34 Karten steht und niemanden angeht,
zieht den Blick von den drei Zeilen darueber weg. .an-karte__stand
ist deshalb klein und still -- --text-still, dieselbe Stimme wie die
Schilder "Wozu"/"Merke", deren Kontrast auf dieser Flaeche schon
geprueft ist. Keine neue, noch blassere Farbe, die niemand bemerkt,
bis sie nicht mehr lesbar ist.

AUSSERDEM: pruef-community-sicht war rot, und zwar zu Recht.
Die handgefuehrte Liste COMMUNITY_SEITEN kannte die neue
Einweisungsseite nicht und meldete "ZU VIEL: anleitung.html". Das ist
kein Mangel der Liste, sondern ihr Zweck -- sie nennt die
ueberzaehlige Seite selbst. anleitung.html ist jetzt eingetragen, mit
Begruendung, und bei willkommen.html steht dran, dass sie nur noch
weiterleitet. 13 -> 14 Seiten, gruen.

GEPRUEFT (pruef-anleitung 188 -> 196):
  - der Weg-Knopf heisst "Hingehen" (1x), "Zur Kachel" nirgends (0x)
  - "aktualisiert am" haengt an der Pflege (1x), nicht an jeder Karte
  - .an-karte__stand ist wirklich gestaltet
  - der Server schickt "geaendert" als ganzen Zeitstempel (14 von 14)
  - ...und die Karte macht daraus einen lesbaren Tag (14 von 14)
  - der reine Tag der Stufenkarte bleibt richtig (13.10.2026)
  - Gegenprobe: was kein Datum ist, wird auch zu keinem gemacht
Die Rechenvorschrift wird dafuer AUSGEFUEHRT und nicht mit einem
Muster angesehen -- ein Muster waere eine zweite, ungenaue
Nachbildung. Und die Voraussetzung ("der Server schickt wirklich
einen Zeitstempel") wird gemessen, nicht angenommen; ohne sie waere
die Zeile darunter eine Rechnung gegen eine Erinnerung, und die
altert.

GEGENPROBE GEFAHREN: `$` wieder eingebaut -> "...und die Karte macht
daraus einen lesbaren Tag (0 von 14)", EXIT=1, und die Zahl bleibt
196. Eine Pruefung, die immer bestaetigt, bestaetigt nichts.

Dazu gruen, gezielt und nicht als Gesamtlauf:
  pruef-css-klassen      4698 Klassenverwendungen, die neue Klasse ist
                         gestaltet; 42 Stellen unter 11,5 px wie
                         bisher (die neue Zeile ist 12,16 px)
  pruef-community-sicht  10 Pruefungen, 0 Fehler
  pruef-haus-trennung    107 geprueft, 0 Fehler -- das Agenturhaus
                         bleibt von der geaenderten Client-Datei
                         unberuehrt
  pruef-deutsche-texte   12 Pruefungen, 0 Fehler

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-10-06 22:23:22 +02:00
co-authored by Claude Opus 5
parent b885b54628
commit c4bdc1c4c2
50 changed files with 847 additions and 690 deletions
+82
View File
@@ -1442,6 +1442,88 @@ melde("\n=== Die Pflegeleiste haengt an beiden Ausgaengen ===");
`…und es gibt genau diese zwei Ausgaenge (${ausgaenge})`);
}
/* =====================================================================
KAPITEL 04 — DER KNOPF UND DER STAND DER KARTE
---------------------------------------------------------------------
Zwei kleine Dinge aus dem Bauplan, und beide koennen lautlos falsch
sein:
1. DER KNOPF HEISST „HINGEHEN". So steht es im Plan, und es ist die
Sprache der Seite: Sie duzt und begruesst mit Namen. „Zur Kachel"
ist unser internes Wort; wer neu ist, hat „Kachel" noch nie
gehoert. Geprueft wird die ZAHL (genau einmal da, altes Wort
keinmal), nicht das blosse Vorkommen -- sonst waere die Zeile auch
gruen, wenn beide Woerter nebeneinander im Code stuenden.
2. „AKTUALISIERT AM" MUSS EIN DATUM SEIN, KEIN ZEITSTEMPEL.
Das ist der eigentliche Grund fuer diesen Block. `datumKurz`
bekommt ZWEI Formen herein, die nur am Anfang gleich aussehen:
die Stufenkarte schickt einen reinen Tag ("2026-10-13"), die
Karte einen ganzen Zeitstempel ("2026-10-06T18:22:31.123Z"). Die
Rechenvorschrift hatte ein `$` am Ende und liess die zweite Form
deshalb UNVERAENDERT durch: Auf der Karte stuende dann woertlich
„aktualisiert am 2026-10-06T18:22:31.123Z". Kein Fehler, kein
Absturz, keine rote Meldung -- genau die Sorte Schaden, die ein
`node --check` nicht sehen kann.
DIE VORAUSSETZUNG WIRD GEMESSEN, NICHT ANGENOMMEN: Dass der Server
wirklich einen Zeitstempel schickt, fragt diese Pruefung beim Server
nach (erste Zeile). Ohne das waere die Zeile darunter eine Rechnung
gegen eine Erinnerung -- und die altert.
===================================================================== */
melde("\n=== Kapitel 04: der Knopf und der Stand der Karte ===");
{
const quelle = readFileSync(
new URL("../workspace/assets/js/anleitung.js", import.meta.url), "utf8");
const nurCode = quelle
.replace(/\/\*[\s\S]*?\*\//g, " ")
.replace(/(^|[^:])\/\/[^\n]*/g, "$1 ");
const hin = (nurCode.match(/'an-karte__weg', 'Hingehen'/g) || []).length;
ok(hin === 1, `der Weg-Knopf heißt „Hingehen" (${hin}x)`);
const altesWort = (nurCode.match(/Zur Kachel/g) || []).length;
ok(altesWort === 0, `…und „Zur Kachel" steht nirgends mehr (${altesWort}x)`);
const nurPflege = (nurCode.match(/pflegeAn && eintrag\.geaendert/g) || []).length;
ok(nurPflege === 1,
`„aktualisiert am" hängt an der Pflege und steht nicht auf jeder Karte (${nurPflege}x)`);
const css = readFileSync(
new URL("../workspace/assets/css/anleitung.css", import.meta.url), "utf8");
ok(/\.an-karte__stand\s*\{/.test(css),
"…und hat eine eigene, stille Schrift (.an-karte__stand in der CSS)");
/* Die Rechenvorschrift wird AUSGEFUEHRT, nicht mit einem Muster
angesehen -- ein Muster waere eine zweite, ungenaue Nachbildung. */
const anfang = quelle.indexOf("const datumKurz = (iso) => {");
const ende = anfang < 0 ? -1 : quelle.indexOf("\n };", anfang);
braucht(anfang >= 0 && ende > anfang,
"datumKurz ist in anleitung.js nicht mehr zu finden — die Prüfung kann ihre Rechnung nicht holen");
const kiste = {};
vm.createContext(kiste);
vm.runInContext(`${quelle.slice(anfang, ende + 5)}\nglobalThis.__dk = datumKurz;\n`,
kiste, { filename: "datumKurz" });
const datumKurz = kiste.__dk;
braucht(typeof datumKurz === "function",
"datumKurz ließ sich nicht ausführen — die Rechnung ist nicht zu messen");
const probe = (await holen("gast", CREW_HOST)).j?.karten || [];
braucht(probe.length > 0,
`keine einzige Karte da — ohne sie ist die Form von „geaendert" nicht zu messen`);
const mitZeit = probe.filter(
(k) => /^\d{4}-\d{2}-\d{2}T\d{2}:/.test(String(k.geaendert || ""))).length;
ok(probe.length > 0 && mitZeit === probe.length,
`der Server schickt „geaendert" als ganzen Zeitstempel (${mitZeit} von ${probe.length})`);
const lesbar = probe.filter(
(k) => /^\d{2}\.\d{2}\.\d{4}$/.test(datumKurz(k.geaendert))).length;
ok(probe.length > 0 && lesbar === probe.length,
`…und die Karte macht daraus einen lesbaren Tag (${lesbar} von ${probe.length})`);
ok(datumKurz("2026-10-13") === "13.10.2026",
"der reine Tag der Stufenkarte bleibt richtig (13.10.2026)");
ok(datumKurz("demnächst") === "demnächst" && datumKurz("") === "",
"Gegenprobe: was kein Datum ist, wird auch zu keinem gemacht");
}
/* ---------- Abschluss ------------------------------------------------ */
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
console.log(`\n${fehler ? "FEHLER: " + fehler : "Alles in Ordnung"} — ${geprueft} Prüfungen`);
+15 -1
View File
@@ -97,6 +97,16 @@ melde("=== 1. Was ueberhaupt offensteht ===");
DAS IST DIESELBE BAUART wie die festgelegten Kachelfarben: nicht
„ungefaehr so viele", sondern „genau diese, und hier steht warum". */
const COMMUNITY_SEITEN = [
/* DIE EINWEISUNG kam am 06.10.2026 dazu (Bauplan „Willkommen &
Anleitung"). Sie ist fuer ein Mitglied die ERSTE Seite ueberhaupt:
Die Kachel „Willkommen & Anleitung" steht breit und vorne in der
Gruppe „Community" und fuehrt hierher. Was darauf steht, erklaert
genau die vierzehn Kacheln, die dieses Mitglied hat -- nichts
darueber hinaus; das misst pruef-anleitung in beide Richtungen.
Diese Zeile hat gefehlt, und die Pruefung ist deshalb rot
geworden -- richtig so: Genau dafuer gibt es sie. */
"anleitung.html", // Willkommen & Anleitung (seit 06.10.2026)
"bereich.html", // die Bretter (Highlights, Anschlag, Wunschliste ...)
"bewerben.html", // Mitmachen
"chat.html", // der Treff
@@ -119,7 +129,11 @@ const COMMUNITY_SEITEN = [
"treff-regeln.html", // die Regeln des Rudels
"unsere-seiten.html", // Draussen
"unterstuetzen.html", // Unterstuetzen
"willkommen.html", // die Begruessung
/* Die alte Adresse bleibt offen -- sie leitet seit dem 06.10.2026
auf anleitung.html weiter. Ein Lesezeichen soll nicht an einer
Schranke enden; die Weiterleitung selbst misst
pruef-willkommen. */
"willkommen.html", // leitet auf die Anleitung weiter
];
const zuViel = erlaubt.filter((s) => !COMMUNITY_SEITEN.includes(s));
const fehltDa = COMMUNITY_SEITEN.filter((s) => !erlaubt.includes(s));