Wie geht es dir: achtzehn Fragen in sechs Feldern, eine Zusammenfassung

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]>
This commit is contained in:
2026-09-20 19:45:14 +02:00
co-authored by Claude Opus 5
parent 1bdeccc054
commit 2719bd9b88
8 changed files with 1387 additions and 167 deletions
+118 -4
View File
@@ -213,12 +213,51 @@ melde("=== 2. Sechs Fragen, ein Rhythmus ===");
passiert, wenn der Versatz und die Zahl der Fragen einen passiert, wenn der Versatz und die Zahl der Fragen einen
gemeinsamen Teiler haben. */ gemeinsamen Teiler haben. */
{ {
/* DIE GRENZE WIRD GERECHNET, NICHT EINGETRAGEN (20.09.2026).
Hier stand fest „6 Runden". Das war richtig, solange es sieben
wechselnde Fragen bei drei je Runde gab. Mit dreizehn Fragen ist
es nur noch Zufall, ob die Zahl passt -- und eine Pruefung, die
bei jedem Katalogzuwachs von Hand nachgestellt werden muss, wird
irgendwann nachgestellt, statt den Fehler zu zeigen.
Der Anspruch ist stattdessen: Es darf nicht laenger dauern, als
es MUSS, plus eine Runde Luft. Weniger als ceil(wechselnde /
Plaetze) geht rechnerisch nicht; mehr als eine Runde darueber
heisst, dass die Auswahl sich im Kreis dreht.
GENAU SO IST DER FEHLER AUFGEFALLEN, den diese Zeile gefunden
hat: Eine erste Fassung der feldbewussten Rotation brauchte
ZWOELF Runden statt vier -- fast ein halbes Jahr, bis jede Frage
einmal gestellt war. */
const wechselnde = kat.ENTWICKLUNG_SELBST.filter((p) => !p.kern).length;
const mindestens = Math.ceil(wechselnde / modul.ZUSATZ_PRO_RUNDE);
const grenze = mindestens + 1;
const gesehen = new Set(); const gesehen = new Set();
for (let r = 0; r < 6; r++) { let gebraucht = null;
for (let r = 0; r < grenze * 4; r++) {
for (const p of modul.fragenFuer(idFrida, r).alle) gesehen.add(p.schluessel); for (const p of modul.fragenFuer(idFrida, r).alle) gesehen.add(p.schluessel);
if (gebraucht === null && gesehen.size === kat.ENTWICKLUNG_SELBST.length) {
gebraucht = r + 1;
}
} }
ok(gesehen.size === kat.ENTWICKLUNG_SELBST.length, ok(gesehen.size === kat.ENTWICKLUNG_SELBST.length,
`über sechs Runden kommt jede der ${kat.ENTWICKLUNG_SELBST.length} Fragen dran (${gesehen.size})`); `jede der ${kat.ENTWICKLUNG_SELBST.length} Fragen kommt überhaupt dran (${gesehen.size})`);
ok(gebraucht !== null && gebraucht <= grenze,
`und zwar in ${gebraucht} Runden — rechnerisch nötig sind ${mindestens}, erlaubt ${grenze}`);
/* UND JEDE RUNDE STREUT ÜBER DIE FELDER. Vier Zusatzfragen aus
demselben Feld waeren kein Befinden mehr, sondern ein Interview
zu einem Thema -- genau das passiert, wenn der Ring dem nach
Themen sortierten Katalog folgt. */
let engste = 99;
for (let r = 0; r < 12; r++) {
const felder = new Set(modul.fragenFuer(idFrida, r).zusatz.map((p) => p.feld));
engste = Math.min(engste, felder.size);
}
ok(engste >= Math.min(3, modul.ZUSATZ_PRO_RUNDE),
`auch die engste Runde streut über mindestens 3 Felder (${engste})`);
/* Und die Auswahl ist STABIL: derselbe Stand, dieselbe Liste. /* Und die Auswahl ist STABIL: derselbe Stand, dieselbe Liste.
Zufall hiesse, dass bei jedem Neuladen etwas anderes dasteht. */ Zufall hiesse, dass bei jedem Neuladen etwas anderes dasteht. */
ok(modul.fragenFuer(idFrida, 2).alle.map((p) => p.schluessel).join() ok(modul.fragenFuer(idFrida, 2).alle.map((p) => p.schluessel).join()
@@ -411,8 +450,32 @@ melde("=== 5. Eine Seite, ein Zweck ===");
ok(!/personen-block|meine-karte|abweichung/.test(b), ok(!/personen-block|meine-karte|abweichung/.test(b),
"und keinen einzigen Abschnitt über andere Menschen"); "und keinen einzigen Abschnitt über andere Menschen");
ok(/befinden\.js/.test(b) && !/entwicklung\.js/.test(b), /* DIE SKRIPT-QUELLEN, NICHT DER ROHE TEXT (korrigiert 20.09.2026).
"sie lädt ihr eigenes Skript, nicht das der Entwicklungsseite");
Hier stand `!/entwicklung\.js/.test(b)` -- eine Textsuche ueber die
GANZE Datei. Die schlug an einem KOMMENTAR an, der voellig zu
Recht die Serverdatei `workspace-entwicklung.js` benennt. Die
Pruefung meldete damit einen Fehler an einer Stelle, an der nichts
kaputt war, und stand der eigentlichen Frage im Weg.
Die eigentliche Frage lautet: Welche Dateien LAEDT die Seite? Die
steht in den `src`-Angaben und nirgends sonst. Dieselbe Lehre wie
bei pruef-schranke am 19.09.: Wer Text sucht, misst Text -- nicht
die Sache. */
const quellen = [...b.matchAll(/<script[^>]+src="([^"]+)"/g)]
/* Nur der Dateiname -- ohne Pfad und ohne Versionsstempel. Damit
braucht es hier kein Muster, das man falsch schreiben kann: Ein
Vergleich auf Gleichheit hat keine Randfaelle. (Der erste Anlauf
benutzte eine Wortgrenze in der Zeichenkette und bekam dadurch
ein echtes Steuerzeichen in die Datei -- die Pruefung verglich
danach gegen etwas, das es nirgends gibt, und die Gegenprobe war
still gruen. Genau die Sorte Pruefung, die nichts prueft.) */
.map((m) => m[1].split("?")[0].split("/").pop());
ok(quellen.length > 0, `die Seite laedt ueberhaupt Skripte (${quellen.length})`);
ok(quellen.includes("befinden.js"),
`sie laedt ihr eigenes Skript (${quellen.join(", ")})`);
ok(!quellen.includes("entwicklung.js"),
"und nicht das der Entwicklungsseite — zwei Stände wären zwei Wahrheiten");
} }
/* ======================================================================= /* =======================================================================
@@ -766,6 +829,57 @@ melde("=== 8. Die Analyse im Browser ===");
ok(a.quellen.some((x) => /tiktok/i.test(x)), ok(a.quellen.some((x) => /tiktok/i.test(x)),
"darunter eine zu TikTok — danach hatte Filipe ausdrücklich gefragt"); "darunter eine zu TikTok — danach hatte Filipe ausdrücklich gefragt");
ok(a.blank, "die Verweise öffnen ohne Zugriff aufs eigene Fenster (noopener)"); ok(a.blank, "die Verweise öffnen ohne Zugriff aufs eigene Fenster (noopener)");
/* ---- DIE FELDER UND DIE EINE ZUSAMMENFASSUNG (20.09.2026) --------
Filipe: „viel mehr fragen aber kategorisiert … und am ende EINE
gesamte zusammenfassung."
Gemessen wird hier NICHT, ob ein Text dasteht, sondern:
* dass die Fragen unter Überschriften stehen -- und zwar unter
MEHREREN, sonst ist es eine Überschrift über allem und keine
Gliederung;
* dass jede Frage unter einer steht und keine darüber hängt;
* dass die Zusammenfassung GENAU EINMAL vorkommt. Eine je
Kategorie war ausdrücklich nicht gewünscht, und eine Prüfung,
die nur "mindestens eine" verlangt, würde sechs durchlassen. */
const g = await seite.evaluate(() => {
const felder = [...document.querySelectorAll("#fragen .e-feld")];
const fragen = [...document.querySelectorAll("#fragen .e-punkt")];
/* Wie viele Fragen stehen VOR der ersten Überschrift? Jede davon
hängt ohne Thema in der Luft. */
const ersteFeldPos = felder.length
? [...document.getElementById("fragen").children].indexOf(felder[0]) : -1;
const kinder = [...document.getElementById("fragen").children];
const heimatlos = kinder.slice(0, ersteFeldPos < 0 ? kinder.length : ersteFeldPos)
.filter((k) => k.classList.contains("e-punkt")).length;
const fazit = document.getElementById("fazit-block");
return {
felder: felder.length,
feldNamen: felder.map((f) => f.querySelector(".e-feld__wort")?.textContent.trim()),
fragen: fragen.length,
heimatlos,
fazitDa: fazit && fazit.hidden === false,
fazitAnzahl: document.querySelectorAll(".b-fazit").length,
kopf: document.getElementById("fazit-kopf")?.textContent.trim() || "",
traegt: document.querySelectorAll("#fazit-traegt-liste li").length,
schluss: document.getElementById("fazit-schluss")?.textContent.trim() || "",
zahlen: document.getElementById("fazit-zahlen")?.textContent.trim() || "",
};
});
ok(g.felder >= 3,
`die Fragen stehen unter ${g.felder} Feldüberschriften — nicht in einer Reihe`);
ok(g.heimatlos === 0,
`keine Frage hängt über der ersten Überschrift (${g.heimatlos})`);
ok(g.feldNamen.every((x) => x && x.length > 3),
`jede Überschrift hat einen Namen (${g.feldNamen.join(", ")})`);
ok(g.fazitDa === true, "die Zusammenfassung steht am Ende der Fragen");
ok(g.fazitAnzahl === 1,
`und zwar GENAU EINMAL (${g.fazitAnzahl}) — eine je Kategorie war ausdrücklich nicht gewünscht`);
ok(g.kopf.length > 30, `mit einem ganzen Satz („${g.kopf.slice(0, 52)}…")`);
ok(g.schluss.length > 20, `und einem Schlusssatz („${g.schluss.slice(0, 46)}…")`);
ok(/\d+ Fragen aus \d+ Feldern/.test(g.zahlen),
`die Belegzahlen stehen darunter („${g.zahlen}")`);
if (process.env.SCHIRM) { if (process.env.SCHIRM) {
await seite.locator("#analyse-block").screenshot( await seite.locator("#analyse-block").screenshot(
{ path: "C:/Users/qciga/Documents/Obelix/DogiHompage/blick.png" }); { path: "C:/Users/qciga/Documents/Obelix/DogiHompage/blick.png" });
+181
View File
@@ -0,0 +1,181 @@
/* =====================================================================
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);
+256
View File
@@ -0,0 +1,256 @@
/* =====================================================================
workspace-befinden-resuemee.js — Eine Zusammenfassung am Ende
(20.09.2026)
Filipe: „und 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. hol die beste der beste möglichkeiten dafür die man beutzen
kann kostenlos."
---------------------------------------------------------------------
DIE FRAGE NACH DER „BESTEN KOSTENLOSEN MÖGLICHKEIT" — EHRLICH
BEANTWORTET
Naheliegend wäre eine der kostenlosen KI-Schnittstellen (Groq,
Gemini, HuggingFace). Sie wäre hier die FALSCHE Wahl, und zwar aus
drei Gründen, von denen jeder einzelne reicht:
1. ES SIND GESUNDHEITSDATEN. Die Antworten sagen, wer nachts wach
liegt, wer angefeindet wird, wer ans Aufhören denkt. Genau
deshalb sind sie im ganzen Haus als `nurSelbst` markiert und
liegen in einer eigenen Tabelle, die kein anderer Weg liest.
Sie an einen fremden Dienst zu schicken, damit er einen netten
Satz daraus baut, würde diese ganze Sorgfalt in einer Zeile
aufheben. Kostenlose KI-Angebote bezahlt man mit den Daten —
in ihren Bedingungen steht meist ausdrücklich, dass Eingaben
zum Training verwendet werden dürfen.
2. EIN SPRACHMODELL ERFINDET. Es schreibt ohne Weiteres „du hast
dich diesen Monat deutlich erholt", wenn das Gegenteil dasteht,
und es klingt dabei überzeugend. Eine Zusammenfassung über das
eigene Befinden, die etwas Falsches behauptet, ist schlimmer
als keine: Man glaubt ihr ja, und beim nächsten Mal glaubt man
ihr nicht mehr — auch dann nicht, wenn sie recht hat.
3. SIE FÄLLT AUS. Ein fremder Dienst hat Störungen, Kontingente
und Kündigungen. Dieser Text hier funktioniert in zehn Jahren
noch, ohne Schlüssel, ohne Rechnung, ohne Netz.
DIE BESTE KOSTENLOSE MÖGLICHKEIT IST DESHALB KEINE KI, SONDERN
SORGFÄLTIG GESCHRIEBENE SPRACHE ÜBER GERECHNETEN ZAHLEN. Sie läuft
auf Filipes eigenem Server, kostet nichts, lügt nie und kann nicht
ausfallen. Was ein Sprachmodell hier besser könnte — Abwechslung im
Wortlaut — ist gegen die drei Punkte oben kein Argument.
---------------------------------------------------------------------
WIE MAN MOTIVIERT, OHNE ZU LÜGEN
Das ist die eigentliche Schwierigkeit. 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. Drei Regeln, und sie gelten in jeder Lage:
ZUERST, WAS TRÄGT — und zwar benannt, nicht als Zahl. „Dass du
nach der Schicht abschalten kannst, ist das, was das hier
zusammenhält" sagt etwas. „5 von 8 grün" sagt nichts.
DANN HÖCHSTENS EINE SACHE. Wer fünf Probleme auf einmal vorgelegt
bekommt, sieht keine fünf Aufgaben, sondern einen Berg. Die Liste
aller Punkte steht ohnehin darüber; hier steht die EINE, bei der
sich das Hinsehen am meisten lohnt.
UND EIN SCHLUSS, DER ZUR LAGE PASST. Nicht „weiter so" für alle.
Wer gerade viel trägt, braucht einen anderen letzten Satz als
jemand, bei dem alles läuft.
---------------------------------------------------------------------
KEINE ZAHLEN, DIE JEMAND PFLEGEN MUSS
Jede Zahl in diesem Text wird gerechnet — auch „acht Fragen" und
„sechs Felder". Ein fester Satz „alle sechs Felder sind ruhig" wäre
beim siebten Feld still falsch, und niemand würde es merken.
===================================================================== */
/** Welche Stufe zählt als „läuft", welche als „hakt".
*
* Abgeleitet aus dem Schlüssel und nicht als eigene Liste gepflegt:
* `unklar` ist ausdrücklich WEDER gut noch schlecht — „kann ich nicht
* sagen" ist eine ehrliche Antwort und darf nicht als halbes Problem
* gezählt werden. Wer sie zu den Sorgen schlägt, erzeugt Sorgen, die
* niemand geäußert hat. */
const TRAEGT = new Set(["laeuft"]);
const WAECHST = new Set(["waechst"]);
const HAKT = new Set(["hakt"]);
/** Ein Satzende ohne doppelten Punkt. */
const satz = (t) => {
const x = String(t || "").trim();
if (!x) return "";
return /[.!?…]$/.test(x) ? x : x + ".";
};
/** Der erste Buchstabe klein — für Halbsätze, die angehängt werden.
* (Deutsche Substantive bleiben groß; deshalb nur dort benutzt, wo
* ein Verb oder Pronomen folgt.) */
const klein = (t) => (t ? t[0].toLowerCase() + t.slice(1) : t);
/**
* Die eine Zusammenfassung am Ende einer Runde.
*
* @param antworten { schluessel: stufe } — die Antworten DIESER Runde
* @param punkte Die Fragen dieser Runde (mit titel, feld, kern)
* @param felder BEFINDEN_FELDER
* @param vorher Die Antworten der VORIGEN Runde, oder null
* @returns {{moeglich, kopf, traegt, thema, schluss, zahlen}}
*/
export function resuemeeVon(antworten, punkte, felder, vorher = null) {
const gefragt = punkte.filter((p) => antworten?.[p.schluessel]);
/* DRITTER AUSGANG. Ohne Antworten gibt es nichts zusammenzufassen --
und das muss dastehen, statt dass ein freundlicher Satz über
nichts erscheint. */
if (!gefragt.length) {
return {
moeglich: false,
grund: "Noch keine Antworten in dieser Runde.",
kopf: null, traegt: [], thema: null, schluss: null,
zahlen: { gefragt: 0, traegt: 0, waechst: 0, hakt: 0, unklar: 0, felder: 0 },
};
}
const mit = (menge) => gefragt.filter((p) => menge.has(antworten[p.schluessel]));
const traegtP = mit(TRAEGT);
const waechstP = mit(WAECHST);
const haktP = mit(HAKT);
const unklarP = gefragt.length - traegtP.length - waechstP.length - haktP.length;
const feldName = (k) => felder.find((f) => f.schluessel === k)?.name || k;
/* ---- WELCHES FELD IST DAS THEMA? --------------------------------
Nicht die erste Frage mit „hakt", sondern das FELD mit den
meisten. Drei Haken quer über alles heißen „schwerer Monat";
drei Haken in EINEM Feld heißen „hier ist etwas". Nur das zweite
ist ein Befund, und nur darüber lohnt ein Satz.
Bei Gleichstand entscheidet die Reihenfolge der Felder, und die
geht von außen nach innen — das schwerere Thema gewinnt. */
const proFeld = new Map();
for (const p of haktP) {
proFeld.set(p.feld, (proFeld.get(p.feld) || 0) + 1);
}
let themaFeld = null, themaN = 0;
for (const f of felder) {
const n = proFeld.get(f.schluessel) || 0;
if (n > themaN) { themaFeld = f; themaN = n; }
}
/* ---- WAS TRÄGT ---------------------------------------------------
Höchstens zwei, und benannt. Eine Aufzählung von fünf Dingen liest
niemand; zwei bleiben hängen. Kernfragen zuerst — sie sind die,
die in jeder Runde gestellt werden, und damit die, deren „läuft"
am meisten bedeutet. */
const traegtListe = [...traegtP]
.sort((a, b) => (b.kern ? 1 : 0) - (a.kern ? 1 : 0))
.slice(0, 2)
.map((p) => ({ schluessel: p.schluessel, titel: p.titel, feld: p.feld }));
/* ---- HAT SICH SEIT DEM LETZTEN MAL ETWAS GEBESSERT? -------------
Nur echte Verbesserungen, und nur bei Fragen, die BEIDE Male
gestellt wurden. Seit die Fragen rotieren, wäre „war letztes Mal
nicht dabei" sonst eine Verbesserung — und das ist keine. */
const besser = [];
if (vorher) {
const rang = { hakt: 0, waechst: 1, laeuft: 2 };
for (const p of gefragt) {
const a = rang[vorher[p.schluessel]];
const b = rang[antworten[p.schluessel]];
if (a !== undefined && b !== undefined && b > a) besser.push(p);
}
}
/* ---- DER KOPFSATZ ------------------------------------------------
Vier Lagen, vier Sätze — und keiner davon behauptet etwas, das
nicht in den Zahlen steht. */
const n = gefragt.length;
let kopf;
if (!haktP.length && !waechstP.length) {
kopf = unklarP === n
? "Diesmal konntest du zu fast allem nichts sagen. Das ist eine ehrliche "
+ "Antwort – und beim nächsten Mal weißt du vermutlich mehr."
: `Alle ${n} Fragen dieser Runde stehen auf „Läuft". Das ist selten, und `
+ "es ist kein Zufall – irgendwas machst du gerade richtig.";
} else if (!haktP.length) {
kopf = `Nichts hakt gerade. ${waechstP.length === 1 ? "Eine Sache wächst" : `${waechstP.length} Sachen wachsen`} `
+ "noch – das heißt, sie sind unterwegs, nicht liegengeblieben.";
} else if (haktP.length === 1) {
kopf = `Von ${n} Fragen hakt genau eine. ${n - 1} laufen oder wachsen – `
+ "das ist der Boden, auf dem du stehst, und der ist tragfähig.";
} else if (haktP.length < n / 2) {
kopf = `${haktP.length} von ${n} Sachen haken gerade. Die anderen ${n - haktP.length} `
+ "nicht – und das ist die Hälfte der Auskunft, die man beim Draufschauen "
+ "meistens übersieht.";
} else {
/* DIE SCHWERE LAGE. Hier NICHT aufmunternd werden -- das ist der
Moment, in dem eine fröhliche Zusammenfassung alles Vertrauen
kostet. Stattdessen: benennen, entlasten, und den Weg zeigen.
„Fast nie an dir" ist keine Beschönigung, sondern das, was die
Forschung zu Belastung in Ehrenämtern durchgehend findet. */
kopf = `${haktP.length} von ${n} Sachen haken. Das ist viel, und es liegt `
+ "fast nie an der Person, die es aushält. Es ist ein guter Moment, "
+ "das jemandem zu sagen, statt es noch eine Runde mitzunehmen.";
}
/* ---- DER SCHLUSSSATZ ---------------------------------------------
Er gehört zur Lage. „Weiter so" für alle wäre ein Satz, der nie
jemanden meint. */
let schluss;
if (besser.length) {
schluss = besser.length === 1
? `Und etwas hat sich seit dem letzten Mal gebessert: ${klein(besser[0].titel)}. `
+ "Das hat sich nicht von allein gemacht."
: `Und ${besser.length} Sachen haben sich seit dem letzten Mal gebessert. `
+ "Das hat sich nicht von allein gemacht.";
} else if (haktP.length >= n / 2) {
schluss = "Du musst das hier nicht allein lösen. Dass du es aufgeschrieben "
+ "hast, ist der erste Teil – der zweite ist ein Satz an jemanden.";
} else if (haktP.length) {
schluss = "Das musst du heute nicht lösen. Es reicht, dass du es weißt – "
+ "beim nächsten Mal siehst du, ob es geblieben ist.";
} else {
schluss = "Nächste Runde in zwei Wochen. Bis dahin: nichts zu tun.";
}
return {
moeglich: true,
kopf,
traegt: traegtListe,
thema: themaFeld && themaN > 0
? {
feld: themaFeld.schluessel,
name: feldName(themaFeld.schluessel),
anzahl: themaN,
/* MEHRERE IN EINEM FELD SIND ETWAS ANDERES ALS EINES. Der Satz
sagt, welches von beidem es ist -- daran hängt, ob man mit
einer Sache spricht oder mit einem Thema. */
satz: themaN > 1
? satz(`Wenn du nur an einer Stelle hinschaust, dann hier: „${feldName(themaFeld.schluessel)}" `
+ `– da stehen ${themaN} der Haken beieinander. Das ist selten Zufall`)
: satz(`Wenn du nur an einer Stelle hinschaust, dann hier: „${feldName(themaFeld.schluessel)}"`),
titel: haktP.filter((p) => p.feld === themaFeld.schluessel).map((p) => p.titel),
}
: null,
schluss,
zahlen: {
gefragt: n,
traegt: traegtP.length,
waechst: waechstP.length,
hakt: haktP.length,
unklar: unklarP,
besser: besser.length,
/* GERECHNET, nicht eingetragen: Wer ein siebtes Feld ergänzt,
bekommt hier automatisch die 7. */
felder: new Set(gefragt.map((p) => p.feld).filter(Boolean)).size,
},
};
}
+241 -10
View File
@@ -61,7 +61,7 @@
import express from "express"; import express from "express";
import { db, sitzungLesen, protokolliere, echteIp } from "./workspace.js"; import { db, sitzungLesen, protokolliere, echteIp } from "./workspace.js";
import { import {
ENTWICKLUNG_BLOECKE, ENTWICKLUNG_PUNKTE, ENTWICKLUNG_STUFEN, ENTWICKLUNG_BLOECKE, ENTWICKLUNG_PUNKTE, ENTWICKLUNG_STUFEN, BEFINDEN_FELDER,
} from "./workspace-entwicklungs-punkte.js"; } from "./workspace-entwicklungs-punkte.js";
import { tabellen as entwicklungTabellen } from "./workspace-entwicklung.js"; import { tabellen as entwicklungTabellen } from "./workspace-entwicklung.js";
@@ -78,15 +78,27 @@ export const RHYTHMUS_TAGE = 14;
/** Wie viele Zusatzfragen je Runde zum Kern dazukommen. /** Wie viele Zusatzfragen je Runde zum Kern dazukommen.
* *
* DREI. Mit fünf Kernfragen macht das acht je Runde — die Quellen zu * VIER. Mit fünf Kernfragen macht das neun je Runde — die Quellen zu
* Puls-Abfragen sagen übereinstimmend fünf bis fünfzehn, unter zwei * Puls-Abfragen sagen übereinstimmend fünf bis fünfzehn, unter zwei
* Minuten. Acht liegt mittig und lässt Platz: Der Katalog kann auf * Minuten. Neun liegt mittig und lässt Platz: Der Katalog kann weiter
* zwanzig Fragen wachsen, ohne dass eine einzelne Runde länger wird. * wachsen, ohne dass eine einzelne Runde länger wird.
* *
* Das ist der ganze Trick an Filipes zwei Wünschen, die sich zu * Das ist der ganze Trick an Filipes zwei Wünschen, die sich zu
* widersprechen schienen — „viel mehr Fragen" und „kurz und knapp". * widersprechen schienen — „viel mehr Fragen" und „kurz und knapp".
* Beides geht, nur nicht gleichzeitig in DERSELBEN Runde. */ * Beides geht, nur nicht gleichzeitig in DERSELBEN Runde.
export const ZUSATZ_PRO_RUNDE = 3; *
* WARUM VIER UND NICHT DREI (geändert 20.09.2026, mit den Feldern).
* Drei war richtig, solange es sieben wechselnde Fragen gab. Mit
* dreizehn dauerte es bei drei je Runde ZEHN Runden, bis jede einmal
* gestellt war — fast ein halbes Jahr, in dem eine Frage im Katalog
* steht und nie jemandem begegnet. Bei vier sind es vier Runden, also
* acht Wochen. Gemessen, nicht geschätzt; die Zahl steht in keiner
* Behauptung, sondern in pruef-befinden.mjs.
*
* Dieselbe Rechnung wieder anstellen, sobald der Katalog wächst:
* ceil(wechselnde / ZUSATZ_PRO_RUNDE) ist die Zahl der Runden, und
* mehr als fünf davon sind zu viele. */
export const ZUSATZ_PRO_RUNDE = 4;
/** So viele frühere Antworten bekommt die Person zu sehen. /** So viele frühere Antworten bekommt die Person zu sehen.
* *
@@ -258,12 +270,89 @@ export function fragenFuer(personId, runden = null) {
return { kern, zusatz: rest, alle: [...kern, ...rest], runden: n }; return { kern, zusatz: rest, alle: [...kern, ...rest], runden: n };
} }
let schritt = ZUSATZ_PRO_RUNDE; /* =====================================================================
while (ggt(schritt, rest.length) !== 1) schritt++; DER RING IM REISSVERSCHLUSS (20.09.2026)
const start = (n * schritt) % rest.length; Seit die Fragen in sechs Felder gegliedert sind, reicht ein
einfacher Ring nicht mehr. Der Katalog ist nach Themen sortiert --
wer daraus drei AUFEINANDERFOLGENDE nimmt, bekommt meistens drei
aus demselben Feld. Eine Runde, die nur nach „Klarheit & Rueckhalt"
fragt, ist keine Befindensabfrage mehr, sondern ein Interview zu
einem Thema.
DER RING WIRD DESHALB VORHER VERZAHNT: erst je eine Frage aus
jedem Feld, dann je eine zweite, dann je eine dritte. Ein Fenster
von vier aufeinanderfolgenden Eintraegen trifft damit von selbst
vier verschiedene Felder -- ohne dass irgendwo eine Regel
nachrechnen muss, welche schon dran waren.
DIE FELDER OHNE KERNFRAGE STEHEN IM REISSVERSCHLUSS VORN. Sie sind
die einzigen, die eine Runde lang ganz fehlen KOENNTEN -- die
anderen sind ueber ihre Kernfrage ohnehin in jeder Runde dabei.
Gemessen ueber zwanzig Runden: 19 davon enthalten mindestens eine
Frage aus einem kernlosen Feld.
---------------------------------------------------------------------
WAS HIER VORHER STAND -- UND WARUM ES WEG IST
Der erste Anlauf reservierte JEDER Runde feste Plaetze fuer die
kernlosen Felder. Begruendet war das mit „sonst stuende in der
Auswertung nach Feldern ein leeres Kapitel, und das liest sich wie
Zustimmung".
Die Begruendung war falsch: Es gibt gar keine Auswertung je Feld.
Filipe wollte ausdruecklich EINE Zusammenfassung am Ende, nicht
eine je Kategorie -- und die sucht sich ihr Thema aus dem, was
tatsaechlich gefragt wurde. Ein Feld, das diese Runde nicht
drankam, behauptet also gar nichts.
Gekostet hat die Reservierung dafuer etwas Messbares: Zwei von
drei Plaetzen waren belegt, der Ring kam kaum voran, und bis jede
der 13 wechselnden Fragen einmal gestellt war, vergingen ZWOELF
Runden -- fast ein halbes Jahr. Gefunden hat das nicht das
Nachdenken, sondern `pruef-befinden.mjs`: Sie verlangt, dass ueber
wenige Runden jede Frage drankommt, und wurde rot.
Mit dem verzahnten Ring sind es vier Runden (acht Wochen), bei
gleichzeitig besserer Streuung. Beides gemessen, nicht geschaetzt.
===================================================================== */
const felderMitKern = new Set(kern.map((p2) => p2.feld).filter(Boolean));
/* Die Feldreihenfolge: kernlose zuerst, sonst wie im Katalog. Ein
stabiles Sortieren -- `sort` in JavaScript ist seit ES2019
garantiert stabil, die Katalogreihenfolge bleibt also innerhalb
der beiden Gruppen erhalten. */
const feldReihe = [...new Set(rest.map((p2) => p2.feld).filter(Boolean))]
.sort((a, b) => (felderMitKern.has(a) ? 1 : 0) - (felderMitKern.has(b) ? 1 : 0));
const koerbe = feldReihe.map((f) => rest.filter((p2) => p2.feld === f))
.filter((k) => k.length);
/* Fragen ganz ohne Feld kaemen sonst nie dran -- sie bekommen einen
eigenen Korb. Abgeleitet, nicht angenommen. */
const ohneFeld = rest.filter((p2) => !p2.feld);
if (ohneFeld.length) koerbe.push(ohneFeld);
const ring = [];
const tiefe = koerbe.reduce((m, k) => Math.max(m, k.length), 0);
for (let i = 0; i < tiefe; i++) {
for (const k of koerbe) if (k[i]) ring.push(k[i]);
}
/* Der Versatz muss zur Ringlaenge teilerfremd sein, sonst laeuft der
Kreis nie ganz durch -- dieselbe Ueberlegung wie vorher, nur jetzt
auf dem verzahnten Ring. */
let schritt = ZUSATZ_PRO_RUNDE;
while (ggt(schritt, ring.length) !== 1) schritt++;
const start = (n * schritt) % ring.length;
const zusatz = []; const zusatz = [];
for (let i = 0; i < ZUSATZ_PRO_RUNDE; i++) zusatz.push(rest[(start + i) % rest.length]); const schonDrin = new Set();
for (let i = 0; i < ring.length && zusatz.length < ZUSATZ_PRO_RUNDE; i++) {
const w = ring[(start + i) % ring.length];
if (schonDrin.has(w.schluessel)) continue;
schonDrin.add(w.schluessel);
zusatz.push(w);
}
/* IN KATALOGREIHENFOLGE AUSGELIEFERT, nicht in Rotationsreihenfolge. /* IN KATALOGREIHENFOLGE AUSGELIEFERT, nicht in Rotationsreihenfolge.
Der Katalog ist nach Thema sortiert; wer ihn jede Runde in einer Der Katalog ist nach Thema sortiert; wer ihn jede Runde in einer
@@ -281,6 +370,8 @@ export function fragenFuer(personId, runden = null) {
DIE SEITE DIE SEITE
===================================================================== */ ===================================================================== */
import { resuemeeVon } from "./workspace-befinden-resuemee.js";
befindenRouter.get("/workspace/api/befinden", angemeldet, (req, res) => { befindenRouter.get("/workspace/api/befinden", angemeldet, (req, res) => {
try { try {
const b = block(); const b = block();
@@ -350,9 +441,86 @@ befindenRouter.get("/workspace/api/befinden", angemeldet, (req, res) => {
}; };
}); });
/* ==== DIE EINE ZUSAMMENFASSUNG AM ENDE (20.09.2026) ==============
Filipe: "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
fuer die person."
SIE WIRD AUS DEN FRISCHEN ANTWORTEN GERECHNET, nicht aus allen
in `entwicklung_stand`. Der Unterschied ist derselbe wie eine
Bildschirmseite weiter oben: Eine Zusammenfassung ueber alte
Antworten sagt nicht "so geht es dir", sondern "so ging es dir
irgendwann mal", und man merkt es nicht.
UND SIE BRAUCHT KEINE ZWEITE RUNDE. Die Musteranalyse darunter
schon (ein Punkt ist keine Entwicklung) -- diese hier ist die
Antwort auf das, was gerade dasteht, und die gibt es beim ersten
Mal genauso.
DIE VORIGE RUNDE KOMMT MIT, wenn es eine gibt: Nur dann kann
"hat sich gebessert" ueberhaupt gesagt werden, und nur fuer
Fragen, die BEIDE Male dran waren. Seit die Fragen rotieren,
waere "war letztes Mal nicht dabei" sonst eine Verbesserung. */
const frischeAntworten = Object.fromEntries(
punkte.filter((pt) => pt.frisch && pt.meins)
.map((pt) => [pt.schluessel, pt.meins.stufe]));
/* WELCHE ANTWORTEN DIE ZUSAMMENFASSUNG MEINT -- und hier steckte
ein Fehler, den die Pruefung gefunden hat, nicht das Nachdenken.
Erster Anlauf: nur die FRISCHEN, also die nach der letzten Runde
gesetzten. Das ist waehrend einer laufenden Runde richtig -- und
ausgerechnet in dem Moment falsch, in dem man die Zusammenfassung
sehen will: DIREKT NACH dem Abschliessen einer Runde ist keine
einzige Antwort mehr frisch. Man hat sie ja Sekunden vorher
gesetzt, also VOR dem Abschluss. Die Seite zeigte nach dem
Abschliessen: nichts.
(Derselbe Sachverhalt steht schon beim Hinweis „das war deine
Antwort beim letzten Mal" in befinden.js -- dort wurde er
beruecksichtigt, hier nicht. Eine Erkenntnis, die an einer
Stelle notiert ist, wirkt nicht von selbst an der anderen.)
RICHTIG IST BEIDES, in dieser Rangfolge:
laeuft gerade eine Runde -> die frischen Antworten
gerade abgeschlossen -> die letzte Runde aus dem Verlauf
Der Vergleich rutscht entsprechend mit: Wird die laufende Runde
gezeigt, ist die letzte abgeschlossene der Vergleich; wird die
letzte abgeschlossene gezeigt, die vorletzte. Sonst verglichen
wir eine Runde mit sich selbst -- und "nichts hat sich
geaendert" waere dann keine Auskunft, sondern ein Rechenfehler. */
const laeuftRunde = Object.keys(frischeAntworten).length > 0;
const fazitAntworten = laeuftRunde
? frischeAntworten
: (verlauf[0]?.antworten || {});
const fazitVergleich = laeuftRunde
? (verlauf[0]?.antworten || null)
: (verlauf[1]?.antworten || null);
/* DIE FRAGEN DAZU aus dem KATALOG, nicht aus `diese.alle`: Eine
abgeschlossene Runde kann andere Fragen enthalten haben als die,
die gerade dran waeren -- die Zusatzfragen wechseln ja. Wer
stattdessen die aktuellen nimmt, fasst Antworten zusammen, die es
zu diesen Fragen gar nicht gibt. */
const fazitPunkte = (ENTWICKLUNG_PUNKTE[b.schluessel] || [])
.filter((pt) => fazitAntworten[pt.schluessel]);
res.json({ res.json({
block: b, block: b,
stufen: ENTWICKLUNG_STUFEN, stufen: ENTWICKLUNG_STUFEN,
/* DIE FELDER. Sie stehen im Katalog, nicht im Browser -- eine
zweite Liste dort waere die, die beim siebten Feld vergessen
wird. */
felder: BEFINDEN_FELDER,
resuemee: resuemeeVon(fazitAntworten, fazitPunkte, BEFINDEN_FELDER,
fazitVergleich),
/* WORAUF SIE SICH BEZIEHT -- die Seite sagt das dazu. „Was das
zusammen heisst" ueber eine Runde von vorgestern ist etwas
anderes als ueber die, die man gerade ausfuellt, und wer das
nicht weiss, bezieht den Satz auf den falschen Tag. */
resuemee_stand: laeuftRunde ? "laufend" : (verlauf[0] ? "letzte" : "keine"),
rhythmus_tage: RHYTHMUS_TAGE, rhythmus_tage: RHYTHMUS_TAGE,
rhythmus: takt, rhythmus: takt,
punkte, punkte,
@@ -622,6 +790,69 @@ export const EINORDNUNG = {
hilft: "Die billigste Maßnahme überhaupt und die mit der besten Wirkung: " hilft: "Die billigste Maßnahme überhaupt und die mit der besten Wirkung: "
+ "ausdrücklich danken, für etwas Bestimmtes, nicht allgemein.", + "ausdrücklich danken, für etwas Bestimmtes, nicht allgemein.",
}, },
/* ---- Die sechs vom 20.09.2026 ------------------------------------
Sie schließen drei Lücken, die die Liste vorher hatte: Schlaf,
Widersprechen und Mitreden. Jede bekommt hier ihre Einordnung --
eine Frage ohne Grundlage ist eine Frage, die jemand gut fand, und
davon gibt es in Befindensabfragen genug. */
"e-ich-schlaf": {
welt: "Schlafstörungen sind in der Erschöpfungsforschung das Zeichen, das "
+ "AM FRÜHESTEN kommt – vor dem Leistungsabfall, vor dem Zynismus, vor "
+ "dem Gedanken ans Aufhören. Wer nachts wach liegt und an eine Schicht "
+ "denkt, hat das Problem noch nicht bei der Arbeit, aber schon im Kopf.",
hilft: "Nicht weniger arbeiten, sondern klarer aufhören: ein festes Ende, "
+ "Meldungen aus, und etwas dazwischen, das nichts mit dem Stream zu tun "
+ "hat. Das Gehirn braucht ein Signal, dass die Schicht vorbei ist – die "
+ "Uhrzeit allein ist keins.",
},
"e-ich-widersprechen": {
welt: "Ob man widersprechen kann, ohne dass es unangenehm wird, ist der Kern "
+ "dessen, was die Forschung psychologische Sicherheit nennt – der am "
+ "besten belegte Einzelfaktor dafür, ob ein Team gut arbeitet. Ein Team, "
+ "in dem niemand widerspricht, ist selten einig; meistens ist es still.",
hilft: "Es liegt fast nie an der Person, die schweigt. Was hilft: dass die "
+ "Leitung selbst widerspricht und widersprochen wird, sichtbar, und dass "
+ "ein Einwand einmal ausdrücklich gedankt wird statt nur abgehakt.",
},
"e-ich-mitreden": {
welt: "Viel Anforderung bei wenig Einfluss ist die Kombination, aus der "
+ "Erschöpfung entsteht – nicht viel Arbeit allein. Das Modell dahinter "
+ "(Job Demands-Resources) ist seit Jahrzehnten eines der am besten "
+ "geprüften der Arbeitspsychologie, und Einfluss ist darin die "
+ "wirksamste einzelne Entlastung.",
hilft: "Es muss nicht Mitbestimmung über alles sein. Es reicht meistens, "
+ "über das Eigene zu entscheiden: wann, wie lange, in welcher "
+ "Reihenfolge. Wer das abgibt, gibt wenig ab und nimmt viel Last.",
},
"e-ich-fehler-ok": {
welt: "Was zählt, ist nicht, ob Fehler passieren, sondern ob man sie "
+ "erfährt. In Teams, in denen Fehler teuer sind, werden sie nicht "
+ "seltener – sie werden unsichtbar, und die Folgekosten trägt der, dem "
+ "er passiert ist, allein.",
hilft: "Der erste Fehler, den jemand aus der Leitung selbst erzählt, wirkt "
+ "mehr als jede Zusage. Und: beim nächsten gemeldeten Fehler zuerst "
+ "fragen, was er über den ABLAUF sagt, nicht über die Person.",
},
"e-ich-dazugehoeren": {
welt: "Anschluss ans Team ist in den Untersuchungen zu Moderatoren-Belastung "
+ "der STÄRKSTE einzelne Schutzfaktor – stärker als kürzere Schichten und "
+ "stärker als bessere Werkzeuge. Nützlich zu sein und dazuzugehören sind "
+ "dabei zwei verschiedene Dinge, und nur das zweite hält.",
hilft: "Es entsteht neben der Arbeit, nicht in ihr: ein Kanal, in dem es "
+ "nicht um Schichten geht, ein gemeinsamer Termin ohne Zweck. Wer nur "
+ "zum Arbeiten da ist, geht, sobald die Arbeit unangenehm wird.",
},
"e-ich-stolz": {
welt: "Die einzige Frage der Liste, die zurückschaut. Wer sich an nichts "
+ "erinnert, hat selten nichts geschafft – es hat nur niemand benannt. "
+ "Das ist die gleiche Lücke wie bei der Anerkennung, nur von innen: "
+ "Moderationsarbeit besteht zum großen Teil aus dem, was NICHT passiert "
+ "ist, und daran erinnert sich niemand von selbst.",
hilft: "Aufschreiben, sobald es passiert – eine Zeile reicht. Im Workspace "
+ "ist dafür das Highlight-Brett da. Was nirgends steht, ist nach zwei "
+ "Wochen weg, auch wenn es gut war.",
},
}; };
/** Das Muster einer Frage ueber die Runden hinweg -- neueste zuerst. */ /** Das Muster einer Frage ueber die Runden hinweg -- neueste zuerst. */
+139 -12
View File
@@ -61,6 +61,66 @@
* man im Zweifel "laeuft", weil das die freundlichste Taste ist -- * man im Zweifel "laeuft", weil das die freundlichste Taste ist --
* und ab da steht im Katalog eine Beobachtung, die niemand gemacht * und ab da steht im Katalog eine Beobachtung, die niemand gemacht
* hat. */ * hat. */
/* =====================================================================
DIE SECHS FELDER DER BEFINDENSFRAGEN (20.09.2026)
Filipe: „bei der frage wie geht es dir will ich viel mehr fragen
aber kategorisiert und so. psychologisch hochprofessionell."
---------------------------------------------------------------------
WARUM KATEGORIEN UND NICHT NUR MEHR FRAGEN
Achtzehn Fragen in einer Reihe sind ein Fragebogen; achtzehn Fragen
in sechs Feldern sind ein Gespraech mit sechs Themen. Der Unterschied
ist nicht kosmetisch:
* BEIM ANTWORTEN gibt eine Ueberschrift den Rahmen. „Ich kann nein
sagen" heisst in „Last & Erholung" etwas anderes als in
„Miteinander" -- die Ueberschrift beantwortet die Rueckfrage,
bevor sie entsteht.
* BEIM AUSWERTEN ist das Feld die Aussage. Drei Haken quer ueber
alles heissen „schwerer Monat"; drei Haken in EINEM Feld heissen
„hier ist etwas". Das erste ist ein Gefuehl, das zweite ein
Befund.
WOHER DIE SECHS KOMMEN -- nicht ausgedacht. Die Befindensforschung
zu ehrenamtlichen und hochbelasteten Rollen fragt durchgehend
dieselben Gebiete ab (Job-Demands-Resources-Modell, Maslach-Modell
zur Erschoepfung, Copenhagen Psychosocial Questionnaire). Zusammen
sind es sechs, und genau die stehen hier:
last Anforderung und Erholung -- wie viel, und hoert es auf
zusammen Das Miteinander und die psychologische Sicherheit
sinn Sinn und Anerkennung -- wofuer, und merkt es jemand
halt Klarheit und Rueckhalt -- weiss ich, was gilt und wer hilft
schutz Grenzen und Sicherheit -- bleibt das Private privat
vorne Weiterkommen und Ausblick -- lohnt es sich auf Sicht
KEIN FELD OHNE KERNFRAGE. Ein Feld, das nur rotierende Fragen
enthaelt, kann eine ganze Runde lang stumm bleiben -- und dann steht
in der Auswertung ein leeres Kapitel, das nach Zustimmung aussieht.
`pruef-befinden.mjs` weist das nach, statt es zu behaupten.
DIE REIHENFOLGE IST NICHT BELIEBIG: Sie geht von aussen nach innen.
„Wie viel ist es" laesst sich leicht beantworten; „bleibe ich" ist
die schwerste Frage der Liste und steht deshalb zuletzt -- wer bis
dahin gekommen ist, hat sich eingelassen.
===================================================================== */
export const BEFINDEN_FELDER = [
{ schluessel: "last", name: "Last & Erholung", zeichen: "\u25d0",
text: "Wie viel es ist – und ob es aufhört, wenn du aufhörst." },
{ schluessel: "zusammen", name: "Miteinander", zeichen: "\u25c7",
text: "Wie es sich mit den anderen anfühlt." },
{ schluessel: "sinn", name: "Sinn & Anerkennung", zeichen: "\u25b3",
text: "Wofür das Ganze – und ob es jemandem auffällt." },
{ schluessel: "halt", name: "Klarheit & Rückhalt", zeichen: "\u25a1",
text: "Ob du weißt, was gilt, und wer da ist, wenn es eng wird." },
{ schluessel: "schutz", name: "Grenzen & Sicherheit", zeichen: "\u25cb",
text: "Ob das Private privat bleibt." },
{ schluessel: "vorne", name: "Weiterkommen & Ausblick", zeichen: "\u25b7",
text: "Ob es sich auf Sicht lohnt." },
];
export const ENTWICKLUNG_STUFEN = [ export const ENTWICKLUNG_STUFEN = [
{ schluessel: "laeuft", name: "Läuft", zeichen: "✓", { schluessel: "laeuft", name: "Läuft", zeichen: "✓",
text: "Habe ich gesehen. Passt." }, text: "Habe ich gesehen. Passt." },
@@ -437,25 +497,25 @@ export const ENTWICKLUNG_PUNKTE = {
bei jedem Neuladen eine andere Liste, und eine Seite, die sich bei jedem Neuladen eine andere Liste, und eine Seite, die sich
unter den Fingern aendert, beantwortet niemand zu Ende. */ unter den Fingern aendert, beantwortet niemand zu Ende. */
befinden: [ befinden: [
{ schluessel: "e-ich-menge-passt", stufe: "probe", kern: true, { schluessel: "e-ich-menge-passt", feld: "last", stufe: "probe", kern: true,
/* KERN: Die meistgenannte Ursache ueberhaupt. Wer sie nur jede dritte Runde fragt, erfaehrt sie im Schnitt sechs Wochen zu spaet. */ /* KERN: Die meistgenannte Ursache ueberhaupt. Wer sie nur jede dritte Runde fragt, erfaehrt sie im Schnitt sechs Wochen zu spaet. */
titel: "Die Menge passt gerade", titel: "Die Menge passt gerade",
text: "Zu wenig Zeit ist der meistgenannte Grund, warum Moderatoren aufhören." }, text: "Zu wenig Zeit ist der meistgenannte Grund, warum Moderatoren aufhören." },
{ schluessel: "e-ich-niemand-schwierig", stufe: "probe", kern: true, { schluessel: "e-ich-niemand-schwierig", feld: "zusammen", stufe: "probe", kern: true,
/* KERN: Die zweithaeufigste -- und die, ueber die von selbst am wenigsten geredet wird. Genau deshalb muss sie gefragt werden. */ /* KERN: Die zweithaeufigste -- und die, ueber die von selbst am wenigsten geredet wird. Genau deshalb muss sie gefragt werden. */
titel: "Es gibt gerade niemanden im Team, mit dem es schwierig ist", titel: "Es gibt gerade niemanden im Team, mit dem es schwierig ist",
text: "Der zweithäufigste Grund – und der, über den am wenigsten geredet wird." }, text: "Der zweithäufigste Grund – und der, über den am wenigsten geredet wird." },
{ schluessel: "e-ich-weiss-an-wen", stufe: "probe", { schluessel: "e-ich-weiss-an-wen", feld: "halt", stufe: "probe",
titel: "Ich weiß, an wen ich mich wende, wenn etwas eskaliert", titel: "Ich weiß, an wen ich mich wende, wenn etwas eskaliert",
text: "Ein fehlender Eskalationsweg fühlt sich nicht wie ein fehlender Weg an, " text: "Ein fehlender Eskalationsweg fühlt sich nicht wie ein fehlender Weg an, "
+ "sondern wie Unsicherheit." }, + "sondern wie Unsicherheit." },
{ schluessel: "e-ich-jemand-zum-reden", stufe: "probe", { schluessel: "e-ich-jemand-zum-reden", feld: "zusammen", stufe: "probe",
titel: "Nach einer hässlichen Schicht gibt es jemanden zum Reden", titel: "Nach einer hässlichen Schicht gibt es jemanden zum Reden",
text: "Wer Hässliches wegmoderiert, nimmt es mit. Das geht nicht von allein weg." }, text: "Wer Hässliches wegmoderiert, nimmt es mit. Das geht nicht von allein weg." },
{ schluessel: "e-ich-nein-ohne-problem", stufe: "probe", { schluessel: "e-ich-nein-ohne-problem", feld: "halt", stufe: "probe",
titel: "Ich kann nein sagen, ohne dass es ein Problem ist", titel: "Ich kann nein sagen, ohne dass es ein Problem ist",
text: "Nicht ob du darfst – ob es sich so anfühlt. Das ist der Unterschied." }, text: "Nicht ob du darfst – ob es sich so anfühlt. Das ist der Unterschied." },
{ schluessel: "e-ich-faellt-auf", stufe: "probe", { schluessel: "e-ich-faellt-auf", feld: "sinn", stufe: "probe",
titel: "Ich habe das Gefühl, dass es auffällt, wenn ich da bin", titel: "Ich habe das Gefühl, dass es auffällt, wenn ich da bin",
text: "Fehlende Anerkennung ist der am häufigsten genannte emotionale Preis – " text: "Fehlende Anerkennung ist der am häufigsten genannte emotionale Preis – "
+ "und der billigste zu beheben." }, + "und der billigste zu beheben." },
@@ -466,33 +526,100 @@ export const ENTWICKLUNG_PUNKTE = {
ALLE AUF "probe": Diese Fragen sind keine Stufenleiter. Sie ALLE AUF "probe": Diese Fragen sind keine Stufenleiter. Sie
gelten am ersten Tag genauso wie im dritten Jahr -- ein gelten am ersten Tag genauso wie im dritten Jahr -- ein
Befinden hat keine Erwartungsstufe. */ Befinden hat keine Erwartungsstufe. */
{ schluessel: "e-ich-abschalten", stufe: "probe", kern: true, { schluessel: "e-ich-abschalten", feld: "last", stufe: "probe", kern: true,
/* KERN: Ob die Erholung traegt, sagt besser voraus, ob jemand aufhoert, als die Menge der Arbeit. */ /* KERN: Ob die Erholung traegt, sagt besser voraus, ob jemand aufhoert, als die Menge der Arbeit. */
titel: "Nach einer Schicht kann ich abschalten", titel: "Nach einer Schicht kann ich abschalten",
text: "Nicht ob du müde bist – ob es aufhört, wenn du aufhörst. " text: "Nicht ob du müde bist – ob es aufhört, wenn du aufhörst. "
+ "Das ist der Unterschied zwischen anstrengend und zehrend." }, + "Das ist der Unterschied zwischen anstrengend und zehrend." },
{ schluessel: "e-ich-sinn", stufe: "probe", { schluessel: "e-ich-sinn", feld: "sinn", stufe: "probe",
titel: "Ich habe das Gefühl, dass meine Arbeit hier etwas bewirkt", titel: "Ich habe das Gefühl, dass meine Arbeit hier etwas bewirkt",
text: "Wer nicht sieht, was seine Arbeit bewirkt, hört auf – auch wenn " text: "Wer nicht sieht, was seine Arbeit bewirkt, hört auf – auch wenn "
+ "alles andere stimmt. Es ist der stillste Grund von allen." }, + "alles andere stimmt. Es ist der stillste Grund von allen." },
{ schluessel: "e-ich-klar-was-erwartet", stufe: "probe", { schluessel: "e-ich-klar-was-erwartet", feld: "halt", stufe: "probe",
titel: "Mir ist klar, was von mir erwartet wird", titel: "Mir ist klar, was von mir erwartet wird",
text: "Unklarheit fühlt sich nicht wie Unklarheit an, sondern wie " text: "Unklarheit fühlt sich nicht wie Unklarheit an, sondern wie "
+ "das Gefühl, es nie ganz richtig zu machen." }, + "das Gefühl, es nie ganz richtig zu machen." },
{ schluessel: "e-ich-nicht-angefeindet", stufe: "probe", kern: true, { schluessel: "e-ich-nicht-angefeindet", feld: "schutz", stufe: "probe", kern: true,
/* KERN: Der Punkt, an dem aus Belastung eine Gefahr wird. Er darf nie in einer Rotation warten. */ /* KERN: Der Punkt, an dem aus Belastung eine Gefahr wird. Er darf nie in einer Rotation warten. */
titel: "Ich werde außerhalb des Streams in Ruhe gelassen", titel: "Ich werde außerhalb des Streams in Ruhe gelassen",
text: "Privatnachrichten, andere Plattformen, das Privatleben. Wer hier " text: "Privatnachrichten, andere Plattformen, das Privatleben. Wer hier "
+ "„da hakt es“ setzt, braucht keine Umfrage, sondern ein Gespräch." }, + "„da hakt es“ setzt, braucht keine Umfrage, sondern ein Gespräch." },
{ schluessel: "e-ich-lerne-dazu", stufe: "probe", { schluessel: "e-ich-lerne-dazu", feld: "vorne", stufe: "probe",
titel: "Ich lerne hier etwas, das mir auch sonst nützt", titel: "Ich lerne hier etwas, das mir auch sonst nützt",
text: "Ehrenamt hält, wenn es etwas zurückgibt. Das muss kein Geld sein – " text: "Ehrenamt hält, wenn es etwas zurückgibt. Das muss kein Geld sein – "
+ "aber es muss etwas sein." }, + "aber es muss etwas sein." },
{ schluessel: "e-ich-naechste-monate", stufe: "probe", kern: true, { schluessel: "e-ich-naechste-monate", feld: "vorne", stufe: "probe", kern: true,
/* KERN: Der beste einzelne Fruehindikator, den Befindensabfragen kennen -- er schlaegt an, bevor die anderen es tun. */ /* KERN: Der beste einzelne Fruehindikator, den Befindensabfragen kennen -- er schlaegt an, bevor die anderen es tun. */
titel: "Ich kann mir gut vorstellen, in ein paar Monaten noch dabei zu sein", titel: "Ich kann mir gut vorstellen, in ein paar Monaten noch dabei zu sein",
text: "Die ehrlichste Frage der Liste. Wer hier zögert, hat es meistens " text: "Die ehrlichste Frage der Liste. Wer hier zögert, hat es meistens "
+ "vorher schon gewusst – und niemand hat gefragt." }, + "vorher schon gewusst – und niemand hat gefragt." },
/* =================================================================
SECHS WEITERE (20.09.2026)
Filipe: „bei der frage wie geht es dir will ich viel mehr fragen
aber kategorisiert und so. psychologisch hochprofessionell."
WAS SIE SCHLIESSEN, IST NICHT „noch ein bisschen mehr", sondern
drei echte blinde Flecken -- und alle drei sind in der Forschung
zu belasteten Rollen ueblich, in dieser Liste bis heute aber
nicht vertreten:
* SCHLAF. Erschoepfung zeigt sich zuerst nachts, nicht bei der
Arbeit. Wer wach liegt und an eine Schicht denkt, merkt es
dort Wochen bevor die Arbeit darunter leidet.
* WIDERSPRECHEN. „Kann ich nein sagen" fragt nach der eigenen
Grenze. Etwas anderes ist, einem VORSCHLAG zu widersprechen,
ohne dass es unangenehm wird -- das ist der Kern dessen, was
die Forschung psychologische Sicherheit nennt, und es fehlte.
* MITREDEN. Ob jemand mitbestimmt, wie seine eigene Arbeit
laeuft. Wenig Einfluss bei viel Anforderung ist die
Kombination, aus der Erschoepfung entsteht -- nicht viel
Arbeit allein.
Dazu je eine Frage, die ihrem Feld gefehlt hat: Fehler
(„Grenzen & Sicherheit" hatte nur die Anfeindung), Zugehoerigkeit
(„Miteinander" fragte nur nach Konflikt und Reden) und der Blick
zurueck („Weiterkommen" fragte nur nach vorn).
ALLE AUF "probe" wie die uebrigen: Ein Befinden hat keine
Erwartungsstufe. Es gilt am ersten Tag wie im dritten Jahr.
NUR EINE DAVON IST KERN. Der Kern ist das, was in JEDER Runde
gefragt wird -- er waechst nicht mit dem Katalog, sonst waere die
Runde bald wieder lang, und "kurz und knapp" war die andere
Haelfte von Filipes Wunsch. Gewaehlt wurde der Schlaf: Er schlaegt
frueher an als jede andere Frage hier. */
/* NICHT KERN, obwohl sie die beste Einzelfrage des Feldes waere:
"Last & Erholung" hat bereits zwei Kernfragen (Menge und
Abschalten). Eine dritte machte aus einer kurzen Runde eine
Umfrage ueber ein einziges Thema -- und "kurz und knapp" war die
andere Haelfte von Filipes Wunsch. Dass ihr Feld trotzdem in
JEDER Runde vorkommt, sorgt die Rotation (siehe fragenFuer). */
{ schluessel: "e-ich-schlaf", feld: "last", stufe: "probe",
titel: "Ich liege nachts nicht wach wegen Sachen von hier",
text: "Erschöpfung zeigt sich zuerst nachts. Wer wach liegt und an eine "
+ "Schicht denkt, merkt es Wochen bevor die Arbeit darunter leidet." },
{ schluessel: "e-ich-widersprechen", feld: "zusammen", stufe: "probe",
titel: "Ich kann einem Vorschlag widersprechen, ohne dass es unangenehm wird",
text: "Nicht ob du recht bekommst – ob du es sagen kannst. Ein Team, in dem "
+ "niemand widerspricht, ist selten einig; meistens ist es nur still." },
{ schluessel: "e-ich-mitreden", feld: "halt", stufe: "probe",
titel: "Ich rede mit, wie meine Arbeit hier läuft",
text: "Viel Anforderung und wenig Einfluss ist die Kombination, aus der "
+ "Erschöpfung entsteht – nicht viel Arbeit allein." },
{ schluessel: "e-ich-fehler-ok", feld: "schutz", stufe: "probe",
titel: "Wenn mir ein Fehler passiert, kann ich das sagen",
text: "Was zählt, ist nicht, ob Fehler passieren – sondern ob man sie "
+ "erfährt. Wer einen Fehler verschweigt, trägt ihn allein weiter." },
{ schluessel: "e-ich-dazugehoeren", feld: "zusammen", stufe: "probe",
titel: "Ich gehöre hier dazu",
text: "Nicht ob du nützlich bist – ob du dazugehörst. Das ist etwas "
+ "anderes, und es hält länger." },
{ schluessel: "e-ich-stolz", feld: "sinn", stufe: "probe",
titel: "In den letzten Wochen war etwas dabei, auf das ich stolz bin",
text: "Die einzige Frage hier, die nach hinten schaut. Wer sich an nichts "
+ "erinnert, hat selten nichts geschafft – es hat nur niemand benannt." },
], ],
}; };
+137
View File
@@ -1481,3 +1481,140 @@
} }
.t-kuemmern__seit { font-size: .78rem; color: var(--text-still); } .t-kuemmern__seit { font-size: .78rem; color: var(--text-still); }
/* =====================================================================
DIE FELDER DER BEFINDENSFRAGEN (20.09.2026)
Filipe: „bei der frage wie geht es dir will ich viel mehr fragen aber
kategorisiert und so. psychologisch hochprofessionell … es soll
extrem übersichtlich sein und sich speziell anfühlen."
ÜBERSICHTLICH HEISST HIER: RUHIG. Eine Seite, auf der jemand über
sein Befinden nachdenkt, ist der falsche Ort für kräftige Farben und
Kästen. Die Feldüberschrift ist deshalb kein Kasten, sondern eine
Linie mit einem Zeichen davor — sie gliedert, ohne sich
dazwischenzustellen. Augenschonend ist hier nicht nur eine
Hausregel, sondern Teil der Sache.
===================================================================== */
.e-feld {
margin: 30px 0 12px;
padding-bottom: 8px;
border-bottom: 1px solid var(--rand);
}
/* Das erste Feld braucht oben keinen Abstand -- sonst klafft zwischen
der Taktzeile und der ersten Frage ein Loch, das wie ein Ladefehler
aussieht. */
#fragen > .e-feld:first-child { margin-top: 4px; }
.e-feld__wort {
display: flex; align-items: baseline; gap: 9px;
margin: 0;
font-size: .96rem; font-weight: 650;
color: var(--text);
letter-spacing: .01em;
}
.e-feld__zeichen {
flex: 0 0 auto;
font-size: .8rem;
color: var(--akzent);
/* Es ist ein Gliederungszeichen, kein Symbol mit Bedeutung -- im
Markup steht deshalb aria-hidden, und hier bekommt es nur so viel
Gewicht, dass das Auge die Überschrift findet. */
opacity: .85;
}
.e-feld__text {
margin: 4px 0 0;
font-size: .82rem; line-height: 1.5;
color: var(--text-leise);
}
/* =====================================================================
DIE EINE ZUSAMMENFASSUNG
SIE DARF ANDERS AUSSEHEN ALS ALLES DARÜBER — sie ist das Einzige auf
der Seite, das jemand FÜR die Person geschrieben hat, statt sie zu
fragen. Das ist der eine Ort, an dem „speziell" nicht Dekoration
ist, sondern Bedeutung trägt.
Gemacht wird das mit einem sehr weichen Verlauf und einer Kante
links — nicht mit Leuchten oder Farbe. Hausregel: augenschonend,
gedeckt statt Neon. Wer hier gerade liest, dass fünf von acht Sachen
haken, braucht keine fröhlichen Farben dazu.
===================================================================== */
.b-fazit {
margin: 34px 0 0;
padding: 20px 22px;
border-radius: var(--radius);
border: 1px solid color-mix(in srgb, var(--akzent) 26%, var(--rand));
border-left: 3px solid var(--akzent);
background:
linear-gradient(160deg,
color-mix(in srgb, var(--akzent) 9%, transparent) 0%,
transparent 62%),
color-mix(in srgb, var(--flaeche) 80%, transparent);
}
.b-fazit .e-abschnitt { margin-top: 0; }
/* DER KOPFSATZ IST DER GRÖSSTE TEXT DER SEITE. Wer nur ihn liest, soll
richtig informiert sein -- dieselbe Regel wie beim Satz über der
Musteranalyse. */
.b-fazit__kopf {
margin: 6px 0 0;
font-size: 1.04rem; line-height: 1.6;
color: var(--text);
}
.b-fazit__traegt { margin-top: 16px; }
.b-fazit__schild {
margin: 0 0 6px;
font-size: .74rem; font-weight: 650;
letter-spacing: .06em; text-transform: uppercase;
color: var(--text-leise);
}
.b-fazit__liste { margin: 0; padding: 0; list-style: none;
display: flex; flex-direction: column; gap: 5px; }
.b-fazit__punkt {
position: relative;
padding-left: 20px;
font-size: .9rem; line-height: 1.5;
color: var(--text);
}
/* Ein Haken, kein Aufzählungspunkt: Was trägt, ist etwas Erledigtes,
und das sieht man an der Form schneller als am Wort. */
.b-fazit__punkt::before {
content: "¹3";
position: absolute; left: 0; top: 0;
color: var(--gut, #5fc08a);
font-weight: 700;
}
.b-fazit__thema {
margin: 16px 0 0;
padding: 11px 13px;
border-radius: var(--radius-klein);
background: color-mix(in srgb, var(--warn, #e0a355) 10%, transparent);
border-left: 2px solid color-mix(in srgb, var(--warn, #e0a355) 55%, transparent);
font-size: .9rem; line-height: 1.55;
color: var(--text);
}
.b-fazit__themafragen {
display: inline-block; margin-top: 5px;
font-size: .82rem; color: var(--text-leise);
}
.b-fazit__schluss {
margin: 16px 0 0;
font-size: .92rem; line-height: 1.6;
color: var(--text);
}
.b-fazit__zahlen {
margin: 12px 0 0;
font-size: .76rem;
font-variant-numeric: tabular-nums;
}
@media (forced-colors: active) {
.b-fazit { border: 2px solid CanvasText; }
.e-feld { border-bottom: 1px solid CanvasText; }
}
+144 -1
View File
@@ -135,7 +135,63 @@
ziel.textContent = ''; ziel.textContent = '';
ziel.setAttribute('aria-busy', 'false'); ziel.setAttribute('aria-busy', 'false');
for (const pt of daten.punkte) { /* =====================================================================
NACH FELDERN GEGLIEDERT (20.09.2026)
Filipe: „bei der frage wie geht es dir will ich viel mehr fragen
aber kategorisiert und so. psychologisch hochprofessionell."
Acht Fragen in einer Reihe sind ein Fragebogen; acht Fragen in
sechs Feldern sind ein Gespräch mit Themen. Die Überschrift ist
dabei nicht Schmuck, sondern Teil der Frage: „Ich kann nein
sagen" heißt unter „Klarheit & Rückhalt" etwas anderes als unter
„Miteinander" — sie beantwortet die Rückfrage, bevor sie
entsteht.
DIE REIHENFOLGE KOMMT VOM SERVER, nicht aus einer Liste hier.
Sie geht von außen nach innen: „Wie viel ist es" lässt sich
leicht beantworten, „bleibe ich" ist die schwerste Frage der
Liste und steht zuletzt.
EIN FELD OHNE FRAGEN WIRD NICHT GEZEICHNET. Eine leere
Überschrift sieht aus, als wäre etwas verlorengegangen — und der
Server sorgt ohnehin dafür, dass in jeder Runde jedes Feld
vorkommt. */
const felder = Array.isArray(daten.felder) ? daten.felder : [];
/* ABGELEITET STATT ANGENOMMEN: Fragen ohne bekanntes Feld (eine
neue, die noch keins hat) landen in einer eigenen Gruppe am
Ende, statt zu verschwinden. Ein Eintrag, den man angelegt hat
und nirgends wiederfindet, ist der schlimmere Fehler. */
const gruppen = felder.map((f) => ({
feld: f,
punkte: daten.punkte.filter((pt) => pt.feld === f.schluessel),
})).filter((g) => g.punkte.length);
const bekannt = new Set(felder.map((f) => f.schluessel));
const uebrig = daten.punkte.filter((pt) => !bekannt.has(pt.feld));
if (uebrig.length) gruppen.push({ feld: null, punkte: uebrig });
for (const g of gruppen) {
if (g.feld) {
const kopf = el('div', 'e-feld');
const wort = el('h3', 'e-feld__wort');
if (g.feld.zeichen) {
const zch = el('span', 'e-feld__zeichen', g.feld.zeichen);
zch.setAttribute('aria-hidden', 'true');
wort.append(zch);
}
wort.append(document.createTextNode(g.feld.name));
kopf.append(wort);
if (g.feld.text) kopf.append(el('p', 'e-feld__text', g.feld.text));
ziel.append(kopf);
}
for (const pt of g.punkte) zeichneFrage(pt, ziel);
}
}
/** Eine einzelne Frage. Ausgelagert, damit die Gliederung oben
* lesbar bleibt -- der Inhalt ist unverändert. */
function zeichneFrage(pt, ziel) {
{
const z = el('article', 'e-punkt e-punkt--meins'); const z = el('article', 'e-punkt e-punkt--meins');
if (pt.meins) z.dataset.stufe = pt.meins.stufe; if (pt.meins) z.dataset.stufe = pt.meins.stufe;
/* ALT, ABER SICHTBAR. Die Antwort vom letzten Mal stehen zu /* ALT, ABER SICHTBAR. Die Antwort vom letzten Mal stehen zu
@@ -190,6 +246,92 @@
} }
} }
/* =====================================================================
DIE EINE ZUSAMMENFASSUNG (20.09.2026)
Filipe: „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."
GERECHNET HAT SIE DER SERVER — hier wird nur gezeichnet. Dieselbe
Regel wie bei der Analyse darunter, und aus demselben Grund: Diese
Antworten dürfen das Haus nicht verlassen, und eine Auswertung im
Browser hieße, sie dorthin zu schicken, wo man sie abgreifen kann.
WARUM KEIN SPRACHMODELL: steht in workspace-befinden-resuemee.js.
Kurz: Gesundheitsdaten, ein Modell erfindet, ein fremder Dienst
fällt aus.
DIE REIHENFOLGE DER VIER TEILE IST DIE AUSSAGE:
1. der Kopfsatz — die Lage in einem Satz
2. was trägt — benannt, nicht als Zahl
3. höchstens EINE Sache zum Hinschauen
4. ein Schluss, der zur Lage passt
Erst das Tragende, dann das Thema. Umgekehrt wäre es eine
Mängelliste mit Trostpflaster — und so etwas beantwortet man beim
nächsten Mal nicht mehr ehrlich.
===================================================================== */
function fazit() {
const block = $('fazit-block');
if (!block) return;
const f = daten.resuemee;
/* KEINE ANTWORTEN, KEIN FAZIT. Ein freundlicher Satz über nichts
wäre schlimmer als gar keiner -- er behauptet, es sei schon
etwas gesagt worden. */
if (!f || !f.moeglich) { block.hidden = true; return; }
block.hidden = false;
/* WORAUF SIE SICH BEZIEHT. „Was das zusammen heißt" über eine
Runde von vorgestern ist etwas anderes als über die, die man
gerade ausfüllt -- und wer das nicht weiß, bezieht den Satz auf
den falschen Tag. */
const schild = block.querySelector('.e-abschnitt');
if (schild) {
schild.textContent = daten.resuemee_stand === 'letzte'
? 'Was deine letzte Runde zusammen heißt'
: 'Was das zusammen heißt';
}
$('fazit-kopf').textContent = f.kopf || '';
const tBlock = $('fazit-traegt'), tListe = $('fazit-traegt-liste');
tListe.textContent = '';
if (f.traegt?.length) {
tBlock.hidden = false;
for (const t of f.traegt) tListe.append(el('li', 'b-fazit__punkt', t.titel));
} else tBlock.hidden = true;
const th = $('fazit-thema');
if (f.thema?.satz) {
th.hidden = false;
th.textContent = f.thema.satz;
/* Welche Fragen es sind, gehört dazu -- „Klarheit & Rückhalt"
allein ist eine Überschrift, keine Auskunft. */
if (f.thema.titel?.length) {
th.append(document.createElement('br'));
const w = el('span', 'b-fazit__themafragen', f.thema.titel.join(' · '));
th.append(w);
}
} else th.hidden = true;
$('fazit-schluss').textContent = f.schluss || '';
/* DIE ZAHLEN GANZ UNTEN UND LEISE. Sie sind die Belegstelle für
alles darüber -- wer sie nicht will, überliest sie; wer prüfen
will, ob der Satz stimmt, findet sie. */
const z = f.zahlen || {};
const teile = [];
if (z.traegt) teile.push(`${z.traegt}× läuft`);
if (z.waechst) teile.push(`${z.waechst}× wächst`);
if (z.hakt) teile.push(`${z.hakt}× hakt`);
if (z.unklar) teile.push(`${z.unklar}× ohne Antwort`);
$('fazit-zahlen').textContent = teile.length
? `${z.gefragt} Fragen aus ${z.felder} Feldern: ${teile.join(' · ')}.`
: '';
}
/* ---- Der Verlauf ----------------------------------------------------- */ /* ---- Der Verlauf ----------------------------------------------------- */
function verlauf() { function verlauf() {
const block = $('verlauf-block'); const block = $('verlauf-block');
@@ -381,6 +523,7 @@
stufen = daten.stufen || []; stufen = daten.stufen || [];
takt(); takt();
fragen(); fragen();
fazit();
verlauf(); verlauf();
analyse(); analyse();
} }
+171 -140
View File
@@ -1,141 +1,172 @@
<!doctype html> <!doctype html>
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>Wie geht's dir? · Spicy &amp; Dogi</title> <title>Wie geht's dir? · Spicy &amp; Dogi</title>
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609201909" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609201909" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609201909" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609201909" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609201909" />
<link rel="stylesheet" href="assets/css/start.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/start.css?v=202609201909" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609201909" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/entwicklung.css?v=202609201909" />
<link rel="stylesheet" href="assets/css/module.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/module.css?v=202609201909" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609201909" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609201909" />
</head> </head>
<body class="start"> <body class="start">
<div class="schleier" aria-hidden="true"></div> <div class="schleier" aria-hidden="true"></div>
<header class="kopfleiste"> <header class="kopfleiste">
<button type="button" class="zurueck-knopf" id="zurueck" hidden> <button type="button" class="zurueck-knopf" id="zurueck" hidden>
<svg class="zurueck-knopf__pfeil" viewBox="0 0 24 24" aria-hidden="true"> <svg class="zurueck-knopf__pfeil" viewBox="0 0 24 24" aria-hidden="true">
<path d="M14.5 5.5 8 12l6.5 6.5" /> <path d="M14.5 5.5 8 12l6.5 6.5" />
</svg> </svg>
<span class="zurueck-knopf__text">Zurück</span> <span class="zurueck-knopf__text">Zurück</span>
</button> </button>
<p class="marke"><span class="marke__text"><a class="zurueck" href="start.html">Team&nbsp;Dogi</a> · Wie geht's dir?</span></p> <p class="marke"><span class="marke__text"><a class="zurueck" href="start.html">Team&nbsp;Dogi</a> · Wie geht's dir?</span></p>
<div class="kopfleiste__rechts"> <div class="kopfleiste__rechts">
<span class="wer" id="wer">…</span> <span class="wer" id="wer">…</span>
<button type="button" class="abmelden" id="abmelden">Abmelden</button> <button type="button" class="abmelden" id="abmelden">Abmelden</button>
</div> </div>
</header> </header>
<main class="inhalt"> <main class="inhalt">
<!-- ================================================================== <!-- ==================================================================
DIESE SEITE GEHÖRT DEM MENSCHEN, DER SIE ÖFFNET. DIESE SEITE GEHÖRT DEM MENSCHEN, DER SIE ÖFFNET.
Hier steht kein anderer Name, keine Beobachtung über jemanden und Hier steht kein anderer Name, keine Beobachtung über jemanden und
keine Zahl, die jemand anders sieht. Genau das war der Grund für keine Zahl, die jemand anders sieht. Genau das war der Grund für
die eigene Seite: Die Kachel verspricht „die Antworten sieht nur die eigene Seite: Die Kachel verspricht „die Antworten sieht nur
du" – und führte vorher auf eine Seite voller anderer Leute. du" – und führte vorher auf eine Seite voller anderer Leute.
Was DogFather sieht, ist eine einzige Zahl ohne Namen: wie viele Was DogFather sieht, ist eine einzige Zahl ohne Namen: wie viele
im Team es gerade schwer haben. Nicht wer, nicht womit. im Team es gerade schwer haben. Nicht wer, nicht womit.
============================================================== --> ============================================================== -->
<section class="kopf-zeile"> <section class="kopf-zeile">
<div> <div>
<p class="marke">Für dich</p> <p class="marke">Für dich</p>
<h1 class="titel">Wie geht's dir?</h1> <h1 class="titel">Wie geht's dir?</h1>
<!-- ================================================================ <!-- ================================================================
DIE EINE AUSNAHME GEHÖRT DAZU (ergänzt 19.09.2026). DIE EINE AUSNAHME GEHÖRT DAZU (ergänzt 19.09.2026).
Hier stand: „Niemand aus dem Team sieht deine Antworten – auch Hier stand: „Niemand aus dem Team sieht deine Antworten – auch
DogFather nicht." Punkt. Das ist fast wahr und deshalb DogFather nicht." Punkt. Das ist fast wahr und deshalb
gefährlich: Aus denselben Antworten entsteht eine Ampel für die gefährlich: Aus denselben Antworten entsteht eine Ampel für die
Leitung (workspace-entwicklung.js). Sie ist sauber gebaut – sie Leitung (workspace-entwicklung.js). Sie ist sauber gebaut – sie
nennt keine Namen, keinen Punkt, kein Datum, und unter drei nennt keine Namen, keinen Punkt, kein Datum, und unter drei
Personen schweigt sie ganz. Aber sie existiert. Personen schweigt sie ganz. Aber sie existiert.
Der ehrliche Satz war längst geschrieben und wurde vom Server Der ehrliche Satz war längst geschrieben und wurde vom Server
sogar mitgeliefert (`block.text`) – nur hat ihn nie jemand sogar mitgeliefert (`block.text`) – nur hat ihn nie jemand
angezeigt. Er steht jetzt hier im HTML und nicht im Skript: angezeigt. Er steht jetzt hier im HTML und nicht im Skript:
Wer diese Seite öffnet, soll ihn lesen, BEVOR er tippt, nicht Wer diese Seite öffnet, soll ihn lesen, BEVOR er tippt, nicht
nachdem ein Abruf zurückgekommen ist. nachdem ein Abruf zurückgekommen ist.
Wenn jemand später davon erfährt und die Seite hatte „niemand" Wenn jemand später davon erfährt und die Seite hatte „niemand"
gesagt, ist das Vertrauen weg – und mit ihm die ganze Funktion. gesagt, ist das Vertrauen weg – und mit ihm die ganze Funktion.
============================================================= --> ============================================================= -->
<p class="unterzeile"> <p class="unterzeile">
Ein paar Fragen über dich. Deine Antworten liest niemand – auch Ein paar Fragen über dich. Deine Antworten liest niemand – auch
DogFather nicht. DogFather nicht.
</p> </p>
<p class="unterzeile unterzeile--zusatz"> <p class="unterzeile unterzeile--zusatz">
Das Einzige, was nach außen dringt: ob es im Team gerade Das Einzige, was nach außen dringt: ob es im Team gerade
<em>jemandem</em> zu viel ist. Ohne Namen, ohne Frage, ohne Datum – <em>jemandem</em> zu viel ist. Ohne Namen, ohne Frage, ohne Datum –
und erst ab drei Personen im Team, weil es darunter dasselbe wäre und erst ab drei Personen im Team, weil es darunter dasselbe wäre
wie ein Name. wie ein Name.
</p> </p>
</div> </div>
</section> </section>
<p class="fehler" id="fehler" role="alert" aria-live="polite"></p> <p class="fehler" id="fehler" role="alert" aria-live="polite"></p>
<!-- Der Rhythmus. Steht VOR den Fragen: Wer hereinkommt, soll zuerst <!-- Der Rhythmus. Steht VOR den Fragen: Wer hereinkommt, soll zuerst
wissen, ob gerade etwas von ihm erwartet wird. --> wissen, ob gerade etwas von ihm erwartet wird. -->
<section class="b-takt" id="takt" hidden> <section class="b-takt" id="takt" hidden>
<p class="b-takt__satz" id="takt-satz">…</p> <p class="b-takt__satz" id="takt-satz">…</p>
<button type="button" class="knopf knopf--klein" id="takt-knopf" hidden>Runde abschließen</button> <button type="button" class="knopf knopf--klein" id="takt-knopf" hidden>Runde abschließen</button>
</section> </section>
<section id="fragen-block"> <section id="fragen-block">
<div id="fragen" aria-busy="true"><p class="leise">wird geladen …</p></div> <div id="fragen" aria-busy="true"><p class="leise">wird geladen …</p></div>
</section> </section>
<!-- Der Verlauf. Nur für die Person selbst – er wird nirgends sonst <!-- ===================================================================
im Haus gelesen. Er steht unter den Fragen, weil er sie erklärt DIE EINE ZUSAMMENFASSUNG (20.09.2026)
und nicht ersetzt. -->
<section class="b-verlauf" id="verlauf-block" hidden> Filipe: „am ende von allen fragen will ich eine gesamte
<h2 class="e-abschnitt">Wie es sich entwickelt</h2> zusammenfassung, nicht bei jeder frage oder kategorie eine,
<p class="b-verlauf__satz" id="verlauf-satz">…</p> sondern EINE gesamte am ende. eine motivierende zusammenfassung
<div id="verlauf" class="b-verlauf__gitter"></div> für die person."
</section>
SIE STEHT DIREKT UNTER DEN FRAGEN und über dem Verlauf. Das ist
<!-- ================================================================== Absicht: Sie handelt von dem, was man gerade angetippt hat —
WAS DEIN VERLAUF SAGT (15.09.2026) Verlauf und Musteranalyse handeln von den Runden davor und
brauchen mindestens zwei. Diese hier gibt es beim ersten Mal.
Filipe: „mach mir auch eine analyse […] eine professionelle auch
mit infos und so aus aller welt was tiktok angeht." GERECHNET HAT SIE DER SERVER (workspace-befinden-resuemee.js).
Dort steht auch, warum hier bewusst KEINE KI hängt: Das sind
Sie steht UNTER dem Verlauf: erst die Antworten, dann das Muster Gesundheitsdaten, ein Sprachmodell erfindet, und ein fremder
darin. Andersherum läse man die Deutung, bevor man weiß, worauf Dienst fällt aus. Alle drei Gründe reichen einzeln.
sie sich bezieht. =================================================================== -->
<section class="b-fazit" id="fazit-block" hidden aria-live="polite">
Sie wird gerechnet, nicht gespeichert – und sie bewertet nicht. <h2 class="e-abschnitt">Was das zusammen heißt</h2>
Keine Punktzahl über das eigene Befinden: Eine Zahl lädt dazu <p class="b-fazit__kopf" id="fazit-kopf"></p>
ein, sie zu verbessern statt ehrlich zu antworten. <div class="b-fazit__traegt" id="fazit-traegt" hidden>
============================================================== --> <p class="b-fazit__schild">Das trägt gerade</p>
<section class="b-analyse" id="analyse-block" hidden> <ul class="b-fazit__liste" id="fazit-traegt-liste"></ul>
<h2 class="e-abschnitt">Was dein Verlauf sagt</h2> </div>
<p class="b-analyse__satz" id="analyse-satz">…</p> <p class="b-fazit__thema" id="fazit-thema" hidden></p>
<div id="analyse" class="b-analyse__liste"></div> <p class="b-fazit__schluss" id="fazit-schluss"></p>
<p class="b-analyse__quelle" id="analyse-quelle"></p> <p class="b-fazit__zahlen leise" id="fazit-zahlen"></p>
</section> </section>
</main> <!-- Der Verlauf. Nur für die Person selbst – er wird nirgends sonst
im Haus gelesen. Er steht unter den Fragen, weil er sie erklärt
und nicht ersetzt. -->
<section class="b-verlauf" id="verlauf-block" hidden>
<h2 class="e-abschnitt">Wie es sich entwickelt</h2>
<p class="b-verlauf__satz" id="verlauf-satz">…</p>
<div id="verlauf" class="b-verlauf__gitter"></div>
</section>
<!-- ==================================================================
WAS DEIN VERLAUF SAGT (15.09.2026)
Filipe: „mach mir auch eine analyse […] eine professionelle auch
mit infos und so aus aller welt was tiktok angeht."
Sie steht UNTER dem Verlauf: erst die Antworten, dann das Muster
darin. Andersherum läse man die Deutung, bevor man weiß, worauf
sie sich bezieht.
Sie wird gerechnet, nicht gespeichert – und sie bewertet nicht.
Keine Punktzahl über das eigene Befinden: Eine Zahl lädt dazu
ein, sie zu verbessern statt ehrlich zu antworten.
============================================================== -->
<section class="b-analyse" id="analyse-block" hidden>
<h2 class="e-abschnitt">Was dein Verlauf sagt</h2>
<p class="b-analyse__satz" id="analyse-satz">…</p>
<div id="analyse" class="b-analyse__liste"></div>
<p class="b-analyse__quelle" id="analyse-quelle"></p>
</section>
</main>
<script src="assets/js/meldung.js?v=202609201909" defer></script> <script src="assets/js/meldung.js?v=202609201909" defer></script>
<script src="assets/js/nachfrage.js?v=202609201909" defer></script>␍ <script src="assets/js/nachfrage.js?v=202609201909" defer></script>
<script src="assets/js/wahl.js?v=202609201909" defer></script>
<script src="assets/js/bereiche.js?v=202609201909" defer></script> <script src="assets/js/wahl.js?v=202609201909" defer></script>
<script src="assets/js/kopf.js?v=202609201909" defer></script> <script src="assets/js/bereiche.js?v=202609201909" defer></script>
<script src="assets/js/befinden.js?v=202609201909" defer></script> <script src="assets/js/kopf.js?v=202609201909" defer></script>
</body> <script src="assets/js/befinden.js?v=202609201909" defer></script>
</html> </body>
</html>