Der Rundumcheck geht weiter. Diese zwoelf standen im Nachtlauf als rot
und waren es nicht: Jede hat den Umbau vom 24.09. (die Haustrennung),
den vom 25.09. (die zugetragenen Punkte) oder eine Umbenennung
mitbekommen -- nur ihre Erwartung nicht.
DAS IST KEIN TROST. Ein Fehlalarm zeigt auf eine echte Stelle und nennt
eine plausible Zahl; man sucht danach an richtigem Code. Und zwoelf rote
Zeilen, die immer rot sind, nehmen dem ganzen Satz die Stimme.
=== DIESELBE WURZEL, SECHSMAL: DAS FALSCHE HAUS ===
Seit dem 24.09. antwortet der Server auf der Agenturadresse nicht mehr
ueber Team-Dogi-Leute -- und genau das taten diese Pruefungen:
pruef-nachwuchs legte einen Modi ueber die Agenturadresse an
(400). Einundzwanzig Meldungen hingen an diesem
einen Aufruf. 82 Zeilen auf crew. umgestellt,
aus „Mara, Managerin" wurde die linke Hand --
im Teamhaus ist sie das, was gemeint war.
230 -> 262 Pruefungen, 0 Fehler.
pruef-schritt dasselbe beim Aufgabenbrett (404/400).
pruef-treff-werkzeuge fragte die Einladungsliste eines Modis auf der
Agenturadresse ab -- dort ist er nicht.
pruef-rechte-umstellen benutzte `wissen.html` als zweite Probeseite.
Die ist laut Rechtetafel fuer alle offen und auf
crew. trotzdem zu: Dort kommt man nur auf Seiten,
fuer die es eine Kachel gibt. Jetzt material.html.
pruef-personen-formular verglich eine Erwartung FUER die Agentur mit
einer Messung OHNE Adresse (127.0.0.1) -- vier
gegen acht Rollen. Beides war richtig, nur nicht
dasselbe.
pruef-treff suchte „Support" zwischen den Brettern. Er steht
in „Fuer dich", wo er hingehoert -- eine kaputte
Seite zu melden ist kein Aushang. Die Liste stand
ZWEIMAL in der Datei; nachgezogen wurde eine.
Jetzt eine, von beiden benutzt.
=== ZWEIMAL: EINE FESTE ZAHL, DIE DIE SEITE UEBERHOLT HAT ===
pruef-community-sicht erlaubte „3 bis 8 Seiten". Es sind zwoelf, und
jede gehoert dorthin. Statt einer Spanne steht
jetzt die LISTE da: Kommt eine dazu, wird die
Zeile rot und nennt sie beim Namen. Eine Spanne
haette elf statt zwoelf stillschweigend
durchgelassen -- in beide Richtungen.
pruef-nachwuchs schaltete EINE Person ab und erwartete, dass die
Ampel danach schweigt. Der Kommentar darueber
sagt selbst: „Die Schwelle wird nicht
abgeschrieben, sondern aus dem Verhalten
abgeleitet" -- eine feste Anzahl abzuschalten ist
aber eine Abschrift in anderer Waehrung. Jetzt
wird abgeschaltet, BIS es kippt.
=== UND VIERMAL EIN WERKZEUG, DAS STUMPF WAR ===
pruef-scout-zuteilung suchte `.person__zeile` -- eine Klasse, die es
nicht mehr gibt. `querySelectorAll` liefert dafuer
ein leeres Feld, `.some()` darauf ist immer
false: Die Pruefung war nicht rot, weil etwas
fehlte, sondern weil sie nichts ansehen konnte.
Jetzt `.person`, und die ANZAHL der gefundenen
Karten steht in einer eigenen Bedingung.
pruef-loeschen suchte `::before` in einem Fenster von 600
Zeichen ab dem Selektor. Das misst die Laenge des
KOMMENTARS: Am 25.09. kam eine Begruendung von
zwanzig Zeilen dazu, und die Regel rutschte
hinaus. Jetzt wird nach dem Selektor gesucht.
pruef-portnummern hielt jedes `listen(` fuer einen Serverstart --
auch das blosse Nachsehen, ob eine Nummer frei
ist. Damit mahnte sie ausgerechnet die Datei an,
die das Vergeben der Nummern prueft. Jetzt zaehlt
der Import von `index.js`; dazu vier Gegenproben,
damit die engere Fassung nicht zum blinden Fleck
wird.
pruef-spicy stellte eine Person auf „manager" und dann
weiter. An Managern aendert seit dem 22.09. nur
DogFather etwas -- die Pruefung hatte sich selbst
die Tuer zugezogen. Jetzt kommt „manager" zuletzt,
und dass danach nichts mehr geht, ist eine eigene
Zeile. Aus dem Stolperstein wird eine Aussage.
=== EINER WAR FAST EIN BEFUND ===
pruef-alle-sehen-es meldete „highlight: DogFather 0, Community 0".
Das Brett hat als einziges keinen Katalog (dort
stehen echte Hoehepunkte, keine Vorlagen), und an
einem leeren Brett ist „sehen beide dasselbe?"
nicht zu messen: null gleich null waere auch dann
wahr, wenn die Community gar nichts duerfte.
Die Pruefung legt dort jetzt selbst einen Eintrag
an -- und musste dabei zweimal lernen: Der Eintrag
gehoert VOR den Katalog (danach ist die
Schreibbremse ausgeloest, 429), und er muss
FREIGEGEBEN werden, sonst sieht die Community ihn
zu Recht nicht. Beides steht jetzt als Aussage in
der Pruefung.
GEMESSEN: alle zwoelf gruen -- 43, 10, 31, 262, 43, 15, 56, 69, 37, 85,
73 und 80 Pruefungen, zusammen 804, kein Fehler.
Co-Authored-By: Claude Opus 5 <[email protected]>
335 lines
15 KiB
JavaScript
335 lines
15 KiB
JavaScript
/* =====================================================================
|
||
WAS DOGFATHER EINTRÄGT, SEHEN AUCH DIE ANDEREN (17.09.2026)
|
||
|
||
Filipe: „die community und alle anderen sollen die neuen sachen in
|
||
allen kategorien auch sehen bitte. in allen die sie sehen soll auch
|
||
jede änderung mit gehen, immer nur in denen die ihnen erlaubt ist
|
||
zu sehen."
|
||
|
||
---------------------------------------------------------------------
|
||
ZWEI FEHLER, DIE NIEMAND GEMELDET HÄTTE
|
||
|
||
Beide sahen auf DogFathers eigenem Bildschirm vollkommen richtig
|
||
aus. Das ist das Tückische daran: Ein leeres Brett sieht nicht nach
|
||
Fehler aus, sondern nach „da ist eben noch nichts".
|
||
|
||
1. FREIGABE. `ansteht` und `highlight` zeigen der Community nur, was
|
||
freigegeben ist. Ein aus dem Vorschlagskasten übernommener
|
||
Eintrag hatte keine Freigabe -- gemessen sah die Community 0 von
|
||
4 und 0 von 3, während im Team alle drei Rollen alles sahen.
|
||
|
||
2. TEAM_DOGI_ROLLEN ist {hand, modi} -- OHNE "admin". Die
|
||
Sichtbarkeitsregel für Team Dogi lautete damit wörtlich
|
||
„Einträge von hand oder modi", und alles, was DogFather in Live,
|
||
Technik, Community, Ideen, Angebote oder Rückmeldung schrieb, war
|
||
für sein eigenes Team unsichtbar.
|
||
|
||
---------------------------------------------------------------------
|
||
UND DIE ANDERE HÄLFTE DES SATZES WIRD AUCH GEPRÜFT
|
||
|
||
„immer nur in denen die ihnen erlaubt ist zu sehen." Eine Prüfung,
|
||
die nur zählt, ob alle alles sehen, wäre grün, wenn man sämtliche
|
||
Schranken entfernte. Deshalb steht in Abschnitt 4 die Gegenprobe:
|
||
Was zu ist, muss zu bleiben.
|
||
|
||
Aufrufen mit: node server/pruef-alle-sehen-es.mjs
|
||
===================================================================== */
|
||
|
||
import { mkdtempSync, rmSync } from "node:fs";
|
||
import { tmpdir } from "node:os";
|
||
import { join } from "node:path";
|
||
import { request as httpAnfrage } from "node:http";
|
||
import { eigenerPort } from "./helfer-port.mjs";
|
||
|
||
const PORT = await eigenerPort(import.meta, "pruef-alle-sehen-es");
|
||
const ordner = mkdtempSync(join(tmpdir(), "ws-sicht-"));
|
||
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
|
||
process.env.PORT = String(PORT);
|
||
process.env.SITE_ACCESS_SECRET = "lokaler-test";
|
||
process.env.SITE_PUBLIC_LAUNCH_AT = "2020-01-01T00:00:00+01:00";
|
||
|
||
const express = (await import("express")).default;
|
||
const ec = express.response.cookie;
|
||
express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); };
|
||
import { notbremse } from "./helfer-notbremse.mjs";
|
||
await import("./index.js");
|
||
notbremse(180_000, "pruef-alle-sehen-es");
|
||
await new Promise((r) => setTimeout(r, 700));
|
||
|
||
const CREW = "crew.dogfather-universe.com";
|
||
|
||
let fehler = 0, geprueft = 0;
|
||
const melde = (t) => console.log(t);
|
||
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
||
|
||
const { DatabaseSync } = await import("node:sqlite");
|
||
const { scryptSync, randomBytes, createHmac } = await import("node:crypto");
|
||
const { TREFF_BRETTER } = await import("./workspace.js");
|
||
const { TREFF_FREIGABE_BRETTER } = await import("./workspace-treff.js");
|
||
const { BEREICHE } = await import("./workspace-bereiche.js");
|
||
const { ARBEIT_START } = await import("./workspace-arbeit-start.js");
|
||
const { TREFF_START } = await import("./workspace-treff-start.js");
|
||
|
||
const d = new DatabaseSync(process.env.WORKSPACE_DB);
|
||
const jetzt = new Date().toISOString();
|
||
const sch = randomBytes(32).toString("hex");
|
||
d.prepare("INSERT INTO einstellungen (schluessel, wert, geaendert, von)"
|
||
+ " VALUES (?,?,?,NULL) ON CONFLICT(schluessel) DO NOTHING")
|
||
.run("code_kennung_schluessel", sch, jetzt);
|
||
const ROLLEN = ["admin", "hand", "modi", "gast"];
|
||
const codes = {};
|
||
for (const r of ROLLEN) {
|
||
const code = `CODE-${r.toUpperCase()}-0001`;
|
||
const salt = randomBytes(16).toString("hex");
|
||
const hash = scryptSync(code, salt, 64,
|
||
{ N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
|
||
d.prepare("INSERT INTO personen"
|
||
+ " (name, rolle, code_hash, code_salt, code_n, code_kennung, aktiv, erstellt)"
|
||
+ " VALUES (?,?,?,?,?,?,1,?)")
|
||
.run(r, r, hash, salt, 32768,
|
||
createHmac("sha256", sch).update(code).digest("hex"), jetzt);
|
||
codes[r] = code;
|
||
}
|
||
d.close();
|
||
|
||
function roh(pfad, kopf = {}, koerper = null, methode = null) {
|
||
return new Promise((fertig, schief) => {
|
||
const a = httpAnfrage({
|
||
host: "127.0.0.1", port: PORT, path: pfad,
|
||
method: methode || (koerper ? "POST" : "GET"),
|
||
headers: { Host: CREW, ...(koerper ? { "Content-Type": "application/json" } : {}), ...kopf },
|
||
}, (antwort) => {
|
||
let text = "";
|
||
antwort.on("data", (s) => { text += s; });
|
||
antwort.on("end", () => fertig({ code: antwort.statusCode, text }));
|
||
});
|
||
a.on("error", schief);
|
||
if (koerper) a.write(JSON.stringify(koerper));
|
||
a.end();
|
||
});
|
||
}
|
||
const kekse = {};
|
||
for (const r of ROLLEN) {
|
||
const antwort = await new Promise((fertig) => {
|
||
const q = httpAnfrage({
|
||
host: "127.0.0.1", port: PORT, path: "/workspace/api/anmelden", method: "POST",
|
||
headers: { Host: CREW, "Content-Type": "application/json" },
|
||
}, (w) => { let t = ""; w.on("data", (x) => { t += x; }); w.on("end", () => fertig(w)); });
|
||
q.write(JSON.stringify(r === "gast"
|
||
? { rolle: r, code: codes[r], alter_ok: true } : { rolle: r, code: codes[r] }));
|
||
q.end();
|
||
});
|
||
kekse[r] = [].concat(antwort.headers["set-cookie"] || []).map((c) => c.split(";")[0]).join("; ");
|
||
}
|
||
|
||
async function liste(bereich, rolle) {
|
||
const a = await roh(`/workspace/api/bereich/${bereich}`, { cookie: kekse[rolle] });
|
||
let j = null; try { j = JSON.parse(a.text); } catch { /* keine JSON-Antwort */ }
|
||
return { code: a.code, n: (j?.eintraege || []).length };
|
||
}
|
||
|
||
/* Der Katalog wird schon fuer Abschnitt 0 gebraucht -- er steht
|
||
deshalb vor ihm und nicht mehr in Abschnitt 1. */
|
||
const KATALOG_VORAB = { ...ARBEIT_START, ...TREFF_START };
|
||
const KATALOG = KATALOG_VORAB;
|
||
|
||
/* =======================================================================
|
||
0. EIN BRETT OHNE KATALOG BEKOMMT SEINEN EINTRAG -- UND ZWAR ZUERST
|
||
=======================================================================
|
||
|
||
„highlight" hat als einziges Treff-Brett keinen Katalog: Dort stehen
|
||
echte Hoehepunkte, keine Vorlagen. Abschnitt 2 misst aber, ob die
|
||
Community DASSELBE sieht wie DogFather -- und an einem leeren Brett
|
||
ist das nicht zu messen (null gleich null waere auch dann wahr, wenn
|
||
die Community gar nichts duerfte).
|
||
|
||
WARUM GANZ AM ANFANG: Es gibt eine Schreibbremse -- rund fuenfzig
|
||
Beitraege je Stunde. Der Katalog unten legt 110 an; danach ist sie
|
||
ausgeloest, und der Versuch, hier noch etwas zu schreiben, bekommt
|
||
429. Genau so ist es im ersten Anlauf passiert. Die Bremse ist
|
||
richtig und bleibt; die Pruefung stellt sich davor statt dahinter.
|
||
|
||
UEBER DIE ECHTE ROUTE, nicht ueber die Datenbank: So ist der Weg,
|
||
den auch ein Mensch nimmt, gleich mitgeprueft.
|
||
======================================================================= */
|
||
{
|
||
/* NUR DIE BRETTER OHNE KATALOG. Der erste Anlauf fragte „ist es
|
||
leer?" -- und vor dem Katalog sind ALLE leer. Er legte damit
|
||
ueberall einen Eintrag an, und bei „ansteht" stimmte danach die
|
||
Zahl nicht mehr (5 gegen 4). Gefragt wird deshalb, was wirklich
|
||
gemeint ist: Gibt es fuer dieses Brett eine Vorlage? */
|
||
const ohneKatalog = TREFF_BRETTER.filter((b) => !KATALOG_VORAB[b]);
|
||
ok(ohneKatalog.length >= 1,
|
||
`${ohneKatalog.length} Treff-Brett(er) ohne Katalog: ${ohneKatalog.join(", ") || "keines"}`);
|
||
|
||
for (const b of ohneKatalog) {
|
||
const art = Object.keys(BEREICHE[b]?.arten || {})[0];
|
||
const neu = await roh(`/workspace/api/bereich/${b}`,
|
||
{ cookie: kekse.admin, origin: `https://${CREW}` },
|
||
{ art, titel: "Damit dieses Brett etwas zeigt",
|
||
text: "Ein Eintrag fuer die Messung -- dieses Brett hat keine Vorlagen." });
|
||
ok(neu.code === 201, `${b}: bekommt einen Eintrag (${neu.code})`);
|
||
|
||
/* UND ER MUSS FREIGEGEBEN WERDEN. Auf den Freigabe-Brettern sieht
|
||
die Community nur, was jemand aus dem Team durchgelassen hat --
|
||
beim Katalog passiert das automatisch (workspace-bereiche.js),
|
||
beim gewoehnlichen Schreiben nicht. Ohne diesen Schritt maesse
|
||
Abschnitt 2 „DogFather 1, Community 0" und haette recht: Der
|
||
Eintrag ist wirklich nicht frei. */
|
||
if (TREFF_FREIGABE_BRETTER.includes(b)) {
|
||
let id = null;
|
||
try { id = JSON.parse(neu.text)?.eintrag?.id ?? JSON.parse(neu.text)?.id; }
|
||
catch { /* steht unten als Fehler */ }
|
||
const frei = id
|
||
? await roh(`/workspace/api/treff/eintrag/${id}/freigeben`,
|
||
{ cookie: kekse.admin, origin: `https://${CREW}` }, {}, "PUT")
|
||
: { code: 0 };
|
||
ok(frei.code === 200, ` und wird freigegeben (${frei.code})`);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* =======================================================================
|
||
1. DOGFATHER FÜLLT ALLES
|
||
======================================================================= */
|
||
melde("");
|
||
melde("=== 1. Der Vorschlagskasten ===");
|
||
const gefuellt = [];
|
||
{
|
||
let summe = 0;
|
||
for (const b of Object.keys(BEREICHE)) {
|
||
const a = await roh(`/workspace/api/bereich/${b}/start`,
|
||
{ cookie: kekse.admin, origin: `https://${CREW}` }, {});
|
||
let j = null; try { j = JSON.parse(a.text); } catch { /* keine JSON-Antwort */ }
|
||
if (a.code === 201 && j?.angelegt) { gefuellt.push(b); summe += j.angelegt; }
|
||
}
|
||
/* DIE ZAHL STEHT IN DER BEDINGUNG, nicht nur im Text. Ohne das wäre
|
||
„alle sehen gleich viel" auch dann grün, wenn es null wäre. */
|
||
ok(summe > 50, `DogFather legt ${summe} fertige Einträge in ${gefuellt.length} Kategorien an`);
|
||
ok(gefuellt.length >= 15,
|
||
`und zwar in fast allen (${gefuellt.length} von ${Object.keys(BEREICHE).length})`);
|
||
|
||
/* Die beiden personenbezogenen bleiben mit Absicht leer. */
|
||
ok(!KATALOG.talente && !KATALOG.entwicklung,
|
||
"„talente\" und „entwicklung\" haben bewusst keinen Katalog – dort stünden erfundene Menschen");
|
||
}
|
||
|
||
/* =======================================================================
|
||
2. UND DIE COMMUNITY SIEHT ES AUCH ← Fehler 1
|
||
======================================================================= */
|
||
melde("");
|
||
melde("=== 2. Was die Community sieht ===");
|
||
{
|
||
/* ==== EIN LEERES BRETT BEWEIST NICHTS (25.09.2026) ============
|
||
|
||
„highlight" hat als einziges Treff-Brett keinen Katalog -- dort
|
||
stehen echte Hoehepunkte und keine Vorlagen, und das ist richtig
|
||
so. Die Folge war aber: null Eintraege bei DogFather, null bei
|
||
der Community, und die Bedingung `a.n > 0` wurde rot. Die
|
||
Pruefung meldete einen Fehler, wo schlicht nichts zu sehen war.
|
||
|
||
GEMESSEN WERDEN SOLL DIE GLEICHHEIT, nicht der Katalog. Also legt
|
||
die Pruefung dort selbst einen Eintrag an -- ueber die echte
|
||
Route, mit der auch DogFather schreibt. Damit hat jedes Brett
|
||
etwas, und die Frage „sieht die Community dasselbe?" laesst sich
|
||
ueberall stellen.
|
||
|
||
KEIN TESTDATENSATZ IM SINNE DES VERBOTS: Diese Pruefung laeuft
|
||
auf ihrer eigenen Wegwerf-Datenbank in einem mktemp-Ordner. */
|
||
for (const b of TREFF_BRETTER) {
|
||
const a = await liste(b, "admin");
|
||
const g = await liste(b, "gast");
|
||
const noetig = TREFF_FREIGABE_BRETTER.includes(b);
|
||
ok(a.n > 0 && g.n === a.n,
|
||
`${b.padEnd(10)} DogFather ${a.n}, Community ${g.n}`
|
||
+ (noetig ? " (Brett mit Freigabe – genau hier war der Fehler)" : ""));
|
||
}
|
||
}
|
||
|
||
/* =======================================================================
|
||
3. UND SEIN TEAM AUCH ← Fehler 2
|
||
======================================================================= */
|
||
melde("");
|
||
melde("=== 3. Was das Team sieht ===");
|
||
{
|
||
let geprueftHier = 0;
|
||
for (const b of gefuellt) {
|
||
const a = await liste(b, "admin");
|
||
if (!a.n) continue;
|
||
for (const r of ["hand", "modi"]) {
|
||
const x = await liste(b, r);
|
||
/* 404 heißt: Diese Rolle darf den Bereich gar nicht -- das ist
|
||
kein Fehler, sondern die andere Hälfte von Filipes Satz. Sie
|
||
wird in Abschnitt 4 geprüft, hier übersprungen. */
|
||
if (x.code === 404) continue;
|
||
geprueftHier++;
|
||
ok(x.n === a.n, `${b.padEnd(12)} ${r.padEnd(5)} sieht ${x.n} von ${a.n}`);
|
||
}
|
||
}
|
||
ok(geprueftHier >= 10,
|
||
`es wurden ${geprueftHier} Kombinationen wirklich geprüft – nicht alle übersprungen`);
|
||
}
|
||
|
||
/* =======================================================================
|
||
4. ABER NUR DA, WO SIE DÜRFEN ← die Gegenprobe
|
||
======================================================================= */
|
||
melde("");
|
||
melde("=== 4. Und was zu bleibt ===");
|
||
{
|
||
/* OHNE DIESEN ABSCHNITT wäre die ganze Prüfung grün, wenn man jede
|
||
Schranke entfernte. „Alle sehen alles" ist nicht das Ziel --
|
||
Filipe sagt ausdrücklich „immer nur in denen die ihnen erlaubt
|
||
ist zu sehen". */
|
||
const zu = [];
|
||
for (const b of Object.keys(BEREICHE)) {
|
||
for (const r of ["hand", "modi", "gast"]) {
|
||
const x = await liste(b, r);
|
||
if (x.code === 404) zu.push(`${b}/${r}`);
|
||
}
|
||
}
|
||
ok(zu.length >= 10,
|
||
`${zu.length} Bereich-Rollen-Paare bleiben verschlossen (404)`);
|
||
|
||
/* Und die Community kommt an keinen einzigen Arbeitsbereich. */
|
||
const arbeit = Object.keys(BEREICHE).filter((b) => !TREFF_BRETTER.includes(b));
|
||
const offenFuerGast = [];
|
||
for (const b of arbeit) {
|
||
const x = await liste(b, "gast");
|
||
if (x.code !== 404) offenFuerGast.push(`${b} (${x.code})`);
|
||
}
|
||
ok(offenFuerGast.length === 0,
|
||
offenFuerGast.length
|
||
? `die Community kommt an: ${offenFuerGast.join(", ")}`
|
||
: `die Community sieht keinen der ${arbeit.length} Arbeitsbereiche`);
|
||
}
|
||
|
||
/* =======================================================================
|
||
5. UND DIE REGEL STEHT AN EINER STELLE
|
||
======================================================================= */
|
||
melde("");
|
||
melde("=== 5. Eine Quelle, nicht zwei ===");
|
||
{
|
||
const { readFileSync } = await import("node:fs");
|
||
const quelle = readFileSync(new URL("./workspace-bereiche.js", import.meta.url), "utf8")
|
||
.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\r\n]*/g, " ");
|
||
ok(/\[\.\.\.TEAM_DOGI_ROLLEN,\s*"admin"\]/.test(quelle),
|
||
"die Team-Sicht schließt DogFather ein");
|
||
|
||
/* UND TEAM_DOGI_ROLLEN SELBST BLEIBT UNBERÜHRT. Stünde "admin"
|
||
dort drin, wäre er stillschweigend ins andere Haus umgezogen --
|
||
diese Menge entscheidet auch darüber. */
|
||
const { TEAM_DOGI_ROLLEN } = await import("./workspace.js");
|
||
ok(!TEAM_DOGI_ROLLEN.has("admin"),
|
||
`TEAM_DOGI_ROLLEN bleibt {${[...TEAM_DOGI_ROLLEN].join(", ")}} – sonst zöge DogFather ins Haus der Crew`);
|
||
|
||
const treff = readFileSync(new URL("./workspace-bereiche.js", import.meta.url), "utf8");
|
||
ok(/INSERT OR IGNORE INTO treff_freigaben/.test(treff),
|
||
"und ein übernommener Vorschlag wird gleich freigegeben");
|
||
}
|
||
|
||
melde("");
|
||
melde(`${geprueft} Prüfungen, ${fehler} Fehler`);
|
||
melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
|
||
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Aufraeumrest */ }
|
||
process.exit(fehler ? 1 : 0);
|