Sechs Fragen mehr (jetzt 18), und alle in sechs Feldern gegliedert: Last & Erholung, Miteinander, Sinn & Anerkennung, Klarheit & Rueckhalt, Grenzen & Sicherheit, Weiterkommen & Ausblick. Die Felder sind nicht ausgedacht -- es sind die Gebiete, die die Forschung zu belasteten Rollen durchgehend abfragt. Die drei neuen Luecken, die sie schliessen: Schlaf (zeigt Erschoepfung frueher als jede andere Frage), Widersprechen (der Kern dessen, was psychologische Sicherheit heisst) und Mitreden (viel Anforderung bei wenig Einfluss ist die Kombination, aus der Erschoepfung entsteht). Jede neue Frage hat ihre belegte Einordnung -- eine Frage ohne Grundlage ist eine Frage, die jemand gut fand. DIE ROTATION MUSSTE NEU. Der Katalog ist nach Themen sortiert; wer daraus drei aufeinanderfolgende nimmt, bekommt drei aus demselben Feld. Jetzt wird der Ring vorher verzahnt -- erst je eine Frage aus jedem Feld, dann je eine zweite. Ein Fenster trifft damit von selbst verschiedene Felder. Ein erster Anlauf reservierte feste Plaetze fuer die kernlosen Felder. Begruendet mit einer Auswertung je Feld, die es gar nicht gibt -- und er kostete: zwoelf Runden, bis jede Frage einmal gestellt war, fast ein halbes Jahr. Gefunden hat das pruef-befinden.mjs, nicht das Nachdenken. Mit dem verzahnten Ring und vier Plaetzen je Runde sind es vier Runden. DIE EINE ZUSAMMENFASSUNG AM ENDE, nicht eine je Kategorie. Sie sagt in dieser Reihenfolge: die Lage in einem Satz, was traegt (benannt, nicht als Zahl), hoechstens EINE Sache zum Hinschauen, ein Schluss, der zur Lage passt. Umgekehrt waere es eine Maengelliste mit Trostpflaster, und so etwas beantwortet man beim naechsten Mal nicht mehr ehrlich. ZUR FRAGE NACH DER BESTEN KOSTENLOSEN MOEGLICHKEIT: bewusst KEINE KI. Das sind Gesundheitsdaten (wer nachts wach liegt, wer angefeindet wird, wer ans Aufhoeren denkt) -- deshalb sind sie im ganzen Haus als nurSelbst markiert. Kostenlose KI-Angebote bezahlt man mit den Daten. Ein Sprachmodell erfindet ausserdem, und zwar ueberzeugend. Und ein fremder Dienst faellt aus. Jeder Grund reicht einzeln. Die Begruendung steht ausfuehrlich in workspace-befinden-resuemee.js. Nebenbefund behoben: Die Zusammenfassung blieb direkt NACH einer abgeschlossenen Runde leer -- da ist keine Antwort mehr "frisch". Genau der Moment, in dem man sie sehen will. Auch eine Pruefung korrigiert: Sie verbot den Text "entwicklung.js" irgendwo in der Datei und schlug an einem Kommentar an, der die Serverdatei benennt. Sie misst jetzt die Skript-Quellen. pruef-befinden.mjs 112/0, pruef-resuemee.mjs 35/0 (neu). Offener Befund, aelter als diese Aenderung: pruef-entwicklung.mjs meldet "ein Modi: keine Kachel fuehrt mehr ersatzweise auf die Entwicklungsseite" -- auch ohne diese Commits. Co-Authored-By: Claude Opus 5 <[email protected]>
182 lines
9.2 KiB
JavaScript
182 lines
9.2 KiB
JavaScript
/* =====================================================================
|
|
pruef-resuemee.mjs — Die eine Zusammenfassung am Ende
|
|
|
|
Filipe, 20.09.2026: „am ende von allen fragen will ich eine gesamte
|
|
zusammenfassung, nicht bei jeder frage oder kategorie eine, sondern
|
|
EINE gesamte am ende. eine motivierende zusammenfassung für die
|
|
person."
|
|
|
|
---------------------------------------------------------------------
|
|
WAS HIER GEPRÜFT WIRD, IST NICHT „steht ein Text da"
|
|
|
|
Sondern die eine Eigenschaft, an der so ein Text scheitert:
|
|
ER DARF NICHT LÜGEN, UM ZU MOTIVIEREN.
|
|
|
|
Eine Zusammenfassung, die bei sechs von acht „da hakt es" fröhlich
|
|
bleibt, ist keine Ermutigung, sondern Hohn — und beim nächsten Mal
|
|
antwortet man ihr nicht mehr ehrlich. Genau das ist mit einem
|
|
Sprachmodell die wahrscheinlichste Fehlerart, und genau deshalb
|
|
rechnet das hier ein Programm.
|
|
|
|
Die Prüfungen gehen deshalb paarweise: einmal die gute Lage, einmal
|
|
die schwere — und der Text MUSS sich unterscheiden. Ein Text, der
|
|
in beiden Fällen gleich klingt, besteht jede Prüfung, die nur nach
|
|
„ist ein Satz da" fragt.
|
|
|
|
AUFRUF: node server/pruef-resuemee.mjs
|
|
===================================================================== */
|
|
|
|
import { resuemeeVon } from "./workspace-befinden-resuemee.js";
|
|
import { ENTWICKLUNG_PUNKTE, BEFINDEN_FELDER } from "./workspace-entwicklungs-punkte.js";
|
|
|
|
let fehler = 0, geprueft = 0;
|
|
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
|
|
|
console.log("\n=== Die eine Zusammenfassung ===\n");
|
|
|
|
const punkte = ENTWICKLUNG_PUNKTE.befinden;
|
|
ok(punkte.length >= 12, `es gibt genug Fragen zum Zusammenfassen (${punkte.length})`);
|
|
ok(punkte.every((p) => !!p.feld),
|
|
`jede Frage gehört zu einem Feld (${punkte.filter((p) => !p.feld).length} ohne)`);
|
|
|
|
/* JEDES FELD KOMMT VOR. Ein Feld ohne Fragen wäre eine Überschrift
|
|
über nichts -- und in der Zusammenfassung ein Thema, das nie
|
|
gewählt werden kann. */
|
|
for (const f of BEFINDEN_FELDER) {
|
|
const n = punkte.filter((p) => p.feld === f.schluessel).length;
|
|
ok(n > 0, ` Feld '${f.name}' hat Fragen (${n})`);
|
|
}
|
|
/* GEGENPROBE IN DIE ANDERE RICHTUNG: kein verwaistes Feld an einer
|
|
Frage, das es in der Liste nicht gibt. Ohne sie bliebe eine
|
|
vertippte Feldkennung unbemerkt -- die Frage stünde dann unter
|
|
„ohne Feld" am Ende, und niemand wüsste warum. */
|
|
const bekannt = new Set(BEFINDEN_FELDER.map((f) => f.schluessel));
|
|
const verwaist = punkte.filter((p) => p.feld && !bekannt.has(p.feld));
|
|
ok(verwaist.length === 0,
|
|
`Gegenprobe: keine Frage zeigt auf ein Feld, das es nicht gibt (${verwaist.map((p) => p.feld).join(", ") || "keine"})`);
|
|
|
|
const bau = (stufen) => {
|
|
const a = {};
|
|
punkte.slice(0, stufen.length).forEach((p, i) => { a[p.schluessel] = stufen[i]; });
|
|
return a;
|
|
};
|
|
const teil = (n, stufe) => Array(n).fill(stufe);
|
|
|
|
/* ---- 1. DIE GUTE LAGE -------------------------------------------- */
|
|
const gut = resuemeeVon(bau(teil(8, "laeuft")), punkte.slice(0, 8), BEFINDEN_FELDER);
|
|
ok(gut.moeglich === true, "bei acht Mal 'Läuft' gibt es eine Zusammenfassung");
|
|
ok(gut.thema === null, " und kein Thema zum Hinschauen — es gibt keins");
|
|
ok(gut.traegt.length > 0, ` aber etwas, das trägt (${gut.traegt.length})`);
|
|
ok(gut.zahlen.hakt === 0 && gut.zahlen.traegt === 8,
|
|
` die Zahlen stimmen (${gut.zahlen.traegt} läuft, ${gut.zahlen.hakt} hakt)`);
|
|
|
|
/* ---- 2. DIE SCHWERE LAGE ----------------------------------------- */
|
|
const schwer = resuemeeVon(bau(teil(6, "hakt").concat(teil(2, "laeuft"))),
|
|
punkte.slice(0, 8), BEFINDEN_FELDER);
|
|
ok(schwer.moeglich === true, "bei sechs von acht 'Da hakt es' auch");
|
|
ok(schwer.zahlen.hakt === 6, ` und sie zählt richtig (${schwer.zahlen.hakt})`);
|
|
|
|
/* DIE ENTSCHEIDENDE PRÜFUNG. */
|
|
ok(gut.kopf !== schwer.kopf,
|
|
"der Kopfsatz ist ein ANDERER als bei der guten Lage — er ist nicht für alle gleich");
|
|
ok(gut.schluss !== schwer.schluss,
|
|
"und der Schlusssatz auch");
|
|
ok(/6 von 8/.test(schwer.kopf),
|
|
`die schwere Lage wird BEIM NAMEN genannt ('${schwer.kopf.slice(0, 44)}…')`);
|
|
ok(!/super|toll|prima|großartig|weiter so/i.test(schwer.kopf + schwer.schluss),
|
|
"und nicht schöngeredet — kein 'super', kein 'weiter so'");
|
|
ok(/jemandem|allein|sagen/i.test(schwer.schluss),
|
|
`der Schluss zeigt einen Weg statt Trost ('${schwer.schluss.slice(0, 50)}…')`);
|
|
|
|
/* UND TROTZDEM NICHT NIEDERSCHMETTERND: Auch in der schweren Lage
|
|
steht das, was trägt — sonst ist es eine Mängelliste. */
|
|
ok(schwer.traegt.length > 0,
|
|
`auch hier steht, was trägt (${schwer.traegt.length}) — sonst wäre es eine Mängelliste`);
|
|
|
|
/* ---- 3. HÖCHSTENS EIN THEMA -------------------------------------- */
|
|
ok(schwer.thema !== null, "bei sechs Haken gibt es ein Thema");
|
|
ok(typeof schwer.thema.name === "string" && schwer.thema.name.length > 2,
|
|
` und es hat einen Namen ('${schwer.thema?.name}')`);
|
|
/* Wer fünf Probleme auf einmal vorgelegt bekommt, sieht keine fünf
|
|
Aufgaben, sondern einen Berg. */
|
|
ok(!Array.isArray(schwer.thema.felder),
|
|
"es ist EIN Feld, keine Liste — fünf Probleme auf einmal sind ein Berg");
|
|
|
|
/* DAS THEMA IST DAS FELD MIT DEN MEISTEN HAKEN, nicht das erste. */
|
|
{
|
|
/* Drei Haken in EINEM Feld gegen einen in einem anderen. */
|
|
const zielFeld = BEFINDEN_FELDER.find((f) =>
|
|
punkte.filter((p) => p.feld === f.schluessel).length >= 3);
|
|
const imFeld = punkte.filter((p) => p.feld === zielFeld.schluessel).slice(0, 3);
|
|
const andere = punkte.find((p) => p.feld !== zielFeld.schluessel);
|
|
const a = {};
|
|
for (const p of imFeld) a[p.schluessel] = "hakt";
|
|
a[andere.schluessel] = "hakt";
|
|
const r = resuemeeVon(a, [...imFeld, andere], BEFINDEN_FELDER);
|
|
ok(r.thema?.feld === zielFeld.schluessel,
|
|
`das Thema ist das Feld mit den meisten Haken ('${r.thema?.name}', ${r.thema?.anzahl})`);
|
|
ok(r.thema?.anzahl === 3, ` und nennt, wie viele es dort sind (${r.thema?.anzahl})`);
|
|
}
|
|
|
|
/* ---- 4. „KANN ICH NICHT SAGEN" IST KEIN PROBLEM ------------------ */
|
|
/* Wer sie zu den Sorgen schlägt, erzeugt Sorgen, die niemand
|
|
geäußert hat. */
|
|
const unklar = resuemeeVon(bau(teil(8, "unklar")), punkte.slice(0, 8), BEFINDEN_FELDER);
|
|
ok(unklar.zahlen.hakt === 0 && unklar.zahlen.unklar === 8,
|
|
`acht Mal 'Kann ich nicht sagen' ergibt null Haken (${unklar.zahlen.hakt})`);
|
|
ok(unklar.thema === null, " und kein Thema — es wurde ja nichts gesagt");
|
|
ok(/ehrliche Antwort/i.test(unklar.kopf),
|
|
` der Satz nennt es eine ehrliche Antwort ('${unklar.kopf.slice(0, 40)}…')`);
|
|
|
|
/* ---- 5. „HAT SICH GEBESSERT" NUR, WENN ES STIMMT ----------------- */
|
|
{
|
|
const p3 = punkte.slice(0, 3);
|
|
const vorher = { [p3[0].schluessel]: "hakt", [p3[1].schluessel]: "laeuft" };
|
|
const jetzt = { [p3[0].schluessel]: "laeuft", [p3[1].schluessel]: "laeuft",
|
|
[p3[2].schluessel]: "laeuft" };
|
|
const r = resuemeeVon(jetzt, p3, BEFINDEN_FELDER, vorher);
|
|
ok(r.zahlen.besser === 1,
|
|
`genau eine echte Verbesserung wird gezählt (${r.zahlen.besser})`);
|
|
/* DIE FALLE: Die dritte Frage war letztes Mal gar nicht dran. „War
|
|
nicht dabei" ist KEINE Verbesserung -- seit die Fragen rotieren,
|
|
wäre das sonst bei jeder frisch dazugekommenen Frage der Fall,
|
|
und der Satz „drei Sachen haben sich gebessert" wäre erfunden. */
|
|
ok(!/2 Sachen|3 Sachen/.test(r.schluss),
|
|
` eine Frage, die letztes Mal nicht dran war, zählt nicht als Verbesserung ("${r.schluss.slice(0, 46)}…")`);
|
|
|
|
/* GEGENPROBE: Wird es schlechter, steht dort KEINE Verbesserung. */
|
|
const rueck = resuemeeVon({ [p3[0].schluessel]: "hakt" }, [p3[0]], BEFINDEN_FELDER,
|
|
{ [p3[0].schluessel]: "laeuft" });
|
|
ok(rueck.zahlen.besser === 0,
|
|
`Gegenprobe: eine Verschlechterung wird nicht als Besserung gezählt (${rueck.zahlen.besser})`);
|
|
}
|
|
|
|
/* ---- 6. DER DRITTE AUSGANG --------------------------------------- */
|
|
const leer = resuemeeVon({}, punkte.slice(0, 5), BEFINDEN_FELDER);
|
|
ok(leer.moeglich === false,
|
|
"ohne Antworten sagt sie, dass sie nichts sagen kann — statt freundlich über nichts zu reden");
|
|
ok(typeof leer.grund === "string" && leer.grund.length > 5,
|
|
` und nennt den Grund ('${leer.grund}')`);
|
|
|
|
/* ---- 7. KEINE ERFUNDENEN ZAHLEN ---------------------------------- */
|
|
/* Jede Zahl im Text muss in `zahlen` wiederzufinden sein. Ein Satz,
|
|
der „12 Fragen" sagt, während acht gestellt wurden, ist genau der
|
|
Fehler, wegen dem hier kein Sprachmodell hängt. */
|
|
{
|
|
const r = resuemeeVon(bau(teil(3, "hakt").concat(teil(5, "laeuft"))),
|
|
punkte.slice(0, 8), BEFINDEN_FELDER);
|
|
const text = [r.kopf, r.schluss, r.thema?.satz].filter(Boolean).join(" ");
|
|
const zahlenImText = [...text.matchAll(/\b(\d+)\b/g)].map((m) => Number(m[1]));
|
|
const erlaubt = new Set(Object.values(r.zahlen).filter((x) => typeof x === "number"));
|
|
/* Auch Differenzen sind erlaubt -- „5 von 8 laufen" nennt 8 minus 3. */
|
|
for (const z of [...erlaubt]) for (const y of [...erlaubt]) erlaubt.add(Math.abs(z - y));
|
|
const erfunden = zahlenImText.filter((z) => !erlaubt.has(z));
|
|
ok(erfunden.length === 0,
|
|
`jede Zahl im Text steht auch in den Zahlen (${erfunden.length} erfunden)`);
|
|
console.log(` Text: '${r.kopf}'`);
|
|
console.log(` Zahlen: ${JSON.stringify(r.zahlen)}`);
|
|
}
|
|
|
|
console.log(`\n${fehler ? fehler + " FEHLER" : "Alles in Ordnung"} — ${geprueft} Prüfungen\n`);
|
|
process.exit(fehler ? 1 : 0);
|